Files
backend/internal/errors/app_errors.go
lafay 736344f123
All checks were successful
Build Backend / build (push) Successful in 12m35s
Build Backend / build-docker (push) Successful in 1m2s
refactor(di): migrate from setter to constructor injection for logService
- Remove SetLogService methods from user, post, comment, and admin post services
- Add logService as constructor parameter to all dependent services
- Centralize call-related and message error definitions in app_errors.go
- Add ConversationID field to WSEventResponse for improved message tracking
- Simplify wire provider functions by removing manual setter calls
2026-03-28 07:03:21 +08:00

159 lines
9.1 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package errors
import (
"errors"
"fmt"
)
// AppError 统一的应用错误类型
type AppError struct {
Code string
Message string
Cause error
}
func (e *AppError) Error() string {
if e.Cause != nil {
return fmt.Sprintf("[%s] %s: %v", e.Code, e.Message, e.Cause)
}
return fmt.Sprintf("[%s] %s", e.Code, e.Message)
}
func (e *AppError) Unwrap() error {
return e.Cause
}
// 预定义错误
var (
// 通用错误
ErrNotFound = &AppError{Code: "NOT_FOUND", Message: "资源不存在"}
ErrUnauthorized = &AppError{Code: "UNAUTHORIZED", Message: "未授权"}
ErrForbidden = &AppError{Code: "FORBIDDEN", Message: "禁止访问"}
ErrBadRequest = &AppError{Code: "BAD_REQUEST", Message: "请求参数错误"}
ErrInternal = &AppError{Code: "INTERNAL_ERROR", Message: "内部服务器错误"}
// 用户相关错误
ErrUserNotFound = &AppError{Code: "USER_NOT_FOUND", Message: "用户不存在"}
ErrUserAlreadyExists = &AppError{Code: "USER_ALREADY_EXISTS", Message: "用户已存在"}
ErrInvalidCredentials = &AppError{Code: "INVALID_CREDENTIALS", Message: "用户名或密码错误"}
ErrInvalidUsername = &AppError{Code: "INVALID_USERNAME", Message: "无效的用户名"}
ErrInvalidEmail = &AppError{Code: "INVALID_EMAIL", Message: "无效的邮箱"}
ErrInvalidPhone = &AppError{Code: "INVALID_PHONE", Message: "无效的手机号"}
ErrWeakPassword = &AppError{Code: "WEAK_PASSWORD", Message: "密码强度不足"}
ErrUsernameExists = &AppError{Code: "USERNAME_EXISTS", Message: "用户名已存在"}
ErrEmailExists = &AppError{Code: "EMAIL_EXISTS", Message: "邮箱已存在"}
ErrPhoneExists = &AppError{Code: "PHONE_EXISTS", Message: "手机号已存在"}
ErrUserBanned = &AppError{Code: "USER_BANNED", Message: "用户已被封禁"}
ErrUserBlocked = &AppError{Code: "USER_BLOCKED", Message: "存在屏蔽关系"}
ErrInvalidOperation = &AppError{Code: "INVALID_OPERATION", Message: "无效操作"}
ErrEmailServiceUnavailable = &AppError{Code: "EMAIL_SERVICE_UNAVAILABLE", Message: "邮件服务不可用"}
ErrVerificationCodeTooFrequent = &AppError{Code: "VERIFICATION_CODE_TOO_FREQUENT", Message: "验证码发送过于频繁"}
ErrVerificationCodeInvalid = &AppError{Code: "VERIFICATION_CODE_INVALID", Message: "验证码无效"}
ErrVerificationCodeExpired = &AppError{Code: "VERIFICATION_CODE_EXPIRED", Message: "验证码已过期"}
ErrVerificationCodeUnavailable = &AppError{Code: "VERIFICATION_CODE_UNAVAILABLE", Message: "验证码存储不可用"}
ErrEmailAlreadyVerified = &AppError{Code: "EMAIL_ALREADY_VERIFIED", Message: "邮箱已验证"}
ErrEmailNotBound = &AppError{Code: "EMAIL_NOT_BOUND", Message: "邮箱未绑定"}
// 帖子相关错误
ErrPostNotFound = &AppError{Code: "POST_NOT_FOUND", Message: "帖子不存在"}
ErrPostDeleted = &AppError{Code: "POST_DELETED", Message: "帖子已删除"}
// 群组相关错误
ErrGroupNotFound = &AppError{Code: "GROUP_NOT_FOUND", Message: "群组不存在"}
ErrNotGroupMember = &AppError{Code: "NOT_GROUP_MEMBER", Message: "不是群组成员"}
ErrAlreadyGroupMember = &AppError{Code: "ALREADY_GROUP_MEMBER", Message: "已是群组成员"}
ErrNotGroupAdmin = &AppError{Code: "NOT_GROUP_ADMIN", Message: "不是群管理员"}
ErrNotGroupOwner = &AppError{Code: "NOT_GROUP_OWNER", Message: "不是群主"}
ErrGroupFull = &AppError{Code: "GROUP_FULL", Message: "群已满"}
ErrCannotRemoveOwner = &AppError{Code: "CANNOT_REMOVE_OWNER", Message: "不能移除群主"}
ErrCannotMuteOwner = &AppError{Code: "CANNOT_MUTE_OWNER", Message: "不能禁言群主"}
ErrMuted = &AppError{Code: "MUTED", Message: "你已被禁言"}
ErrMuteAllEnabled = &AppError{Code: "MUTE_ALL_ENABLED", Message: "全员禁言中"}
ErrCannotJoin = &AppError{Code: "CANNOT_JOIN", Message: "该群不允许加入"}
ErrJoinRequestPending = &AppError{Code: "JOIN_REQUEST_PENDING", Message: "加群申请已提交"}
ErrGroupRequestNotFound = &AppError{Code: "GROUP_REQUEST_NOT_FOUND", Message: "加群请求不存在"}
ErrGroupRequestHandled = &AppError{Code: "GROUP_REQUEST_HANDLED", Message: "该加群请求已处理"}
ErrNotRequestTarget = &AppError{Code: "NOT_REQUEST_TARGET", Message: "不是邀请目标用户"}
ErrNoEligibleInvitee = &AppError{Code: "NO_ELIGIBLE_INVITEE", Message: "没有可邀请的用户"}
ErrNotMutualFollow = &AppError{Code: "NOT_MUTUAL_FOLLOW", Message: "仅支持邀请互相关注用户"}
ErrInviteNotAccepted = &AppError{Code: "INVITE_NOT_ACCEPTED", Message: "被邀请人尚未同意邀请,无法审批"}
// 表情包相关错误
ErrStickerAlreadyExists = &AppError{Code: "STICKER_ALREADY_EXISTS", Message: "表情包已存在"}
ErrInvalidStickerURL = &AppError{Code: "INVALID_STICKER_URL", Message: "无效的表情包URL"}
// 日程相关错误
ErrInvalidSchedulePayload = &AppError{Code: "INVALID_SCHEDULE_PAYLOAD", Message: "无效的日程数据"}
ErrScheduleCourseNotFound = &AppError{Code: "SCHEDULE_COURSE_NOT_FOUND", Message: "日程课程不存在"}
ErrScheduleForbidden = &AppError{Code: "SCHEDULE_FORBIDDEN", Message: "禁止的日程操作"}
ErrScheduleColorDuplicated = &AppError{Code: "SCHEDULE_COLOR_DUPLICATED", Message: "课程颜色已被使用"}
// 通知相关错误
ErrUnauthorizedNotification = &AppError{Code: "UNAUTHORIZED_NOTIFICATION", Message: "无权删除此通知"}
// Casbin 相关错误
ErrPermissionDenied = &AppError{Code: "PERMISSION_DENIED", Message: "权限不足"}
ErrRoleNotFound = &AppError{Code: "ROLE_NOT_FOUND", Message: "角色不存在"}
ErrRoleAlreadyAssigned = &AppError{Code: "ROLE_ALREADY_ASSIGNED", Message: "用户已拥有该角色"}
ErrRoleNotAssigned = &AppError{Code: "ROLE_NOT_ASSIGNED", Message: "用户未拥有该角色"}
ErrCannotModifyOwnRole = &AppError{Code: "CANNOT_MODIFY_OWN_ROLE", Message: "不能修改自己的角色"}
ErrCannotModifySuperAdmin = &AppError{Code: "CANNOT_MODIFY_SUPER_ADMIN", Message: "不能修改超级管理员角色"}
ErrCasbinInternal = &AppError{Code: "CASBIN_INTERNAL_ERROR", Message: "权限系统内部错误"}
// 通话相关错误
ErrCallNotFound = &AppError{Code: "CALL_NOT_FOUND", Message: "通话不存在"}
ErrCallNotActive = &AppError{Code: "CALL_NOT_ACTIVE", Message: "通话未激活"}
ErrCallInProgress = &AppError{Code: "CALL_IN_PROGRESS", Message: "用户之间已有通话"}
ErrNotCallParticipant = &AppError{Code: "NOT_CALL_PARTICIPANT", Message: "不是通话参与者"}
ErrInvalidCallState = &AppError{Code: "INVALID_CALL_STATE", Message: "通话状态无效"}
ErrCalleeOffline = &AppError{Code: "CALLEE_OFFLINE", Message: "对方不在线"}
ErrCallAlreadyAnswered = &AppError{Code: "CALL_ALREADY_ANSWERED", Message: "通话已在其他设备应答"}
// 消息相关错误
ErrConversationNotFound = &AppError{Code: "CONVERSATION_NOT_FOUND", Message: "会话不存在或无权限"}
ErrNotConversationMember = &AppError{Code: "NOT_CONVERSATION_MEMBER", Message: "不是会话参与者"}
ErrMessageNotFound = &AppError{Code: "MESSAGE_NOT_FOUND", Message: "消息不存在"}
ErrMessageAlreadyRecalled = &AppError{Code: "MESSAGE_ALREADY_RECALLED", Message: "消息已撤回"}
ErrMessageRecallTimeout = &AppError{Code: "MESSAGE_RECALL_TIMEOUT", Message: "消息撤回超时2分钟"}
ErrCannotSendMessage = &AppError{Code: "CANNOT_SEND_MESSAGE", Message: "无法发送消息"}
ErrCannotSendImage = &AppError{Code: "CANNOT_SEND_IMAGE", Message: "对方未关注你,暂不支持发送图片"}
ErrMessageLimitReached = &AppError{Code: "MESSAGE_LIMIT_REACHED", Message: "对方未关注你前,仅允许发送一条消息"}
ErrQRCodeSessionExpired = &AppError{Code: "QRCODE_SESSION_EXPIRED", Message: "二维码已过期"}
ErrQRCodeAlreadyScanned = &AppError{Code: "QRCODE_ALREADY_SCANNED", Message: "二维码已被扫描"}
ErrQRCodeInvalidStatus = &AppError{Code: "QRCODE_INVALID_STATUS", Message: "二维码状态无效"}
ErrPushNotImplemented = &AppError{Code: "PUSH_NOT_IMPLEMENTED", Message: "推送服务未实现"}
ErrPushQueueFull = &AppError{Code: "PUSH_QUEUE_FULL", Message: "推送队列已满"}
ErrUserOffline = &AppError{Code: "USER_OFFLINE", Message: "用户不在线"}
// 学习资料相关错误
ErrSubjectHasMaterials = &AppError{Code: "SUBJECT_HAS_MATERIALS", Message: "学科下存在资料,无法删除"}
)
// Wrap 包装错误
func Wrap(err error, appErr *AppError) *AppError {
return &AppError{
Code: appErr.Code,
Message: appErr.Message,
Cause: err,
}
}
// New 创建新错误
func New(code, message string) *AppError {
return &AppError{Code: code, Message: message}
}
// Is 判断是否为特定错误
func Is(err, target error) bool {
return errors.Is(err, target)
}
// As 将错误转换为 AppError
func As(err error) (*AppError, bool) {
var appErr *AppError
if errors.As(err, &appErr) {
return appErr, true
}
return nil, false
}