github.com/litesolutions/justifay-api@v1.0.0-2.0.20220707114139-46f28a909481/server/user.go (about) 1 package server 2 3 import ( 4 "context" 5 "errors" 6 "fmt" 7 "regexp" 8 "strings" 9 "time" 10 11 uuid "github.com/google/uuid" 12 uuidpkg "github.com/litesolutions/justifay-api/pkg/uuid" 13 14 "github.com/litesolutions/justifay-api/model" 15 pbUser "github.com/litesolutions/justifay-api/proto/user" 16 ) 17 18 // AddUser adds a user to the DB 19 func (s *Server) AddUser(ctx context.Context, user *pbUser.UserAddRequest) (*pbUser.UserRequest, error) { 20 err := checkRequiredAddAttributes(user) 21 if err != nil { 22 return nil, err 23 } 24 25 err = s.db.NewSelect().Model(&model.User{}). 26 Where("username = ?", strings.ToLower(user.Username)). 27 Scan(ctx) 28 29 if err == nil { 30 return nil, errors.New("Email is taken") 31 } 32 33 var thisRole int32 34 35 // if requested role is not admin, grant it 36 if user.RoleId != nil && *user.RoleId >= int32(model.LabelRole) { 37 thisRole = *user.RoleId 38 } else { 39 40 defaultRole := new(model.Role) 41 42 err = s.db.NewSelect(). 43 Model(defaultRole). 44 Where("is_default = TRUE"). 45 Scan(ctx) 46 47 if err != nil { 48 return nil, err 49 } 50 51 thisRole = int32(defaultRole.ID) 52 } 53 54 // defaults to User Role, must update with greater privileges to change role 55 newUser := &model.User{ 56 Username: strings.ToLower(user.Username), 57 RoleID: thisRole, 58 FullName: user.FullName, 59 FirstName: user.FirstName, 60 LastName: user.LastName, 61 Member: user.Member, 62 Country: user.Country, 63 NewsletterNotification: user.NewsletterNotification, 64 } 65 66 newUser.ID = uuid.Must(uuid.NewRandom()) 67 68 _, err = s.db.NewInsert(). 69 Column( 70 "id", 71 "username", 72 "full_name", 73 "first_name", 74 "last_name", 75 "role_id", 76 "tenant_id", 77 "member", 78 "country", 79 "newsletter_notification", 80 ). 81 Model(newUser). 82 Exec(ctx) 83 84 if err != nil { 85 return nil, err 86 } 87 88 res := &pbUser.UserRequest{Id: newUser.ID.String()} 89 90 if err != nil { 91 return nil, err 92 } 93 94 return res, nil 95 } 96 97 // GetUser Gets a user from the DB 98 func (s *Server) GetUser(ctx context.Context, user *pbUser.UserRequest) (*pbUser.UserPublicResponse, error) { 99 100 u := new(model.User) 101 102 err := s.db.NewSelect().Model(u). 103 Column("user.*"). 104 Where("id = ?", user.Id). 105 Scan(ctx) 106 107 if err != nil { 108 return nil, err 109 } 110 111 return &pbUser.UserPublicResponse{ 112 Id: u.ID.String(), 113 Username: u.Username, 114 FullName: u.FullName, 115 FirstName: u.FirstName, 116 LastName: u.LastName, 117 Member: u.Member, 118 Country: u.Country, 119 FollowedGroups: uuidpkg.ConvertUUIDToStrArray(u.FollowedGroups), 120 }, nil 121 } 122 123 // GetUserRestricted intended for privileged roles only supplies more detailed, private info about user. 124 func (s *Server) GetUserRestricted(ctx context.Context, user *pbUser.UserRequest) (*pbUser.UserPrivateResponse, error) { 125 126 u := new(model.User) 127 128 err := s.db.NewSelect().Model(u). 129 Column("user.*"). 130 Where("id = ?", user.Id). 131 Scan(ctx) 132 133 if err != nil { 134 return nil, err 135 } 136 137 return &pbUser.UserPrivateResponse{ 138 Id: u.ID.String(), 139 Username: u.Username, 140 FullName: u.FullName, 141 FirstName: u.FirstName, 142 LastName: u.LastName, 143 Member: u.Member, 144 RoleId: u.RoleID, 145 TenantId: u.TenantID, 146 FollowedGroups: uuidpkg.ConvertUUIDToStrArray(u.FollowedGroups), 147 NewsletterNotification: u.NewsletterNotification, 148 }, nil 149 } 150 151 // DeleteUser Deletes a user from the DB 152 func (s *Server) DeleteUser(ctx context.Context, user *pbUser.UserRequest) (*pbUser.Empty, error) { 153 u := new(model.User) 154 155 _, err := s.db.NewDelete(). 156 Model(u). 157 Where("id = ?", user.Id). 158 Exec(ctx) 159 160 if err != nil { 161 return nil, err 162 } 163 164 return &pbUser.Empty{}, nil 165 } 166 167 // UpdateUser updates a users basic attributes 168 func (s *Server) UpdateUser(ctx context.Context, UserUpdateRequest *pbUser.UserUpdateRequest) (*pbUser.Empty, error) { 169 170 var updatedUserValues = make(map[string]interface{}) 171 172 if UserUpdateRequest.Username != nil { 173 updatedUserValues["username"] = *UserUpdateRequest.Username 174 re := regexp.MustCompile("^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$") 175 if !re.MatchString(*UserUpdateRequest.Username) { 176 return nil, errors.New("username must be a valid email") 177 } 178 } 179 180 if UserUpdateRequest.RoleId != nil && *UserUpdateRequest.RoleId >= int32(model.LabelRole) { 181 updatedUserValues["role_id"] = *UserUpdateRequest.RoleId 182 } 183 if UserUpdateRequest.FirstName != nil { 184 updatedUserValues["first_name"] = *UserUpdateRequest.FirstName 185 } 186 if UserUpdateRequest.LastName != nil { 187 updatedUserValues["last_name"] = *UserUpdateRequest.LastName 188 } 189 if UserUpdateRequest.FullName != nil { 190 updatedUserValues["full_name"] = *UserUpdateRequest.FullName 191 } 192 if UserUpdateRequest.NewsletterNotification != nil { 193 updatedUserValues["newsletter_notification"] = *UserUpdateRequest.NewsletterNotification 194 } 195 196 updatedUserValues["updated_at"] = time.Now().UTC() 197 198 rows, err := s.db.NewUpdate().Model(&updatedUserValues).TableExpr("users").Where("id = ?", UserUpdateRequest.Id).Exec(ctx) 199 200 if err != nil { 201 return nil, err 202 } 203 204 number, _ := rows.RowsAffected() 205 206 if number == 0 { 207 return nil, errors.New("warning: no rows were updated") 208 } 209 210 return &pbUser.Empty{}, nil 211 } 212 213 // UpdateUserRestricted updates a users more restricted attributes 214 func (s *Server) UpdateUserRestricted(ctx context.Context, UserUpdateRestrictedRequest *pbUser.UserUpdateRestrictedRequest) (*pbUser.Empty, error) { 215 216 var updatedUserValues = make(map[string]interface{}) 217 218 if UserUpdateRestrictedRequest.Username != nil { 219 updatedUserValues["username"] = *UserUpdateRestrictedRequest.Username 220 re := regexp.MustCompile("^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$") 221 if !re.MatchString(*UserUpdateRestrictedRequest.Username) { 222 return nil, errors.New("username must be a valid email") 223 } 224 } 225 if UserUpdateRestrictedRequest.FirstName != nil { 226 updatedUserValues["first_name"] = *UserUpdateRestrictedRequest.FirstName 227 } 228 if UserUpdateRestrictedRequest.LastName != nil { 229 updatedUserValues["last_name"] = *UserUpdateRestrictedRequest.LastName 230 } 231 if UserUpdateRestrictedRequest.FullName != nil { 232 updatedUserValues["full_name"] = *UserUpdateRestrictedRequest.FullName 233 } 234 if UserUpdateRestrictedRequest.Member != nil { 235 updatedUserValues["member"] = *UserUpdateRestrictedRequest.Member 236 } 237 if UserUpdateRestrictedRequest.RoleId != nil { 238 updatedUserValues["role_id"] = *UserUpdateRestrictedRequest.RoleId 239 } 240 if UserUpdateRestrictedRequest.TenantId != nil { 241 updatedUserValues["tenant_id"] = *UserUpdateRestrictedRequest.TenantId 242 } 243 if UserUpdateRestrictedRequest.NewsletterNotification != nil { 244 updatedUserValues["newsletter_notification"] = *UserUpdateRestrictedRequest.NewsletterNotification 245 } 246 247 updatedUserValues["updated_at"] = time.Now().UTC() 248 249 rows, err := s.db.NewUpdate().Model(&updatedUserValues).TableExpr("users").Where("id = ?", UserUpdateRestrictedRequest.Id).Exec(ctx) 250 251 if err != nil { 252 return nil, err 253 } 254 255 number, _ := rows.RowsAffected() 256 257 if number == 0 { 258 return nil, errors.New("warning: no rows were updated") 259 } 260 261 return &pbUser.Empty{}, nil 262 } 263 264 // ListUsers lists all users in the store. 265 func (s *Server) ListUsers(ctx context.Context, Empty *pbUser.Empty) (*pbUser.UserListResponse, error) { 266 267 var users []model.User 268 var results pbUser.UserListResponse 269 270 err := s.db.NewSelect(). 271 Model(&users). 272 Scan(ctx) 273 274 if err != nil { 275 return nil, err 276 } 277 278 for _, user := range users { 279 var result pbUser.UserPrivateResponse 280 result.Id = uuid.UUID.String(user.ID) 281 result.Username = user.Username 282 result.FullName = user.FullName 283 result.FirstName = user.FirstName 284 result.LastName = user.LastName 285 result.Member = user.Member 286 result.RoleId = user.RoleID 287 result.TenantId = user.TenantID 288 result.NewsletterNotification = user.NewsletterNotification 289 result.FollowedGroups = uuidpkg.ConvertUUIDToStrArray(user.FollowedGroups) 290 results.User = append(results.User, &result) 291 } 292 293 return &results, nil 294 } 295 296 func checkRequiredAddAttributes(user *pbUser.UserAddRequest) error { 297 if user.Username == "" { 298 argument := "username" 299 return fmt.Errorf("argument %v is required", argument) 300 } 301 re := regexp.MustCompile("^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$") 302 if !re.MatchString(user.Username) { 303 return errors.New("username must be a valid email") 304 } 305 return nil 306 } 307 308 func getUserGroupResponse(ownerOfGroup []model.UserGroup) []*pbUser.RelatedUserGroup { 309 groups := make([]*pbUser.RelatedUserGroup, len(ownerOfGroup)) 310 for i, group := range ownerOfGroup { 311 groups[i] = &pbUser.RelatedUserGroup{Id: group.ID.String(), DisplayName: group.DisplayName} 312 } 313 return groups 314 } 315 316 func (s *Server) DerefString(str *string) string { 317 if str != nil { 318 return *str 319 } 320 321 return "" 322 }