refactor: remove unused Pinia stores and related code
- Deleted the layout-store, profiles-store, and index.ts files from the Pinia store setup. - Removed the zod-sync script as it is no longer needed. - Cleaned up the tsconfig.json file by removing unnecessary references. - Updated the login logic in the profiles package to use polling for login results instead of in-process waiters. - Added validation methods for personal data and profile parameters. - Introduced new tests for validation logic in profiles and registration packages. - Enhanced email normalization and validation in the registration package.
This commit is contained in:
@@ -4,11 +4,9 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"encore.dev/beta/auth"
|
||||
"encore.dev/beta/errs"
|
||||
"encore.dev/storage/sqldb"
|
||||
"encore.dev/types/uuid"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
type RegisterParams struct {
|
||||
@@ -16,6 +14,16 @@ type RegisterParams struct {
|
||||
Password string `json:"password" encore:"sensitive"`
|
||||
}
|
||||
|
||||
func (p *RegisterParams) Validate() error {
|
||||
if p == nil {
|
||||
return &errs.Error{Code: errs.InvalidArgument, Message: "register params are required"}
|
||||
}
|
||||
if p.UserID == uuid.Nil {
|
||||
return &errs.Error{Code: errs.InvalidArgument, Message: "user id is required"}
|
||||
}
|
||||
return validatePassword(p.Password)
|
||||
}
|
||||
|
||||
// Register stores the initial password hash for a newly created profile.
|
||||
// Called directly (service-to-service) by profiles.Insert during registration,
|
||||
// since that flow needs to know immediately whether credential setup succeeded.
|
||||
@@ -35,6 +43,23 @@ func Register(ctx context.Context, p *RegisterParams) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *SetPasswordParams) Validate() error {
|
||||
if p == nil {
|
||||
return &errs.Error{Code: errs.InvalidArgument, Message: "password params are required"}
|
||||
}
|
||||
if err := validatePassword(p.CurrentPassword); err != nil {
|
||||
return err
|
||||
}
|
||||
return validatePassword(p.Password)
|
||||
}
|
||||
|
||||
func (p *SetUserPasswordParams) Validate() error {
|
||||
if p == nil {
|
||||
return &errs.Error{Code: errs.InvalidArgument, Message: "user password params are required"}
|
||||
}
|
||||
return validatePassword(p.Password)
|
||||
}
|
||||
|
||||
type SetPasswordParams struct {
|
||||
CurrentPassword string `json:"current_password" encore:"sensitive"`
|
||||
Password string `json:"password" encore:"sensitive"`
|
||||
@@ -49,40 +74,11 @@ type SetUserPasswordParams struct {
|
||||
//
|
||||
//encore:api auth method=PUT path=/auth/password
|
||||
func SetPassword(ctx context.Context, p *SetPasswordParams) error {
|
||||
uid, ok := auth.UserID()
|
||||
if !ok {
|
||||
return &errs.Error{Code: errs.Unauthenticated, Message: "missing auth"}
|
||||
}
|
||||
userID, err := uuid.FromString(string(uid))
|
||||
userID, err := authenticatedUserID()
|
||||
if err != nil {
|
||||
return errs.WrapCode(err, errs.Internal, "invalid user id")
|
||||
return err
|
||||
}
|
||||
|
||||
var currentHash string
|
||||
err = db.QueryRow(ctx, `
|
||||
SELECT password_hash FROM credentials WHERE user_id = $1
|
||||
`, userID).Scan(¤tHash)
|
||||
if errors.Is(err, sqldb.ErrNoRows) {
|
||||
return &errs.Error{Code: errs.NotFound, Message: "credentials not found"}
|
||||
}
|
||||
if err != nil {
|
||||
return errs.WrapCode(err, errs.Internal, "failed to fetch credentials")
|
||||
}
|
||||
if err := bcrypt.CompareHashAndPassword([]byte(currentHash), pepperedPassword(p.CurrentPassword)); err != nil {
|
||||
return &errs.Error{Code: errs.Unauthenticated, Message: "invalid current password"}
|
||||
}
|
||||
|
||||
hash, err := hashPassword(p.Password)
|
||||
if err != nil {
|
||||
return errs.WrapCode(err, errs.Internal, "failed to hash password")
|
||||
}
|
||||
_, err = db.Exec(ctx, `
|
||||
UPDATE credentials SET password_hash = $2, updated_at = NOW() WHERE user_id = $1
|
||||
`, userID, hash)
|
||||
if err != nil {
|
||||
return errs.WrapCode(err, errs.Internal, "failed to update password")
|
||||
}
|
||||
return nil
|
||||
return setPasswordWithCurrentCheck(ctx, userID, p.CurrentPassword, p.Password)
|
||||
}
|
||||
|
||||
// SetUserPassword changes a user's password from trusted internal flows.
|
||||
@@ -92,13 +88,77 @@ func SetUserPassword(ctx context.Context, userID uuid.UUID, p *SetUserPasswordPa
|
||||
if p.UserID != uuid.Nil && p.UserID != userID {
|
||||
return &errs.Error{Code: errs.InvalidArgument, Message: "user id mismatch"}
|
||||
}
|
||||
return replacePassword(ctx, userID, p.Password)
|
||||
}
|
||||
|
||||
hash, err := hashPassword(p.Password)
|
||||
func setPasswordWithCurrentCheck(ctx context.Context, userID uuid.UUID, currentPassword, newPassword string) error {
|
||||
if err := validatePassword(newPassword); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tx, err := db.Begin(ctx)
|
||||
if err != nil {
|
||||
return errs.WrapCode(err, errs.Internal, "failed to begin password update transaction")
|
||||
}
|
||||
defer func() {
|
||||
if err != nil {
|
||||
_ = tx.Rollback()
|
||||
}
|
||||
}()
|
||||
|
||||
var currentHash string
|
||||
err = tx.QueryRow(ctx, `
|
||||
SELECT password_hash FROM credentials WHERE user_id = $1 FOR UPDATE
|
||||
`, userID).Scan(¤tHash)
|
||||
if errors.Is(err, sqldb.ErrNoRows) {
|
||||
return &errs.Error{Code: errs.NotFound, Message: "credentials not found"}
|
||||
}
|
||||
if err != nil {
|
||||
return errs.WrapCode(err, errs.Internal, "failed to fetch credentials")
|
||||
}
|
||||
if err = verifyPassword(currentHash, currentPassword); err != nil {
|
||||
return &errs.Error{Code: errs.Unauthenticated, Message: "invalid current password"}
|
||||
}
|
||||
if isPasswordReuse(currentHash, newPassword) {
|
||||
return &errs.Error{Code: errs.InvalidArgument, Message: "new password must be different from the current password"}
|
||||
}
|
||||
|
||||
hash, err := hashPassword(newPassword)
|
||||
if err != nil {
|
||||
return errs.WrapCode(err, errs.Internal, "failed to hash password")
|
||||
}
|
||||
_, err = tx.Exec(ctx, `
|
||||
UPDATE credentials SET password_hash = $2, updated_at = NOW() WHERE user_id = $1
|
||||
`, userID, hash)
|
||||
if err != nil {
|
||||
return errs.WrapCode(err, errs.Internal, "failed to update password")
|
||||
}
|
||||
if err = tx.Commit(); err != nil {
|
||||
return errs.WrapCode(err, errs.Internal, "failed to commit password update")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
res, err := db.Exec(ctx, `
|
||||
func replacePassword(ctx context.Context, userID uuid.UUID, newPassword string) error {
|
||||
if err := validatePassword(newPassword); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tx, err := db.Begin(ctx)
|
||||
if err != nil {
|
||||
return errs.WrapCode(err, errs.Internal, "failed to begin password update transaction")
|
||||
}
|
||||
defer func() {
|
||||
if err != nil {
|
||||
_ = tx.Rollback()
|
||||
}
|
||||
}()
|
||||
|
||||
hash, err := hashPassword(newPassword)
|
||||
if err != nil {
|
||||
return errs.WrapCode(err, errs.Internal, "failed to hash password")
|
||||
}
|
||||
res, err := tx.Exec(ctx, `
|
||||
UPDATE credentials SET password_hash = $2, updated_at = NOW() WHERE user_id = $1
|
||||
`, userID, hash)
|
||||
if err != nil {
|
||||
@@ -107,5 +167,8 @@ func SetUserPassword(ctx context.Context, userID uuid.UUID, p *SetUserPasswordPa
|
||||
if res.RowsAffected() == 0 {
|
||||
return &errs.Error{Code: errs.NotFound, Message: "credentials not found"}
|
||||
}
|
||||
if err = tx.Commit(); err != nil {
|
||||
return errs.WrapCode(err, errs.Internal, "failed to commit password update")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user