unified code verification service

This commit is contained in:
Stephan D
2026-02-10 01:55:33 +01:00
parent 76c3bfdea9
commit 7f540671c1
120 changed files with 1863 additions and 1394 deletions

View File

@@ -155,14 +155,18 @@ func (s *service) CreateAccount(
func (s *service) VerifyAccount(
ctx context.Context,
acct *model.Account,
) (verificationToken string, err error) {
verificationToken, err = s.vdb.Create(ctx, *acct.GetID(), model.PurposeAccountActivation, "", time.Duration(time.Hour*24))
) (string, error) {
token, err := s.vdb.Create(
ctx,
verification.NewLinkRequest(*acct.GetID(), model.PurposeAccountActivation, "").
WithTTL(time.Duration(time.Hour*24)),
)
if err != nil {
s.logger.Warn("Failed to create verification token for new account", zap.Error(err), mzap.StorableRef(acct))
return "", err
}
return verificationToken, nil
return token, nil
}
@@ -174,19 +178,19 @@ func (s *service) DeleteAccount(
// Check if this is the only member in the organization
if len(org.Members) <= 1 {
s.logger.Warn("Cannot delete account - it's the only member in the organization",
mzap.ObjRef("account_ref", accountRef), mzap.StorableRef(org))
mzap.AccRef(accountRef), mzap.StorableRef(org))
return merrors.InvalidArgument("Cannot delete the only member of an organization")
}
// 1) Remove from organization
if err := s.RemoveAccountFromOrganization(ctx, org, accountRef); err != nil {
s.logger.Warn("Failed to revoke account role", zap.Error(err), mzap.ObjRef("account_ref", accountRef))
s.logger.Warn("Failed to revoke account role", zap.Error(err), mzap.AccRef(accountRef))
return err
}
// 2) Delete the account document
if err := s.accountDB.Delete(ctx, accountRef); err != nil {
s.logger.Warn("Failed to delete account", zap.Error(err), mzap.ObjRef("account_ref", accountRef))
s.logger.Warn("Failed to delete account", zap.Error(err), mzap.AccRef(accountRef))
return err
}
return nil
@@ -203,13 +207,13 @@ func (s *service) RemoveAccountFromOrganization(
roles, err := s.enforcer.GetRoles(ctx, accountRef, org.ID)
if err != nil {
s.logger.Warn("Failed to fetch account permissions", zap.Error(err), mzap.StorableRef(org),
mzap.ObjRef("account_ref", accountRef))
mzap.AccRef(accountRef))
return err
}
for _, role := range roles {
if err := s.roleManager.Revoke(ctx, role.DescriptionRef, accountRef, org.ID); err != nil {
s.logger.Warn("Failed to revoke account role", zap.Error(err),
mzap.ObjRef("account_ref", accountRef), mzap.ObjRef("role_ref", role.DescriptionRef))
mzap.AccRef(accountRef), mzap.ObjRef("role_ref", role.DescriptionRef))
return err
}
}
@@ -218,7 +222,7 @@ func (s *service) RemoveAccountFromOrganization(
// Remove the member by slicing it out
org.Members = append(org.Members[:i], org.Members[i+1:]...)
if err := s.orgDB.Update(ctx, accountRef, org); err != nil {
s.logger.Warn("Failed to remove member from organization", zap.Error(err), mzap.ObjRef("account_ref", accountRef))
s.logger.Warn("Failed to remove member from organization", zap.Error(err), mzap.AccRef(accountRef))
return err
}
break
@@ -231,7 +235,11 @@ func (s *service) ResetPassword(
ctx context.Context,
acct *model.Account,
) (string, error) {
return s.vdb.Create(ctx, *acct.GetID(), model.PurposePasswordReset, "", time.Duration(time.Hour*1))
return s.vdb.Create(
ctx,
verification.NewOTPRequest(*acct.GetID(), model.PurposePasswordReset, "").
WithTTL(time.Duration(time.Hour*1)),
)
}
func (s *service) UpdateLogin(
@@ -239,7 +247,11 @@ func (s *service) UpdateLogin(
acct *model.Account,
newLogin string,
) (string, error) {
return s.vdb.Create(ctx, *acct.GetID(), model.PurposeEmailChange, newLogin, time.Duration(time.Hour*1))
return s.vdb.Create(
ctx,
verification.NewOTPRequest(*acct.GetID(), model.PurposeEmailChange, newLogin).
WithTTL(time.Duration(time.Hour*1)),
)
}
func (s *service) JoinOrganization(
@@ -350,7 +362,7 @@ func (s *service) DeleteAll(
accountRef bson.ObjectID,
) error {
s.logger.Info("Starting complete deletion (organization + account)",
mzap.StorableRef(org), mzap.ObjRef("account_ref", accountRef))
mzap.StorableRef(org), mzap.AccRef(accountRef))
// 1. First delete the organization and all its data
if err := s.DeleteOrganization(ctx, org); err != nil {
@@ -359,11 +371,11 @@ func (s *service) DeleteAll(
// 2. Then delete the account
if err := s.accountDB.Delete(ctx, accountRef); err != nil {
s.logger.Warn("Failed to delete account", zap.Error(err), mzap.ObjRef("account_ref", accountRef))
s.logger.Warn("Failed to delete account", zap.Error(err), mzap.AccRef(accountRef))
return err
}
s.logger.Info("Complete deletion successful", mzap.StorableRef(org), mzap.ObjRef("account_ref", accountRef))
s.logger.Info("Complete deletion successful", mzap.StorableRef(org), mzap.AccRef(accountRef))
return nil
}

View File

@@ -12,10 +12,9 @@ type pendingLoginResponse struct {
Account accountResponse `json:"account"`
PendingToken TokenData `json:"pendingToken"`
Destination string `json:"destination"`
TTLSeconds int `json:"ttlSeconds"`
}
func LoginPending(logger mlogger.Logger, account *model.Account, pendingToken *TokenData, destination string, ttlSeconds int) http.HandlerFunc {
func LoginPending(logger mlogger.Logger, account *model.Account, pendingToken *TokenData, destination string) http.HandlerFunc {
return response.Accepted(
logger,
&pendingLoginResponse{
@@ -25,7 +24,6 @@ func LoginPending(logger mlogger.Logger, account *model.Account, pendingToken *T
},
PendingToken: *pendingToken,
Destination: destination,
TTLSeconds: ttlSeconds,
},
)
}

View File

@@ -1,11 +1,11 @@
package confirmation
package verification
import (
"github.com/tech/sendico/pkg/mservice"
"github.com/tech/sendico/server/interface/api"
"github.com/tech/sendico/server/internal/server/confirmationimp"
"github.com/tech/sendico/server/internal/server/verificationimp"
)
func Create(a api.API) (mservice.MicroService, error) {
return confirmationimp.CreateAPI(a)
return verificationimp.CreateAPI(a)
}