diff --git a/README.md b/README.md index 545503d..a84c6f3 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # A股工具 · 用户体系 -基于 **Go + PostgreSQL + Docker Compose** 的用户权限管理模块,角色覆盖:系统管理员、管理员、用户、游客。前端界面复用 `refer/` 目录下的暗色主题设计语言。 +基于 **Go + PostgreSQL + Docker Compose** 的用户权限管理模块,角色覆盖:系统管理员、管理员、用户。前端界面复用 `refer/` 目录下的暗色主题设计语言。 ## 技术栈 @@ -50,13 +50,11 @@ WHERE username = '你的用户名'; | 系统管理员 | 管理管理员、用户、系统配置 | | 管理员 | 管理普通用户 | | 用户 | 访问业务功能、修改个人资料 | -| 游客 | 仅查看公开内容,不可操作 | ## 主要 API | 方法 | 路径 | 说明 | 权限 | |---|---|---|---| -| GET | /api/public | 公开信息 | 公开 | | POST | /api/auth/register | 注册(默认 user) | 公开 | | POST | /api/auth/login | 登录 | 公开 | | GET | /api/auth/me | 当前用户 | 需登录 | @@ -107,5 +105,4 @@ npm run dev ## 注意事项 - 生产环境请务必修改 `JWT_SECRET`。 -- 游客通过首页直接访问,无需登录。 - 首次启动时 GORM 会自动创建表并插入默认角色。 diff --git a/backend/internal/handlers/admin.go b/backend/internal/handlers/admin.go index 2c8f0b2..3b66ec4 100644 --- a/backend/internal/handlers/admin.go +++ b/backend/internal/handlers/admin.go @@ -20,9 +20,9 @@ type AdminHandler struct { func allowedRolesForCreation(actor models.RoleName) []models.RoleName { switch actor { case models.RoleSystemAdmin: - return []models.RoleName{models.RoleAdmin, models.RoleUser, models.RoleGuest} + return []models.RoleName{models.RoleAdmin, models.RoleUser} case models.RoleAdmin: - return []models.RoleName{models.RoleUser, models.RoleGuest} + return []models.RoleName{models.RoleUser} default: return nil } diff --git a/backend/internal/handlers/auth.go b/backend/internal/handlers/auth.go index d79e71b..9fdd4ae 100644 --- a/backend/internal/handlers/auth.go +++ b/backend/internal/handlers/auth.go @@ -153,13 +153,6 @@ func (h *AuthHandler) Logout(c *gin.Context) { c.JSON(http.StatusOK, gin.H{"message": "登出成功"}) } -func (h *AuthHandler) PublicInfo(c *gin.Context) { - c.JSON(http.StatusOK, gin.H{ - "message": "欢迎访问 A股工具公开信息", - "guest_allowed": true, - }) -} - func hashPassword(password string) (string, error) { bytes, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) return string(bytes), err diff --git a/backend/internal/middleware/auth.go b/backend/internal/middleware/auth.go index c29303e..c728854 100644 --- a/backend/internal/middleware/auth.go +++ b/backend/internal/middleware/auth.go @@ -19,6 +19,11 @@ type CurrentUser struct { Role models.RoleName } +var publicPaths = map[string]struct{}{ + "/api/auth/register": {}, + "/api/auth/login": {}, +} + func AuthMiddleware(cfg *config.Config, db *gorm.DB) gin.HandlerFunc { return func(c *gin.Context) { authHeader := c.GetHeader("Authorization") @@ -41,6 +46,17 @@ func AuthMiddleware(cfg *config.Config, db *gorm.DB) gin.HandlerFunc { } } + if _, exists := c.Get("currentUser"); !exists { + if c.Request.Method == "OPTIONS" { + c.Next() + return + } + if _, ok := publicPaths[c.Request.URL.Path]; !ok { + c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"success": false, "error": "访问令牌无效或已过期"}) + return + } + } + c.Next() } } diff --git a/backend/internal/models/user.go b/backend/internal/models/user.go index dea9733..ec037e9 100644 --- a/backend/internal/models/user.go +++ b/backend/internal/models/user.go @@ -13,7 +13,6 @@ const ( RoleSystemAdmin RoleName = "system_admin" RoleAdmin RoleName = "admin" RoleUser RoleName = "user" - RoleGuest RoleName = "guest" ) func (r RoleName) String() string { return string(r) } @@ -43,10 +42,8 @@ func ParseRoleName(s string) (RoleName, error) { return RoleAdmin, nil case "user": return RoleUser, nil - case "guest": - return RoleGuest, nil default: - return RoleGuest, fmt.Errorf("unknown role: %s", s) + return "", fmt.Errorf("unknown role: %s", s) } } @@ -105,7 +102,6 @@ func SeedRoles(db *gorm.DB) error { {Name: string(RoleSystemAdmin), Description: strPtr("系统管理员,可管理管理员与系统配置"), Permissions: `["*"]`}, {Name: string(RoleAdmin), Description: strPtr("管理员,可管理普通用户"), Permissions: `["users.read", "users.write", "users.create"]`}, {Name: string(RoleUser), Description: strPtr("普通用户,可访问业务功能"), Permissions: `["dashboard.read", "profile.write"]`}, - {Name: string(RoleGuest), Description: strPtr("游客,仅可查看公开内容"), Permissions: `["public.read"]`}, } for _, role := range roles { var existing Role diff --git a/backend/internal/routes/routes.go b/backend/internal/routes/routes.go index a57925c..e12cfe9 100644 --- a/backend/internal/routes/routes.go +++ b/backend/internal/routes/routes.go @@ -30,8 +30,7 @@ func Setup(cfg *config.Config, db *gorm.DB) *gin.Engine { r.Use(middleware.AuthMiddleware(cfg, db)) - // 公开接口 - r.GET("/api/public", authHandler.PublicInfo) + // 公开接口(仅登录/注册) r.POST("/api/auth/register", authHandler.Register) r.POST("/api/auth/login", authHandler.Login) diff --git a/frontend/src/lib/api.ts b/frontend/src/lib/api.ts index ac792c8..0b6f696 100644 --- a/frontend/src/lib/api.ts +++ b/frontend/src/lib/api.ts @@ -10,14 +10,14 @@ export interface UserInfo { id: string username: string email?: string - role: 'system_admin' | 'admin' | 'user' | 'guest' + role: 'system_admin' | 'admin' | 'user' status: string created_at: string } export interface Role { id: number - name: 'system_admin' | 'admin' | 'user' | 'guest' + name: 'system_admin' | 'admin' | 'user' description?: string permissions: string[] created_at: string @@ -79,9 +79,6 @@ async function request( } export const api = { - publicInfo: () => - request<{ message: string; guest_allowed: boolean }>('/api/public'), - register: (body: { username: string; email?: string; password: string }) => request('/api/auth/register', { method: 'POST', diff --git a/frontend/src/lib/auth.ts b/frontend/src/lib/auth.ts index 03e46da..e7ecd71 100644 --- a/frontend/src/lib/auth.ts +++ b/frontend/src/lib/auth.ts @@ -30,13 +30,12 @@ export function clearAuth() { localStorage.removeItem('user') } -export type RoleName = 'system_admin' | 'admin' | 'user' | 'guest' +export type RoleName = 'system_admin' | 'admin' | 'user' const ROLE_RANK: Record = { system_admin: 3, admin: 2, user: 1, - guest: 0, } export function roleRank(role: RoleName): number { @@ -51,8 +50,6 @@ export function roleLabel(role: RoleName): string { return '管理员' case 'user': return '用户' - case 'guest': - return '游客' } } diff --git a/frontend/src/pages/Dashboard.tsx b/frontend/src/pages/Dashboard.tsx index 3782de2..0a41e7e 100644 --- a/frontend/src/pages/Dashboard.tsx +++ b/frontend/src/pages/Dashboard.tsx @@ -1,16 +1,9 @@ -import { useEffect, useState } from 'react' -import { LayoutDashboard, Globe, ShieldCheck } from 'lucide-react' -import { api } from '@/lib/api' +import { LayoutDashboard, ShieldCheck } from 'lucide-react' import { getStoredUser, roleLabel } from '@/lib/auth' export function Dashboard() { - const [publicInfo, setPublicInfo] = useState<{ message: string } | null>(null) const user = getStoredUser() - useEffect(() => { - api.publicInfo().then(setPublicInfo).catch(() => null) - }, []) - return (
@@ -19,7 +12,7 @@ export function Dashboard() {

看板

-

欢迎回来,{user?.username || '游客'}

+

欢迎回来,{user?.username || '—'}

@@ -27,14 +20,8 @@ export function Dashboard() { } title="当前身份" - value={user ? roleLabel(user.role) : '游客'} - desc={user ? `用户:${user.username}` : '未登录,仅可查看公开信息'} - /> - } - title="公开信息" - value="已接入" - desc={publicInfo?.message || '加载中…'} + value={user ? roleLabel(user.role) : '—'} + desc={user ? `用户:${user.username}` : '加载中…'} /> @@ -44,7 +31,6 @@ export function Dashboard() {
  • 系统管理员:可管理管理员、用户、系统配置
  • 管理员:可管理普通用户
  • 用户:可访问业务功能、修改个人资料
  • -
  • 游客:仅查看公开内容,不可操作
  • diff --git a/frontend/src/router.tsx b/frontend/src/router.tsx index f87dda4..470663c 100644 --- a/frontend/src/router.tsx +++ b/frontend/src/router.tsx @@ -10,7 +10,11 @@ export const router = createBrowserRouter([ { path: '/login', element: }, { path: '/', - element: , + element: ( + + + + ), children: [ { index: true, element: }, { @@ -23,11 +27,7 @@ export const router = createBrowserRouter([ }, { path: 'profile', - element: ( - - - - ), + element: , }, ], },