check whether api token is enabled when using an api token

This commit is contained in:
MaysWind
2025-11-03 22:52:15 +08:00
parent b0e01d36ab
commit 03c342f6f6
26 changed files with 162 additions and 143 deletions

View File

@@ -176,7 +176,7 @@ func startWebServer(c *core.CliContext) error {
if config.AvatarProvider == core.USER_AVATAR_PROVIDER_INTERNAL {
avatarRoute := router.Group("/avatar")
avatarRoute.Use(bindMiddleware(middlewares.JWTAuthorizationByQueryString))
avatarRoute.Use(bindMiddleware(middlewares.JWTAuthorizationByQueryString(config)))
{
avatarRoute.GET("/:fileName", bindImage(api.Users.UserGetAvatarHandler))
}
@@ -184,7 +184,7 @@ func startWebServer(c *core.CliContext) error {
if config.EnableTransactionPictures {
pictureRoute := router.Group("/pictures")
pictureRoute.Use(bindMiddleware(middlewares.JWTAuthorizationByQueryString))
pictureRoute.Use(bindMiddleware(middlewares.JWTAuthorizationByQueryString(config)))
{
pictureRoute.GET("/:fileName", bindImage(api.TransactionPictures.TransactionPictureGetHandler))
}
@@ -193,7 +193,7 @@ func startWebServer(c *core.CliContext) error {
router.GET("/healthz.json", bindApi(api.Healths.HealthStatusHandler))
proxyRoute := router.Group("/proxy")
proxyRoute.Use(bindMiddleware(middlewares.JWTAuthorizationByQueryString))
proxyRoute.Use(bindMiddleware(middlewares.JWTAuthorizationByQueryString(config)))
{
if config.EnableMapDataFetchProxy {
if config.MapProvider == settings.OpenStreetMapProvider ||
@@ -217,7 +217,7 @@ func startWebServer(c *core.CliContext) error {
if config.MapProvider == settings.AmapProvider && config.AmapSecurityVerificationMethod == settings.AmapSecurityVerificationInternalProxyMethod {
amapApiProxyRoute := router.Group("/_AMapService")
amapApiProxyRoute.Use(bindMiddleware(middlewares.JWTAuthorizationByCookie))
amapApiProxyRoute.Use(bindMiddleware(middlewares.JWTAuthorizationByCookie(config)))
{
amapApiProxyRoute.GET("/*action", bindProxy(api.AmapApis.AmapApiProxyHandler))
}
@@ -235,7 +235,7 @@ func startWebServer(c *core.CliContext) error {
mcpRoute.Use(bindMiddleware(middlewares.RequestId(config)))
mcpRoute.Use(bindMiddleware(middlewares.RequestLog))
mcpRoute.Use(bindMiddleware(middlewares.MCPServerIpLimit(config)))
mcpRoute.Use(bindMiddleware(middlewares.JWTMCPAuthorization))
mcpRoute.Use(bindMiddleware(middlewares.JWTMCPAuthorization(config)))
{
mcpRoute.POST("", bindJSONRPCApi(map[string]core.JSONRPCApiHandlerFunc{
"initialize": api.ModelContextProtocols.InitializeHandler,
@@ -272,7 +272,7 @@ func startWebServer(c *core.CliContext) error {
if config.EnableInternalAuth && config.EnableTwoFactor {
twoFactorRoute := apiRoute.Group("/2fa")
twoFactorRoute.Use(bindMiddleware(middlewares.JWTTwoFactorAuthorization))
twoFactorRoute.Use(bindMiddleware(middlewares.JWTTwoFactorAuthorization(config)))
{
twoFactorRoute.POST("/authorize.json", bindApiWithTokenUpdate(api.Authorizations.TwoFactorAuthorizeHandler, config))
twoFactorRoute.POST("/recovery.json", bindApiWithTokenUpdate(api.Authorizations.TwoFactorAuthorizeByRecoveryCodeHandler, config))
@@ -281,7 +281,7 @@ func startWebServer(c *core.CliContext) error {
if config.EnableOAuth2Login {
oauth2Route := apiRoute.Group("/oauth2")
oauth2Route.Use(bindMiddleware(middlewares.JWTOAuth2CallbackAuthorization))
oauth2Route.Use(bindMiddleware(middlewares.JWTOAuth2CallbackAuthorization(config)))
{
oauth2Route.POST("/authorize.json", bindApiWithTokenUpdate(api.Authorizations.OAuth2CallbackAuthorizeHandler, config))
}
@@ -295,7 +295,7 @@ func startWebServer(c *core.CliContext) error {
apiRoute.POST("/verify_email/resend.json", bindApi(api.Users.UserSendVerifyEmailByUnloginUserHandler))
emailVerifyRoute := apiRoute.Group("/verify_email")
emailVerifyRoute.Use(bindMiddleware(middlewares.JWTEmailVerifyAuthorization))
emailVerifyRoute.Use(bindMiddleware(middlewares.JWTEmailVerifyAuthorization(config)))
{
emailVerifyRoute.POST("/by_token.json", bindApi(api.Users.UserEmailVerifyHandler))
}
@@ -305,7 +305,7 @@ func startWebServer(c *core.CliContext) error {
apiRoute.POST("/forget_password/request.json", bindApi(api.ForgetPasswords.UserForgetPasswordRequestHandler))
resetPasswordRoute := apiRoute.Group("/forget_password/reset")
resetPasswordRoute.Use(bindMiddleware(middlewares.JWTResetPasswordAuthorization))
resetPasswordRoute.Use(bindMiddleware(middlewares.JWTResetPasswordAuthorization(config)))
{
resetPasswordRoute.POST("/by_token.json", bindApi(api.ForgetPasswords.UserResetPasswordHandler))
}
@@ -314,7 +314,7 @@ func startWebServer(c *core.CliContext) error {
apiRoute.GET("/logout.json", bindApiWithTokenUpdate(api.Tokens.TokenRevokeCurrentHandler, config))
apiV1Route := apiRoute.Group("/v1")
apiV1Route.Use(bindMiddleware(middlewares.JWTAuthorization))
apiV1Route.Use(bindMiddleware(middlewares.JWTAuthorization(config)))
{
// Tokens
apiV1Route.GET("/tokens/list.json", bindApi(api.Tokens.TokenListHandler))

View File

@@ -264,7 +264,7 @@ email_verify_token_expired_time = 3600
password_reset_token_expired_time = 3600
# Set to true to enable API token generation
enable_generate_api_token = false
enable_api_token = false
# Maximum count of password / token check failures (0 - 4294967295) per IP per minute (use the above duplicate checker), default is 5, set to 0 to disable
max_failures_per_ip_per_minute = 5

View File

@@ -39,7 +39,7 @@ func (a *ServerSettingsApi) ServerSettingsJavascriptHandler(c *core.WebContext)
a.appendBooleanSetting(builder, "o", config.EnableOAuth2Login)
a.appendBooleanSetting(builder, "r", config.EnableInternalAuth && config.EnableUserRegister)
a.appendBooleanSetting(builder, "f", config.EnableInternalAuth && config.EnableUserForgetPassword)
a.appendBooleanSetting(builder, "t", config.EnableGenerateAPIToken)
a.appendBooleanSetting(builder, "t", config.EnableAPIToken)
a.appendBooleanSetting(builder, "v", config.EnableUserVerifyEmail)
a.appendBooleanSetting(builder, "p", config.EnableTransactionPictures)
a.appendBooleanSetting(builder, "s", config.EnableScheduledTransaction)

View File

@@ -85,8 +85,8 @@ func (a *TokensApi) TokenListHandler(c *core.WebContext) (any, *errs.Error) {
// TokenGenerateAPIHandler generates a new API token for current user
func (a *TokensApi) TokenGenerateAPIHandler(c *core.WebContext) (any, *errs.Error) {
if !a.CurrentConfig().EnableGenerateAPIToken {
return nil, errs.ErrNotAllowedToGenerateAPIToken
if !a.CurrentConfig().EnableAPIToken {
return nil, errs.ErrAPITokenNotEnabled
}
var generateAPITokenReq models.TokenGenerateAPIRequest

View File

@@ -422,8 +422,8 @@ func (l *UserDataCli) CreateNewUserToken(c *core.CliContext, username string, to
var tokenRecord *models.TokenRecord
if tokenType == "api" {
if !l.CurrentConfig().EnableGenerateAPIToken {
return nil, "", errs.ErrNotAllowedToGenerateAPIToken
if !l.CurrentConfig().EnableAPIToken {
return nil, "", errs.ErrAPITokenNotEnabled
}
if user.FeatureRestriction.Contains(core.USER_FEATURE_RESTRICTION_TYPE_GENERATE_API_TOKEN) {

View File

@@ -21,5 +21,5 @@ var (
ErrTokenIsEmpty = NewNormalError(NormalSubcategoryToken, 12, http.StatusBadRequest, "token is empty")
ErrEmailVerifyTokenIsInvalidOrExpired = NewNormalError(NormalSubcategoryToken, 13, http.StatusBadRequest, "email verify token is invalid or expired")
ErrPasswordResetTokenIsInvalidOrExpired = NewNormalError(NormalSubcategoryToken, 14, http.StatusBadRequest, "password reset token is invalid or expired")
ErrNotAllowedToGenerateAPIToken = NewNormalError(NormalSubcategoryToken, 15, http.StatusForbidden, "not allowed to generate api token")
ErrAPITokenNotEnabled = NewNormalError(NormalSubcategoryToken, 15, http.StatusForbidden, "api token is not enabled")
)

View File

@@ -7,6 +7,7 @@ import (
"github.com/mayswind/ezbookkeeping/pkg/errs"
"github.com/mayswind/ezbookkeeping/pkg/log"
"github.com/mayswind/ezbookkeeping/pkg/services"
"github.com/mayswind/ezbookkeeping/pkg/settings"
"github.com/mayswind/ezbookkeeping/pkg/utils"
)
@@ -21,143 +22,161 @@ const (
)
// JWTAuthorization verifies whether current request is valid by jwt token in header
func JWTAuthorization(c *core.WebContext) {
jwtAuthorization(c, TOKEN_SOURCE_TYPE_HEADER)
func JWTAuthorization(config *settings.Config) core.MiddlewareHandlerFunc {
return jwtAuthorization(config, TOKEN_SOURCE_TYPE_HEADER)
}
// JWTAuthorizationByQueryString verifies whether current request is valid by jwt token in query string
func JWTAuthorizationByQueryString(c *core.WebContext) {
jwtAuthorization(c, TOKEN_SOURCE_TYPE_ARGUMENT)
func JWTAuthorizationByQueryString(config *settings.Config) core.MiddlewareHandlerFunc {
return jwtAuthorization(config, TOKEN_SOURCE_TYPE_ARGUMENT)
}
// JWTAuthorizationByCookie verifies whether current request is valid by jwt token in cookie
func JWTAuthorizationByCookie(c *core.WebContext) {
jwtAuthorization(c, TOKEN_SOURCE_TYPE_COOKIE)
func JWTAuthorizationByCookie(config *settings.Config) core.MiddlewareHandlerFunc {
return jwtAuthorization(config, TOKEN_SOURCE_TYPE_COOKIE)
}
// JWTTwoFactorAuthorization verifies whether current request is valid by 2fa passcode
func JWTTwoFactorAuthorization(c *core.WebContext) {
claims, tokenContext, err := getTokenClaims(c, TOKEN_SOURCE_TYPE_HEADER)
func JWTTwoFactorAuthorization(config *settings.Config) core.MiddlewareHandlerFunc {
return func(c *core.WebContext) {
claims, tokenContext, err := getTokenClaims(c, TOKEN_SOURCE_TYPE_HEADER)
if err != nil {
utils.PrintJsonErrorResult(c, err)
return
if err != nil {
utils.PrintJsonErrorResult(c, err)
return
}
if claims.Type != core.USER_TOKEN_TYPE_REQUIRE_2FA {
log.Warnf(c, "[authorization.JWTTwoFactorAuthorization] user \"uid:%d\" token is not need two-factor authorization", claims.Uid)
utils.PrintJsonErrorResult(c, errs.ErrCurrentTokenNotRequire2FA)
return
}
c.SetTokenClaims(claims)
c.SetTokenContext(tokenContext)
c.Next()
}
if claims.Type != core.USER_TOKEN_TYPE_REQUIRE_2FA {
log.Warnf(c, "[authorization.JWTTwoFactorAuthorization] user \"uid:%d\" token is not need two-factor authorization", claims.Uid)
utils.PrintJsonErrorResult(c, errs.ErrCurrentTokenNotRequire2FA)
return
}
c.SetTokenClaims(claims)
c.SetTokenContext(tokenContext)
c.Next()
}
// JWTEmailVerifyAuthorization verifies whether current request is email verification
func JWTEmailVerifyAuthorization(c *core.WebContext) {
claims, tokenContext, err := getTokenClaims(c, TOKEN_SOURCE_TYPE_ARGUMENT)
func JWTEmailVerifyAuthorization(config *settings.Config) core.MiddlewareHandlerFunc {
return func(c *core.WebContext) {
claims, tokenContext, err := getTokenClaims(c, TOKEN_SOURCE_TYPE_ARGUMENT)
if err != nil {
utils.PrintJsonErrorResult(c, errs.ErrEmailVerifyTokenIsInvalidOrExpired)
return
if err != nil {
utils.PrintJsonErrorResult(c, errs.ErrEmailVerifyTokenIsInvalidOrExpired)
return
}
if claims.Type != core.USER_TOKEN_TYPE_EMAIL_VERIFY {
log.Warnf(c, "[authorization.JWTEmailVerifyAuthorization] user \"uid:%d\" token is not for email verification", claims.Uid)
utils.PrintJsonErrorResult(c, errs.ErrCurrentInvalidToken)
return
}
c.SetTokenClaims(claims)
c.SetTokenContext(tokenContext)
c.Next()
}
if claims.Type != core.USER_TOKEN_TYPE_EMAIL_VERIFY {
log.Warnf(c, "[authorization.JWTEmailVerifyAuthorization] user \"uid:%d\" token is not for email verification", claims.Uid)
utils.PrintJsonErrorResult(c, errs.ErrCurrentInvalidToken)
return
}
c.SetTokenClaims(claims)
c.SetTokenContext(tokenContext)
c.Next()
}
// JWTResetPasswordAuthorization verifies whether current request is password reset
func JWTResetPasswordAuthorization(c *core.WebContext) {
claims, tokenContext, err := getTokenClaims(c, TOKEN_SOURCE_TYPE_ARGUMENT)
func JWTResetPasswordAuthorization(config *settings.Config) core.MiddlewareHandlerFunc {
return func(c *core.WebContext) {
claims, tokenContext, err := getTokenClaims(c, TOKEN_SOURCE_TYPE_ARGUMENT)
if err != nil {
utils.PrintJsonErrorResult(c, errs.ErrPasswordResetTokenIsInvalidOrExpired)
return
if err != nil {
utils.PrintJsonErrorResult(c, errs.ErrPasswordResetTokenIsInvalidOrExpired)
return
}
if claims.Type != core.USER_TOKEN_TYPE_PASSWORD_RESET {
log.Warnf(c, "[authorization.JWTResetPasswordAuthorization] user \"uid:%d\" token is not for password request", claims.Uid)
utils.PrintJsonErrorResult(c, errs.ErrCurrentInvalidToken)
return
}
c.SetTokenClaims(claims)
c.SetTokenContext(tokenContext)
c.Next()
}
if claims.Type != core.USER_TOKEN_TYPE_PASSWORD_RESET {
log.Warnf(c, "[authorization.JWTResetPasswordAuthorization] user \"uid:%d\" token is not for password request", claims.Uid)
utils.PrintJsonErrorResult(c, errs.ErrCurrentInvalidToken)
return
}
c.SetTokenClaims(claims)
c.SetTokenContext(tokenContext)
c.Next()
}
// JWTMCPAuthorization verifies whether current request is valid by jwt mcp token in header
func JWTMCPAuthorization(c *core.WebContext) {
claims, tokenContext, err := getTokenClaims(c, TOKEN_SOURCE_TYPE_HEADER)
func JWTMCPAuthorization(config *settings.Config) core.MiddlewareHandlerFunc {
return func(c *core.WebContext) {
claims, tokenContext, err := getTokenClaims(c, TOKEN_SOURCE_TYPE_HEADER)
if err != nil {
utils.PrintJsonErrorResult(c, err)
return
if err != nil {
utils.PrintJsonErrorResult(c, err)
return
}
if claims.Type != core.USER_TOKEN_TYPE_MCP {
log.Warnf(c, "[authorization.jwtAuthorization] user \"uid:%d\" token type (%d) is not mcp token", claims.Uid, claims.Type)
utils.PrintJsonErrorResult(c, errs.ErrCurrentInvalidTokenType)
return
}
c.SetTokenClaims(claims)
c.SetTokenContext(tokenContext)
c.Next()
}
if claims.Type != core.USER_TOKEN_TYPE_MCP {
log.Warnf(c, "[authorization.jwtAuthorization] user \"uid:%d\" token type (%d) is not mcp token", claims.Uid, claims.Type)
utils.PrintJsonErrorResult(c, errs.ErrCurrentInvalidTokenType)
return
}
c.SetTokenClaims(claims)
c.SetTokenContext(tokenContext)
c.Next()
}
// JWTOAuth2CallbackAuthorization verifies whether current request is OAuth 2.0 callback
func JWTOAuth2CallbackAuthorization(c *core.WebContext) {
claims, tokenContext, err := getTokenClaims(c, TOKEN_SOURCE_TYPE_HEADER)
func JWTOAuth2CallbackAuthorization(config *settings.Config) core.MiddlewareHandlerFunc {
return func(c *core.WebContext) {
claims, tokenContext, err := getTokenClaims(c, TOKEN_SOURCE_TYPE_HEADER)
if err != nil {
utils.PrintJsonErrorResult(c, errs.ErrTokenExpired)
return
if err != nil {
utils.PrintJsonErrorResult(c, errs.ErrTokenExpired)
return
}
if claims.Type != core.USER_TOKEN_TYPE_OAUTH2_CALLBACK && claims.Type != core.USER_TOKEN_TYPE_OAUTH2_CALLBACK_REQUIRE_VERIFY {
log.Warnf(c, "[authorization.JWTOAuth2CallbackAuthorization] user \"uid:%d\" token is not for oauth 2.0 callback request", claims.Uid)
utils.PrintJsonErrorResult(c, errs.ErrCurrentInvalidToken)
return
}
c.SetTokenClaims(claims)
c.SetTokenContext(tokenContext)
c.Next()
}
if claims.Type != core.USER_TOKEN_TYPE_OAUTH2_CALLBACK && claims.Type != core.USER_TOKEN_TYPE_OAUTH2_CALLBACK_REQUIRE_VERIFY {
log.Warnf(c, "[authorization.JWTOAuth2CallbackAuthorization] user \"uid:%d\" token is not for oauth 2.0 callback request", claims.Uid)
utils.PrintJsonErrorResult(c, errs.ErrCurrentInvalidToken)
return
}
c.SetTokenClaims(claims)
c.SetTokenContext(tokenContext)
c.Next()
}
func jwtAuthorization(c *core.WebContext, source TokenSourceType) {
claims, tokenContext, err := getTokenClaims(c, source)
func jwtAuthorization(config *settings.Config, source TokenSourceType) core.MiddlewareHandlerFunc {
return func(c *core.WebContext) {
claims, tokenContext, err := getTokenClaims(c, source)
if err != nil {
utils.PrintJsonErrorResult(c, err)
return
if err != nil {
utils.PrintJsonErrorResult(c, err)
return
}
if claims.Type == core.USER_TOKEN_TYPE_REQUIRE_2FA {
log.Warnf(c, "[authorization.jwtAuthorization] user \"uid:%d\" token requires 2fa", claims.Uid)
utils.PrintJsonErrorResult(c, errs.ErrCurrentTokenRequire2FA)
return
}
if claims.Type != core.USER_TOKEN_TYPE_NORMAL && claims.Type != core.USER_TOKEN_TYPE_API {
log.Warnf(c, "[authorization.jwtAuthorization] user \"uid:%d\" token type (%d) is invalid", claims.Uid, claims.Type)
utils.PrintJsonErrorResult(c, errs.ErrCurrentInvalidTokenType)
return
}
if claims.Type == core.USER_TOKEN_TYPE_API && !config.EnableAPIToken {
log.Warnf(c, "[authorization.jwtAuthorization] api token is not enabled")
utils.PrintJsonErrorResult(c, errs.ErrAPITokenNotEnabled)
return
}
c.SetTokenClaims(claims)
c.SetTokenContext(tokenContext)
c.Next()
}
if claims.Type == core.USER_TOKEN_TYPE_REQUIRE_2FA {
log.Warnf(c, "[authorization.jwtAuthorization] user \"uid:%d\" token requires 2fa", claims.Uid)
utils.PrintJsonErrorResult(c, errs.ErrCurrentTokenRequire2FA)
return
}
if claims.Type != core.USER_TOKEN_TYPE_NORMAL && claims.Type != core.USER_TOKEN_TYPE_API {
log.Warnf(c, "[authorization.jwtAuthorization] user \"uid:%d\" token type (%d) is invalid", claims.Uid, claims.Type)
utils.PrintJsonErrorResult(c, errs.ErrCurrentInvalidTokenType)
return
}
c.SetTokenClaims(claims)
c.SetTokenContext(tokenContext)
c.Next()
}
func getTokenClaims(c *core.WebContext, source TokenSourceType) (*core.UserTokenClaims, string, *errs.Error) {

View File

@@ -357,7 +357,7 @@ type Config struct {
EmailVerifyTokenExpiredTimeDuration time.Duration
PasswordResetTokenExpiredTime uint32
PasswordResetTokenExpiredTimeDuration time.Duration
EnableGenerateAPIToken bool
EnableAPIToken bool
MaxFailuresPerIpPerMinute uint32
MaxFailuresPerUserPerMinute uint32
@@ -978,7 +978,7 @@ func loadSecurityConfiguration(config *Config, configFile *ini.File, sectionName
config.PasswordResetTokenExpiredTimeDuration = time.Duration(config.PasswordResetTokenExpiredTime) * time.Second
config.EnableGenerateAPIToken = getConfigItemBoolValue(configFile, sectionName, "enable_generate_api_token", false)
config.EnableAPIToken = getConfigItemBoolValue(configFile, sectionName, "enable_api_token", false)
config.MaxFailuresPerIpPerMinute = getConfigItemUint32Value(configFile, sectionName, "max_failures_per_ip_per_minute", defaultMaxFailuresPerIpPerMinute)
config.MaxFailuresPerUserPerMinute = getConfigItemUint32Value(configFile, sectionName, "max_failures_per_user_per_minute", defaultMaxFailuresPerUserPerMinute)

View File

@@ -19,7 +19,7 @@ export function isUserForgetPasswordEnabled(): boolean {
return getServerSetting('f') === 1;
}
export function isGenerateAPITokenEnabled(): boolean {
export function isAPITokenEnabled(): boolean {
return getServerSetting('t') === 1;
}

View File

@@ -1109,7 +1109,7 @@
"token is empty": "Token ist leer",
"email verify token is invalid or expired": "E-Mail-Verifizierungstoken ist ungültig oder abgelaufen",
"password reset token is invalid or expired": "Passwort-Zurücksetzungstoken ist ungültig oder abgelaufen",
"not allowed to generate api token": "Not allowed to generate API token",
"api token is not enabled": "API token is not enabled",
"passcode is invalid": "Passcode ist ungültig",
"two-factor backup code is invalid": "Zwei-Faktor-Backup-Code ist ungültig",
"two-factor is not enabled": "Zwei-Faktor-Authentifizierung ist nicht aktiviert",

View File

@@ -1109,7 +1109,7 @@
"token is empty": "Token is empty",
"email verify token is invalid or expired": "Email verify token is invalid or expired",
"password reset token is invalid or expired": "Password reset token is invalid or expired",
"not allowed to generate api token": "Not allowed to generate API token",
"api token is not enabled": "API token is not enabled",
"passcode is invalid": "Passcode is invalid",
"two-factor backup code is invalid": "Two-factor backup code is invalid",
"two-factor is not enabled": "Two-factor is not enabled",

View File

@@ -1109,7 +1109,7 @@
"token is empty": "El token está vacío.",
"email verify token is invalid or expired": "El token de verificación de correo electrónico no es válido o ha caducado",
"password reset token is invalid or expired": "El token de restablecimiento de contraseña no es válido o ha caducado",
"not allowed to generate api token": "Not allowed to generate API token",
"api token is not enabled": "API token is not enabled",
"passcode is invalid": "El código de acceso no es válido",
"two-factor backup code is invalid": "El código de respaldo de dos factores no es válido",
"two-factor is not enabled": "El doble factor no está habilitado",

View File

@@ -1109,7 +1109,7 @@
"token is empty": "Le token est vide",
"email verify token is invalid or expired": "Le token de vérification d'email est invalide ou expiré",
"password reset token is invalid or expired": "Le token de réinitialisation de mot de passe est invalide ou expiré",
"not allowed to generate api token": "Not allowed to generate API token",
"api token is not enabled": "API token is not enabled",
"passcode is invalid": "Le code d'accès est invalide",
"two-factor backup code is invalid": "Le code de sauvegarde à deux facteurs est invalide",
"two-factor is not enabled": "L'authentification à deux facteurs n'est pas activée",

View File

@@ -1109,7 +1109,7 @@
"token is empty": "Token vuoto",
"email verify token is invalid or expired": "Il token di verifica email non è valido o è scaduto",
"password reset token is invalid or expired": "Il token di reimpostazione della password non è valido o è scaduto",
"not allowed to generate api token": "Not allowed to generate API token",
"api token is not enabled": "API token is not enabled",
"passcode is invalid": "Passcode non valido",
"two-factor backup code is invalid": "Codice di backup a due fattori non valido",
"two-factor is not enabled": "L'autenticazione a due fattori non è abilitata",

View File

@@ -1109,7 +1109,7 @@
"token is empty": "トークンを記入してください",
"email verify token is invalid or expired": "メール認証トークンが無効または期限切れです",
"password reset token is invalid or expired": "パスワードリセットトークンが無効または期限切れです",
"not allowed to generate api token": "Not allowed to generate API token",
"api token is not enabled": "API token is not enabled",
"passcode is invalid": "パスコードが無効です",
"two-factor backup code is invalid": "二要素バックアップコードが無効です",
"two-factor is not enabled": "二要素が有効になっていません",

View File

@@ -1109,7 +1109,7 @@
"token is empty": "토큰이 비어 있습니다",
"email verify token is invalid or expired": "이메일 확인 토큰이 유효하지 않거나 만료되었습니다",
"password reset token is invalid or expired": "비밀번호 재설정 토큰이 유효하지 않거나 만료되었습니다",
"not allowed to generate api token": "Not allowed to generate API token",
"api token is not enabled": "API token is not enabled",
"passcode is invalid": "일회용 비밀번호가 유효하지 않습니다",
"two-factor backup code is invalid": "2단계 백업 코드가 유효하지 않습니다",
"two-factor is not enabled": "2단계 인증이 활성화되지 않았습니다",

View File

@@ -1109,7 +1109,7 @@
"token is empty": "Token is leeg",
"email verify token is invalid or expired": "E-mailverificatietoken is ongeldig of verlopen",
"password reset token is invalid or expired": "Wachtwoord-resettoken is ongeldig of verlopen",
"not allowed to generate api token": "Not allowed to generate API token",
"api token is not enabled": "API token is not enabled",
"passcode is invalid": "Verificatiecode is ongeldig",
"two-factor backup code is invalid": "Back-upcode voor twee-stapsverificatie is ongeldig",
"two-factor is not enabled": "Twee-stapsverificatie is niet ingeschakeld",

View File

@@ -1109,7 +1109,7 @@
"token is empty": "Token está vazio",
"email verify token is invalid or expired": "O token de verificação de e-mail é inválido ou expirado",
"password reset token is invalid or expired": "O token de redefinição de senha é inválido ou expirado",
"not allowed to generate api token": "Not allowed to generate API token",
"api token is not enabled": "API token is not enabled",
"passcode is invalid": "Código é inválido",
"two-factor backup code is invalid": "Código de backup de duas etapas é inválido",
"two-factor is not enabled": "Autenticação em duas etapas não está ativada",

View File

@@ -1109,7 +1109,7 @@
"token is empty": "Токен пуст",
"email verify token is invalid or expired": "Токен подтверждения электронной почты недействителен или истек",
"password reset token is invalid or expired": "Токен сброса пароля недействителен или истек",
"not allowed to generate api token": "Not allowed to generate API token",
"api token is not enabled": "API token is not enabled",
"passcode is invalid": "Код доступа недействителен",
"two-factor backup code is invalid": "Резервный код двухфакторной аутентификации недействителен",
"two-factor is not enabled": "Двухфакторная аутентификация не включена",

View File

@@ -1109,7 +1109,7 @@
"token is empty": "โทเค็นว่างเปล่า",
"email verify token is invalid or expired": "โทเค็นยืนยันอีเมลไม่ถูกต้องหรือหมดอายุ",
"password reset token is invalid or expired": "โทเค็นรีเซ็ตรหัสผ่านไม่ถูกต้องหรือหมดอายุ",
"not allowed to generate api token": "Not allowed to generate API token",
"api token is not enabled": "API token is not enabled",
"passcode is invalid": "รหัสผ่านชั่วคราวไม่ถูกต้อง",
"two-factor backup code is invalid": "รหัสสำรองสองขั้นตอนไม่ถูกต้อง",
"two-factor is not enabled": "ยังไม่ได้เปิดใช้งานการยืนยันสองขั้นตอน",

View File

@@ -1109,7 +1109,7 @@
"token is empty": "Токен порожній",
"email verify token is invalid or expired": "Токен підтвердження електронної пошти недійсний або прострочений",
"password reset token is invalid or expired": "Токен скидання пароля недійсний або прострочений",
"not allowed to generate api token": "Not allowed to generate API token",
"api token is not enabled": "API token is not enabled",
"passcode is invalid": "Код доступу недійсний",
"two-factor backup code is invalid": "Резервний код двофакторної автентифікації недійсний",
"two-factor is not enabled": "Двофакторна автентифікація не увімкнена",

View File

@@ -1109,7 +1109,7 @@
"token is empty": "Mã thông báo trống",
"email verify token is invalid or expired": "Mã thông báo xác minh email không hợp lệ hoặc đã hết hạn",
"password reset token is invalid or expired": "Mã thông báo đặt lại mật khẩu không hợp lệ hoặc đã hết hạn",
"not allowed to generate api token": "Not allowed to generate API token",
"api token is not enabled": "API token is not enabled",
"passcode is invalid": "Mã số không hợp lệ",
"two-factor backup code is invalid": "Mã sao lưu hai yếu tố không hợp lệ",
"two-factor is not enabled": "Xác thực hai yếu tố chưa được bật",

View File

@@ -1109,7 +1109,7 @@
"token is empty": "认证令牌为空",
"email verify token is invalid or expired": "邮箱验证令牌无效或已过期",
"password reset token is invalid or expired": "密码重置令牌无效或已过期",
"not allowed to generate api token": "不允许生成 API 认证令牌",
"api token is not enabled": "API 令牌没有启用",
"passcode is invalid": "验证码无效",
"two-factor backup code is invalid": "两步验证备用码无效",
"two-factor is not enabled": "两步验证没有启用",

View File

@@ -1109,7 +1109,7 @@
"token is empty": "驗證令牌為空",
"email verify token is invalid or expired": "電子郵件驗證令牌無效或已過期",
"password reset token is invalid or expired": "密碼重設令牌無效或已過期",
"not allowed to generate api token": "不允許產生 API 認證令牌",
"api token is not enabled": "API 令牌未啟用",
"passcode is invalid": "驗證碼無效",
"two-factor backup code is invalid": "二步驟驗證備用碼無效",
"two-factor is not enabled": "二步驟驗證沒有啟用",

View File

@@ -123,7 +123,7 @@ import { useTokensStore } from '@/stores/token.ts';
import { type NameValue } from '@/core/base.ts';
import { type TokenGenerateMCPResponse } from '@/models/token.ts';
import { isGenerateAPITokenEnabled, isMCPServerEnabled } from '@/lib/server_settings.ts';
import { isAPITokenEnabled, isMCPServerEnabled } from '@/lib/server_settings.ts';
import { copyTextToClipboard } from '@/lib/ui/common.ts';
type SnackBarType = InstanceType<typeof SnackBar>;
@@ -139,7 +139,7 @@ let resolveFunc: (() => void) | null = null;
let rejectFunc: ((reason?: unknown) => void) | null = null;
const showState = ref<boolean>(false);
const tokenType = ref<'api' | 'mcp'>(isGenerateAPITokenEnabled() ? 'api' : (isMCPServerEnabled() ? 'mcp' : 'api'));
const tokenType = ref<'api' | 'mcp'>(isAPITokenEnabled() ? 'api' : (isMCPServerEnabled() ? 'mcp' : 'api'));
const tokenExpirationTime = ref<number>(86400);
const tokenCustomExpirationTime = ref<number>(86400);
const currentPassword = ref<string>('');
@@ -151,7 +151,7 @@ const generatedToken = ref<string>('');
const tokenTypeOptions = computed<NameValue[]>(() => {
const options: NameValue[] = [];
if (isGenerateAPITokenEnabled()) {
if (isAPITokenEnabled()) {
options.push({ name: tt('API Token'), value: 'api' });
}
@@ -179,7 +179,7 @@ const mcpServerConfiguration = computed<string>(() => {
function open(): Promise<void> {
showState.value = true;
currentPassword.value = '';
tokenType.value = isGenerateAPITokenEnabled() ? 'api' : (isMCPServerEnabled() ? 'mcp' : 'api');
tokenType.value = isAPITokenEnabled() ? 'api' : (isMCPServerEnabled() ? 'mcp' : 'api');
tokenExpirationTime.value = 86400;
tokenCustomExpirationTime.value = 86400;
generating.value = false;

View File

@@ -132,7 +132,7 @@
<div class="d-flex align-center">
<span>{{ tt('Device & Sessions') }}</span>
<v-btn class="ms-3" density="compact" color="default" variant="outlined"
@click="generateToken" v-if="isGenerateAPITokenEnabled() || isMCPServerEnabled()">{{ tt('Generate Token') }}</v-btn>
@click="generateToken" v-if="isAPITokenEnabled() || isMCPServerEnabled()">{{ tt('Generate Token') }}</v-btn>
<v-btn density="compact" color="default" variant="text" size="24"
class="ms-2" :icon="true" :loading="loadingSession" @click="reloadSessions(false)">
<template #loader>
@@ -218,7 +218,7 @@ import { type TokenInfoResponse, SessionDeviceType, SessionInfo } from '@/models
import { isEquals } from '@/lib/common.ts';
import { parseSessionInfo } from '@/lib/session.ts';
import {
isGenerateAPITokenEnabled,
isAPITokenEnabled,
isOAuth2Enabled,
getOAuth2Provider,
getOIDCCustomDisplayNames,