diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..844477d --- /dev/null +++ b/.env.example @@ -0,0 +1,35 @@ +# Captcha settings +CAPTCHA_DEV_PASSCODE=114514 +CAPTCHA_TYPE=turnstile +CAPTCHA_SITE_SECRET=89dh29djha28dh +CAPTCHA_SECRET_KEY=89dh28912dh1289dh128d9d + +# Database settings +DB_DRIVER=sqlite +DB_NAME=blog +DB_PATH=./data/data.db +DB_HOST=postgres +DB_PORT=5432 +DB_USER=blog +DB_PASSWORD=blog + +# Email settings +EMAIL_ENABLED=false +EMAIL_USERNAME=xxx@bbb.com +EMAIL_PASSWORD=xxx +EMAIL_ADDRESS=xxx@bbb.com +EMAIL_HOST=smtp.xxx.com +EMAIL_PORT=465 +EMAIL_SSL=true + +# App settings +MAX_REQUEST_BODY_SIZE=1000000 +MODE=prod +PORT=8888 +PASSWORD_SALT=1234567890 +JWT_SECRET=1234567890 +TOKEN_DURATION=3600 +REFRESH_TOKEN_DURATION=604800 +REFRESH_TOKEN_DURATION_WITH_REMEMBER=1209600 + + diff --git a/internal/controller/v1/user.go b/internal/controller/v1/user.go index 3cea327..a36b6e8 100644 --- a/internal/controller/v1/user.go +++ b/internal/controller/v1/user.go @@ -101,7 +101,7 @@ func (u *userType) VerifyEmail(ctx context.Context, c *app.RequestContext) { } func (u *userType) setTokenCookie(c *app.RequestContext, token, refreshToken string) { - c.SetCookie("token", token, utils.Env.GetenvAsInt(constant.EnvKeyTokenDuration, constant.EnvKeyTokenDurationDefault), "/", "", protocol.CookieSameSiteLaxMode, true, true) + c.SetCookie("token", token, utils.Env.GetAsInt(constant.EnvKeyTokenDuration, constant.EnvKeyTokenDurationDefault), "/", "", protocol.CookieSameSiteLaxMode, true, true) c.SetCookie("refresh_token", refreshToken, -1, "/", "", protocol.CookieSameSiteLaxMode, true, true) } diff --git a/internal/repo/init.go b/internal/repo/init.go index 42d31e8..1487618 100644 --- a/internal/repo/init.go +++ b/internal/repo/init.go @@ -38,7 +38,7 @@ func loadDBConfig() DBConfig { Driver: utils.Env.Get("DB_DRIVER", "sqlite"), Path: utils.Env.Get("DB_PATH", "./data/data.db"), Host: utils.Env.Get("DB_HOST", "postgres"), - Port: utils.Env.GetenvAsInt("DB_PORT", 5432), + Port: utils.Env.GetAsInt("DB_PORT", 5432), User: utils.Env.Get("DB_USER", "blog"), Password: utils.Env.Get("DB_PASSWORD", "blog"), DBName: utils.Env.Get("DB_NAME", "blog"), diff --git a/internal/router/router.go b/internal/router/router.go index a981426..e4bb7b4 100644 --- a/internal/router/router.go +++ b/internal/router/router.go @@ -23,7 +23,7 @@ func Run() error { func init() { h = server.New( server.WithHostPorts(":"+utils.Env.Get("PORT", "8888")), - server.WithMaxRequestBodySize(utils.Env.GetenvAsInt("MAX_REQUEST_BODY_SIZE", 1048576000)), // 1000MiB + server.WithMaxRequestBodySize(utils.Env.GetAsInt("MAX_REQUEST_BODY_SIZE", 1048576000)), // 1000MiB ) apiv1.RegisterRoutes(h) } diff --git a/internal/service/user.go b/internal/service/user.go index e49142e..6f6dc63 100644 --- a/internal/service/user.go +++ b/internal/service/user.go @@ -36,13 +36,13 @@ func (s *userService) UserLogin(req *dto.UserLoginReq) (*dto.UserLoginResp, erro } if utils.Password.VerifyPassword(req.Password, user.Password, utils.Env.Get(constant.EnvKeyPasswordSalt, "default_salt")) { - token := utils.Jwt.NewClaims(user.ID, "", false, time.Duration(utils.Env.GetenvAsInt(constant.EnvKeyTokenDuration, 24)*int(time.Hour))) + token := utils.Jwt.NewClaims(user.ID, "", false, time.Duration(utils.Env.GetAsInt(constant.EnvKeyTokenDuration, 24)*int(time.Hour))) tokenString, err := token.ToString() if err != nil { return nil, errs.ErrInternalServer } - refreshToken := utils.Jwt.NewClaims(user.ID, utils.Strings.GenerateRandomString(64), true, time.Duration(utils.Env.GetenvAsInt(constant.EnvKeyRefreshTokenDuration, 30)*int(time.Hour))) + refreshToken := utils.Jwt.NewClaims(user.ID, utils.Strings.GenerateRandomString(64), true, time.Duration(utils.Env.GetAsInt(constant.EnvKeyRefreshTokenDuration, 30)*int(time.Hour))) refreshTokenString, err := refreshToken.ToString() if err != nil { return nil, errs.ErrInternalServer @@ -65,10 +65,15 @@ func (s *userService) UserLogin(req *dto.UserLoginReq) (*dto.UserLoginResp, erro func (s *userService) UserRegister(req *dto.UserRegisterReq) (*dto.UserRegisterResp, error) { // 验证邮箱验证码 - kv := utils.KV.GetInstance() - verificationCode, ok := kv.Get(constant.KVKeyEmailVerificationCode + ":" + req.Email) - if !ok || verificationCode != req.VerificationCode { - return nil, errs.ErrInvalidCredentials + if !utils.Env.GetAsBool("ENABLE_REGISTER", true) { + return nil, errs.ErrForbidden + } + if utils.Env.GetAsBool("ENABLE_EMAIL_VERIFICATION", true) { + kv := utils.KV.GetInstance() + verificationCode, ok := kv.Get(constant.KVKeyEmailVerificationCode + ":" + req.Email) + if !ok || verificationCode != req.VerificationCode { + return nil, errs.ErrInvalidCredentials + } } // 检查用户名或邮箱是否已存在 existingUser, err := repo.User.GetByUsernameOrEmail(req.Username) @@ -79,7 +84,6 @@ func (s *userService) UserRegister(req *dto.UserRegisterReq) (*dto.UserRegisterR return nil, errs.New(http.StatusConflict, "Username or email already exists", nil) } // 创建新用户 - newUser := &model.User{ Username: req.Username, Nickname: req.Nickname, @@ -93,12 +97,12 @@ func (s *userService) UserRegister(req *dto.UserRegisterReq) (*dto.UserRegisterR return nil, errs.ErrInternalServer } // 生成访问令牌和刷新令牌 - token := utils.Jwt.NewClaims(newUser.ID, "", false, time.Duration(utils.Env.GetenvAsInt(constant.EnvKeyTokenDuration, 24)*int(time.Hour))) + token := utils.Jwt.NewClaims(newUser.ID, "", false, time.Duration(utils.Env.GetAsInt(constant.EnvKeyTokenDuration, 24)*int(time.Hour))) tokenString, err := token.ToString() if err != nil { return nil, errs.ErrInternalServer } - refreshToken := utils.Jwt.NewClaims(newUser.ID, utils.Strings.GenerateRandomString(64), true, time.Duration(utils.Env.GetenvAsInt(constant.EnvKeyRefreshTokenDuration, 30)*int(time.Hour))) + refreshToken := utils.Jwt.NewClaims(newUser.ID, utils.Strings.GenerateRandomString(64), true, time.Duration(utils.Env.GetAsInt(constant.EnvKeyRefreshTokenDuration, 30)*int(time.Hour))) refreshTokenString, err := refreshToken.ToString() if err != nil { return nil, errs.ErrInternalServer diff --git a/pkg/utils/email.go b/pkg/utils/email.go index 1b1632c..0145cd7 100644 --- a/pkg/utils/email.go +++ b/pkg/utils/email.go @@ -73,12 +73,12 @@ func (e *emailUtils) SendEmail(emailConfig *EmailConfig, target, subject, conten func (e *emailUtils) GetEmailConfigFromEnv() *EmailConfig { return &EmailConfig{ - Enable: Env.GetenvAsBool("EMAIL_ENABLE", false), + Enable: Env.GetAsBool("EMAIL_ENABLE", false), Username: Env.Get("EMAIL_USERNAME", ""), Address: Env.Get("EMAIL_ADDRESS", ""), Host: Env.Get("EMAIL_HOST", "smtp.example.com"), - Port: Env.GetenvAsInt("EMAIL_PORT", 587), + Port: Env.GetAsInt("EMAIL_PORT", 587), Password: Env.Get("EMAIL_PASSWORD", ""), - SSL: Env.GetenvAsBool("EMAIL_SSL", true), + SSL: Env.GetAsBool("EMAIL_SSL", true), } } diff --git a/pkg/utils/env.go b/pkg/utils/env.go index 3fbba78..da3d6b8 100644 --- a/pkg/utils/env.go +++ b/pkg/utils/env.go @@ -30,7 +30,7 @@ func (e *envUtils) Get(key string, defaultValue ...string) string { return value } -func (e *envUtils) GetenvAsInt(key string, defaultValue ...int) int { +func (e *envUtils) GetAsInt(key string, defaultValue ...int) int { value := os.Getenv(key) if value == "" && len(defaultValue) > 0 { return defaultValue[0] @@ -42,7 +42,7 @@ func (e *envUtils) GetenvAsInt(key string, defaultValue ...int) int { return intValue } -func (e *envUtils) GetenvAsBool(key string, defaultValue ...bool) bool { +func (e *envUtils) GetAsBool(key string, defaultValue ...bool) bool { value := os.Getenv(key) if value == "" && len(defaultValue) > 0 { return defaultValue[0]