/
change_password.go
111 lines (90 loc) · 2.43 KB
/
change_password.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
package userself
import (
"fmt"
v "github.com/RussellLuo/validating/v3"
"golang.org/x/crypto/bcrypt"
"github.com/th0th/poeticmetric/backend/pkg/depot"
"github.com/th0th/poeticmetric/backend/pkg/model"
"github.com/th0th/poeticmetric/backend/pkg/service/useraccesstoken"
)
type ChangePasswordPayload struct {
NewPassword *string `json:"newPassword"`
NewPassword2 *string `json:"newPassword2"`
}
func ChangePassword(dp *depot.Depot, id uint64, payload *ChangePasswordPayload) (*UserSelf, *useraccesstoken.UserAccessToken, error) {
err := validateChangePasswordPayload(payload)
if err != nil {
return nil, nil, err
}
newPasswordByteSlice, err := bcrypt.GenerateFromPassword([]byte(*payload.NewPassword), 10)
if err != nil {
return nil, nil, err
}
userAccessToken := &useraccesstoken.UserAccessToken{}
err = dp.WithPostgresTransaction(func(dp2 *depot.Depot) error {
err = dp.Postgres().
Model(&model.User{}).
Where("id = ?", id).
Update("password", string(newPasswordByteSlice)).
Error
if err != nil {
return err
}
err = dp.Postgres().
Where("user_id = ?", id).
Delete(&model.UserAccessToken{}).
Error
if err != nil {
return err
}
userAccessToken, err = useraccesstoken.Create(dp, id)
if err != nil {
return err
}
return nil
})
if err != nil {
return nil, nil, err
}
err = dp.Postgres().
Model(&model.User{}).
Where("id = ?", id).
Update("password", string(newPasswordByteSlice)).
Error
if err != nil {
return nil, nil, err
}
user, err := Read(dp, id)
if err != nil {
return nil, nil, err
}
return user, userAccessToken, nil
}
func validateChangePasswordPayload(payload *ChangePasswordPayload) error {
errs := v.Validate(v.Schema{
v.F("newPassword", payload.NewPassword): v.All(
v.Nonzero[*string]().Msg("This field is required."),
v.Is(func(t *string) bool {
return len(*t) >= model.UserPasswordMinLength && len(*t) <= model.UserPasswordMaxLength
}).Msg(fmt.Sprintf(
"This field should be between %d and %d characters in length.",
model.UserPasswordMinLength,
model.UserPasswordMaxLength,
)),
),
v.F("newPassword2", payload.NewPassword2): v.All(
v.Nonzero[*string]().Msg("This field is required."),
v.Is(
func(t *string) bool {
if payload.NewPassword == nil {
return true
}
return *t == *payload.NewPassword
}).Msg("Passwords don't match."),
),
})
if len(errs) > 0 {
return errs
}
return nil
}