| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| package schema |
| |
| import ( |
| "context" |
| "strings" |
| "time" |
| |
| "github.com/apache/answer/internal/base/constant" |
| "github.com/apache/answer/internal/base/handler" |
| "github.com/apache/answer/internal/base/reason" |
| "github.com/apache/answer/internal/base/translator" |
| "github.com/apache/answer/internal/base/validator" |
| "github.com/apache/answer/internal/entity" |
| "github.com/segmentfault/pacman/errors" |
| ) |
| |
| // UpdateUserStatusReq update user request |
| type UpdateUserStatusReq struct { |
| UserID string `validate:"required" json:"user_id"` |
| Status string `validate:"required,oneof=normal suspended deleted inactive" json:"status" enums:"normal,suspended,deleted,inactive"` |
| SuspendDuration string `validate:"omitempty,oneof=24h 48h 72h 7d 14d 1m 2m 3m 6m 1y forever" json:"suspend_duration"` |
| RemoveAllContent bool `validate:"omitempty" json:"remove_all_content"` |
| LoginUserID string `json:"-"` |
| } |
| |
| func (r *UpdateUserStatusReq) IsNormal() bool { return r.Status == constant.UserNormal } |
| func (r *UpdateUserStatusReq) IsSuspended() bool { return r.Status == constant.UserSuspended } |
| func (r *UpdateUserStatusReq) IsDeleted() bool { return r.Status == constant.UserDeleted } |
| func (r *UpdateUserStatusReq) IsInactive() bool { return r.Status == constant.UserInactive } |
| |
| // GetSuspendedUntil calculates the suspended until time based on duration |
| func (r *UpdateUserStatusReq) GetSuspendedUntil() time.Time { |
| if !r.IsSuspended() || r.SuspendDuration == "" || r.SuspendDuration == "forever" { |
| return entity.PermanentSuspensionTime // permanent suspension |
| } |
| |
| now := time.Now() |
| switch r.SuspendDuration { |
| case "24h": |
| return now.Add(24 * time.Hour) |
| case "48h": |
| return now.Add(48 * time.Hour) |
| case "72h": |
| return now.Add(72 * time.Hour) |
| case "7d": |
| return now.Add(7 * 24 * time.Hour) |
| case "14d": |
| return now.Add(14 * 24 * time.Hour) |
| case "1m": |
| return now.AddDate(0, 1, 0) |
| case "2m": |
| return now.AddDate(0, 2, 0) |
| case "3m": |
| return now.AddDate(0, 3, 0) |
| case "6m": |
| return now.AddDate(0, 6, 0) |
| case "1y": |
| return now.AddDate(1, 0, 0) |
| default: |
| return entity.PermanentSuspensionTime // fallback to permanent |
| } |
| } |
| |
| // GetUserPageReq get user list page request |
| type GetUserPageReq struct { |
| // page |
| Page int `validate:"omitempty,min=1" form:"page"` |
| // page size |
| PageSize int `validate:"omitempty,min=1" form:"page_size"` |
| // email |
| Query string `validate:"omitempty,gt=0,lte=100" form:"query"` |
| // user status |
| Status string `validate:"omitempty,oneof=normal suspended deleted inactive" form:"status"` |
| // staff, if staff is true means query admin or moderator |
| Staff bool `validate:"omitempty" form:"staff"` |
| } |
| |
| func (r *GetUserPageReq) IsSuspended() bool { return r.Status == constant.UserSuspended } |
| func (r *GetUserPageReq) IsDeleted() bool { return r.Status == constant.UserDeleted } |
| func (r *GetUserPageReq) IsInactive() bool { return r.Status == constant.UserInactive } |
| |
| // GetUserPageResp get user response |
| type GetUserPageResp struct { |
| // user id |
| UserID string `json:"user_id"` |
| // create time |
| CreatedAt int64 `json:"created_at"` |
| // delete time |
| DeletedAt int64 `json:"deleted_at"` |
| // suspended time |
| SuspendedAt int64 `json:"suspended_at"` |
| // suspended until time |
| SuspendedUntil int64 `json:"suspended_until"` |
| // username |
| Username string `json:"username"` |
| // email |
| EMail string `json:"e_mail"` |
| // rank |
| Rank int `json:"rank"` |
| // user status(normal,suspended,deleted,inactive) |
| Status string `json:"status"` |
| // display name |
| DisplayName string `json:"display_name"` |
| // avatar |
| Avatar string `json:"avatar"` |
| // role id |
| RoleID int `json:"role_id"` |
| // role name |
| RoleName string `json:"role_name"` |
| } |
| |
| // GetUserInfoReq get user request |
| type GetUserInfoReq struct { |
| UserID string `validate:"required" json:"user_id"` |
| } |
| |
| // GetUserInfoResp get user response |
| type GetUserInfoResp struct { |
| // suspended until |
| SuspendedUntil time.Time `json:"suspended_until"` |
| } |
| |
| // UpdateUserRoleReq update user role request |
| type UpdateUserRoleReq struct { |
| // user id |
| UserID string `validate:"required" json:"user_id"` |
| // role id |
| RoleID int `validate:"required" json:"role_id"` |
| // login user id |
| LoginUserID string `json:"-"` |
| } |
| |
| // EditUserProfileReq edit user profile request |
| type EditUserProfileReq struct { |
| UserID string `validate:"required" json:"user_id"` |
| DisplayName string `validate:"required,gte=2,lte=30" json:"display_name"` |
| Username string `validate:"omitempty,gte=2,lte=30" json:"username"` |
| Email string `validate:"required,email,gt=0,lte=500" json:"email"` |
| LoginUserID string `json:"-"` |
| IsAdmin bool `json:"-"` |
| } |
| |
| // AddUserReq add user request |
| type AddUserReq struct { |
| DisplayName string `validate:"required,gte=2,lte=30" json:"display_name"` |
| Email string `validate:"required,email,gt=0,lte=500" json:"email"` |
| Password string `validate:"required,gte=8,lte=32" json:"password"` |
| LoginUserID string `json:"-"` |
| } |
| |
| // AddUsersReq add users request |
| type AddUsersReq struct { |
| // users info line by line |
| UsersStr string `json:"users"` |
| Users []*AddUserReq `json:"-"` |
| } |
| |
| // DeletePermanentlyReq delete permanently request |
| type DeletePermanentlyReq struct { |
| Type string `validate:"required,oneof=users questions answers" json:"type"` |
| } |
| |
| type AddUsersErrorData struct { |
| // optional. error field name. |
| Field string `json:"field"` |
| // must. error line number. |
| Line int `json:"line"` |
| // must. error content. |
| Content string `json:"content"` |
| // optional. error message. |
| ExtraMessage string `json:"extra_message"` |
| } |
| |
| func (e *AddUsersErrorData) GetErrField(ctx context.Context) (errFields []*validator.FormErrorField) { |
| return append([]*validator.FormErrorField{}, &validator.FormErrorField{ |
| ErrorField: "users", |
| ErrorMsg: translator.TrWithData(handler.GetLangByCtx(ctx), reason.AddBulkUsersFormatError, e), |
| }) |
| } |
| |
| func (req *AddUsersReq) ParseUsers(ctx context.Context) (errFields []*validator.FormErrorField, err error) { |
| req.UsersStr = strings.TrimSpace(req.UsersStr) |
| lines := strings.Split(req.UsersStr, "\n") |
| req.Users = make([]*AddUserReq, 0) |
| for i, line := range lines { |
| arr := strings.Split(line, ",") |
| if len(arr) != 3 { |
| errFields = append([]*validator.FormErrorField{}, &validator.FormErrorField{ |
| ErrorField: "users", |
| ErrorMsg: translator.TrWithData(handler.GetLangByCtx(ctx), reason.AddBulkUsersFormatError, |
| &AddUsersErrorData{ |
| Line: i + 1, |
| Content: line, |
| }), |
| }) |
| return errFields, errors.BadRequest(reason.RequestFormatError) |
| } |
| req.Users = append(req.Users, &AddUserReq{ |
| DisplayName: strings.TrimSpace(arr[0]), |
| Email: strings.TrimSpace(arr[1]), |
| Password: strings.TrimSpace(arr[2]), |
| }) |
| } |
| |
| // check users amount |
| if len(req.Users) <= 0 || len(req.Users) > constant.DefaultBulkUser { |
| errFields = append([]*validator.FormErrorField{}, &validator.FormErrorField{ |
| ErrorField: "users", |
| ErrorMsg: translator.TrWithData(handler.GetLangByCtx(ctx), reason.AddBulkUsersAmountError, |
| map[string]int{ |
| "MaxAmount": constant.DefaultBulkUser, |
| }), |
| }) |
| return errFields, errors.BadRequest(reason.RequestFormatError) |
| } |
| return nil, nil |
| } |
| |
| // UpdateUserPasswordReq update user password request |
| type UpdateUserPasswordReq struct { |
| UserID string `validate:"required" json:"user_id"` |
| Password string `validate:"required,gte=8,lte=32" json:"password"` |
| LoginUserID string `json:"-"` |
| } |
| |
| // GetUserActivationReq get user activation |
| type GetUserActivationReq struct { |
| UserID string `validate:"required" form:"user_id"` |
| } |
| |
| // GetUserActivationResp get user activation |
| type GetUserActivationResp struct { |
| ActivationURL string `json:"activation_url"` |
| } |
| |
| // SendUserActivationReq send user activation |
| type SendUserActivationReq struct { |
| UserID string `validate:"required" json:"user_id"` |
| } |