Feature/all method #4
|
@ -48,6 +48,7 @@ func (payload CreateOptions) newUser() (result User, err error) {
|
|||
return User{
|
||||
ID: mongodb.NewObjectID(),
|
||||
Name: payload.Name,
|
||||
SearchString: getSearchString(payload.Name, payload.Phone, payload.Email),
|
||||
Phone: payload.Phone,
|
||||
Email: payload.Email,
|
||||
HashedPassword: hashPassword(payload.Password),
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
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 ResponseUserAll) {
|
||||
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 []User) []ResponseUser {
|
||||
res := make([]ResponseUser, 0)
|
||||
|
||||
for _, user := range users {
|
||||
role, _ := s.roleFindByID(ctx, user.RoleID)
|
||||
res = append(res, ResponseUser{
|
||||
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
|
||||
}
|
|
@ -44,12 +44,13 @@ func (s Service) UpdateByUserID(userID string, payload UpdateOptions) error {
|
|||
roleID, _ := mongodb.NewIDFromString(payload.RoleID)
|
||||
updateData := bson.M{
|
||||
"$set": bson.M{
|
||||
"name": payload.Name,
|
||||
"phone": payload.Phone,
|
||||
"email": payload.Email,
|
||||
"roleId": roleID,
|
||||
"other": payload.Other,
|
||||
"updatedAt": now(),
|
||||
"name": payload.Name,
|
||||
"searchString": getSearchString(payload.Name, payload.Phone, payload.Email),
|
||||
"phone": payload.Phone,
|
||||
"email": payload.Email,
|
||||
"roleId": roleID,
|
||||
"other": payload.Other,
|
||||
"updatedAt": now(),
|
||||
},
|
||||
}
|
||||
|
||||
|
|
57
db.go
57
db.go
|
@ -8,6 +8,7 @@ import (
|
|||
"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 ...
|
||||
|
@ -92,9 +93,9 @@ func (s Service) userUpdateOneByCondition(ctx context.Context, cond interface{},
|
|||
_, err := col.UpdateOne(ctx, cond, payload)
|
||||
if err != nil {
|
||||
logger.Error("usermngmt - Update", logger.LogData{
|
||||
"cond": cond,
|
||||
"cond": cond,
|
||||
"payload": payload,
|
||||
"err": err.Error(),
|
||||
"err": err.Error(),
|
||||
})
|
||||
return fmt.Errorf("error when update user: %s", err.Error())
|
||||
}
|
||||
|
@ -109,4 +110,56 @@ func (s Service) userFindByID(ctx context.Context, id primitive.ObjectID) (User,
|
|||
)
|
||||
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) {
|
||||
var (
|
||||
col = s.getUserCollection()
|
||||
)
|
||||
docs = make([]User, 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) (Role, error) {
|
||||
var (
|
||||
col = s.getRoleCollection()
|
||||
doc Role
|
||||
)
|
||||
err := col.FindOne(ctx, bson.M{"_id": id}).Decode(&doc)
|
||||
return doc, err
|
||||
}
|
24
helper.go
24
helper.go
|
@ -1,6 +1,11 @@
|
|||
package usermngmt
|
||||
|
||||
import "golang.org/x/crypto/bcrypt"
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/Selly-Modules/mongodb"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
func hashPassword(password string) string {
|
||||
bytes, _ := bcrypt.GenerateFromPassword([]byte(password), passwordHashingCost)
|
||||
|
@ -11,3 +16,20 @@ func checkPasswordHash(password, hash string) bool {
|
|||
err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password))
|
||||
return err == nil
|
||||
}
|
||||
|
||||
func getSearchString(fieldList ...string) string {
|
||||
var (
|
||||
searchList = make([]interface{}, 0)
|
||||
format = ""
|
||||
)
|
||||
|
||||
for i, value := range fieldList {
|
||||
searchList = append(searchList, mongodb.NonAccentVietnamese(value))
|
||||
if i == 0 {
|
||||
format += "%s"
|
||||
continue
|
||||
}
|
||||
format += " %s"
|
||||
}
|
||||
return fmt.Sprintf(format, searchList...)
|
||||
}
|
||||
|
|
28
model.go
28
model.go
|
@ -10,6 +10,7 @@ import (
|
|||
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:"-"`
|
||||
|
@ -20,6 +21,19 @@ type User struct {
|
|||
UpdatedAt time.Time `bson:"updatedAt" json:"updatedAt"`
|
||||
}
|
||||
|
||||
// ResponseUser ...
|
||||
type ResponseUser 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"`
|
||||
}
|
||||
|
||||
// Role ...
|
||||
type Role struct {
|
||||
ID primitive.ObjectID `bson:"_id" json:"_id"`
|
||||
|
@ -29,3 +43,17 @@ type Role struct {
|
|||
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"`
|
||||
IsAdmin bool `json:"isAdmin"`
|
||||
}
|
||||
|
||||
type (
|
||||
// ResponseUserAll ...
|
||||
ResponseUserAll struct {
|
||||
List []ResponseUser `json:"list"`
|
||||
Total int64 `json:"total"`
|
||||
}
|
||||
)
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
package usermngmt
|
||||
|
||||
import (
|
||||
"github.com/Selly-Modules/mongodb"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
)
|
||||
|
||||
type commonQuery struct {
|
||||
Page int64
|
||||
Limit int64
|
||||
Keyword string
|
||||
RoleID string
|
||||
Status string
|
||||
Sort interface{}
|
||||
}
|
||||
|
||||
// AssignKeyword ...
|
||||
func (q *commonQuery) AssignKeyword(cond bson.M) {
|
||||
if q.Keyword != "" {
|
||||
cond["searchString"] = mongodb.GenerateQuerySearchString(q.Keyword)
|
||||
}
|
||||
}
|
||||
|
||||
// AssignRoleID ...
|
||||
func (q *commonQuery) AssignRoleID(cond bson.M) {
|
||||
if q.RoleID != "" {
|
||||
if id, isValid := mongodb.NewIDFromString(q.RoleID); isValid {
|
||||
cond["roleId"] = id
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// AssignStatus ...
|
||||
func (q *commonQuery) AssignStatus(cond bson.M) {
|
||||
if q.Status != "" {
|
||||
cond["status"] = q.Status
|
||||
}
|
||||
}
|
||||
|
||||
// GetFindOptionsUsingPage ...
|
||||
func (q *commonQuery) GetFindOptionsUsingPage() *options.FindOptions {
|
||||
opts := options.Find()
|
||||
if q.Limit > 0 {
|
||||
opts.SetLimit(q.Limit).SetSkip(q.Limit * q.Page)
|
||||
}
|
||||
if q.Sort != nil {
|
||||
opts.SetSort(q.Sort)
|
||||
}
|
||||
return opts
|
||||
}
|
||||
|
||||
// SetDefaultLimit ...
|
||||
func (q *commonQuery) SetDefaultLimit() {
|
||||
if q.Limit <= 0 || q.Limit > 20 {
|
||||
q.Limit = 20
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue