Skip to content

Commit e419ef6

Browse files
authored
encrypt password of corp managers (#81)
* encrypt password of corp managers * minor update * do more update * update api
1 parent d5565f1 commit e419ef6

File tree

12 files changed

+181
-27
lines changed

12 files changed

+181
-27
lines changed

config/config.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ type appConfig struct {
1616
CLAFieldsNumber int `json:"cla_fields_number" required:"true"`
1717
MaxSizeOfCorpCLAPDF int `json:"max_size_of_corp_cla_pdf"`
1818
MaxSizeOfOrgSignaturePDF int `json:"max_size_of_org_signature_pdf"`
19+
MinLengthOfPassword int `json:"min_length_of_password"`
20+
MaxLengthOfPassword int `json:"max_length_of_password"`
1921
VerificationCodeExpiry int64 `json:"verification_code_expiry" required:"true"`
2022
APITokenExpiry int64 `json:"api_token_expiry" required:"true"`
2123
APITokenKey string `json:"api_token_key" required:"true"`
@@ -47,6 +49,8 @@ func InitAppConfig() error {
4749

4850
maxSizeOfCorpCLAPDF := beego.AppConfig.DefaultInt("max_size_of_corp_cla_pdf", (2 << 20))
4951
maxSizeOfOrgSignaturePDF := beego.AppConfig.DefaultInt("max_size_of_org_signature_pdf", (1 << 20))
52+
minLengthOfPassword := beego.AppConfig.DefaultInt("min_length_of_password", 6)
53+
maxLengthOfPassword := beego.AppConfig.DefaultInt("max_length_of_password", 16)
5054

5155
tokenExpiry, err := beego.AppConfig.Int64("api_token_expiry")
5256
if err != nil {
@@ -68,6 +72,8 @@ func InitAppConfig() error {
6872
CLAFieldsNumber: claFieldsNumber,
6973
MaxSizeOfCorpCLAPDF: maxSizeOfCorpCLAPDF,
7074
MaxSizeOfOrgSignaturePDF: maxSizeOfOrgSignaturePDF,
75+
MinLengthOfPassword: minLengthOfPassword,
76+
MaxLengthOfPassword: maxLengthOfPassword,
7177
VerificationCodeExpiry: codeExpiry,
7278
APITokenExpiry: tokenExpiry,
7379
APITokenKey: beego.AppConfig.String("api_token_key"),

controllers/corporation-manager.go

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -94,9 +94,21 @@ func (this *CorporationManagerController) Put() {
9494
}
9595

9696
// @Title Patch
97-
// @Description reset password of corporation administrator
98-
// @Success 204 {int} map
99-
// @Failure util.ErrInvalidAccountOrPw
97+
// @Description reset password of corporation manager
98+
// @Param body body dbmodels.CorporationManagerResetPassword true "body for resetting password"
99+
// @Success 204 {string} "reset password successfully"
100+
// @Failure 401 missing_token: token is missing
101+
// @Failure 402 unknown_token: token is unknown
102+
// @Failure 403 expired_token: token is expired
103+
// @Failure 404 unauthorized_token: the permission of token is unmatched
104+
// @Failure 405 error_parsing_api_body: parse payload of request failed
105+
// @Failure 406 same_password: the old and new passwords are same
106+
// @Failure 407 too_short_or_long_password: the length of new password is too short or long
107+
// @Failure 408 invalid_password: the format of new password is invalid
108+
// @Failure 409 corp_manager_does_not_exist: manager may be removed
109+
// @Failure 410 wrong_old_password: the old password is not correct
110+
// @Failure 411 frequent_operation: don't operate frequently
111+
// @Failure 500 system_error: system error
100112
// @router / [patch]
101113
func (this *CorporationManagerController) Patch() {
102114
action := "reset password of corp's manager"
@@ -120,7 +132,11 @@ func (this *CorporationManagerController) Patch() {
120132
}
121133

122134
if err := (&info).Reset(pl.LinkID, pl.Email); err != nil {
123-
this.sendModelErrorAsResp(err, action)
135+
if err.IsErrorOf(models.ErrNoLinkOrNoManagerOrFO) {
136+
this.sendFailedResponse(400, errFrequentOperation, err, action)
137+
} else {
138+
this.sendModelErrorAsResp(err, action)
139+
}
124140
return
125141
}
126142

controllers/error.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ const (
1414
errResigned = "resigned"
1515
errUnsigned = string(models.ErrUnsigned)
1616
errNoLink = string(models.ErrNoLink)
17-
errNoEmployeeManager = "no_employee_manager"
1817
errWrongIDOrPassword = "wrong_id_or_pw"
1918
errCorpManagerExists = string(models.ErrCorpManagerExists)
2019
errNoRefreshToken = "no_refresh_token"
@@ -39,6 +38,7 @@ const (
3938
errGoToSignEmployeeCLA = "go_to_sign_employee_cla"
4039
errUnsupportedCLALang = "unsupported_cla_lang"
4140
errNotSameCorp = string(models.ErrNotSameCorp)
41+
errFrequentOperation = "frequent_operation"
4242
)
4343

4444
func parseModelError(err models.IModelError) *failedApiResult {

dbmodels/corporation-manager.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ type CorporationManagerCheckInfo struct {
1717
ID string
1818
Email string
1919
EmailSuffix string
20-
Password string
2120
}
2221

2322
type CorporationManagerResetPassword struct {
@@ -29,6 +28,7 @@ type CorporationManagerCheckResult struct {
2928
Role string
3029
Name string
3130
Email string
31+
Password string
3232
InitialPWChanged bool
3333

3434
OrgInfo

dbmodels/db.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ type ICorporationManager interface {
4343
DeleteEmployeeManager(orgCLAID string, emails []string) ([]CorporationManagerCreateOption, IDBError)
4444
ResetCorporationManagerPassword(string, string, CorporationManagerResetPassword) IDBError
4545
ListCorporationManager(orgCLAID, email, role string) ([]CorporationManagerListResult, IDBError)
46+
GetCorporationManager(linkID, email string) (*CorporationManagerCheckResult, IDBError)
4647
}
4748

4849
type IOrgEmail interface {

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ require (
1111
github.com/huaweicloud/golangsdk v0.0.0-20201228013212-d10065a3dc7f
1212
github.com/opensourceways/gofpdf v1.16.4
1313
go.mongodb.org/mongo-driver v1.4.4
14+
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a
1415
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5
1516
google.golang.org/api v0.36.0
1617
sigs.k8s.io/yaml v1.2.0

go.sum

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,6 @@ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
167167
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
168168
github.com/google/go-cmp v0.5.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M=
169169
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
170-
github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY=
171170
github.com/google/go-github/v33 v33.0.0 h1:qAf9yP0qc54ufQxzwv+u9H0tiVOnPJxo0lI/JXqw3ZM=
172171
github.com/google/go-github/v33 v33.0.0/go.mod h1:GMdDnVZY/2TsWgp/lkYnpSAh6TrzhANBBwm6k6TTEXg=
173172
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=

models/corporation-manager.go

Lines changed: 65 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"fmt"
55
"strings"
66

7+
"github.com/opensourceways/app-cla-server/config"
78
"github.com/opensourceways/app-cla-server/dbmodels"
89
"github.com/opensourceways/app-cla-server/util"
910
)
@@ -14,7 +15,7 @@ type CorporationManagerAuthentication struct {
1415
}
1516

1617
func (this CorporationManagerAuthentication) Authenticate() (map[string]dbmodels.CorporationManagerCheckResult, IModelError) {
17-
info := dbmodels.CorporationManagerCheckInfo{Password: this.Password}
18+
info := dbmodels.CorporationManagerCheckInfo{}
1819
if merr := checkEmailFormat(this.User); merr == nil {
1920
info.Email = this.User
2021
} else {
@@ -29,25 +30,35 @@ func (this CorporationManagerAuthentication) Authenticate() (map[string]dbmodels
2930

3031
v, err := dbmodels.GetDB().CheckCorporationManagerExist(info)
3132
if err == nil {
33+
for k := range v {
34+
if !isSamePasswords(v[k].Password, this.Password) {
35+
delete(v, k)
36+
}
37+
}
3238
return v, nil
3339
}
3440

3541
return nil, parseDBError(err)
3642
}
3743

3844
func CreateCorporationAdministrator(linkID, name, email string) (*dbmodels.CorporationManagerCreateOption, IModelError) {
39-
pw := util.RandStr(8, "alphanum")
45+
pw := newPWForCorpManager()
46+
encryptedPW, merr := encryptPassword(pw)
47+
if merr != nil {
48+
return nil, merr
49+
}
4050

4151
opt := &dbmodels.CorporationManagerCreateOption{
4252
ID: "admin",
4353
Name: name,
4454
Email: email,
45-
Password: pw,
55+
Password: encryptedPW,
4656
Role: dbmodels.RoleAdmin,
4757
}
4858
err := dbmodels.GetDB().AddCorpAdministrator(linkID, opt)
4959
if err == nil {
5060
opt.ID = fmt.Sprintf("admin_%s", util.EmailSuffix(email))
61+
opt.Password = pw
5162
return opt, nil
5263
}
5364

@@ -64,23 +75,67 @@ func (this CorporationManagerResetPassword) Validate() IModelError {
6475
if this.NewPassword == this.OldPassword {
6576
return newModelError(ErrSamePassword, fmt.Errorf("the new password is same as old one"))
6677
}
67-
return nil
78+
79+
n := len(this.NewPassword)
80+
cfg := config.AppConfig
81+
if n < cfg.MinLengthOfPassword || n > cfg.MaxLengthOfPassword {
82+
return newModelError(
83+
ErrTooShortOrLongPassword,
84+
fmt.Errorf(
85+
"the length of password should be between %d and %d",
86+
cfg.MinLengthOfPassword, cfg.MaxLengthOfPassword,
87+
))
88+
}
89+
90+
return checkPassword(this.NewPassword)
6891
}
6992

7093
func (this CorporationManagerResetPassword) Reset(linkID, email string) IModelError {
94+
pw, merr := encryptPassword(this.NewPassword)
95+
if merr != nil {
96+
return merr
97+
}
98+
99+
record, merr := this.getCorporationManager(linkID, email)
100+
if merr != nil {
101+
return merr
102+
}
103+
if record == nil {
104+
return newModelError(ErrCorpManagerDoesNotExist, fmt.Errorf("corp manager does not exist"))
105+
}
106+
107+
if !isSamePasswords(record.Password, this.OldPassword) {
108+
return newModelError(ErrWrongOldPassword, fmt.Errorf("old password is not correct"))
109+
}
110+
71111
err := dbmodels.GetDB().ResetCorporationManagerPassword(
72-
linkID, email, dbmodels.CorporationManagerResetPassword(this),
112+
linkID, email, dbmodels.CorporationManagerResetPassword{
113+
OldPassword: record.Password, NewPassword: pw,
114+
},
73115
)
74116
if err == nil {
75117
return nil
76118
}
77119

78120
if err.IsErrorOf(dbmodels.ErrNoDBRecord) {
79-
return newModelError(ErrNoLinkOrNoManager, err)
121+
return newModelError(ErrNoLinkOrNoManagerOrFO, err)
80122
}
81123
return parseDBError(err)
82124
}
83125

126+
func (this CorporationManagerResetPassword) getCorporationManager(linkID, email string) (*dbmodels.CorporationManagerCheckResult, IModelError) {
127+
v, err := dbmodels.GetDB().GetCorporationManager(linkID, email)
128+
if err == nil {
129+
return v, nil
130+
}
131+
132+
if err.IsErrorOf(dbmodels.ErrNoDBRecord) {
133+
return v, newModelError(ErrNoLink, err)
134+
}
135+
136+
return v, parseDBError(err)
137+
}
138+
84139
func ListCorporationManagers(linkID, email, role string) ([]dbmodels.CorporationManagerListResult, IModelError) {
85140
v, err := dbmodels.GetDB().ListCorporationManager(linkID, email, role)
86141
if err == nil {
@@ -96,3 +151,7 @@ func ListCorporationManagers(linkID, email, role string) ([]dbmodels.Corporation
96151

97152
return v, parseDBError(err)
98153
}
154+
155+
func newPWForCorpManager() string {
156+
return util.RandStr(8, "alphanum")
157+
}

models/employee-manager.go

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,17 +76,24 @@ func (this *EmployeeManagerCreateOption) ValidateWhenAdding(linkID, adminEmail s
7676
}
7777

7878
func (this *EmployeeManagerCreateOption) Create(linkID string) ([]dbmodels.CorporationManagerCreateOption, IModelError) {
79+
pws := map[string]string{}
7980
opt := make([]dbmodels.CorporationManagerCreateOption, 0, len(this.Managers))
8081

8182
for i := range this.Managers {
8283
item := &this.Managers[i]
83-
pw := util.RandStr(8, "alphanum")
8484

85+
pw := newPWForCorpManager()
86+
encryptedPW, merr := encryptPassword(pw)
87+
if merr != nil {
88+
return nil, merr
89+
}
90+
91+
pws[item.Email] = pw
8592
opt = append(opt, dbmodels.CorporationManagerCreateOption{
8693
ID: item.ID,
8794
Name: item.Name,
8895
Email: item.Email,
89-
Password: pw,
96+
Password: encryptedPW,
9097
Role: dbmodels.RoleManager,
9198
})
9299
}
@@ -101,9 +108,12 @@ func (this *EmployeeManagerCreateOption) Create(linkID string) ([]dbmodels.Corpo
101108

102109
es := util.EmailSuffix(opt[0].Email)
103110
for i := range opt {
104-
if opt[i].ID != "" {
105-
opt[i].ID = fmt.Sprintf("%s_%s", opt[i].ID, es)
111+
item := &opt[i]
112+
113+
if item.ID != "" {
114+
item.ID = fmt.Sprintf("%s_%s", item.ID, es)
106115
}
116+
item.Password = pws[item.Email]
107117
}
108118
return opt, nil
109119
}

models/error.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,13 @@ const (
2121
ErrNoLinkOrUnsigned ModelErrCode = "no_link_or_unsigned"
2222
ErrUnsigned ModelErrCode = "unsigned"
2323
ErrSamePassword ModelErrCode = "same_password"
24-
ErrNoLinkOrNoManager ModelErrCode = "no_link_or_no_manager"
24+
ErrWrongOldPassword ModelErrCode = "wrong_old_password"
25+
ErrTooShortOrLongPassword ModelErrCode = "too_short_or_long_password"
26+
ErrInvalidPassword ModelErrCode = "invalid_password"
27+
ErrNoLinkOrNoManagerOrFO ModelErrCode = "no_link_or_no_manager_or_frequent_operation"
2528
ErrNoLinkOrManagerExists ModelErrCode = "no_link_or_manager_exists"
2629
ErrCorpManagerExists ModelErrCode = "corp_manager_exists"
30+
ErrCorpManagerDoesNotExist ModelErrCode = "corp_manager_does_not_exist"
2731
ErrInvalidManagerID ModelErrCode = "invalid_manager_id"
2832
ErrDuplicateManagerID ModelErrCode = "duplicate_manager_id"
2933
ErrEmptyPayload ModelErrCode = "empty_payload"

0 commit comments

Comments
 (0)