From efa28749de9f7d8f6e330e93de6a9e31134f6a0b Mon Sep 17 00:00:00 2001 From: Hoang Date: Tue, 9 Nov 2021 14:16:34 +0700 Subject: [PATCH 1/8] fix userModel --- action_create.go | 4 ++-- action_get_all.go | 8 ++++---- db.go | 16 ++++++++-------- db_model.go | 32 ++++++++++++++++++++++++++++++++ model.go | 35 ++++------------------------------- 5 files changed, 50 insertions(+), 45 deletions(-) create mode 100644 db_model.go diff --git a/action_create.go b/action_create.go index 616eae2..d09d1af 100644 --- a/action_create.go +++ b/action_create.go @@ -42,10 +42,10 @@ func (s Service) Create(payload CreateOptions) error { return nil } -func (payload CreateOptions) newUser() (result User, err error) { +func (payload CreateOptions) newUser() (result dbUser, err error) { timeNow := now() roleID, _ := mongodb.NewIDFromString(payload.RoleID) - return User{ + return dbUser{ ID: mongodb.NewObjectID(), Name: payload.Name, SearchString: getSearchString(payload.Name, payload.Phone, payload.Email), diff --git a/action_get_all.go b/action_get_all.go index 47b65c7..a169559 100644 --- a/action_get_all.go +++ b/action_get_all.go @@ -17,7 +17,7 @@ type AllQuery struct { } // All ... -func (s Service) All(queryParams AllQuery) (r ResponseUserAll) { +func (s Service) All(queryParams AllQuery) (r UserAll) { var ( ctx = context.Background() wg sync.WaitGroup @@ -56,12 +56,12 @@ func (s Service) All(queryParams AllQuery) (r ResponseUserAll) { return } -func getResponseList(ctx context.Context, users []User) []ResponseUser { - res := make([]ResponseUser, 0) +func getResponseList(ctx context.Context, users []dbUser) []User { + res := make([]User, 0) for _, user := range users { role, _ := s.roleFindByID(ctx, user.RoleID) - res = append(res, ResponseUser{ + res = append(res, User{ ID: user.ID.Hex(), Name: user.Name, Phone: user.Phone, diff --git a/db.go b/db.go index dbfade4..0e88f3e 100644 --- a/db.go +++ b/db.go @@ -68,7 +68,7 @@ func (s Service) isRoleIDExisted(ctx context.Context, roleID primitive.ObjectID) return total != 0 } -func (s Service) userCreate(ctx context.Context, doc User) error { +func (s Service) userCreate(ctx context.Context, doc dbUser) error { var ( col = s.getUserCollection() ) @@ -103,20 +103,20 @@ func (s Service) userUpdateOneByCondition(ctx context.Context, cond interface{}, return err } -func (s Service) userFindByID(ctx context.Context, id primitive.ObjectID) (User, error) { +func (s Service) userFindByID(ctx context.Context, id primitive.ObjectID) (dbUser, error) { var ( col = s.getUserCollection() - doc User + doc dbUser ) err := col.FindOne(ctx, bson.M{"_id": id}).Decode(&doc) return doc, err } -func (s Service) userFindByCondition(ctx context.Context, cond interface{}, opts ...*options.FindOptions) (docs []User) { +func (s Service) userFindByCondition(ctx context.Context, cond interface{}, opts ...*options.FindOptions) (docs []dbUser) { var ( col = s.getUserCollection() ) - docs = make([]User, 0) + docs = make([]dbUser, 0) cursor, err := col.Find(ctx, cond, opts...) if err != nil { @@ -155,11 +155,11 @@ func (s Service) userCountByCondition(ctx context.Context, cond interface{}) int return total } -func (s Service) roleFindByID(ctx context.Context, id primitive.ObjectID) (Role, error) { +func (s Service) roleFindByID(ctx context.Context, id primitive.ObjectID) (dbRole, error) { var ( col = s.getRoleCollection() - doc Role + doc dbRole ) err := col.FindOne(ctx, bson.M{"_id": id}).Decode(&doc) return doc, err -} \ No newline at end of file +} diff --git a/db_model.go b/db_model.go new file mode 100644 index 0000000..2eb0465 --- /dev/null +++ b/db_model.go @@ -0,0 +1,32 @@ +package usermngmt + +import ( + "time" + + "go.mongodb.org/mongo-driver/bson/primitive" +) + +// dbUser ... +type dbUser struct { + ID primitive.ObjectID `bson:"_id"` + Name string `bson:"name"` + SearchString string `bson:"searchString"` + Phone string `bson:"phone"` // unique + Email string `bson:"email"` // unique + HashedPassword string `bson:"hashedPassword"` + Status string `bson:"status"` + RoleID primitive.ObjectID `bson:"roleId"` + Other string `bson:"other"` + CreatedAt time.Time `bson:"createdAt"` + UpdatedAt time.Time `bson:"updatedAt"` +} + +// dbRole ... +type dbRole struct { + ID primitive.ObjectID `bson:"_id" json:"_id"` + Name string `bson:"name" json:"name"` + Code string `bson:"code" json:"code"` + IsAdmin bool `bson:"isAdmin" json:"isAdmin"` + CreatedAt time.Time `bson:"createdAt" json:"createdAt"` + UpdatedAt time.Time `bson:"updatedAt" json:"updatedAt"` +} diff --git a/model.go b/model.go index a44ee3d..7fe6391 100644 --- a/model.go +++ b/model.go @@ -2,27 +2,10 @@ package usermngmt import ( "time" - - "go.mongodb.org/mongo-driver/bson/primitive" ) // User ... type User struct { - ID primitive.ObjectID `bson:"_id" json:"_id"` - Name string `bson:"name" json:"name"` - SearchString string `bson:"searchString" json:"-"` - Phone string `bson:"phone" json:"phone"` // unique - Email string `bson:"email" json:"email"` // unique - HashedPassword string `bson:"hashedPassword" json:"-"` - Status string `bson:"status" json:"status"` - RoleID primitive.ObjectID `bson:"roleId" json:"roleId"` - Other string `bson:"other" json:"other"` - CreatedAt time.Time `bson:"createdAt" json:"createdAt"` - UpdatedAt time.Time `bson:"updatedAt" json:"updatedAt"` -} - -// ResponseUser ... -type ResponseUser struct { ID string `json:"_id"` Name string `json:"name"` Phone string `json:"phone"` @@ -34,16 +17,6 @@ type ResponseUser struct { UpdatedAt time.Time `json:"updatedAt"` } -// Role ... -type Role struct { - ID primitive.ObjectID `bson:"_id" json:"_id"` - Name string `bson:"name" json:"name"` - Code string `bson:"code" json:"code"` - IsAdmin bool `bson:"isAdmin" json:"isAdmin"` - CreatedAt time.Time `bson:"createdAt" json:"createdAt"` - UpdatedAt time.Time `bson:"updatedAt" json:"updatedAt"` -} - type RoleShort struct { ID string `json:"_id"` Name string `json:"name"` @@ -51,9 +24,9 @@ type RoleShort struct { } type ( - // ResponseUserAll ... - ResponseUserAll struct { - List []ResponseUser `json:"list"` - Total int64 `json:"total"` + // UserAll ... + UserAll struct { + List []User `json:"list"` + Total int64 `json:"total"` } ) From c082388d64f09ef9794616d43c1e7aebde9c1c52 Mon Sep 17 00:00:00 2001 From: Hoang Date: Wed, 10 Nov 2021 08:44:22 +0700 Subject: [PATCH 2/8] design pkg again --- action.go | 30 ++++ action_create.go | 61 ------- action_get_all.go | 82 ---------- action_update.go | 125 -------------- constant.go | 4 - db.go | 148 ----------------- go.mod | 2 +- init_handle.go | 21 +++ internal/constant.go | 9 + db_model.go => internal/db_model.go | 25 +-- helper.go => internal/helper.go | 9 +- query.go => internal/query.go | 15 +- internal/role_model.go | 12 ++ time.go => internal/time.go | 7 +- internal/user_model.go | 187 +++++++++++++++++++++ model.go | 32 ---- role/db.go | 17 ++ role/handle.go | 25 +++ user/db.go | 130 +++++++++++++++ user/handle.go | 245 ++++++++++++++++++++++++++++ validate.go | 145 ---------------- 21 files changed, 707 insertions(+), 624 deletions(-) create mode 100644 action.go delete mode 100644 action_create.go delete mode 100644 action_get_all.go delete mode 100644 action_update.go create mode 100644 init_handle.go create mode 100644 internal/constant.go rename db_model.go => internal/db_model.go (92%) rename helper.go => internal/helper.go (77%) rename query.go => internal/query.go (73%) create mode 100644 internal/role_model.go rename time.go => internal/time.go (88%) create mode 100644 internal/user_model.go delete mode 100644 model.go create mode 100644 role/db.go create mode 100644 role/handle.go create mode 100644 user/db.go create mode 100644 user/handle.go delete mode 100644 validate.go diff --git a/action.go b/action.go new file mode 100644 index 0000000..fb41213 --- /dev/null +++ b/action.go @@ -0,0 +1,30 @@ +package usermngmt + +import "github.com/Selly-Modules/usermngmt/internal" + +// Create ... +func (s Service) Create(payload internal.CreateOptions) error { + return s.userHandle().Create(payload) +} + +// Update ... +func (s Service) Update(userID string, payload internal.UpdateOptions) error { + return s.userHandle().UpdateByUserID(userID, payload) +} + +// ChangeUserPassword ... +func (s Service) ChangeUserPassword(userID string, payload internal.ChangePasswordOptions) error { + return s.userHandle().ChangeUserPassword(userID, payload) +} + +func (s Service) ChangeUserStatus(userID, newStatus string) error { + return s.userHandle().ChangeUserStatus(userID, newStatus) +} + +func (s Service) All(query internal.AllQuery) internal.UserAll { + return s.userHandle().All(query) +} + +func (s Service) RoleCreate(payload internal.RoleCreateOptions) error { + return s.roleHandle().Create(payload) +} diff --git a/action_create.go b/action_create.go deleted file mode 100644 index d09d1af..0000000 --- a/action_create.go +++ /dev/null @@ -1,61 +0,0 @@ -package usermngmt - -import ( - "context" - - "github.com/Selly-Modules/mongodb" -) - -// CreateOptions ... -type CreateOptions struct { - Name string - Phone string - Email string - Password string - Status string - RoleID string - Other string -} - -// Create ... -func (s Service) Create(payload CreateOptions) error { - var ( - ctx = context.Background() - ) - - // Validate payload - if err := payload.validate(ctx); err != nil { - return err - } - - // New user data from payload - doc, err := payload.newUser() - if err != nil { - return err - } - - // Create user - if err = s.userCreate(ctx, doc); err != nil { - return err - } - - return nil -} - -func (payload CreateOptions) newUser() (result dbUser, err error) { - timeNow := now() - roleID, _ := mongodb.NewIDFromString(payload.RoleID) - return dbUser{ - ID: mongodb.NewObjectID(), - Name: payload.Name, - SearchString: getSearchString(payload.Name, payload.Phone, payload.Email), - Phone: payload.Phone, - Email: payload.Email, - HashedPassword: hashPassword(payload.Password), - Status: payload.Status, - RoleID: roleID, - Other: payload.Other, - CreatedAt: timeNow, - UpdatedAt: timeNow, - }, nil -} diff --git a/action_get_all.go b/action_get_all.go deleted file mode 100644 index a169559..0000000 --- a/action_get_all.go +++ /dev/null @@ -1,82 +0,0 @@ -package usermngmt - -import ( - "context" - "sync" - - "go.mongodb.org/mongo-driver/bson" -) - -// AllQuery ... -type AllQuery struct { - Page int64 - Limit int64 - Keyword string - RoleID string - Status string -} - -// All ... -func (s Service) All(queryParams AllQuery) (r UserAll) { - var ( - ctx = context.Background() - wg sync.WaitGroup - cond = bson.M{} - ) - query := commonQuery{ - Page: queryParams.Page, - Limit: queryParams.Limit, - Keyword: queryParams.Keyword, - RoleID: queryParams.RoleID, - Status: queryParams.Status, - Sort: bson.M{"createdAt": -1}, - } - - // Assign condition - query.SetDefaultLimit() - query.AssignKeyword(cond) - query.AssignRoleID(cond) - query.AssignStatus(cond) - - wg.Add(1) - go func() { - defer wg.Done() - docs := s.userFindByCondition(ctx, cond, query.GetFindOptionsUsingPage()) - r.List = getResponseList(ctx, docs) - }() - - wg.Add(1) - go func() { - defer wg.Done() - r.Total = s.userCountByCondition(ctx, cond) - }() - - wg.Wait() - - return -} - -func getResponseList(ctx context.Context, users []dbUser) []User { - res := make([]User, 0) - - for _, user := range users { - role, _ := s.roleFindByID(ctx, user.RoleID) - res = append(res, User{ - ID: user.ID.Hex(), - Name: user.Name, - Phone: user.Phone, - Email: user.Email, - Status: user.Status, - Role: RoleShort{ - ID: role.ID.Hex(), - Name: role.Name, - IsAdmin: role.IsAdmin, - }, - Other: user.Other, - CreatedAt: user.CreatedAt, - UpdatedAt: user.UpdatedAt, - }) - } - - return res -} diff --git a/action_update.go b/action_update.go deleted file mode 100644 index 6612e13..0000000 --- a/action_update.go +++ /dev/null @@ -1,125 +0,0 @@ -package usermngmt - -import ( - "context" - "errors" - - "github.com/Selly-Modules/mongodb" - "go.mongodb.org/mongo-driver/bson" -) - -// UpdateOptions ... -type UpdateOptions struct { - Name string - Phone string - Email string - RoleID string - Other string -} - -// ChangePasswordOptions ... -type ChangePasswordOptions struct { - OldPassword string - NewPassword string -} - -// UpdateByUserID ... -func (s Service) UpdateByUserID(userID string, payload UpdateOptions) error { - var ( - ctx = context.Background() - ) - - // Validate payload - if err := payload.validate(ctx); err != nil { - return err - } - - // Setup condition - id, _ := mongodb.NewIDFromString(userID) - cond := bson.M{ - "_id": id, - } - - // Setup update data - roleID, _ := mongodb.NewIDFromString(payload.RoleID) - updateData := bson.M{ - "$set": bson.M{ - "name": payload.Name, - "searchString": getSearchString(payload.Name, payload.Phone, payload.Email), - "phone": payload.Phone, - "email": payload.Email, - "roleId": roleID, - "other": payload.Other, - "updatedAt": now(), - }, - } - - // Update - if err := s.userUpdateOneByCondition(ctx, cond, updateData); err != nil { - return err - } - - return nil -} - -// ChangeUserPassword ... -func (s Service) ChangeUserPassword(userID string, opt ChangePasswordOptions) error { - var ( - ctx = context.Background() - ) - - // Validate payload - err := opt.validate(userID) - if err != nil { - return err - } - - // Find user - id, _ := mongodb.NewIDFromString(userID) - user, _ := s.userFindByID(ctx, id) - if user.ID.IsZero() { - return errors.New("user not found") - } - - // Check old password - if isValid := checkPasswordHash(opt.OldPassword, user.HashedPassword); !isValid { - return errors.New("the password is incorrect") - } - - // Update password - if err = s.userUpdateOneByCondition(ctx, bson.M{"_id": user.ID}, bson.M{ - "$set": bson.M{ - "hashedPassword": hashPassword(opt.NewPassword), - "updatedAt": now(), - }, - }); err != nil { - return err - } - - return nil -} - -// ChangeUserStatus ... -func (s Service) ChangeUserStatus(userID, newStatus string) error { - var ( - ctx = context.Background() - ) - - // Validate userID - id, isValid := mongodb.NewIDFromString(userID) - if !isValid { - return errors.New("invalid user id data") - } - - // Update status - if err := s.userUpdateOneByCondition(ctx, bson.M{"_id": id}, bson.M{ - "$set": bson.M{ - "status": newStatus, - "updatedAt": now(), - }, - }); err != nil { - return err - } - - return nil -} diff --git a/constant.go b/constant.go index ab8a97d..4252788 100644 --- a/constant.go +++ b/constant.go @@ -5,8 +5,4 @@ const ( tableUser = "users" tableRole = "roles" tablePrefixDefault = "usermngmt" - - timezoneHCM = "Asia/Ho_Chi_Minh" - - passwordHashingCost = 14 ) diff --git a/db.go b/db.go index 0e88f3e..ef436a8 100644 --- a/db.go +++ b/db.go @@ -1,14 +1,9 @@ package usermngmt import ( - "context" "fmt" - "github.com/Selly-Modules/logger" - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/bson/primitive" "go.mongodb.org/mongo-driver/mongo" - "go.mongodb.org/mongo-driver/mongo/options" ) // getUserCollection ... @@ -20,146 +15,3 @@ func (s Service) getUserCollection() *mongo.Collection { func (s Service) getRoleCollection() *mongo.Collection { return s.DB.Collection(fmt.Sprintf("%s-%s", s.TablePrefix, tableRole)) } - -func (s Service) isPhoneNumberOrEmailExisted(ctx context.Context, phone, email string) bool { - var ( - col = s.getUserCollection() - ) - - // Find - cond := bson.M{ - "$or": []bson.M{ - { - "phone": phone, - }, - { - "email": email, - }, - }, - } - total, err := col.CountDocuments(ctx, cond) - if err != nil { - logger.Error("usermngmt - countUserByCondition", logger.LogData{ - "condition": cond, - "err": err.Error(), - }) - return true - } - return total != 0 -} - -func (s Service) isRoleIDExisted(ctx context.Context, roleID primitive.ObjectID) bool { - var ( - col = s.getRoleCollection() - ) - - // Find - cond := bson.M{ - "_id": roleID, - } - total, err := col.CountDocuments(ctx, cond) - if err != nil { - logger.Error("usermngmt - countRoleByCondition", logger.LogData{ - "condition": cond, - "err": err.Error(), - }) - return false - } - return total != 0 -} - -func (s Service) userCreate(ctx context.Context, doc dbUser) error { - var ( - col = s.getUserCollection() - ) - - _, err := col.InsertOne(ctx, doc) - if err != nil { - logger.Error("usermngmt - Create", logger.LogData{ - "doc": doc, - "err": err.Error(), - }) - return fmt.Errorf("error when create user: %s", err.Error()) - } - - return nil -} - -func (s Service) userUpdateOneByCondition(ctx context.Context, cond interface{}, payload interface{}) error { - var ( - col = s.getUserCollection() - ) - - _, err := col.UpdateOne(ctx, cond, payload) - if err != nil { - logger.Error("usermngmt - Update", logger.LogData{ - "cond": cond, - "payload": payload, - "err": err.Error(), - }) - return fmt.Errorf("error when update user: %s", err.Error()) - } - - return err -} - -func (s Service) userFindByID(ctx context.Context, id primitive.ObjectID) (dbUser, error) { - var ( - col = s.getUserCollection() - doc dbUser - ) - err := col.FindOne(ctx, bson.M{"_id": id}).Decode(&doc) - return doc, err -} - -func (s Service) userFindByCondition(ctx context.Context, cond interface{}, opts ...*options.FindOptions) (docs []dbUser) { - var ( - col = s.getUserCollection() - ) - docs = make([]dbUser, 0) - - cursor, err := col.Find(ctx, cond, opts...) - if err != nil { - logger.Error("usermngmt - All", logger.LogData{ - "cond": cond, - "opts": opts, - "err": err.Error(), - }) - return - } - defer cursor.Close(ctx) - if err = cursor.All(ctx, &docs); err != nil { - logger.Error("usermngmt - All - decode", logger.LogData{ - "cond": cond, - "opts": opts, - "err": err.Error(), - }) - return - } - return -} - -// userCountByCondition ... -func (s Service) userCountByCondition(ctx context.Context, cond interface{}) int64 { - var ( - col = s.getUserCollection() - ) - - total, err := col.CountDocuments(ctx, cond) - if err != nil { - logger.Error("usermngmt - Count", logger.LogData{ - "err": err.Error(), - "cond": cond, - }) - } - return total -} - -func (s Service) roleFindByID(ctx context.Context, id primitive.ObjectID) (dbRole, error) { - var ( - col = s.getRoleCollection() - doc dbRole - ) - err := col.FindOne(ctx, bson.M{"_id": id}).Decode(&doc) - return doc, err -} diff --git a/go.mod b/go.mod index 8091cd4..70aa30c 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module github.com/selly-Modules/usermngmt +module github.com/Selly-Modules/usermngmt go 1.17 diff --git a/init_handle.go b/init_handle.go new file mode 100644 index 0000000..30816b3 --- /dev/null +++ b/init_handle.go @@ -0,0 +1,21 @@ +package usermngmt + +import ( + "github.com/Selly-Modules/usermngmt/role" + "github.com/Selly-Modules/usermngmt/user" +) + +// userHandle ... +func (s Service) userHandle() user.Handle { + return user.Handle{ + Col: s.getUserCollection(), + RoleCol: s.getRoleCollection(), + } +} + +// roleHandle ... +func (s Service) roleHandle() role.Handle { + return role.Handle{ + Col: s.getRoleCollection(), + } +} diff --git a/internal/constant.go b/internal/constant.go new file mode 100644 index 0000000..7a5b32b --- /dev/null +++ b/internal/constant.go @@ -0,0 +1,9 @@ +package internal + +// Constant ... +const ( + timezoneHCM = "Asia/Ho_Chi_Minh" + + passwordHashingCost = 14 +) + diff --git a/db_model.go b/internal/db_model.go similarity index 92% rename from db_model.go rename to internal/db_model.go index 2eb0465..8b183bb 100644 --- a/db_model.go +++ b/internal/db_model.go @@ -1,4 +1,4 @@ -package usermngmt +package internal import ( "time" @@ -6,8 +6,18 @@ import ( "go.mongodb.org/mongo-driver/bson/primitive" ) -// dbUser ... -type dbUser struct { +// DBRole ... +type DBRole struct { + ID primitive.ObjectID `bson:"_id" json:"_id"` + Name string `bson:"name" json:"name"` + Code string `bson:"code" json:"code"` + IsAdmin bool `bson:"isAdmin" json:"isAdmin"` + CreatedAt time.Time `bson:"createdAt" json:"createdAt"` + UpdatedAt time.Time `bson:"updatedAt" json:"updatedAt"` +} + +// DBUser ... +type DBUser struct { ID primitive.ObjectID `bson:"_id"` Name string `bson:"name"` SearchString string `bson:"searchString"` @@ -21,12 +31,3 @@ type dbUser struct { UpdatedAt time.Time `bson:"updatedAt"` } -// dbRole ... -type dbRole struct { - ID primitive.ObjectID `bson:"_id" json:"_id"` - Name string `bson:"name" json:"name"` - Code string `bson:"code" json:"code"` - IsAdmin bool `bson:"isAdmin" json:"isAdmin"` - CreatedAt time.Time `bson:"createdAt" json:"createdAt"` - UpdatedAt time.Time `bson:"updatedAt" json:"updatedAt"` -} diff --git a/helper.go b/internal/helper.go similarity index 77% rename from helper.go rename to internal/helper.go index fbee0db..584a13d 100644 --- a/helper.go +++ b/internal/helper.go @@ -1,4 +1,4 @@ -package usermngmt +package internal import ( "fmt" @@ -7,17 +7,17 @@ import ( "golang.org/x/crypto/bcrypt" ) -func hashPassword(password string) string { +func HashPassword(password string) string { bytes, _ := bcrypt.GenerateFromPassword([]byte(password), passwordHashingCost) return string(bytes) } -func checkPasswordHash(password, hash string) bool { +func CheckPasswordHash(password, hash string) bool { err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password)) return err == nil } -func getSearchString(fieldList ...string) string { +func GetSearchString(fieldList ...string) string { var ( searchList = make([]interface{}, 0) format = "" @@ -33,3 +33,4 @@ func getSearchString(fieldList ...string) string { } return fmt.Sprintf(format, searchList...) } + diff --git a/query.go b/internal/query.go similarity index 73% rename from query.go rename to internal/query.go index 704edfa..d4bf9a7 100644 --- a/query.go +++ b/internal/query.go @@ -1,4 +1,4 @@ -package usermngmt +package internal import ( "github.com/Selly-Modules/mongodb" @@ -6,7 +6,7 @@ import ( "go.mongodb.org/mongo-driver/mongo/options" ) -type commonQuery struct { +type CommonQuery struct { Page int64 Limit int64 Keyword string @@ -16,14 +16,14 @@ type commonQuery struct { } // AssignKeyword ... -func (q *commonQuery) AssignKeyword(cond bson.M) { +func (q *CommonQuery) AssignKeyword(cond bson.M) { if q.Keyword != "" { cond["searchString"] = mongodb.GenerateQuerySearchString(q.Keyword) } } // AssignRoleID ... -func (q *commonQuery) AssignRoleID(cond bson.M) { +func (q *CommonQuery) AssignRoleID(cond bson.M) { if q.RoleID != "" { if id, isValid := mongodb.NewIDFromString(q.RoleID); isValid { cond["roleId"] = id @@ -32,14 +32,14 @@ func (q *commonQuery) AssignRoleID(cond bson.M) { } // AssignStatus ... -func (q *commonQuery) AssignStatus(cond bson.M) { +func (q *CommonQuery) AssignStatus(cond bson.M) { if q.Status != "" { cond["status"] = q.Status } } // GetFindOptionsUsingPage ... -func (q *commonQuery) GetFindOptionsUsingPage() *options.FindOptions { +func (q *CommonQuery) GetFindOptionsUsingPage() *options.FindOptions { opts := options.Find() if q.Limit > 0 { opts.SetLimit(q.Limit).SetSkip(q.Limit * q.Page) @@ -51,8 +51,9 @@ func (q *commonQuery) GetFindOptionsUsingPage() *options.FindOptions { } // SetDefaultLimit ... -func (q *commonQuery) SetDefaultLimit() { +func (q *CommonQuery) SetDefaultLimit() { if q.Limit <= 0 || q.Limit > 20 { q.Limit = 20 } } + diff --git a/internal/role_model.go b/internal/role_model.go new file mode 100644 index 0000000..6db9c33 --- /dev/null +++ b/internal/role_model.go @@ -0,0 +1,12 @@ +package internal + +type RoleShort struct { + ID string `json:"_id"` + Name string `json:"name"` + IsAdmin bool `json:"isAdmin"` +} + +// RoleCreateOptions ... +type RoleCreateOptions struct { + Name string +} diff --git a/time.go b/internal/time.go similarity index 88% rename from time.go rename to internal/time.go index 8e31061..f1b88a1 100644 --- a/time.go +++ b/internal/time.go @@ -1,4 +1,4 @@ -package usermngmt +package internal import "time" @@ -14,7 +14,8 @@ func getHCMLocation() *time.Location { return l } -// now ... -func now() time.Time { +// Now ... +func Now() time.Time { return time.Now().In(getHCMLocation()) } + diff --git a/internal/user_model.go b/internal/user_model.go new file mode 100644 index 0000000..333ae7a --- /dev/null +++ b/internal/user_model.go @@ -0,0 +1,187 @@ +package internal + +import ( + "errors" + "time" + + "github.com/Selly-Modules/logger" + "github.com/Selly-Modules/mongodb" +) + +// CreateOptions ... +type CreateOptions struct { + Name string + Phone string + Email string + Password string + Status string + RoleID string + Other string +} + +// UpdateOptions ... +type UpdateOptions struct { + Name string + Phone string + Email string + RoleID string + Other string +} + +// ChangePasswordOptions ... +type ChangePasswordOptions struct { + OldPassword string + NewPassword string +} + +// AllQuery ... +type AllQuery struct { + Page int64 + Limit int64 + Keyword string + RoleID string + Status string +} + +// User ... +type User struct { + ID string `json:"_id"` + Name string `json:"name"` + Phone string `json:"phone"` + Email string `json:"email"` + Status string `json:"status"` + Role RoleShort `json:"role"` + Other string `json:"other"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` +} + +type ( + // UserAll ... + UserAll struct { + List []User `json:"list"` + Total int64 `json:"total"` + } +) + +// NewUser ... +func (payload CreateOptions) NewUser() (result DBUser, err error) { + timeNow := Now() + roleID, _ := mongodb.NewIDFromString(payload.RoleID) + return DBUser{ + ID: mongodb.NewObjectID(), + Name: payload.Name, + SearchString: GetSearchString(payload.Name, payload.Phone, payload.Email), + Phone: payload.Phone, + Email: payload.Email, + HashedPassword: HashPassword(payload.Password), + Status: payload.Status, + RoleID: roleID, + Other: payload.Other, + CreatedAt: timeNow, + UpdatedAt: timeNow, + }, nil +} + +// Validate ... +func (co CreateOptions) Validate() error { + // Name + if co.Name == "" { + logger.Error("usermngmt - Create: no Name data", logger.LogData{ + "payload": co, + }) + return errors.New("no name data") + } + + // Phone + if co.Phone == "" { + logger.Error("usermngmt - Create: no phone data", logger.LogData{ + "payload": co, + }) + return errors.New("no phone data") + } + + // Email + if co.Email == "" { + logger.Error("usermngmt - Create: no email data", logger.LogData{ + "payload": co, + }) + return errors.New("no email data") + } + + // Password + if co.Password == "" { + logger.Error("usermngmt - Create: no password data", logger.LogData{ + "payload": co, + }) + return errors.New("no password data") + } + + // Status + if co.Status == "" { + logger.Error("usermngmt - Create: no status data", logger.LogData{ + "payload": co, + }) + return errors.New("no status data") + } + + // RoleID + if co.RoleID == "" { + logger.Error("usermngmt - Create: no roleID data", logger.LogData{ + "payload": co, + }) + return errors.New("no role id data") + } + + return nil +} + +// Validate ... +func (uo UpdateOptions) Validate() error { + // Name + if uo.Name == "" { + logger.Error("usermngmt - Update: no name data", logger.LogData{ + "payload": uo, + }) + return errors.New("no name data") + } + + // Phone + if uo.Phone == "" { + logger.Error("usermngmt - Update: no phone data", logger.LogData{ + "payload": uo, + }) + return errors.New("no phone data") + } + + // Email + if uo.Email == "" { + logger.Error("usermngmt - Update: no email data", logger.LogData{ + "payload": uo, + }) + return errors.New("no email data") + } + + // RoleID + if uo.RoleID == "" { + logger.Error("usermngmt - Update: no roleID data", logger.LogData{ + "payload": uo, + }) + return errors.New("no role id data") + } + + return nil +} + +// Validate ... +func (co ChangePasswordOptions) Validate() error { + // OldPassword, NewPassword + if co.OldPassword == "" || co.NewPassword == "" { + logger.Error("usermngmt - ChangePassword: old or new password cannot be empty", logger.LogData{ + "payload": co, + }) + return errors.New("old or new password cannot be empty") + } + + return nil +} diff --git a/model.go b/model.go deleted file mode 100644 index 7fe6391..0000000 --- a/model.go +++ /dev/null @@ -1,32 +0,0 @@ -package usermngmt - -import ( - "time" -) - -// User ... -type User struct { - ID string `json:"_id"` - Name string `json:"name"` - Phone string `json:"phone"` - Email string `json:"email"` - Status string `json:"status"` - Role RoleShort `json:"role"` - Other string `json:"other"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` -} - -type RoleShort struct { - ID string `json:"_id"` - Name string `json:"name"` - IsAdmin bool `json:"isAdmin"` -} - -type ( - // UserAll ... - UserAll struct { - List []User `json:"list"` - Total int64 `json:"total"` - } -) diff --git a/role/db.go b/role/db.go new file mode 100644 index 0000000..2a7793c --- /dev/null +++ b/role/db.go @@ -0,0 +1,17 @@ +package role + +import ( + "context" + + "github.com/Selly-Modules/usermngmt/internal" + "go.mongodb.org/mongo-driver/bson" + "go.mongodb.org/mongo-driver/bson/primitive" +) + +func (h Handle) findByID(ctx context.Context, id primitive.ObjectID) (internal.DBRole, error) { + var ( + doc internal.DBRole + ) + err := h.Col.FindOne(ctx, bson.M{"_id": id}).Decode(&doc) + return doc, err +} diff --git a/role/handle.go b/role/handle.go new file mode 100644 index 0000000..0178083 --- /dev/null +++ b/role/handle.go @@ -0,0 +1,25 @@ +package role + +import ( + "context" + + "github.com/Selly-Modules/usermngmt/internal" + "go.mongodb.org/mongo-driver/bson/primitive" + "go.mongodb.org/mongo-driver/mongo" +) + +type Handle struct { + Col *mongo.Collection +} + +// FindByID ... +func (h Handle) FindByID(ctx context.Context, id primitive.ObjectID) (internal.DBRole, error) { + role, err := h.findByID(ctx, id) + return role, err +} + +// Create ... +func (h Handle) Create(payload internal.RoleCreateOptions) error { + // TODO later + return nil +} diff --git a/user/db.go b/user/db.go new file mode 100644 index 0000000..6316ab2 --- /dev/null +++ b/user/db.go @@ -0,0 +1,130 @@ +package user + +import ( + "context" + "fmt" + + "github.com/Selly-Modules/logger" + "github.com/Selly-Modules/usermngmt/internal" + "go.mongodb.org/mongo-driver/bson" + "go.mongodb.org/mongo-driver/bson/primitive" + "go.mongodb.org/mongo-driver/mongo/options" +) + +func (h Handle) isPhoneNumberOrEmailExisted(ctx context.Context, phone, email string) bool { + // Find + cond := bson.M{ + "$or": []bson.M{ + { + "phone": phone, + }, + { + "email": email, + }, + }, + } + total, err := h.Col.CountDocuments(ctx, cond) + if err != nil { + logger.Error("usermngmt - countUserByCondition", logger.LogData{ + "condition": cond, + "err": err.Error(), + }) + return true + } + return total != 0 +} + +func (h Handle) isRoleIDExisted(ctx context.Context, roleID primitive.ObjectID) bool { + // Find + cond := bson.M{ + "_id": roleID, + } + total, err := h.RoleCol.CountDocuments(ctx, cond) + if err != nil { + logger.Error("usermngmt - countRoleByCondition", logger.LogData{ + "condition": cond, + "err": err.Error(), + }) + return false + } + return total != 0 +} + +func (h Handle) roleFindByID(ctx context.Context, id primitive.ObjectID) (internal.DBRole, error) { + var ( + doc internal.DBRole + ) + err := h.RoleCol.FindOne(ctx, bson.M{"_id": id}).Decode(&doc) + return doc, err +} + +func (h Handle) create(ctx context.Context, doc internal.DBUser) error { + _, err := h.Col.InsertOne(ctx, doc) + if err != nil { + logger.Error("usermngmt - Create", logger.LogData{ + "doc": doc, + "err": err.Error(), + }) + return fmt.Errorf("error when create user: %s", err.Error()) + } + + return nil +} + +func (h Handle) updateOneByCondition(ctx context.Context, cond interface{}, payload interface{}) error { + _, err := h.Col.UpdateOne(ctx, cond, payload) + if err != nil { + logger.Error("usermngmt - Update", logger.LogData{ + "cond": cond, + "payload": payload, + "err": err.Error(), + }) + return fmt.Errorf("error when update user: %s", err.Error()) + } + + return err +} + +func (h Handle) findByID(ctx context.Context, id primitive.ObjectID) (internal.DBUser, error) { + var ( + doc internal.DBUser + ) + err := h.Col.FindOne(ctx, bson.M{"_id": id}).Decode(&doc) + return doc, err +} + +func (h Handle) findByCondition(ctx context.Context, cond interface{}, opts ...*options.FindOptions) (docs []internal.DBUser) { + docs = make([]internal.DBUser, 0) + + cursor, err := h.Col.Find(ctx, cond, opts...) + if err != nil { + logger.Error("usermngmt - All", logger.LogData{ + "cond": cond, + "opts": opts, + "err": err.Error(), + }) + return + } + defer cursor.Close(ctx) + if err = cursor.All(ctx, &docs); err != nil { + logger.Error("usermngmt - All - decode", logger.LogData{ + "cond": cond, + "opts": opts, + "err": err.Error(), + }) + return + } + return +} + +// countByCondition ... +func (h Handle) countByCondition(ctx context.Context, cond interface{}) int64 { + total, err := h.Col.CountDocuments(ctx, cond) + if err != nil { + logger.Error("usermngmt - Count", logger.LogData{ + "err": err.Error(), + "cond": cond, + }) + } + return total +} diff --git a/user/handle.go b/user/handle.go new file mode 100644 index 0000000..8bf935c --- /dev/null +++ b/user/handle.go @@ -0,0 +1,245 @@ +package user + +import ( + "context" + "errors" + "sync" + + "github.com/Selly-Modules/logger" + "github.com/Selly-Modules/mongodb" + "github.com/Selly-Modules/usermngmt/internal" + "go.mongodb.org/mongo-driver/bson" + "go.mongodb.org/mongo-driver/mongo" +) + +type Handle struct { + Col *mongo.Collection + RoleCol *mongo.Collection +} + +// Create ... +func (h Handle) Create(payload internal.CreateOptions) error { + var ( + ctx = context.Background() + ) + + // Validate payload + if err := payload.Validate(); err != nil { + return err + } + + // Find roleID exists or not + roleID, isValid := mongodb.NewIDFromString(payload.RoleID) + if !isValid { + return errors.New("invalid role id data") + } + if !h.isRoleIDExisted(ctx, roleID) { + return errors.New("role id does not exist") + } + + // Find phone number,email exists or not + if h.isPhoneNumberOrEmailExisted(ctx, payload.Phone, payload.Email) { + return errors.New("phone number or email already existed") + } + + // New user data from payload + doc, err := payload.NewUser() + if err != nil { + return err + } + + // Create user + if err = h.create(ctx, doc); err != nil { + return err + } + + return nil +} + +// All ... +func (h Handle) All(queryParams internal.AllQuery) (r internal.UserAll) { + var ( + ctx = context.Background() + wg sync.WaitGroup + cond = bson.M{} + ) + query := internal.CommonQuery{ + Page: queryParams.Page, + Limit: queryParams.Limit, + Keyword: queryParams.Keyword, + RoleID: queryParams.RoleID, + Status: queryParams.Status, + Sort: bson.M{"createdAt": -1}, + } + + // Assign condition + query.SetDefaultLimit() + query.AssignKeyword(cond) + query.AssignRoleID(cond) + query.AssignStatus(cond) + + wg.Add(1) + go func() { + defer wg.Done() + docs := h.findByCondition(ctx, cond, query.GetFindOptionsUsingPage()) + r.List = h.getResponseList(ctx, docs) + }() + + wg.Add(1) + go func() { + defer wg.Done() + r.Total = h.countByCondition(ctx, cond) + }() + + wg.Wait() + + return +} + +func (h Handle) getResponseList(ctx context.Context, users []internal.DBUser) []internal.User { + res := make([]internal.User, 0) + + for _, user := range users { + roleRaw, _ := h.roleFindByID(ctx, user.RoleID) + res = append(res, internal.User{ + ID: user.ID.Hex(), + Name: user.Name, + Phone: user.Phone, + Email: user.Email, + Status: user.Status, + Role: internal.RoleShort{ + ID: roleRaw.ID.Hex(), + Name: roleRaw.Name, + IsAdmin: roleRaw.IsAdmin, + }, + Other: user.Other, + CreatedAt: user.CreatedAt, + UpdatedAt: user.UpdatedAt, + }) + } + + return res +} + +// UpdateByUserID ... +func (h Handle) UpdateByUserID(userID string, payload internal.UpdateOptions) error { + var ( + ctx = context.Background() + ) + + // Validate payload + if err := payload.Validate(); err != nil { + return err + } + + // Find roleID exists or not + roleID, isValid := mongodb.NewIDFromString(payload.RoleID) + if !isValid { + return errors.New("invalid role id data") + } + if !h.isRoleIDExisted(ctx, roleID) { + return errors.New("role id does not exist") + } + + // Find phone number,email exists or not + if h.isPhoneNumberOrEmailExisted(ctx, payload.Phone, payload.Email) { + return errors.New("phone number or email already existed") + } + + // Setup condition + id, _ := mongodb.NewIDFromString(userID) + cond := bson.M{ + "_id": id, + } + + // Setup update data + updateData := bson.M{ + "$set": bson.M{ + "name": payload.Name, + "searchString": internal.GetSearchString(payload.Name, payload.Phone, payload.Email), + "phone": payload.Phone, + "email": payload.Email, + "roleId": roleID, + "other": payload.Other, + "updatedAt": internal.Now(), + }, + } + + // Update + if err := h.updateOneByCondition(ctx, cond, updateData); err != nil { + return err + } + + return nil +} + +// ChangeUserPassword ... +func (h Handle) ChangeUserPassword(userID string, opt internal.ChangePasswordOptions) error { + var ( + ctx = context.Background() + ) + + // Validate payload + err := opt.Validate() + if err != nil { + return err + } + + // Validate userID + if _, isValid := mongodb.NewIDFromString(userID); !isValid { + logger.Error("usermngmt - ChangePassword: invalid userID data", logger.LogData{ + "payload": opt, + "userID": userID, + }) + return errors.New("invalid user id data") + } + + // Find user + id, _ := mongodb.NewIDFromString(userID) + user, _ := h.findByID(ctx, id) + if user.ID.IsZero() { + return errors.New("user not found") + } + + // Check old password + if isValid := internal.CheckPasswordHash(opt.OldPassword, user.HashedPassword); !isValid { + return errors.New("the password is incorrect") + } + + // Update password + if err = h.updateOneByCondition(ctx, bson.M{"_id": user.ID}, bson.M{ + "$set": bson.M{ + "hashedPassword": internal.HashPassword(opt.NewPassword), + "updatedAt": internal.Now(), + }, + }); err != nil { + return err + } + + return nil +} + +// ChangeUserStatus ... +func (h Handle) ChangeUserStatus(userID, newStatus string) error { + var ( + ctx = context.Background() + ) + + // Validate userID + id, isValid := mongodb.NewIDFromString(userID) + if !isValid { + return errors.New("invalid user id data") + } + + // Update status + if err := h.updateOneByCondition(ctx, bson.M{"_id": id}, bson.M{ + "$set": bson.M{ + "status": newStatus, + "updatedAt": internal.Now(), + }, + }); err != nil { + return err + } + + return nil +} diff --git a/validate.go b/validate.go deleted file mode 100644 index a856ab3..0000000 --- a/validate.go +++ /dev/null @@ -1,145 +0,0 @@ -package usermngmt - -import ( - "context" - "errors" - - "github.com/Selly-Modules/logger" - "github.com/Selly-Modules/mongodb" -) - -func (co CreateOptions) validate(ctx context.Context) error { - // Name - if co.Name == "" { - logger.Error("usermngmt - Create: no Name data", logger.LogData{ - "payload": co, - }) - return errors.New("no name data") - } - - // Phone - if co.Phone == "" { - logger.Error("usermngmt - Create: no phone data", logger.LogData{ - "payload": co, - }) - return errors.New("no phone data") - } - - // Email - if co.Email == "" { - logger.Error("usermngmt - Create: no email data", logger.LogData{ - "payload": co, - }) - return errors.New("no email data") - } - - // Password - if co.Password == "" { - logger.Error("usermngmt - Create: no password data", logger.LogData{ - "payload": co, - }) - return errors.New("no password data") - } - - // Status - if co.Status == "" { - logger.Error("usermngmt - Create: no status data", logger.LogData{ - "payload": co, - }) - return errors.New("no status data") - } - - // RoleID - if co.RoleID == "" { - logger.Error("usermngmt - Create: no roleID data", logger.LogData{ - "payload": co, - }) - return errors.New("no role id data") - } - - // Find roleID exists or not - roleID, isValid := mongodb.NewIDFromString(co.RoleID) - if !isValid { - return errors.New("invalid role id data") - } - if !s.isRoleIDExisted(ctx, roleID) { - return errors.New("role id does not exist") - } - - // Find phone number,email exists or not - if s.isPhoneNumberOrEmailExisted(ctx, co.Phone, co.Email) { - return errors.New("phone number or email already existed") - } - - return nil -} - -func (co UpdateOptions) validate(ctx context.Context) error { - // Name - if co.Name == "" { - logger.Error("usermngmt - Update: no name data", logger.LogData{ - "payload": co, - }) - return errors.New("no name data") - } - - // Phone - if co.Phone == "" { - logger.Error("usermngmt - Update: no phone data", logger.LogData{ - "payload": co, - }) - return errors.New("no phone data") - } - - // Email - if co.Email == "" { - logger.Error("usermngmt - Update: no email data", logger.LogData{ - "payload": co, - }) - return errors.New("no email data") - } - - // RoleID - if co.RoleID == "" { - logger.Error("usermngmt - Update: no roleID data", logger.LogData{ - "payload": co, - }) - return errors.New("no role id data") - } - - // Find roleID exists or not - roleID, isValid := mongodb.NewIDFromString(co.RoleID) - if !isValid { - return errors.New("invalid role id data") - } - if !s.isRoleIDExisted(ctx, roleID) { - return errors.New("role id does not exist") - } - - // Find phone number,email exists or not - if s.isPhoneNumberOrEmailExisted(ctx, co.Phone, co.Email) { - return errors.New("phone number or email already existed") - } - - return nil -} - -func (co ChangePasswordOptions) validate(userID string) error { - // OldPassword, NewPassword - if co.OldPassword == "" || co.NewPassword == "" { - logger.Error("usermngmt - ChangePassword: old or new password cannot be empty", logger.LogData{ - "payload": co, - }) - return errors.New("old or new password cannot be empty") - } - - // UserID - if _, isValid := mongodb.NewIDFromString(userID); !isValid { - logger.Error("usermngmt - ChangePassword: invalid userID data", logger.LogData{ - "payload": co, - }) - return errors.New("invalid user id data") - } - - return nil -} From 4173187e21be943c7ef0bd3e8aaa6cd8f7f782be Mon Sep 17 00:00:00 2001 From: Hoang Date: Wed, 10 Nov 2021 09:54:49 +0700 Subject: [PATCH 3/8] fix comment --- action.go | 26 +++++++++--------- db.go | 11 +++----- init_handle.go | 21 --------------- internal/{ => model}/db_model.go | 3 +-- internal/{ => model}/query.go | 2 +- internal/{ => model}/role_model.go | 2 +- internal/{ => model}/user_model.go | 22 +--------------- role/db.go | 6 ++--- role/handle.go | 6 ++--- user/db.go | 16 ++++++------ user/handle.go | 42 ++++++++++++++++++++++-------- usermngmt.go | 28 +++++++++++++++++--- 12 files changed, 90 insertions(+), 95 deletions(-) delete mode 100644 init_handle.go rename internal/{ => model}/db_model.go (98%) rename internal/{ => model}/query.go (98%) rename internal/{ => model}/role_model.go (91%) rename internal/{ => model}/user_model.go (83%) diff --git a/action.go b/action.go index fb41213..5608282 100644 --- a/action.go +++ b/action.go @@ -1,30 +1,32 @@ package usermngmt -import "github.com/Selly-Modules/usermngmt/internal" +import ( + "github.com/Selly-Modules/usermngmt/internal/model" +) // Create ... -func (s Service) Create(payload internal.CreateOptions) error { - return s.userHandle().Create(payload) +func (s Service) Create(payload model.CreateOptions) error { + return s.handler.User.Create(payload) } // Update ... -func (s Service) Update(userID string, payload internal.UpdateOptions) error { - return s.userHandle().UpdateByUserID(userID, payload) +func (s Service) Update(userID string, payload model.UpdateOptions) error { + return s.handler.User.UpdateByUserID(userID, payload) } // ChangeUserPassword ... -func (s Service) ChangeUserPassword(userID string, payload internal.ChangePasswordOptions) error { - return s.userHandle().ChangeUserPassword(userID, payload) +func (s Service) ChangeUserPassword(userID string, payload model.ChangePasswordOptions) error { + return s.handler.User.ChangeUserPassword(userID, payload) } func (s Service) ChangeUserStatus(userID, newStatus string) error { - return s.userHandle().ChangeUserStatus(userID, newStatus) + return s.handler.User.ChangeUserStatus(userID, newStatus) } -func (s Service) All(query internal.AllQuery) internal.UserAll { - return s.userHandle().All(query) +func (s Service) All(query model.AllQuery) model.UserAll { + return s.handler.User.All(query) } -func (s Service) RoleCreate(payload internal.RoleCreateOptions) error { - return s.roleHandle().Create(payload) +func (s Service) RoleCreate(payload model.RoleCreateOptions) error { + return s.handler.Role.Create(payload) } diff --git a/db.go b/db.go index ef436a8..2b765fe 100644 --- a/db.go +++ b/db.go @@ -6,12 +6,7 @@ import ( "go.mongodb.org/mongo-driver/mongo" ) -// getUserCollection ... -func (s Service) getUserCollection() *mongo.Collection { - return s.DB.Collection(fmt.Sprintf("%s-%s", s.TablePrefix, tableUser)) -} - -// getRoleCollection ... -func (s Service) getRoleCollection() *mongo.Collection { - return s.DB.Collection(fmt.Sprintf("%s-%s", s.TablePrefix, tableRole)) +// getCollectionName ... +func (s Service) getCollectionName(tablePrefix, table string) *mongo.Collection { + return s.db.Collection(fmt.Sprintf("%s-%s", tablePrefix, table)) } diff --git a/init_handle.go b/init_handle.go deleted file mode 100644 index 30816b3..0000000 --- a/init_handle.go +++ /dev/null @@ -1,21 +0,0 @@ -package usermngmt - -import ( - "github.com/Selly-Modules/usermngmt/role" - "github.com/Selly-Modules/usermngmt/user" -) - -// userHandle ... -func (s Service) userHandle() user.Handle { - return user.Handle{ - Col: s.getUserCollection(), - RoleCol: s.getRoleCollection(), - } -} - -// roleHandle ... -func (s Service) roleHandle() role.Handle { - return role.Handle{ - Col: s.getRoleCollection(), - } -} diff --git a/internal/db_model.go b/internal/model/db_model.go similarity index 98% rename from internal/db_model.go rename to internal/model/db_model.go index 8b183bb..53aca13 100644 --- a/internal/db_model.go +++ b/internal/model/db_model.go @@ -1,4 +1,4 @@ -package internal +package model import ( "time" @@ -30,4 +30,3 @@ type DBUser struct { CreatedAt time.Time `bson:"createdAt"` UpdatedAt time.Time `bson:"updatedAt"` } - diff --git a/internal/query.go b/internal/model/query.go similarity index 98% rename from internal/query.go rename to internal/model/query.go index d4bf9a7..4ddf74c 100644 --- a/internal/query.go +++ b/internal/model/query.go @@ -1,4 +1,4 @@ -package internal +package model import ( "github.com/Selly-Modules/mongodb" diff --git a/internal/role_model.go b/internal/model/role_model.go similarity index 91% rename from internal/role_model.go rename to internal/model/role_model.go index 6db9c33..1f381b1 100644 --- a/internal/role_model.go +++ b/internal/model/role_model.go @@ -1,4 +1,4 @@ -package internal +package model type RoleShort struct { ID string `json:"_id"` diff --git a/internal/user_model.go b/internal/model/user_model.go similarity index 83% rename from internal/user_model.go rename to internal/model/user_model.go index 333ae7a..34562a2 100644 --- a/internal/user_model.go +++ b/internal/model/user_model.go @@ -1,11 +1,10 @@ -package internal +package model import ( "errors" "time" "github.com/Selly-Modules/logger" - "github.com/Selly-Modules/mongodb" ) // CreateOptions ... @@ -64,25 +63,6 @@ type ( } ) -// NewUser ... -func (payload CreateOptions) NewUser() (result DBUser, err error) { - timeNow := Now() - roleID, _ := mongodb.NewIDFromString(payload.RoleID) - return DBUser{ - ID: mongodb.NewObjectID(), - Name: payload.Name, - SearchString: GetSearchString(payload.Name, payload.Phone, payload.Email), - Phone: payload.Phone, - Email: payload.Email, - HashedPassword: HashPassword(payload.Password), - Status: payload.Status, - RoleID: roleID, - Other: payload.Other, - CreatedAt: timeNow, - UpdatedAt: timeNow, - }, nil -} - // Validate ... func (co CreateOptions) Validate() error { // Name diff --git a/role/db.go b/role/db.go index 2a7793c..bf98c99 100644 --- a/role/db.go +++ b/role/db.go @@ -3,14 +3,14 @@ package role import ( "context" - "github.com/Selly-Modules/usermngmt/internal" + "github.com/Selly-Modules/usermngmt/internal/model" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson/primitive" ) -func (h Handle) findByID(ctx context.Context, id primitive.ObjectID) (internal.DBRole, error) { +func (h Handle) findByID(ctx context.Context, id primitive.ObjectID) (model.DBRole, error) { var ( - doc internal.DBRole + doc model.DBRole ) err := h.Col.FindOne(ctx, bson.M{"_id": id}).Decode(&doc) return doc, err diff --git a/role/handle.go b/role/handle.go index 0178083..b00b9b1 100644 --- a/role/handle.go +++ b/role/handle.go @@ -3,7 +3,7 @@ package role import ( "context" - "github.com/Selly-Modules/usermngmt/internal" + "github.com/Selly-Modules/usermngmt/internal/model" "go.mongodb.org/mongo-driver/bson/primitive" "go.mongodb.org/mongo-driver/mongo" ) @@ -13,13 +13,13 @@ type Handle struct { } // FindByID ... -func (h Handle) FindByID(ctx context.Context, id primitive.ObjectID) (internal.DBRole, error) { +func (h Handle) FindByID(ctx context.Context, id primitive.ObjectID) (model.DBRole, error) { role, err := h.findByID(ctx, id) return role, err } // Create ... -func (h Handle) Create(payload internal.RoleCreateOptions) error { +func (h Handle) Create(payload model.RoleCreateOptions) error { // TODO later return nil } diff --git a/user/db.go b/user/db.go index 6316ab2..0df6cf6 100644 --- a/user/db.go +++ b/user/db.go @@ -5,7 +5,7 @@ import ( "fmt" "github.com/Selly-Modules/logger" - "github.com/Selly-Modules/usermngmt/internal" + "github.com/Selly-Modules/usermngmt/internal/model" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson/primitive" "go.mongodb.org/mongo-driver/mongo/options" @@ -50,15 +50,15 @@ func (h Handle) isRoleIDExisted(ctx context.Context, roleID primitive.ObjectID) return total != 0 } -func (h Handle) roleFindByID(ctx context.Context, id primitive.ObjectID) (internal.DBRole, error) { +func (h Handle) roleFindByID(ctx context.Context, id primitive.ObjectID) (model.DBRole, error) { var ( - doc internal.DBRole + doc model.DBRole ) err := h.RoleCol.FindOne(ctx, bson.M{"_id": id}).Decode(&doc) return doc, err } -func (h Handle) create(ctx context.Context, doc internal.DBUser) error { +func (h Handle) create(ctx context.Context, doc model.DBUser) error { _, err := h.Col.InsertOne(ctx, doc) if err != nil { logger.Error("usermngmt - Create", logger.LogData{ @@ -85,16 +85,16 @@ func (h Handle) updateOneByCondition(ctx context.Context, cond interface{}, payl return err } -func (h Handle) findByID(ctx context.Context, id primitive.ObjectID) (internal.DBUser, error) { +func (h Handle) findByID(ctx context.Context, id primitive.ObjectID) (model.DBUser, error) { var ( - doc internal.DBUser + doc model.DBUser ) err := h.Col.FindOne(ctx, bson.M{"_id": id}).Decode(&doc) return doc, err } -func (h Handle) findByCondition(ctx context.Context, cond interface{}, opts ...*options.FindOptions) (docs []internal.DBUser) { - docs = make([]internal.DBUser, 0) +func (h Handle) findByCondition(ctx context.Context, cond interface{}, opts ...*options.FindOptions) (docs []model.DBUser) { + docs = make([]model.DBUser, 0) cursor, err := h.Col.Find(ctx, cond, opts...) if err != nil { diff --git a/user/handle.go b/user/handle.go index 8bf935c..f824490 100644 --- a/user/handle.go +++ b/user/handle.go @@ -8,6 +8,7 @@ import ( "github.com/Selly-Modules/logger" "github.com/Selly-Modules/mongodb" "github.com/Selly-Modules/usermngmt/internal" + "github.com/Selly-Modules/usermngmt/internal/model" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/mongo" ) @@ -18,7 +19,7 @@ type Handle struct { } // Create ... -func (h Handle) Create(payload internal.CreateOptions) error { +func (h Handle) Create(payload model.CreateOptions) error { var ( ctx = context.Background() ) @@ -43,7 +44,7 @@ func (h Handle) Create(payload internal.CreateOptions) error { } // New user data from payload - doc, err := payload.NewUser() + doc, err := newUser(payload) if err != nil { return err } @@ -56,14 +57,33 @@ func (h Handle) Create(payload internal.CreateOptions) error { return nil } +// newUser ... +func newUser(payload model.CreateOptions) (result model.DBUser, err error) { + timeNow := internal.Now() + roleID, _ := mongodb.NewIDFromString(payload.RoleID) + return model.DBUser{ + ID: mongodb.NewObjectID(), + Name: payload.Name, + SearchString: internal.GetSearchString(payload.Name, payload.Phone, payload.Email), + Phone: payload.Phone, + Email: payload.Email, + HashedPassword: internal.HashPassword(payload.Password), + Status: payload.Status, + RoleID: roleID, + Other: payload.Other, + CreatedAt: timeNow, + UpdatedAt: timeNow, + }, nil +} + // All ... -func (h Handle) All(queryParams internal.AllQuery) (r internal.UserAll) { +func (h Handle) All(queryParams model.AllQuery) (r model.UserAll) { var ( ctx = context.Background() wg sync.WaitGroup cond = bson.M{} ) - query := internal.CommonQuery{ + query := model.CommonQuery{ Page: queryParams.Page, Limit: queryParams.Limit, Keyword: queryParams.Keyword, @@ -96,18 +116,18 @@ func (h Handle) All(queryParams internal.AllQuery) (r internal.UserAll) { return } -func (h Handle) getResponseList(ctx context.Context, users []internal.DBUser) []internal.User { - res := make([]internal.User, 0) +func (h Handle) getResponseList(ctx context.Context, users []model.DBUser) []model.User { + res := make([]model.User, 0) for _, user := range users { roleRaw, _ := h.roleFindByID(ctx, user.RoleID) - res = append(res, internal.User{ + res = append(res, model.User{ ID: user.ID.Hex(), Name: user.Name, Phone: user.Phone, Email: user.Email, Status: user.Status, - Role: internal.RoleShort{ + Role: model.RoleShort{ ID: roleRaw.ID.Hex(), Name: roleRaw.Name, IsAdmin: roleRaw.IsAdmin, @@ -122,7 +142,7 @@ func (h Handle) getResponseList(ctx context.Context, users []internal.DBUser) [] } // UpdateByUserID ... -func (h Handle) UpdateByUserID(userID string, payload internal.UpdateOptions) error { +func (h Handle) UpdateByUserID(userID string, payload model.UpdateOptions) error { var ( ctx = context.Background() ) @@ -174,7 +194,7 @@ func (h Handle) UpdateByUserID(userID string, payload internal.UpdateOptions) er } // ChangeUserPassword ... -func (h Handle) ChangeUserPassword(userID string, opt internal.ChangePasswordOptions) error { +func (h Handle) ChangeUserPassword(userID string, opt model.ChangePasswordOptions) error { var ( ctx = context.Background() ) @@ -189,7 +209,7 @@ func (h Handle) ChangeUserPassword(userID string, opt internal.ChangePasswordOpt if _, isValid := mongodb.NewIDFromString(userID); !isValid { logger.Error("usermngmt - ChangePassword: invalid userID data", logger.LogData{ "payload": opt, - "userID": userID, + "userID": userID, }) return errors.New("invalid user id data") } diff --git a/usermngmt.go b/usermngmt.go index 5979cff..9e90bb7 100644 --- a/usermngmt.go +++ b/usermngmt.go @@ -5,6 +5,8 @@ import ( "fmt" "github.com/Selly-Modules/mongodb" + "github.com/Selly-Modules/usermngmt/role" + "github.com/Selly-Modules/usermngmt/user" "go.mongodb.org/mongo-driver/mongo" ) @@ -21,10 +23,17 @@ type Config struct { TablePrefix string } +// Handler ... +type Handler struct { + User user.Handle + Role role.Handle +} + // Service ... type Service struct { - Config - DB *mongo.Database + config Config + db *mongo.Database + handler Handler } var s *Service @@ -55,8 +64,19 @@ func Init(config Config) (*Service, error) { } s = &Service{ - Config: config, - DB: db, + config: config, + db: db, + } + + // Setup handle + s.handler = Handler{ + User: user.Handle{ + Col: s.getCollectionName(config.TablePrefix, tableUser), + RoleCol: s.getCollectionName(config.TablePrefix, tableRole), + }, + Role: role.Handle{ + Col: s.getCollectionName(config.TablePrefix, tableRole), + }, } return s, nil From d6bc1a1c027ee1487a350971b3385bce8eb1d7fa Mon Sep 17 00:00:00 2001 From: Hoang Date: Wed, 10 Nov 2021 09:59:41 +0700 Subject: [PATCH 4/8] change fileName --- internal/model/{db_model.go => db.go} | 0 internal/model/{role_model.go => role.go} | 0 internal/model/{user_model.go => user.go} | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename internal/model/{db_model.go => db.go} (100%) rename internal/model/{role_model.go => role.go} (100%) rename internal/model/{user_model.go => user.go} (100%) diff --git a/internal/model/db_model.go b/internal/model/db.go similarity index 100% rename from internal/model/db_model.go rename to internal/model/db.go diff --git a/internal/model/role_model.go b/internal/model/role.go similarity index 100% rename from internal/model/role_model.go rename to internal/model/role.go diff --git a/internal/model/user_model.go b/internal/model/user.go similarity index 100% rename from internal/model/user_model.go rename to internal/model/user.go From e95ab2ec0f786136298d0fe13ff3623f83be62fa Mon Sep 17 00:00:00 2001 From: Hoang Date: Wed, 10 Nov 2021 11:01:39 +0700 Subject: [PATCH 5/8] fix comment again --- action.go | 8 ++-- constant.go | 2 - database/db.go | 31 +++++++++++++++ db.go | 12 ------ {internal/model => model}/db.go | 0 {internal/model => model}/query.go | 0 model/role_request.go | 7 ++++ .../model/role.go => model/role_response.go | 7 +--- .../model/user.go => model/user_request.go | 38 ++++-------------- model/user_response.go | 26 +++++++++++++ role/db.go | 6 ++- role/handle.go | 4 +- user/db.go | 39 ++++++++++++++----- user/handle.go | 13 +++---- usermngmt.go | 20 ++++------ 15 files changed, 124 insertions(+), 89 deletions(-) create mode 100644 database/db.go delete mode 100644 db.go rename {internal/model => model}/db.go (100%) rename {internal/model => model}/query.go (100%) create mode 100644 model/role_request.go rename internal/model/role.go => model/role_response.go (63%) rename internal/model/user.go => model/user_request.go (78%) create mode 100644 model/user_response.go diff --git a/action.go b/action.go index 5608282..64d3acb 100644 --- a/action.go +++ b/action.go @@ -1,16 +1,16 @@ package usermngmt import ( - "github.com/Selly-Modules/usermngmt/internal/model" + "github.com/Selly-Modules/usermngmt/model" ) // Create ... -func (s Service) Create(payload model.CreateOptions) error { +func (s Service) Create(payload model.UserCreateOptions) error { return s.handler.User.Create(payload) } // Update ... -func (s Service) Update(userID string, payload model.UpdateOptions) error { +func (s Service) Update(userID string, payload model.UserUpdateOptions) error { return s.handler.User.UpdateByUserID(userID, payload) } @@ -23,7 +23,7 @@ func (s Service) ChangeUserStatus(userID, newStatus string) error { return s.handler.User.ChangeUserStatus(userID, newStatus) } -func (s Service) All(query model.AllQuery) model.UserAll { +func (s Service) All(query model.UserAllQuery) model.UserAll { return s.handler.User.All(query) } diff --git a/constant.go b/constant.go index 4252788..fe98da9 100644 --- a/constant.go +++ b/constant.go @@ -2,7 +2,5 @@ package usermngmt // Constant ... const ( - tableUser = "users" - tableRole = "roles" tablePrefixDefault = "usermngmt" ) diff --git a/database/db.go b/database/db.go new file mode 100644 index 0000000..6f30c60 --- /dev/null +++ b/database/db.go @@ -0,0 +1,31 @@ +package database + +import ( + "fmt" + + "go.mongodb.org/mongo-driver/mongo" +) + +// Table +var ( + tableUser = "users" + tableRole = "roles" +) + +var ( + db *mongo.Database + prefix string +) + +func Set(instance *mongo.Database, tablePrefix string) { + db = instance + prefix = tablePrefix +} + +func GetUserCol() *mongo.Collection { + return db.Collection(fmt.Sprintf("%s-%s", prefix, tableUser)) +} + +func GetRoleCol() *mongo.Collection { + return db.Collection(fmt.Sprintf("%s-%s", prefix, tableRole)) +} diff --git a/db.go b/db.go deleted file mode 100644 index 2b765fe..0000000 --- a/db.go +++ /dev/null @@ -1,12 +0,0 @@ -package usermngmt - -import ( - "fmt" - - "go.mongodb.org/mongo-driver/mongo" -) - -// getCollectionName ... -func (s Service) getCollectionName(tablePrefix, table string) *mongo.Collection { - return s.db.Collection(fmt.Sprintf("%s-%s", tablePrefix, table)) -} diff --git a/internal/model/db.go b/model/db.go similarity index 100% rename from internal/model/db.go rename to model/db.go diff --git a/internal/model/query.go b/model/query.go similarity index 100% rename from internal/model/query.go rename to model/query.go diff --git a/model/role_request.go b/model/role_request.go new file mode 100644 index 0000000..db992a0 --- /dev/null +++ b/model/role_request.go @@ -0,0 +1,7 @@ +package model + +// RoleCreateOptions ... +type RoleCreateOptions struct { + Name string +} + diff --git a/internal/model/role.go b/model/role_response.go similarity index 63% rename from internal/model/role.go rename to model/role_response.go index 1f381b1..0c84d23 100644 --- a/internal/model/role.go +++ b/model/role_response.go @@ -4,9 +4,4 @@ type RoleShort struct { ID string `json:"_id"` Name string `json:"name"` IsAdmin bool `json:"isAdmin"` -} - -// RoleCreateOptions ... -type RoleCreateOptions struct { - Name string -} +} \ No newline at end of file diff --git a/internal/model/user.go b/model/user_request.go similarity index 78% rename from internal/model/user.go rename to model/user_request.go index 34562a2..d27b3f1 100644 --- a/internal/model/user.go +++ b/model/user_request.go @@ -2,13 +2,12 @@ package model import ( "errors" - "time" "github.com/Selly-Modules/logger" ) -// CreateOptions ... -type CreateOptions struct { +// UserCreateOptions ... +type UserCreateOptions struct { Name string Phone string Email string @@ -18,8 +17,8 @@ type CreateOptions struct { Other string } -// UpdateOptions ... -type UpdateOptions struct { +// UserUpdateOptions ... +type UserUpdateOptions struct { Name string Phone string Email string @@ -33,8 +32,8 @@ type ChangePasswordOptions struct { NewPassword string } -// AllQuery ... -type AllQuery struct { +// UserAllQuery ... +type UserAllQuery struct { Page int64 Limit int64 Keyword string @@ -42,29 +41,8 @@ type AllQuery struct { Status string } -// User ... -type User struct { - ID string `json:"_id"` - Name string `json:"name"` - Phone string `json:"phone"` - Email string `json:"email"` - Status string `json:"status"` - Role RoleShort `json:"role"` - Other string `json:"other"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` -} - -type ( - // UserAll ... - UserAll struct { - List []User `json:"list"` - Total int64 `json:"total"` - } -) - // Validate ... -func (co CreateOptions) Validate() error { +func (co UserCreateOptions) Validate() error { // Name if co.Name == "" { logger.Error("usermngmt - Create: no Name data", logger.LogData{ @@ -117,7 +95,7 @@ func (co CreateOptions) Validate() error { } // Validate ... -func (uo UpdateOptions) Validate() error { +func (uo UserUpdateOptions) Validate() error { // Name if uo.Name == "" { logger.Error("usermngmt - Update: no name data", logger.LogData{ diff --git a/model/user_response.go b/model/user_response.go new file mode 100644 index 0000000..5344b7b --- /dev/null +++ b/model/user_response.go @@ -0,0 +1,26 @@ +package model + +import ( + "time" +) + +// User ... +type User struct { + ID string `json:"_id"` + Name string `json:"name"` + Phone string `json:"phone"` + Email string `json:"email"` + Status string `json:"status"` + Role RoleShort `json:"role"` + Other string `json:"other"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` +} + +type ( + // UserAll ... + UserAll struct { + List []User `json:"list"` + Total int64 `json:"total"` + } +) diff --git a/role/db.go b/role/db.go index bf98c99..3871ac4 100644 --- a/role/db.go +++ b/role/db.go @@ -3,7 +3,8 @@ package role import ( "context" - "github.com/Selly-Modules/usermngmt/internal/model" + "github.com/Selly-Modules/usermngmt/database" + "github.com/Selly-Modules/usermngmt/model" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson/primitive" ) @@ -11,7 +12,8 @@ import ( func (h Handle) findByID(ctx context.Context, id primitive.ObjectID) (model.DBRole, error) { var ( doc model.DBRole + col = database.GetRoleCol() ) - err := h.Col.FindOne(ctx, bson.M{"_id": id}).Decode(&doc) + err := col.FindOne(ctx, bson.M{"_id": id}).Decode(&doc) return doc, err } diff --git a/role/handle.go b/role/handle.go index b00b9b1..6cd48c4 100644 --- a/role/handle.go +++ b/role/handle.go @@ -3,13 +3,11 @@ package role import ( "context" - "github.com/Selly-Modules/usermngmt/internal/model" + "github.com/Selly-Modules/usermngmt/model" "go.mongodb.org/mongo-driver/bson/primitive" - "go.mongodb.org/mongo-driver/mongo" ) type Handle struct { - Col *mongo.Collection } // FindByID ... diff --git a/user/db.go b/user/db.go index 0df6cf6..493bafd 100644 --- a/user/db.go +++ b/user/db.go @@ -5,13 +5,17 @@ import ( "fmt" "github.com/Selly-Modules/logger" - "github.com/Selly-Modules/usermngmt/internal/model" + "github.com/Selly-Modules/usermngmt/database" + "github.com/Selly-Modules/usermngmt/model" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson/primitive" "go.mongodb.org/mongo-driver/mongo/options" ) func (h Handle) isPhoneNumberOrEmailExisted(ctx context.Context, phone, email string) bool { + var ( + col = database.GetUserCol() + ) // Find cond := bson.M{ "$or": []bson.M{ @@ -23,7 +27,7 @@ func (h Handle) isPhoneNumberOrEmailExisted(ctx context.Context, phone, email st }, }, } - total, err := h.Col.CountDocuments(ctx, cond) + total, err := col.CountDocuments(ctx, cond) if err != nil { logger.Error("usermngmt - countUserByCondition", logger.LogData{ "condition": cond, @@ -35,11 +39,14 @@ func (h Handle) isPhoneNumberOrEmailExisted(ctx context.Context, phone, email st } func (h Handle) isRoleIDExisted(ctx context.Context, roleID primitive.ObjectID) bool { + var ( + col = database.GetRoleCol() + ) // Find cond := bson.M{ "_id": roleID, } - total, err := h.RoleCol.CountDocuments(ctx, cond) + total, err := col.CountDocuments(ctx, cond) if err != nil { logger.Error("usermngmt - countRoleByCondition", logger.LogData{ "condition": cond, @@ -53,13 +60,17 @@ func (h Handle) isRoleIDExisted(ctx context.Context, roleID primitive.ObjectID) func (h Handle) roleFindByID(ctx context.Context, id primitive.ObjectID) (model.DBRole, error) { var ( doc model.DBRole + col = database.GetRoleCol() ) - err := h.RoleCol.FindOne(ctx, bson.M{"_id": id}).Decode(&doc) + err := col.FindOne(ctx, bson.M{"_id": id}).Decode(&doc) return doc, err } func (h Handle) create(ctx context.Context, doc model.DBUser) error { - _, err := h.Col.InsertOne(ctx, doc) + var ( + col = database.GetUserCol() + ) + _, err := col.InsertOne(ctx, doc) if err != nil { logger.Error("usermngmt - Create", logger.LogData{ "doc": doc, @@ -72,7 +83,10 @@ func (h Handle) create(ctx context.Context, doc model.DBUser) error { } func (h Handle) updateOneByCondition(ctx context.Context, cond interface{}, payload interface{}) error { - _, err := h.Col.UpdateOne(ctx, cond, payload) + var ( + col = database.GetUserCol() + ) + _, err := col.UpdateOne(ctx, cond, payload) if err != nil { logger.Error("usermngmt - Update", logger.LogData{ "cond": cond, @@ -88,15 +102,19 @@ func (h Handle) updateOneByCondition(ctx context.Context, cond interface{}, payl func (h Handle) findByID(ctx context.Context, id primitive.ObjectID) (model.DBUser, error) { var ( doc model.DBUser + col = database.GetUserCol() ) - err := h.Col.FindOne(ctx, bson.M{"_id": id}).Decode(&doc) + err := col.FindOne(ctx, bson.M{"_id": id}).Decode(&doc) return doc, err } func (h Handle) findByCondition(ctx context.Context, cond interface{}, opts ...*options.FindOptions) (docs []model.DBUser) { + var ( + col = database.GetUserCol() + ) docs = make([]model.DBUser, 0) - cursor, err := h.Col.Find(ctx, cond, opts...) + cursor, err := col.Find(ctx, cond, opts...) if err != nil { logger.Error("usermngmt - All", logger.LogData{ "cond": cond, @@ -119,7 +137,10 @@ func (h Handle) findByCondition(ctx context.Context, cond interface{}, opts ...* // countByCondition ... func (h Handle) countByCondition(ctx context.Context, cond interface{}) int64 { - total, err := h.Col.CountDocuments(ctx, cond) + var ( + col = database.GetUserCol() + ) + total, err := col.CountDocuments(ctx, cond) if err != nil { logger.Error("usermngmt - Count", logger.LogData{ "err": err.Error(), diff --git a/user/handle.go b/user/handle.go index f824490..82ca23b 100644 --- a/user/handle.go +++ b/user/handle.go @@ -8,18 +8,15 @@ import ( "github.com/Selly-Modules/logger" "github.com/Selly-Modules/mongodb" "github.com/Selly-Modules/usermngmt/internal" - "github.com/Selly-Modules/usermngmt/internal/model" + "github.com/Selly-Modules/usermngmt/model" "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/mongo" ) type Handle struct { - Col *mongo.Collection - RoleCol *mongo.Collection } // Create ... -func (h Handle) Create(payload model.CreateOptions) error { +func (h Handle) Create(payload model.UserCreateOptions) error { var ( ctx = context.Background() ) @@ -58,7 +55,7 @@ func (h Handle) Create(payload model.CreateOptions) error { } // newUser ... -func newUser(payload model.CreateOptions) (result model.DBUser, err error) { +func newUser(payload model.UserCreateOptions) (result model.DBUser, err error) { timeNow := internal.Now() roleID, _ := mongodb.NewIDFromString(payload.RoleID) return model.DBUser{ @@ -77,7 +74,7 @@ func newUser(payload model.CreateOptions) (result model.DBUser, err error) { } // All ... -func (h Handle) All(queryParams model.AllQuery) (r model.UserAll) { +func (h Handle) All(queryParams model.UserAllQuery) (r model.UserAll) { var ( ctx = context.Background() wg sync.WaitGroup @@ -142,7 +139,7 @@ func (h Handle) getResponseList(ctx context.Context, users []model.DBUser) []mod } // UpdateByUserID ... -func (h Handle) UpdateByUserID(userID string, payload model.UpdateOptions) error { +func (h Handle) UpdateByUserID(userID string, payload model.UserUpdateOptions) error { var ( ctx = context.Background() ) diff --git a/usermngmt.go b/usermngmt.go index 9e90bb7..a8b99ed 100644 --- a/usermngmt.go +++ b/usermngmt.go @@ -5,9 +5,9 @@ import ( "fmt" "github.com/Selly-Modules/mongodb" + "github.com/Selly-Modules/usermngmt/database" "github.com/Selly-Modules/usermngmt/role" "github.com/Selly-Modules/usermngmt/user" - "go.mongodb.org/mongo-driver/mongo" ) // MongoDBConfig ... @@ -32,7 +32,6 @@ type Handler struct { // Service ... type Service struct { config Config - db *mongo.Database handler Handler } @@ -63,19 +62,14 @@ func Init(config Config) (*Service, error) { return nil, err } + // Set database + database.Set(db, config.TablePrefix) + s = &Service{ config: config, - db: db, - } - - // Setup handle - s.handler = Handler{ - User: user.Handle{ - Col: s.getCollectionName(config.TablePrefix, tableUser), - RoleCol: s.getCollectionName(config.TablePrefix, tableRole), - }, - Role: role.Handle{ - Col: s.getCollectionName(config.TablePrefix, tableRole), + handler: Handler{ + User: user.Handle{}, + Role: role.Handle{}, }, } From 4f4ea8550e8e28108b4da2fe2ba4f53b2f3872fa Mon Sep 17 00:00:00 2001 From: Hoang Date: Wed, 10 Nov 2021 11:42:23 +0700 Subject: [PATCH 6/8] fix comment again --- action.go | 17 +++++++++++------ database/db.go | 2 ++ internal/constant.go | 1 - internal/helper.go | 1 - internal/time.go | 1 - model/query.go | 2 +- model/role_response.go | 1 + role/db.go | 2 +- role/handle.go | 9 +++------ user/db.go | 16 ++++++++-------- user/handle.go | 41 +++++++++++++++++++---------------------- usermngmt.go | 15 +-------------- 12 files changed, 47 insertions(+), 61 deletions(-) diff --git a/action.go b/action.go index 64d3acb..6ea86f2 100644 --- a/action.go +++ b/action.go @@ -2,31 +2,36 @@ package usermngmt import ( "github.com/Selly-Modules/usermngmt/model" + "github.com/Selly-Modules/usermngmt/role" + "github.com/Selly-Modules/usermngmt/user" ) // Create ... func (s Service) Create(payload model.UserCreateOptions) error { - return s.handler.User.Create(payload) + return user.Create(payload) } // Update ... func (s Service) Update(userID string, payload model.UserUpdateOptions) error { - return s.handler.User.UpdateByUserID(userID, payload) + return user.UpdateByUserID(userID, payload) } // ChangeUserPassword ... func (s Service) ChangeUserPassword(userID string, payload model.ChangePasswordOptions) error { - return s.handler.User.ChangeUserPassword(userID, payload) + return user.ChangeUserPassword(userID, payload) } +// ChangeUserStatus ... func (s Service) ChangeUserStatus(userID, newStatus string) error { - return s.handler.User.ChangeUserStatus(userID, newStatus) + return user.ChangeUserStatus(userID, newStatus) } +// All ... func (s Service) All(query model.UserAllQuery) model.UserAll { - return s.handler.User.All(query) + return user.All(query) } +// RoleCreate ... func (s Service) RoleCreate(payload model.RoleCreateOptions) error { - return s.handler.Role.Create(payload) + return role.Create(payload) } diff --git a/database/db.go b/database/db.go index 6f30c60..f5ebbcf 100644 --- a/database/db.go +++ b/database/db.go @@ -22,10 +22,12 @@ func Set(instance *mongo.Database, tablePrefix string) { prefix = tablePrefix } +// GetUserCol ... func GetUserCol() *mongo.Collection { return db.Collection(fmt.Sprintf("%s-%s", prefix, tableUser)) } +// GetRoleCol ... func GetRoleCol() *mongo.Collection { return db.Collection(fmt.Sprintf("%s-%s", prefix, tableRole)) } diff --git a/internal/constant.go b/internal/constant.go index 7a5b32b..c41e88b 100644 --- a/internal/constant.go +++ b/internal/constant.go @@ -6,4 +6,3 @@ const ( passwordHashingCost = 14 ) - diff --git a/internal/helper.go b/internal/helper.go index 584a13d..e99d3b6 100644 --- a/internal/helper.go +++ b/internal/helper.go @@ -33,4 +33,3 @@ func GetSearchString(fieldList ...string) string { } return fmt.Sprintf(format, searchList...) } - diff --git a/internal/time.go b/internal/time.go index f1b88a1..f3acf96 100644 --- a/internal/time.go +++ b/internal/time.go @@ -18,4 +18,3 @@ func getHCMLocation() *time.Location { func Now() time.Time { return time.Now().In(getHCMLocation()) } - diff --git a/model/query.go b/model/query.go index 4ddf74c..b2af79d 100644 --- a/model/query.go +++ b/model/query.go @@ -6,6 +6,7 @@ import ( "go.mongodb.org/mongo-driver/mongo/options" ) +// CommonQuery ... type CommonQuery struct { Page int64 Limit int64 @@ -56,4 +57,3 @@ func (q *CommonQuery) SetDefaultLimit() { q.Limit = 20 } } - diff --git a/model/role_response.go b/model/role_response.go index 0c84d23..117cf85 100644 --- a/model/role_response.go +++ b/model/role_response.go @@ -1,5 +1,6 @@ package model +// RoleShort ... type RoleShort struct { ID string `json:"_id"` Name string `json:"name"` diff --git a/role/db.go b/role/db.go index 3871ac4..6b41add 100644 --- a/role/db.go +++ b/role/db.go @@ -9,7 +9,7 @@ import ( "go.mongodb.org/mongo-driver/bson/primitive" ) -func (h Handle) findByID(ctx context.Context, id primitive.ObjectID) (model.DBRole, error) { +func findByID(ctx context.Context, id primitive.ObjectID) (model.DBRole, error) { var ( doc model.DBRole col = database.GetRoleCol() diff --git a/role/handle.go b/role/handle.go index 6cd48c4..9572478 100644 --- a/role/handle.go +++ b/role/handle.go @@ -7,17 +7,14 @@ import ( "go.mongodb.org/mongo-driver/bson/primitive" ) -type Handle struct { -} - // FindByID ... -func (h Handle) FindByID(ctx context.Context, id primitive.ObjectID) (model.DBRole, error) { - role, err := h.findByID(ctx, id) +func FindByID(ctx context.Context, id primitive.ObjectID) (model.DBRole, error) { + role, err := findByID(ctx, id) return role, err } // Create ... -func (h Handle) Create(payload model.RoleCreateOptions) error { +func Create(payload model.RoleCreateOptions) error { // TODO later return nil } diff --git a/user/db.go b/user/db.go index 493bafd..7134c53 100644 --- a/user/db.go +++ b/user/db.go @@ -12,7 +12,7 @@ import ( "go.mongodb.org/mongo-driver/mongo/options" ) -func (h Handle) isPhoneNumberOrEmailExisted(ctx context.Context, phone, email string) bool { +func isPhoneNumberOrEmailExisted(ctx context.Context, phone, email string) bool { var ( col = database.GetUserCol() ) @@ -38,7 +38,7 @@ func (h Handle) isPhoneNumberOrEmailExisted(ctx context.Context, phone, email st return total != 0 } -func (h Handle) isRoleIDExisted(ctx context.Context, roleID primitive.ObjectID) bool { +func isRoleIDExisted(ctx context.Context, roleID primitive.ObjectID) bool { var ( col = database.GetRoleCol() ) @@ -57,7 +57,7 @@ func (h Handle) isRoleIDExisted(ctx context.Context, roleID primitive.ObjectID) return total != 0 } -func (h Handle) roleFindByID(ctx context.Context, id primitive.ObjectID) (model.DBRole, error) { +func roleFindByID(ctx context.Context, id primitive.ObjectID) (model.DBRole, error) { var ( doc model.DBRole col = database.GetRoleCol() @@ -66,7 +66,7 @@ func (h Handle) roleFindByID(ctx context.Context, id primitive.ObjectID) (model. return doc, err } -func (h Handle) create(ctx context.Context, doc model.DBUser) error { +func create(ctx context.Context, doc model.DBUser) error { var ( col = database.GetUserCol() ) @@ -82,7 +82,7 @@ func (h Handle) create(ctx context.Context, doc model.DBUser) error { return nil } -func (h Handle) updateOneByCondition(ctx context.Context, cond interface{}, payload interface{}) error { +func updateOneByCondition(ctx context.Context, cond interface{}, payload interface{}) error { var ( col = database.GetUserCol() ) @@ -99,7 +99,7 @@ func (h Handle) updateOneByCondition(ctx context.Context, cond interface{}, payl return err } -func (h Handle) findByID(ctx context.Context, id primitive.ObjectID) (model.DBUser, error) { +func findByID(ctx context.Context, id primitive.ObjectID) (model.DBUser, error) { var ( doc model.DBUser col = database.GetUserCol() @@ -108,7 +108,7 @@ func (h Handle) findByID(ctx context.Context, id primitive.ObjectID) (model.DBUs return doc, err } -func (h Handle) findByCondition(ctx context.Context, cond interface{}, opts ...*options.FindOptions) (docs []model.DBUser) { +func findByCondition(ctx context.Context, cond interface{}, opts ...*options.FindOptions) (docs []model.DBUser) { var ( col = database.GetUserCol() ) @@ -136,7 +136,7 @@ func (h Handle) findByCondition(ctx context.Context, cond interface{}, opts ...* } // countByCondition ... -func (h Handle) countByCondition(ctx context.Context, cond interface{}) int64 { +func countByCondition(ctx context.Context, cond interface{}) int64 { var ( col = database.GetUserCol() ) diff --git a/user/handle.go b/user/handle.go index 82ca23b..684013a 100644 --- a/user/handle.go +++ b/user/handle.go @@ -12,11 +12,8 @@ import ( "go.mongodb.org/mongo-driver/bson" ) -type Handle struct { -} - // Create ... -func (h Handle) Create(payload model.UserCreateOptions) error { +func Create(payload model.UserCreateOptions) error { var ( ctx = context.Background() ) @@ -31,12 +28,12 @@ func (h Handle) Create(payload model.UserCreateOptions) error { if !isValid { return errors.New("invalid role id data") } - if !h.isRoleIDExisted(ctx, roleID) { + if !isRoleIDExisted(ctx, roleID) { return errors.New("role id does not exist") } // Find phone number,email exists or not - if h.isPhoneNumberOrEmailExisted(ctx, payload.Phone, payload.Email) { + if isPhoneNumberOrEmailExisted(ctx, payload.Phone, payload.Email) { return errors.New("phone number or email already existed") } @@ -47,7 +44,7 @@ func (h Handle) Create(payload model.UserCreateOptions) error { } // Create user - if err = h.create(ctx, doc); err != nil { + if err = create(ctx, doc); err != nil { return err } @@ -74,7 +71,7 @@ func newUser(payload model.UserCreateOptions) (result model.DBUser, err error) { } // All ... -func (h Handle) All(queryParams model.UserAllQuery) (r model.UserAll) { +func All(queryParams model.UserAllQuery) (r model.UserAll) { var ( ctx = context.Background() wg sync.WaitGroup @@ -98,14 +95,14 @@ func (h Handle) All(queryParams model.UserAllQuery) (r model.UserAll) { wg.Add(1) go func() { defer wg.Done() - docs := h.findByCondition(ctx, cond, query.GetFindOptionsUsingPage()) - r.List = h.getResponseList(ctx, docs) + docs := findByCondition(ctx, cond, query.GetFindOptionsUsingPage()) + r.List = getResponseList(ctx, docs) }() wg.Add(1) go func() { defer wg.Done() - r.Total = h.countByCondition(ctx, cond) + r.Total = countByCondition(ctx, cond) }() wg.Wait() @@ -113,11 +110,11 @@ func (h Handle) All(queryParams model.UserAllQuery) (r model.UserAll) { return } -func (h Handle) getResponseList(ctx context.Context, users []model.DBUser) []model.User { +func getResponseList(ctx context.Context, users []model.DBUser) []model.User { res := make([]model.User, 0) for _, user := range users { - roleRaw, _ := h.roleFindByID(ctx, user.RoleID) + roleRaw, _ := roleFindByID(ctx, user.RoleID) res = append(res, model.User{ ID: user.ID.Hex(), Name: user.Name, @@ -139,7 +136,7 @@ func (h Handle) getResponseList(ctx context.Context, users []model.DBUser) []mod } // UpdateByUserID ... -func (h Handle) UpdateByUserID(userID string, payload model.UserUpdateOptions) error { +func UpdateByUserID(userID string, payload model.UserUpdateOptions) error { var ( ctx = context.Background() ) @@ -154,12 +151,12 @@ func (h Handle) UpdateByUserID(userID string, payload model.UserUpdateOptions) e if !isValid { return errors.New("invalid role id data") } - if !h.isRoleIDExisted(ctx, roleID) { + if !isRoleIDExisted(ctx, roleID) { return errors.New("role id does not exist") } // Find phone number,email exists or not - if h.isPhoneNumberOrEmailExisted(ctx, payload.Phone, payload.Email) { + if isPhoneNumberOrEmailExisted(ctx, payload.Phone, payload.Email) { return errors.New("phone number or email already existed") } @@ -183,7 +180,7 @@ func (h Handle) UpdateByUserID(userID string, payload model.UserUpdateOptions) e } // Update - if err := h.updateOneByCondition(ctx, cond, updateData); err != nil { + if err := updateOneByCondition(ctx, cond, updateData); err != nil { return err } @@ -191,7 +188,7 @@ func (h Handle) UpdateByUserID(userID string, payload model.UserUpdateOptions) e } // ChangeUserPassword ... -func (h Handle) ChangeUserPassword(userID string, opt model.ChangePasswordOptions) error { +func ChangeUserPassword(userID string, opt model.ChangePasswordOptions) error { var ( ctx = context.Background() ) @@ -213,7 +210,7 @@ func (h Handle) ChangeUserPassword(userID string, opt model.ChangePasswordOption // Find user id, _ := mongodb.NewIDFromString(userID) - user, _ := h.findByID(ctx, id) + user, _ := findByID(ctx, id) if user.ID.IsZero() { return errors.New("user not found") } @@ -224,7 +221,7 @@ func (h Handle) ChangeUserPassword(userID string, opt model.ChangePasswordOption } // Update password - if err = h.updateOneByCondition(ctx, bson.M{"_id": user.ID}, bson.M{ + if err = updateOneByCondition(ctx, bson.M{"_id": user.ID}, bson.M{ "$set": bson.M{ "hashedPassword": internal.HashPassword(opt.NewPassword), "updatedAt": internal.Now(), @@ -237,7 +234,7 @@ func (h Handle) ChangeUserPassword(userID string, opt model.ChangePasswordOption } // ChangeUserStatus ... -func (h Handle) ChangeUserStatus(userID, newStatus string) error { +func ChangeUserStatus(userID, newStatus string) error { var ( ctx = context.Background() ) @@ -249,7 +246,7 @@ func (h Handle) ChangeUserStatus(userID, newStatus string) error { } // Update status - if err := h.updateOneByCondition(ctx, bson.M{"_id": id}, bson.M{ + if err := updateOneByCondition(ctx, bson.M{"_id": id}, bson.M{ "$set": bson.M{ "status": newStatus, "updatedAt": internal.Now(), diff --git a/usermngmt.go b/usermngmt.go index a8b99ed..8df9586 100644 --- a/usermngmt.go +++ b/usermngmt.go @@ -6,8 +6,6 @@ import ( "github.com/Selly-Modules/mongodb" "github.com/Selly-Modules/usermngmt/database" - "github.com/Selly-Modules/usermngmt/role" - "github.com/Selly-Modules/usermngmt/user" ) // MongoDBConfig ... @@ -23,16 +21,9 @@ type Config struct { TablePrefix string } -// Handler ... -type Handler struct { - User user.Handle - Role role.Handle -} - // Service ... type Service struct { - config Config - handler Handler + config Config } var s *Service @@ -67,10 +58,6 @@ func Init(config Config) (*Service, error) { s = &Service{ config: config, - handler: Handler{ - User: user.Handle{}, - Role: role.Handle{}, - }, } return s, nil From d423c25256b3c5620d28f7723c1cdfdc234f8e6a Mon Sep 17 00:00:00 2001 From: Hoang Date: Wed, 10 Nov 2021 11:52:07 +0700 Subject: [PATCH 7/8] fix comment --- database/db.go | 1 + internal/helper.go | 3 +++ 2 files changed, 4 insertions(+) diff --git a/database/db.go b/database/db.go index f5ebbcf..62ba40d 100644 --- a/database/db.go +++ b/database/db.go @@ -17,6 +17,7 @@ var ( prefix string ) +// Set ... func Set(instance *mongo.Database, tablePrefix string) { db = instance prefix = tablePrefix diff --git a/internal/helper.go b/internal/helper.go index e99d3b6..597fef5 100644 --- a/internal/helper.go +++ b/internal/helper.go @@ -7,16 +7,19 @@ import ( "golang.org/x/crypto/bcrypt" ) +// HashPassword ... func HashPassword(password string) string { bytes, _ := bcrypt.GenerateFromPassword([]byte(password), passwordHashingCost) return string(bytes) } +// CheckPasswordHash ... func CheckPasswordHash(password, hash string) bool { err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password)) return err == nil } +// GetSearchString ... func GetSearchString(fieldList ...string) string { var ( searchList = make([]interface{}, 0) From b954532159b037dd44fa5bdaef9202ab612dd455 Mon Sep 17 00:00:00 2001 From: Hoang Date: Wed, 10 Nov 2021 12:07:58 +0700 Subject: [PATCH 8/8] fix comment again --- action.go | 28 ++++++++++++++++++++-------- constant.go | 6 ------ internal/constant.go | 2 ++ model/role_request.go | 1 - model/role_response.go | 2 +- usermngmt.go | 3 ++- 6 files changed, 25 insertions(+), 17 deletions(-) delete mode 100644 constant.go diff --git a/action.go b/action.go index 6ea86f2..b94c5b2 100644 --- a/action.go +++ b/action.go @@ -6,13 +6,19 @@ import ( "github.com/Selly-Modules/usermngmt/user" ) -// Create ... -func (s Service) Create(payload model.UserCreateOptions) error { +// +// User +// + +// user methods + +// CreateUser ... +func (s Service) CreateUser(payload model.UserCreateOptions) error { return user.Create(payload) } -// Update ... -func (s Service) Update(userID string, payload model.UserUpdateOptions) error { +// UpdateUser ... +func (s Service) UpdateUser(userID string, payload model.UserUpdateOptions) error { return user.UpdateByUserID(userID, payload) } @@ -26,12 +32,18 @@ func (s Service) ChangeUserStatus(userID, newStatus string) error { return user.ChangeUserStatus(userID, newStatus) } -// All ... -func (s Service) All(query model.UserAllQuery) model.UserAll { +// GetAllUser ... +func (s Service) GetAllUser(query model.UserAllQuery) model.UserAll { return user.All(query) } -// RoleCreate ... -func (s Service) RoleCreate(payload model.RoleCreateOptions) error { +// +// Role +// + +// role methods + +// CreateRole ... +func (s Service) CreateRole(payload model.RoleCreateOptions) error { return role.Create(payload) } diff --git a/constant.go b/constant.go deleted file mode 100644 index fe98da9..0000000 --- a/constant.go +++ /dev/null @@ -1,6 +0,0 @@ -package usermngmt - -// Constant ... -const ( - tablePrefixDefault = "usermngmt" -) diff --git a/internal/constant.go b/internal/constant.go index c41e88b..c048f83 100644 --- a/internal/constant.go +++ b/internal/constant.go @@ -5,4 +5,6 @@ const ( timezoneHCM = "Asia/Ho_Chi_Minh" passwordHashingCost = 14 + + TablePrefixDefault = "usermngmt" ) diff --git a/model/role_request.go b/model/role_request.go index db992a0..81a8e0f 100644 --- a/model/role_request.go +++ b/model/role_request.go @@ -4,4 +4,3 @@ package model type RoleCreateOptions struct { Name string } - diff --git a/model/role_response.go b/model/role_response.go index 117cf85..abe20f0 100644 --- a/model/role_response.go +++ b/model/role_response.go @@ -5,4 +5,4 @@ type RoleShort struct { ID string `json:"_id"` Name string `json:"name"` IsAdmin bool `json:"isAdmin"` -} \ No newline at end of file +} diff --git a/usermngmt.go b/usermngmt.go index 8df9586..b2a2236 100644 --- a/usermngmt.go +++ b/usermngmt.go @@ -6,6 +6,7 @@ import ( "github.com/Selly-Modules/mongodb" "github.com/Selly-Modules/usermngmt/database" + "github.com/Selly-Modules/usermngmt/internal" ) // MongoDBConfig ... @@ -36,7 +37,7 @@ func Init(config Config) (*Service, error) { // If prefixTable is empty then it is usermngmt if config.TablePrefix == "" { - config.TablePrefix = tablePrefixDefault + config.TablePrefix = internal.TablePrefixDefault } // Connect MongoDB