feat(notification): add user notification config API

This commit is contained in:
LinkinStars 2023-08-21 15:07:30 +08:00
parent 0d2c9cfd45
commit 6a3d2f95d2
17 changed files with 481 additions and 114 deletions

View File

@ -5526,14 +5526,14 @@ const docTemplate = `{
}
}
},
"/answer/api/v1/user/notice/set": {
"post": {
"/answer/api/v1/user/notification/config": {
"put": {
"security": [
{
"ApiKeyAuth": []
}
],
"description": "UserNoticeSet",
"description": "update user's notification config",
"consumes": [
"application/json"
],
@ -5543,18 +5543,44 @@ const docTemplate = `{
"tags": [
"User"
],
"summary": "UserNoticeSet",
"summary": "update user's notification config",
"parameters": [
{
"description": "UserNoticeSetRequest",
"description": "UpdateUserNotificationConfigReq",
"name": "data",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/schema.UserNoticeSetRequest"
"$ref": "#/definitions/schema.UpdateUserNotificationConfigReq"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/handler.RespBody"
}
}
}
},
"post": {
"security": [
{
"ApiKeyAuth": []
}
],
"description": "get user's notification config",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"User"
],
"summary": "get user's notification config",
"responses": {
"200": {
"description": "OK",
@ -5567,7 +5593,7 @@ const docTemplate = `{
"type": "object",
"properties": {
"data": {
"$ref": "#/definitions/schema.UserNoticeSetResp"
"$ref": "#/definitions/schema.GetUserNotificationConfigResp"
}
}
}
@ -6198,6 +6224,15 @@ const docTemplate = `{
}
},
"definitions": {
"constant.NotificationChannel": {
"type": "string",
"enum": [
"email"
],
"x-enum-varnames": [
"EmailChannel"
]
},
"constant.Privilege": {
"type": "object",
"properties": {
@ -6301,6 +6336,9 @@ const docTemplate = `{
"type": "string",
"maxLength": 30
},
"login_required": {
"type": "boolean"
},
"name": {
"type": "string",
"maxLength": 30
@ -7595,6 +7633,29 @@ const docTemplate = `{
}
}
},
"schema.GetUserNotificationConfigResp": {
"type": "object",
"properties": {
"all_new_question": {
"type": "array",
"items": {
"$ref": "#/definitions/schema.NotificationChannelConfig"
}
},
"all_new_question_for_following_tags": {
"type": "array",
"items": {
"$ref": "#/definitions/schema.NotificationChannelConfig"
}
},
"inbox": {
"type": "array",
"items": {
"$ref": "#/definitions/schema.NotificationChannelConfig"
}
}
}
},
"schema.GetUserPageResp": {
"type": "object",
"properties": {
@ -7706,6 +7767,17 @@ const docTemplate = `{
}
}
},
"schema.NotificationChannelConfig": {
"type": "object",
"properties": {
"enable": {
"type": "boolean"
},
"key": {
"$ref": "#/definitions/constant.NotificationChannel"
}
}
},
"schema.NotificationClearIDRequest": {
"type": "object",
"properties": {
@ -9103,6 +9175,29 @@ const docTemplate = `{
}
}
},
"schema.UpdateUserNotificationConfigReq": {
"type": "object",
"properties": {
"all_new_question": {
"type": "array",
"items": {
"$ref": "#/definitions/schema.NotificationChannelConfig"
}
},
"all_new_question_for_following_tags": {
"type": "array",
"items": {
"$ref": "#/definitions/schema.NotificationChannelConfig"
}
},
"inbox": {
"type": "array",
"items": {
"$ref": "#/definitions/schema.NotificationChannelConfig"
}
}
}
},
"schema.UpdateUserPasswordReq": {
"type": "object",
"required": [
@ -9382,22 +9477,6 @@ const docTemplate = `{
}
}
},
"schema.UserNoticeSetRequest": {
"type": "object",
"properties": {
"notice_switch": {
"type": "boolean"
}
}
},
"schema.UserNoticeSetResp": {
"type": "object",
"properties": {
"notice_switch": {
"type": "boolean"
}
}
},
"schema.UserRankingResp": {
"type": "object",
"properties": {

View File

@ -5514,14 +5514,14 @@
}
}
},
"/answer/api/v1/user/notice/set": {
"post": {
"/answer/api/v1/user/notification/config": {
"put": {
"security": [
{
"ApiKeyAuth": []
}
],
"description": "UserNoticeSet",
"description": "update user's notification config",
"consumes": [
"application/json"
],
@ -5531,18 +5531,44 @@
"tags": [
"User"
],
"summary": "UserNoticeSet",
"summary": "update user's notification config",
"parameters": [
{
"description": "UserNoticeSetRequest",
"description": "UpdateUserNotificationConfigReq",
"name": "data",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/schema.UserNoticeSetRequest"
"$ref": "#/definitions/schema.UpdateUserNotificationConfigReq"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/handler.RespBody"
}
}
}
},
"post": {
"security": [
{
"ApiKeyAuth": []
}
],
"description": "get user's notification config",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"User"
],
"summary": "get user's notification config",
"responses": {
"200": {
"description": "OK",
@ -5555,7 +5581,7 @@
"type": "object",
"properties": {
"data": {
"$ref": "#/definitions/schema.UserNoticeSetResp"
"$ref": "#/definitions/schema.GetUserNotificationConfigResp"
}
}
}
@ -6186,6 +6212,15 @@
}
},
"definitions": {
"constant.NotificationChannel": {
"type": "string",
"enum": [
"email"
],
"x-enum-varnames": [
"EmailChannel"
]
},
"constant.Privilege": {
"type": "object",
"properties": {
@ -6289,6 +6324,9 @@
"type": "string",
"maxLength": 30
},
"login_required": {
"type": "boolean"
},
"name": {
"type": "string",
"maxLength": 30
@ -7583,6 +7621,29 @@
}
}
},
"schema.GetUserNotificationConfigResp": {
"type": "object",
"properties": {
"all_new_question": {
"type": "array",
"items": {
"$ref": "#/definitions/schema.NotificationChannelConfig"
}
},
"all_new_question_for_following_tags": {
"type": "array",
"items": {
"$ref": "#/definitions/schema.NotificationChannelConfig"
}
},
"inbox": {
"type": "array",
"items": {
"$ref": "#/definitions/schema.NotificationChannelConfig"
}
}
}
},
"schema.GetUserPageResp": {
"type": "object",
"properties": {
@ -7694,6 +7755,17 @@
}
}
},
"schema.NotificationChannelConfig": {
"type": "object",
"properties": {
"enable": {
"type": "boolean"
},
"key": {
"$ref": "#/definitions/constant.NotificationChannel"
}
}
},
"schema.NotificationClearIDRequest": {
"type": "object",
"properties": {
@ -9091,6 +9163,29 @@
}
}
},
"schema.UpdateUserNotificationConfigReq": {
"type": "object",
"properties": {
"all_new_question": {
"type": "array",
"items": {
"$ref": "#/definitions/schema.NotificationChannelConfig"
}
},
"all_new_question_for_following_tags": {
"type": "array",
"items": {
"$ref": "#/definitions/schema.NotificationChannelConfig"
}
},
"inbox": {
"type": "array",
"items": {
"$ref": "#/definitions/schema.NotificationChannelConfig"
}
}
}
},
"schema.UpdateUserPasswordReq": {
"type": "object",
"required": [
@ -9370,22 +9465,6 @@
}
}
},
"schema.UserNoticeSetRequest": {
"type": "object",
"properties": {
"notice_switch": {
"type": "boolean"
}
}
},
"schema.UserNoticeSetResp": {
"type": "object",
"properties": {
"notice_switch": {
"type": "boolean"
}
}
},
"schema.UserRankingResp": {
"type": "object",
"properties": {

View File

@ -1,4 +1,10 @@
definitions:
constant.NotificationChannel:
enum:
- email
type: string
x-enum-varnames:
- EmailChannel
constant.Privilege:
properties:
key:
@ -63,6 +69,8 @@ definitions:
lang:
maxLength: 30
type: string
login_required:
type: boolean
name:
maxLength: 30
type: string
@ -983,6 +991,21 @@ definitions:
activation_url:
type: string
type: object
schema.GetUserNotificationConfigResp:
properties:
all_new_question:
items:
$ref: '#/definitions/schema.NotificationChannelConfig'
type: array
all_new_question_for_following_tags:
items:
$ref: '#/definitions/schema.NotificationChannelConfig'
type: array
inbox:
items:
$ref: '#/definitions/schema.NotificationChannelConfig'
type: array
type: object
schema.GetUserPageResp:
properties:
avatar:
@ -1064,6 +1087,13 @@ definitions:
text:
type: string
type: object
schema.NotificationChannelConfig:
properties:
enable:
type: boolean
key:
$ref: '#/definitions/constant.NotificationChannel'
type: object
schema.NotificationClearIDRequest:
properties:
id:
@ -2028,6 +2058,21 @@ definitions:
required:
- language
type: object
schema.UpdateUserNotificationConfigReq:
properties:
all_new_question:
items:
$ref: '#/definitions/schema.NotificationChannelConfig'
type: array
all_new_question_for_following_tags:
items:
$ref: '#/definitions/schema.NotificationChannelConfig'
type: array
inbox:
items:
$ref: '#/definitions/schema.NotificationChannelConfig'
type: array
type: object
schema.UpdateUserPasswordReq:
properties:
password:
@ -2228,16 +2273,6 @@ definitions:
required:
- pass
type: object
schema.UserNoticeSetRequest:
properties:
notice_switch:
type: boolean
type: object
schema.UserNoticeSetResp:
properties:
notice_switch:
type: boolean
type: object
schema.UserRankingResp:
properties:
staffs:
@ -5698,18 +5733,11 @@ paths:
summary: user logout
tags:
- User
/answer/api/v1/user/notice/set:
/answer/api/v1/user/notification/config:
post:
consumes:
- application/json
description: UserNoticeSet
parameters:
- description: UserNoticeSetRequest
in: body
name: data
required: true
schema:
$ref: '#/definitions/schema.UserNoticeSetRequest'
description: get user's notification config
produces:
- application/json
responses:
@ -5720,11 +5748,34 @@ paths:
- $ref: '#/definitions/handler.RespBody'
- properties:
data:
$ref: '#/definitions/schema.UserNoticeSetResp'
$ref: '#/definitions/schema.GetUserNotificationConfigResp'
type: object
security:
- ApiKeyAuth: []
summary: UserNoticeSet
summary: get user's notification config
tags:
- User
put:
consumes:
- application/json
description: update user's notification config
parameters:
- description: UpdateUserNotificationConfigReq
in: body
name: data
required: true
schema:
$ref: '#/definitions/schema.UpdateUserNotificationConfigReq'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/handler.RespBody'
security:
- ApiKeyAuth: []
summary: update user's notification config
tags:
- User
/answer/api/v1/user/password:

View File

@ -39,6 +39,19 @@ const (
NotificationInvitedYouToAnswer = "notification.action.invited_you_to_answer"
)
type NotificationChannel string
type NotificationSource string
const (
InboxChannel NotificationSource = "inbox"
AllNewQuestionChannel NotificationSource = "all_new_question"
AllNewQuestionForFollowingTagsChannel NotificationSource = "all_new_question_for_following_tags"
)
const (
EmailChannel NotificationChannel = "email"
)
var (
NotificationMsgTypeMapping = map[string]int{
NotificationUpdateQuestion: 1,

View File

@ -488,25 +488,40 @@ func (uc *UserController) UserRegisterCaptcha(ctx *gin.Context) {
handler.HandleResponse(ctx, err, resp)
}
// UserNoticeSet godoc
// @Summary UserNoticeSet
// @Description UserNoticeSet
// GetUserNotificationConfig get user's notification config
// @Summary get user's notification config
// @Description get user's notification config
// @Tags User
// @Accept json
// @Produce json
// @Security ApiKeyAuth
// @Param data body schema.UserNoticeSetRequest true "UserNoticeSetRequest"
// @Success 200 {object} handler.RespBody{data=schema.UserNoticeSetResp}
// @Router /answer/api/v1/user/notice/set [post]
func (uc *UserController) UserNoticeSet(ctx *gin.Context) {
req := &schema.UserNoticeSetRequest{}
// @Success 200 {object} handler.RespBody{data=schema.GetUserNotificationConfigResp}
// @Router /answer/api/v1/user/notification/config [post]
func (uc *UserController) GetUserNotificationConfig(ctx *gin.Context) {
userID := middleware.GetLoginUserIDFromContext(ctx)
resp, err := uc.userService.GetUserNotificationConfig(ctx, userID)
handler.HandleResponse(ctx, err, resp)
}
// UpdateUserNotificationConfig update user's notification config
// @Summary update user's notification config
// @Description update user's notification config
// @Tags User
// @Accept json
// @Produce json
// @Security ApiKeyAuth
// @Param data body schema.UpdateUserNotificationConfigReq true "UpdateUserNotificationConfigReq"
// @Success 200 {object} handler.RespBody{}
// @Router /answer/api/v1/user/notification/config [put]
func (uc *UserController) UpdateUserNotificationConfig(ctx *gin.Context) {
req := &schema.UpdateUserNotificationConfigReq{}
if handler.BindAndCheck(ctx, req) {
return
}
req.UserID = middleware.GetLoginUserIDFromContext(ctx)
resp, err := uc.userService.UserNoticeSet(ctx, req.UserID, req.NoticeSwitch)
handler.HandleResponse(ctx, err, resp)
err := uc.userService.UpdateUserNotificationConfig(ctx, req)
handler.HandleResponse(ctx, err, nil)
}
// UserChangeEmailSendCode send email to the user email then change their email

View File

@ -46,6 +46,7 @@ type User struct {
IPInfo string `xorm:"not null default '' VARCHAR(255) ip_info"`
IsAdmin bool `xorm:"not null default false BOOL is_admin"`
Language string `xorm:"not null default '' VARCHAR(100) language"`
NoticeConfig string `xorm:"not null TEXT notice_config"`
}
// TableName user table name

View File

@ -71,6 +71,7 @@ var migrations = []Migration{
NewMigration("v1.1.0-beta.2", "update question post time", updateQuestionPostTime, true),
NewMigration("v1.1.0", "add gravatar base url", updateCount, true),
NewMigration("v1.1.1", "update the length of revision content", updateTheLengthOfRevisionContent, false),
NewMigration("v1.1.2", "add notification config", addNoticeConfig, false),
}
func GetMigrations() []Migration {

View File

@ -0,0 +1,13 @@
package migrations
import (
"context"
"xorm.io/xorm"
)
func addNoticeConfig(ctx context.Context, x *xorm.Engine) error {
type User struct {
NoticeConfig string `xorm:"not null TEXT notice_config"`
}
return x.Context(ctx).Sync(new(User))
}

View File

@ -120,6 +120,16 @@ func (ur *userRepo) UpdateNoticeStatus(ctx context.Context, userID string, notic
return nil
}
// UpdateNoticeConfig update notice config
func (ur *userRepo) UpdateNoticeConfig(ctx context.Context, userID string, noticeConfig string) error {
cond := &entity.User{NoticeConfig: noticeConfig}
_, err := ur.data.DB.Context(ctx).Where("id = ?", userID).Cols("notice_config").Update(cond)
if err != nil {
return errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
}
return nil
}
func (ur *userRepo) UpdatePass(ctx context.Context, userID, pass string) error {
_, err := ur.data.DB.Context(ctx).Where("id = ?", userID).Cols("pass").Update(&entity.User{Pass: pass})
if err != nil {

View File

@ -215,7 +215,8 @@ func (a *AnswerAPIRouter) RegisterAnswerAPIRouter(r *gin.RouterGroup) {
r.PUT("/user/password", middleware.BanAPIForUserCenter, a.userController.UserModifyPassWord)
r.PUT("/user/info", a.userController.UserUpdateInfo)
r.PUT("/user/interface", a.userController.UserUpdateInterface)
r.POST("/user/notice/set", a.userController.UserNoticeSet)
r.GET("/user/notification/config", a.userController.GetUserNotificationConfig)
r.PUT("/user/notification/config", a.userController.UpdateUserNotificationConfig)
r.GET("/user/info/search", a.userController.SearchUserListByName)
// vote

View File

@ -0,0 +1,108 @@
package schema
import (
"encoding/json"
"github.com/answerdev/answer/internal/base/constant"
)
type NotificationChannelConfig struct {
Key constant.NotificationChannel `json:"key"`
Enable bool `json:"enable"`
}
type NotificationChannelConfigList []*NotificationChannelConfig
func (n *NotificationChannelConfigList) Format(sequences []constant.NotificationChannel) {
if n == nil {
*n = make([]*NotificationChannelConfig, 0)
return
}
newList := make([]*NotificationChannelConfig, 0)
mapping := make(map[constant.NotificationChannel]*NotificationChannelConfig)
for _, item := range *n {
mapping[item.Key] = &NotificationChannelConfig{
Key: item.Key,
Enable: item.Enable,
}
}
for _, ch := range sequences {
if c, ok := mapping[ch]; ok {
newList = append(newList, c)
} else {
newList = append(newList, &NotificationChannelConfig{
Key: ch,
})
}
}
*n = newList
}
func (n *NotificationChannelConfigList) CheckEnable(ch constant.NotificationChannel) bool {
if n == nil {
return false
}
for _, item := range *n {
if item.Key == ch {
return item.Enable
}
}
return false
}
type NotificationConfig struct {
Inbox NotificationChannelConfigList `json:"inbox"`
AllNewQuestion NotificationChannelConfigList `json:"all_new_question"`
AllNewQuestionForFollowingTags NotificationChannelConfigList `json:"all_new_question_for_following_tags"`
}
func (n *NotificationConfig) ToJsonString() string {
data, _ := json.Marshal(n)
return string(data)
}
func NewNotificationConfig(data string) *NotificationConfig {
nc := &NotificationConfig{}
nc.FromJsonString(data)
return nc
}
func (n *NotificationConfig) FromJsonString(data string) {
if len(data) > 0 {
_ = json.Unmarshal([]byte(data), n)
return
}
n.Inbox = make([]*NotificationChannelConfig, 0)
n.AllNewQuestion = make([]*NotificationChannelConfig, 0)
n.AllNewQuestionForFollowingTags = make([]*NotificationChannelConfig, 0)
return
}
func (n *NotificationConfig) Format() {
n.Inbox.Format([]constant.NotificationChannel{constant.EmailChannel})
n.AllNewQuestion.Format([]constant.NotificationChannel{constant.EmailChannel})
n.AllNewQuestionForFollowingTags.Format([]constant.NotificationChannel{constant.EmailChannel})
}
func (n *NotificationConfig) CheckEnable(
source constant.NotificationSource, channel constant.NotificationChannel) bool {
switch source {
case constant.InboxChannel:
return n.Inbox.CheckEnable(channel)
case constant.AllNewQuestionChannel:
return n.AllNewQuestion.CheckEnable(channel)
case constant.AllNewQuestionForFollowingTagsChannel:
return n.AllNewQuestionForFollowingTags.CheckEnable(channel)
}
return false
}
// UpdateUserNotificationConfigReq update user notification config request
type UpdateUserNotificationConfigReq struct {
NotificationConfig
UserID string `json:"-"`
}
// GetUserNotificationConfigResp get user notification config response
type GetUserNotificationConfigResp struct {
NotificationConfig
}

View File

@ -293,15 +293,6 @@ func (u *UserRePassWordRequest) Check() (errFields []*validator.FormErrorField,
return nil, nil
}
type UserNoticeSetRequest struct {
NoticeSwitch bool `json:"notice_switch"`
UserID string `json:"-"`
}
type UserNoticeSetResp struct {
NoticeSwitch bool `json:"notice_switch"`
}
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:"-"`

View File

@ -613,7 +613,8 @@ func (as *AnswerService) notificationAnswerTheQuestion(ctx context.Context,
log.Warnf("user %s not found", questionUserID)
return
}
if userInfo.NoticeStatus == schema.NoticeStatusOff || len(userInfo.EMail) == 0 {
if len(userInfo.EMail) == 0 ||
schema.NewNotificationConfig(userInfo.NoticeConfig).CheckEnable(constant.InboxChannel, constant.EmailChannel) {
return
}

View File

@ -493,7 +493,9 @@ func (cs *CommentService) notificationQuestionComment(ctx context.Context, quest
log.Warnf("user %s not found", questionUserID)
return
}
if receiverUserInfo.NoticeStatus == schema.NoticeStatusOff || len(receiverUserInfo.EMail) == 0 {
if len(receiverUserInfo.EMail) == 0 ||
schema.NewNotificationConfig(receiverUserInfo.NoticeConfig).
CheckEnable(constant.InboxChannel, constant.EmailChannel) {
return
}
@ -552,7 +554,9 @@ func (cs *CommentService) notificationAnswerComment(ctx context.Context,
log.Warnf("user %s not found", answerUserID)
return
}
if receiverUserInfo.NoticeStatus == schema.NoticeStatusOff || len(receiverUserInfo.EMail) == 0 {
if len(receiverUserInfo.EMail) == 0 ||
schema.NewNotificationConfig(receiverUserInfo.NoticeConfig).
CheckEnable(constant.InboxChannel, constant.EmailChannel) {
return
}

View File

@ -645,7 +645,9 @@ func (qs *QuestionService) notificationInviteUser(
log.Warnf("user %s not found", userID)
return
}
if userInfo.NoticeStatus == schema.NoticeStatusOff || len(userInfo.EMail) == 0 {
if len(userInfo.EMail) == 0 ||
schema.NewNotificationConfig(userInfo.NoticeConfig).
CheckEnable(constant.InboxChannel, constant.EmailChannel) {
return
}

View File

@ -27,6 +27,7 @@ type UserRepo interface {
UpdateLastLoginDate(ctx context.Context, userID string) (err error)
UpdateEmailStatus(ctx context.Context, userID string, emailStatus int) error
UpdateNoticeStatus(ctx context.Context, userID string, noticeStatus int) error
UpdateNoticeConfig(ctx context.Context, userID string, noticeConfig string) error
UpdateEmail(ctx context.Context, userID, email string) error
UpdateLanguage(ctx context.Context, userID, language string) error
UpdatePass(ctx context.Context, userID, pass string) error

View File

@ -28,8 +28,6 @@ import (
"golang.org/x/crypto/bcrypt"
)
// UserRepo user repository
// UserService user service
type UserService struct {
userCommonService *usercommon.UserCommon
@ -93,8 +91,7 @@ func (us *UserService) GetUserInfoByUserID(ctx context.Context, token, userID st
}
func (us *UserService) GetOtherUserInfoByUsername(ctx context.Context, username string) (
resp *schema.GetOtherUserInfoByUsernameResp, err error,
) {
resp *schema.GetOtherUserInfoByUsernameResp, err error) {
userInfo, exist, err := us.userRepo.GetByUsername(ctx, username)
if err != nil {
return nil, err
@ -345,14 +342,6 @@ func (us *UserService) formatUserInfoForUpdateInfo(
return userInfo
}
func (us *UserService) UserEmailHas(ctx context.Context, email string) (bool, error) {
_, has, err := us.userRepo.GetByEmail(ctx, email)
if err != nil {
return false, err
}
return has, nil
}
// UserUpdateInterface update user interface
func (us *UserService) UserUpdateInterface(ctx context.Context, req *schema.UpdateUserInterfaceRequest) (err error) {
if !translator.CheckLanguageIsValid(req.Language) {
@ -470,23 +459,31 @@ func (us *UserService) UserVerifyEmailSend(ctx context.Context, userID string) e
return nil
}
func (us *UserService) UserNoticeSet(ctx context.Context, userID string, noticeSwitch bool) (
resp *schema.UserNoticeSetResp, err error,
) {
userInfo, has, err := us.userRepo.GetByUserID(ctx, userID)
func (us *UserService) GetUserNotificationConfig(ctx context.Context, userID string) (
resp *schema.GetUserNotificationConfigResp, err error) {
userInfo, exist, err := us.userRepo.GetByUserID(ctx, userID)
if err != nil {
return nil, err
}
if !has {
if !exist {
return nil, errors.BadRequest(reason.UserNotFound)
}
if noticeSwitch {
userInfo.NoticeStatus = schema.NoticeStatusOn
} else {
userInfo.NoticeStatus = schema.NoticeStatusOff
resp = &schema.GetUserNotificationConfigResp{}
resp.FromJsonString(userInfo.NoticeConfig)
resp.Format()
return resp, nil
}
func (us *UserService) UpdateUserNotificationConfig(ctx context.Context, req *schema.UpdateUserNotificationConfigReq) (err error) {
_, exist, err := us.userRepo.GetByUserID(ctx, req.UserID)
if err != nil {
return err
}
err = us.userRepo.UpdateNoticeStatus(ctx, userInfo.ID, userInfo.NoticeStatus)
return &schema.UserNoticeSetResp{NoticeSwitch: noticeSwitch}, err
if !exist {
return errors.BadRequest(reason.UserNotFound)
}
req.NotificationConfig.Format()
return us.userRepo.UpdateNoticeConfig(ctx, req.UserID, req.NotificationConfig.ToJsonString())
}
func (us *UserService) UserVerifyEmail(ctx context.Context, req *schema.UserVerifyEmailReq) (resp *schema.UserLoginResp, err error) {