Initial commit: Open sourcing all of the Maple Open Technologies code.
This commit is contained in:
commit
755d54a99d
2010 changed files with 448675 additions and 0 deletions
109
cloud/maplefile-backend/internal/service/user/publiclookup.go
Normal file
109
cloud/maplefile-backend/internal/service/user/publiclookup.go
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
// codeberg.org/mapleopentech/monorepo/cloud/maplefile-backend/internal/service/user/publiclookup.go
|
||||
package user
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"strings"
|
||||
|
||||
"go.uber.org/zap"
|
||||
|
||||
"codeberg.org/mapleopentech/monorepo/cloud/maplefile-backend/config"
|
||||
uc_user "codeberg.org/mapleopentech/monorepo/cloud/maplefile-backend/internal/usecase/user"
|
||||
"codeberg.org/mapleopentech/monorepo/cloud/maplefile-backend/pkg/httperror"
|
||||
"codeberg.org/mapleopentech/monorepo/cloud/maplefile-backend/pkg/validation"
|
||||
)
|
||||
|
||||
type UserPublicLookupRequestDTO struct {
|
||||
Email string `json:"email"`
|
||||
}
|
||||
|
||||
type UserPublicLookupResponseDTO struct {
|
||||
UserID string `json:"user_id"`
|
||||
Email string `json:"email"`
|
||||
Name string `json:"name"` // Optional: for display
|
||||
PublicKeyInBase64 string `json:"public_key_in_base64"` // Base64 encoded
|
||||
VerificationID string `json:"verification_id"`
|
||||
}
|
||||
|
||||
type UserPublicLookupService interface {
|
||||
Execute(ctx context.Context, req *UserPublicLookupRequestDTO) (*UserPublicLookupResponseDTO, error)
|
||||
}
|
||||
|
||||
type userPublicLookupServiceImpl struct {
|
||||
config *config.Config
|
||||
logger *zap.Logger
|
||||
userGetByEmailUC uc_user.UserGetByEmailUseCase
|
||||
}
|
||||
|
||||
func NewUserPublicLookupService(
|
||||
cfg *config.Config,
|
||||
logger *zap.Logger,
|
||||
userGetByEmailUC uc_user.UserGetByEmailUseCase,
|
||||
) UserPublicLookupService {
|
||||
logger = logger.Named("UserPublicLookupService")
|
||||
return &userPublicLookupServiceImpl{cfg, logger, userGetByEmailUC}
|
||||
}
|
||||
|
||||
func (svc *userPublicLookupServiceImpl) Execute(ctx context.Context, req *UserPublicLookupRequestDTO) (*UserPublicLookupResponseDTO, error) {
|
||||
//
|
||||
// STEP 1: Sanitization of the input.
|
||||
//
|
||||
|
||||
// Defensive Code: For security purposes we need to perform some sanitization on the inputs.
|
||||
req.Email = strings.ToLower(req.Email)
|
||||
req.Email = strings.ReplaceAll(req.Email, " ", "")
|
||||
req.Email = strings.ReplaceAll(req.Email, "\t", "")
|
||||
req.Email = strings.TrimSpace(req.Email)
|
||||
|
||||
svc.logger.Debug("sanitized email",
|
||||
zap.String("email", validation.MaskEmail(req.Email)))
|
||||
|
||||
//
|
||||
// STEP 2: Validation of input.
|
||||
//
|
||||
|
||||
e := make(map[string]string)
|
||||
if req.Email == "" {
|
||||
e["email"] = "Email is required"
|
||||
}
|
||||
if len(req.Email) > 255 {
|
||||
e["email"] = "Email is too long"
|
||||
}
|
||||
|
||||
if len(e) != 0 {
|
||||
svc.logger.Warn("failed validating",
|
||||
zap.Any("e", e))
|
||||
return nil, httperror.NewForBadRequest(&e)
|
||||
}
|
||||
|
||||
//
|
||||
// STEP 3: Lookup user by email
|
||||
//
|
||||
|
||||
// Lookup the user in our database, else return a `400 Bad Request` error.
|
||||
// Note: We return a generic error message to prevent user enumeration attacks.
|
||||
u, err := svc.userGetByEmailUC.Execute(ctx, req.Email)
|
||||
if err != nil {
|
||||
svc.logger.Error("failed getting user by email from database",
|
||||
zap.Any("error", err))
|
||||
return nil, httperror.NewForBadRequestWithSingleField("email", "Unable to complete lookup")
|
||||
}
|
||||
if u == nil {
|
||||
svc.logger.Warn("user lookup attempted for non-existent email",
|
||||
zap.String("email", validation.MaskEmail(req.Email)))
|
||||
// Return same error message as above to prevent user enumeration
|
||||
return nil, httperror.NewForBadRequestWithSingleField("email", "Unable to complete lookup")
|
||||
}
|
||||
|
||||
// STEP 4: Build response DTO
|
||||
dto := &UserPublicLookupResponseDTO{
|
||||
UserID: u.ID.String(),
|
||||
Email: u.Email,
|
||||
Name: u.Name,
|
||||
PublicKeyInBase64: base64.StdEncoding.EncodeToString(u.SecurityData.PublicKey.Key),
|
||||
VerificationID: u.SecurityData.VerificationID,
|
||||
}
|
||||
|
||||
return dto, nil
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue