diff --git a/frontend/components/common/docs/api.tsx b/frontend/components/common/docs/api.tsx
index 704ab4f4..c608d6d7 100644
--- a/frontend/components/common/docs/api.tsx
+++ b/frontend/components/common/docs/api.tsx
@@ -205,7 +205,6 @@ export const apiSections: PolicySection[] = [
"name": "my-dev-key",
"masked_token": "at_628d...29c9",
"is_admin": false,
- "last_used_at": null,
"created_at": "2026-06-07T21:30:00+08:00"
}
}
@@ -219,7 +218,7 @@ export const apiSections: PolicySection[] = [
3.4 轮换令牌密钥
接口:POST /api/v1/user/access-tokens/:id/rotate
- 说明:轮换指定令牌的物理密钥值。系统将废弃原有密钥,返回新生成的明文 Token,并将 `last_used_at` 置空,令牌名称与 ID 保持一致。
+ 说明:轮换指定令牌的物理密钥值。系统将废弃原有密钥,返回新生成的明文 Token,令牌名称与 ID 保持一致。
),
children: [
diff --git a/frontend/components/common/settings/access-token.tsx b/frontend/components/common/settings/access-token.tsx
index ccdeb1d2..24a12015 100644
--- a/frontend/components/common/settings/access-token.tsx
+++ b/frontend/components/common/settings/access-token.tsx
@@ -206,11 +206,15 @@ export function AccessTokenMain() {
{token.name}
- {token.is_admin && (
+ {token.is_admin ? (
管理员
+ ) : (
+
+ 用户令牌
+
)}
@@ -219,7 +223,6 @@ export function AccessTokenMain() {
创建于: {formatDate(token.created_at)}
- 最后使用: {formatDate(token.last_used_at)}
diff --git a/frontend/lib/services/user/user.service.ts b/frontend/lib/services/user/user.service.ts
index 7cc5b4b1..5e94920f 100644
--- a/frontend/lib/services/user/user.service.ts
+++ b/frontend/lib/services/user/user.service.ts
@@ -6,7 +6,6 @@ export interface AccessToken {
name: string;
masked_token: string;
is_admin: boolean;
- last_used_at?: string;
created_at: string;
updated_at: string;
}
diff --git a/internal/apps/oauth/middlewares.go b/internal/apps/oauth/middlewares.go
index 3ab98596..ae876fa6 100644
--- a/internal/apps/oauth/middlewares.go
+++ b/internal/apps/oauth/middlewares.go
@@ -6,7 +6,6 @@ package oauth
import (
"net/http"
- "time"
"github.com/Rain-kl/Wavelet/internal/common"
"github.com/Rain-kl/Wavelet/internal/db"
@@ -56,9 +55,6 @@ func LoginRequired() gin.HandlerFunc {
authenticated = true
tokenAuth = true
tokenAdmin = tokenRecord.IsAdmin
- // update token last used time
- now := time.Now()
- db.DB(ctx).Model(&tokenRecord).Update("last_used_at", &now)
}
}
}
diff --git a/internal/apps/user/access_tokens.go b/internal/apps/user/access_tokens.go
index 8a29a0cc..c6859232 100644
--- a/internal/apps/user/access_tokens.go
+++ b/internal/apps/user/access_tokens.go
@@ -203,7 +203,6 @@ func RotateAccessToken(c *gin.Context) {
tokenRecord.TokenHash = newTokenHash
tokenRecord.MaskedToken = newMaskedToken
- tokenRecord.LastUsedAt = nil // 轮换后重置使用时间
if err := db.DB(ctx).Save(&tokenRecord).Error; err != nil {
c.JSON(http.StatusOK, util.Err(err.Error()))
diff --git a/internal/db/migrator/goose/postgres/202606110001_remove_access_token_last_used_at.sql b/internal/db/migrator/goose/postgres/202606110001_remove_access_token_last_used_at.sql
new file mode 100644
index 00000000..4a0fa676
--- /dev/null
+++ b/internal/db/migrator/goose/postgres/202606110001_remove_access_token_last_used_at.sql
@@ -0,0 +1,9 @@
+-- +goose Up
+-- +goose StatementBegin
+ALTER TABLE access_tokens DROP COLUMN IF EXISTS last_used_at;
+-- +goose StatementEnd
+
+-- +goose Down
+-- +goose StatementBegin
+ALTER TABLE access_tokens ADD COLUMN last_used_at TIMESTAMPTZ;
+-- +goose StatementEnd
diff --git a/internal/db/migrator/goose/sqlite/202606110001_remove_access_token_last_used_at.sql b/internal/db/migrator/goose/sqlite/202606110001_remove_access_token_last_used_at.sql
new file mode 100644
index 00000000..1b2c38c7
--- /dev/null
+++ b/internal/db/migrator/goose/sqlite/202606110001_remove_access_token_last_used_at.sql
@@ -0,0 +1,9 @@
+-- +goose Up
+-- +goose StatementBegin
+ALTER TABLE access_tokens DROP COLUMN last_used_at;
+-- +goose StatementEnd
+
+-- +goose Down
+-- +goose StatementBegin
+ALTER TABLE access_tokens ADD COLUMN last_used_at DATETIME;
+-- +goose StatementEnd
diff --git a/internal/model/access_token.go b/internal/model/access_token.go
index 281637d2..db548073 100644
--- a/internal/model/access_token.go
+++ b/internal/model/access_token.go
@@ -20,15 +20,14 @@ const (
// AccessToken 个人访问令牌实体
type AccessToken struct {
- ID uint64 `json:"id" gorm:"primaryKey;autoIncrement"`
- UserID uint64 `json:"user_id" gorm:"index;not null"`
- Name string `json:"name" gorm:"size:128;not null"`
- TokenHash string `json:"-" gorm:"size:64;uniqueIndex;not null"`
- MaskedToken string `json:"masked_token" gorm:"size:64;not null"`
- IsAdmin bool `json:"is_admin" gorm:"default:false"`
- LastUsedAt *time.Time `json:"last_used_at"`
- CreatedAt time.Time `json:"created_at" gorm:"autoCreateTime"`
- UpdatedAt time.Time `json:"updated_at" gorm:"autoUpdateTime"`
+ ID uint64 `json:"id" gorm:"primaryKey;autoIncrement"`
+ UserID uint64 `json:"user_id" gorm:"index;not null"`
+ Name string `json:"name" gorm:"size:128;not null"`
+ TokenHash string `json:"-" gorm:"size:64;uniqueIndex;not null"`
+ MaskedToken string `json:"masked_token" gorm:"size:64;not null"`
+ IsAdmin bool `json:"is_admin" gorm:"default:false"`
+ CreatedAt time.Time `json:"created_at" gorm:"autoCreateTime"`
+ UpdatedAt time.Time `json:"updated_at" gorm:"autoUpdateTime"`
}
// GenerateTokenString 生成加密安全的随机 Token 值