blob: d209c8f58fc23f50e024fed9e109391fab48a45a [file] [log] [blame]
/*
* 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"
"encoding/json"
"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/pkg/day"
"github.com/segmentfault/pacman/errors"
"github.com/apache/answer/internal/base/constant"
"github.com/apache/answer/internal/base/validator"
"github.com/apache/answer/internal/entity"
"github.com/apache/answer/pkg/checker"
"github.com/apache/answer/pkg/converter"
"github.com/jinzhu/copier"
)
// UserVerifyEmailReq user verify email request
type UserVerifyEmailReq struct {
// code
Code string `validate:"required,gt=0,lte=500" form:"code"`
// content
Content string `json:"-"`
}
// UserLoginResp get user response
type UserLoginResp struct {
// user id
ID string `json:"id"`
// create time
CreatedAt int64 `json:"created_at"`
// last login date
LastLoginDate int64 `json:"last_login_date"`
// username
Username string `json:"username"`
// email
EMail string `json:"e_mail"`
// mail status(1 pass 2 to be verified)
MailStatus int `json:"mail_status"`
// notice status(1 on 2off)
NoticeStatus int `json:"notice_status"`
// follow count
FollowCount int `json:"follow_count"`
// answer count
AnswerCount int `json:"answer_count"`
// question count
QuestionCount int `json:"question_count"`
// rank
Rank int `json:"rank"`
// authority group
AuthorityGroup int `json:"authority_group"`
// display name
DisplayName string `json:"display_name"`
// avatar
Avatar string `json:"avatar"`
// mobile
Mobile string `json:"mobile"`
// bio markdown
Bio string `json:"bio"`
// bio html
BioHTML string `json:"bio_html"`
// website
Website string `json:"website"`
// location
Location string `json:"location"`
// language
Language string `json:"language"`
// Color scheme
ColorScheme string `json:"color_scheme"`
// access token
AccessToken string `json:"access_token"`
// role id
RoleID int `json:"role_id"`
// user status
Status string `json:"status"`
// user have password
HavePassword bool `json:"have_password"`
// visit token
VisitToken string `json:"visit_token"`
// suspended until timestamp
SuspendedUntil int64 `json:"suspended_until"`
}
func (r *UserLoginResp) ConvertFromUserEntity(userInfo *entity.User) {
_ = copier.Copy(r, userInfo)
r.CreatedAt = userInfo.CreatedAt.Unix()
r.LastLoginDate = userInfo.LastLoginDate.Unix()
r.Status = constant.ConvertUserStatus(userInfo.Status, userInfo.MailStatus)
r.HavePassword = len(userInfo.Pass) > 0
if !userInfo.SuspendedUntil.IsZero() {
r.SuspendedUntil = userInfo.SuspendedUntil.Unix()
}
}
type GetCurrentLoginUserInfoResp struct {
*UserLoginResp
Avatar *AvatarInfo `json:"avatar"`
}
func (r *GetCurrentLoginUserInfoResp) ConvertFromUserEntity(userInfo *entity.User) {
_ = copier.Copy(r, userInfo)
r.CreatedAt = userInfo.CreatedAt.Unix()
r.LastLoginDate = userInfo.LastLoginDate.Unix()
r.Status = constant.ConvertUserStatus(userInfo.Status, userInfo.MailStatus)
if len(r.ColorScheme) == 0 {
r.ColorScheme = constant.ColorSchemeDefault
}
if !userInfo.SuspendedUntil.IsZero() {
r.SuspendedUntil = userInfo.SuspendedUntil.Unix()
}
}
// GetOtherUserInfoByUsernameResp get user response
type GetOtherUserInfoByUsernameResp struct {
// user id
ID string `json:"id"`
// create time
CreatedAt int64 `json:"created_at"`
// last login date
LastLoginDate int64 `json:"last_login_date"`
// username
Username string `json:"username"`
// email
// follow count
FollowCount int `json:"follow_count"`
// answer count
AnswerCount int `json:"answer_count"`
// question count
QuestionCount int `json:"question_count"`
// rank
Rank int `json:"rank"`
// display name
DisplayName string `json:"display_name"`
// avatar
Avatar string `json:"avatar"`
// mobile
Mobile string `json:"mobile"`
// bio markdown
Bio string `json:"bio"`
// bio html
BioHTML string `json:"bio_html"`
// website
Website string `json:"website"`
// location
Location string `json:"location"`
Status string `json:"status"`
StatusMsg string `json:"status_msg,omitempty"`
// suspended until timestamp
SuspendedUntil int64 `json:"suspended_until"`
}
func (r *GetOtherUserInfoByUsernameResp) ConvertFromUserEntity(userInfo *entity.User) {
_ = copier.Copy(r, userInfo)
r.CreatedAt = userInfo.CreatedAt.Unix()
r.LastLoginDate = userInfo.LastLoginDate.Unix()
r.Status = constant.ConvertUserStatus(userInfo.Status, userInfo.MailStatus)
if !userInfo.SuspendedUntil.IsZero() {
r.SuspendedUntil = userInfo.SuspendedUntil.Unix()
}
r.StatusMsg = ""
}
func (r *GetOtherUserInfoByUsernameResp) ConvertFromUserEntityWithLang(ctx context.Context, userInfo *entity.User) {
_ = copier.Copy(r, userInfo)
r.CreatedAt = userInfo.CreatedAt.Unix()
r.LastLoginDate = userInfo.LastLoginDate.Unix()
r.Status = constant.ConvertUserStatus(userInfo.Status, userInfo.MailStatus)
lang := handler.GetLangByCtx(ctx)
if userInfo.MailStatus == entity.EmailStatusToBeVerified {
r.StatusMsg = translator.Tr(lang, reason.UserStatusInactive)
}
switch userInfo.Status {
case entity.UserStatusSuspended:
if userInfo.SuspendedUntil.IsZero() || userInfo.SuspendedUntil.Year() >= 2099 {
r.StatusMsg = translator.Tr(lang, reason.UserStatusSuspendedForever)
} else {
r.SuspendedUntil = userInfo.SuspendedUntil.Unix()
trans := translator.GlobalTrans.Tr(lang, "ui.dates.long_date_with_time")
suspendedUntilFormatted := day.Format(userInfo.SuspendedUntil.Unix(), trans, "UTC")
r.StatusMsg = translator.TrWithData(lang, reason.UserStatusSuspendedUntil, map[string]any{
"SuspendedUntil": suspendedUntilFormatted,
})
}
case entity.UserStatusDeleted:
r.StatusMsg = translator.Tr(lang, reason.UserStatusDeleted)
}
}
// UserEmailLoginReq user email login request
type UserEmailLoginReq struct {
Email string `validate:"required,email,gt=0,lte=500" json:"e_mail"`
Pass string `validate:"required,gte=8,lte=32" json:"pass"`
CaptchaID string `json:"captcha_id"`
CaptchaCode string `json:"captcha_code"`
}
// UserRegisterReq user register request
type UserRegisterReq struct {
Name string `validate:"required,gte=2,lte=30" json:"name"`
Email string `validate:"required,email,gt=0,lte=500" json:"e_mail" `
Pass string `validate:"required,gte=8,lte=32" json:"pass"`
CaptchaID string `json:"captcha_id"`
CaptchaCode string `json:"captcha_code"`
IP string `json:"-" `
}
func (u *UserRegisterReq) Check() (errFields []*validator.FormErrorField, err error) {
if err = checker.CheckPassword(u.Pass); err != nil {
errFields = append(errFields, &validator.FormErrorField{
ErrorField: "pass",
ErrorMsg: err.Error(),
})
return errFields, err
}
return nil, nil
}
type UserModifyPasswordReq struct {
OldPass string `validate:"omitempty,gte=8,lte=32" json:"old_pass"`
Pass string `validate:"required,gte=8,lte=32" json:"pass"`
CaptchaID string `json:"captcha_id"`
CaptchaCode string `json:"captcha_code"`
UserID string `json:"-"`
AccessToken string `json:"-"`
}
func (u *UserModifyPasswordReq) Check() (errFields []*validator.FormErrorField, err error) {
if err = checker.CheckPassword(u.Pass); err != nil {
errFields = append(errFields, &validator.FormErrorField{
ErrorField: "pass",
ErrorMsg: err.Error(),
})
return errFields, err
}
return nil, nil
}
type UpdateInfoRequest struct {
DisplayName string `validate:"omitempty,gte=2,lte=30" json:"display_name"`
Username string `validate:"omitempty,gte=2,lte=30" json:"username"`
Avatar AvatarInfo `json:"avatar"`
Bio string `validate:"omitempty,gt=0,lte=4096" json:"bio"`
BioHTML string `json:"-"`
Website string `validate:"omitempty,gt=0,lte=500" json:"website"`
Location string `validate:"omitempty,gt=0,lte=100" json:"location"`
UserID string `json:"-"`
IsAdmin bool `json:"-"`
}
type AvatarInfo struct {
Type string `validate:"omitempty,gt=0,lte=100" json:"type"`
Gravatar string `validate:"omitempty,gt=0,lte=200" json:"gravatar"`
Custom string `validate:"omitempty,gt=0,lte=200" json:"custom"`
}
func (a *AvatarInfo) ToJsonString() string {
data, _ := json.Marshal(a)
return string(data)
}
func (a *AvatarInfo) GetURL() string {
switch a.Type {
case constant.AvatarTypeGravatar:
return a.Gravatar
case constant.AvatarTypeCustom:
return a.Custom
default:
return ""
}
}
func CustomAvatar(url string) *AvatarInfo {
return &AvatarInfo{
Type: constant.AvatarTypeCustom,
Custom: url,
}
}
func (req *UpdateInfoRequest) Check() (errFields []*validator.FormErrorField, err error) {
req.BioHTML = converter.Markdown2BasicHTML(req.Bio)
if len(req.Website) > 0 && !checker.IsURL(req.Website) {
return append(errFields, &validator.FormErrorField{
ErrorField: "website",
ErrorMsg: reason.InvalidURLError,
}), errors.BadRequest(reason.InvalidURLError)
}
return nil, nil
}
// UpdateUserInterfaceRequest update user interface request
type UpdateUserInterfaceRequest struct {
// language
Language string `validate:"required,gt=1,lte=100" json:"language"`
// Color scheme
ColorScheme string `validate:"required,gt=1,lte=100" json:"color_scheme"`
// user id
UserId string `json:"-"`
}
func (req *UpdateUserInterfaceRequest) Check() (errFields []*validator.FormErrorField, err error) {
if !translator.CheckLanguageIsValid(req.Language) {
return nil, errors.BadRequest(reason.LangNotFound)
}
if req.ColorScheme != constant.ColorSchemeDefault &&
req.ColorScheme != constant.ColorSchemeLight &&
req.ColorScheme != constant.ColorSchemeDark &&
req.ColorScheme != constant.ColorSchemeSystem {
req.ColorScheme = constant.ColorSchemeDefault
}
return nil, nil
}
type UserRetrievePassWordRequest struct {
Email string `validate:"required,email,gt=0,lte=500" json:"e_mail"`
CaptchaID string `json:"captcha_id"`
CaptchaCode string `json:"captcha_code"`
}
type UserRePassWordRequest struct {
Code string `validate:"required,gt=0,lte=100" json:"code"`
Pass string `validate:"required,gt=0,lte=32" json:"pass"`
Content string `json:"-"`
}
func (u *UserRePassWordRequest) Check() (errFields []*validator.FormErrorField, err error) {
if err = checker.CheckPassword(u.Pass); err != nil {
errFields = append(errFields, &validator.FormErrorField{
ErrorField: "pass",
ErrorMsg: err.Error(),
})
return errFields, err
}
return nil, nil
}
type ActionRecordReq struct {
Action string `validate:"required,oneof=email password edit_userinfo question answer comment edit invitation_answer search report delete vote" form:"action"`
IP string `json:"-"`
UserID string `json:"-"`
}
type ActionRecordResp struct {
CaptchaID string `json:"captcha_id"`
CaptchaImg string `json:"captcha_img"`
Verify bool `json:"verify"`
}
type UserBasicInfo struct {
ID string `json:"id"`
Username string `json:"username"`
Rank int `json:"rank"`
DisplayName string `json:"display_name"`
Avatar string `json:"avatar"`
Website string `json:"website"`
Location string `json:"location"`
Language string `json:"language"`
Status string `json:"status"`
SuspendedUntil int64 `json:"suspended_until"`
}
type GetOtherUserInfoByUsernameReq struct {
Username string `validate:"required,gt=0,lte=500" form:"username"`
UserID string `json:"-"`
IsAdmin bool `json:"-"`
}
type GetOtherUserInfoResp struct {
Info *GetOtherUserInfoByUsernameResp `json:"info"`
}
type UserChangeEmailSendCodeReq struct {
UserVerifyEmailSendReq
Email string `validate:"required,email,gt=0,lte=500" json:"e_mail"`
Pass string `validate:"omitempty,gte=8,lte=32" json:"pass"`
UserID string `json:"-"`
}
type UserChangeEmailVerifyReq struct {
Code string `validate:"required,gt=0,lte=500" json:"code"`
Content string `json:"-"`
}
type UserVerifyEmailSendReq struct {
CaptchaID string `json:"captcha_id"`
CaptchaCode string `json:"captcha_code"`
}
// UserRankingResp user ranking response
type UserRankingResp struct {
UsersWithTheMostReputation []*UserRankingSimpleInfo `json:"users_with_the_most_reputation"`
UsersWithTheMostVote []*UserRankingSimpleInfo `json:"users_with_the_most_vote"`
Staffs []*UserRankingSimpleInfo `json:"staffs"`
}
// UserRankingSimpleInfo user ranking simple info
type UserRankingSimpleInfo struct {
// username
Username string `json:"username"`
// rank
Rank int `json:"rank"`
// vote
VoteCount int `json:"vote_count"`
// display name
DisplayName string `json:"display_name"`
// avatar
Avatar string `json:"avatar"`
}
// UserUnsubscribeNotificationReq user unsubscribe email notification request
type UserUnsubscribeNotificationReq struct {
Code string `validate:"required,gt=0,lte=500" json:"code"`
Content string `json:"-"`
}
// GetUserStaffReq get user staff request
type GetUserStaffReq struct {
Username string `validate:"omitempty,gt=0,lte=500" form:"username"`
PageSize int `validate:"omitempty,min=1" form:"page_size"`
}
// GetUserStaffResp get user staff response
type GetUserStaffResp struct {
// username
Username string `json:"username"`
// display name
DisplayName string `json:"display_name"`
// avatar
Avatar string `json:"avatar"`
}