Forráskód Böngészése

feat: extend UserRole enum, add scopes field, SecurityUtils role helpers, and RequireRole annotation

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
wangkangyjy 2 hónapja
szülő
commit
a9fd7be0af

+ 10 - 0
backend/src/main/java/com/yimeng/okr/annotation/RequireRole.java

@@ -0,0 +1,10 @@
+package com.yimeng.okr.annotation;
+
+import com.yimeng.okr.enums.UserRole;
+import java.lang.annotation.*;
+
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface RequireRole {
+    UserRole[] value() default {UserRole.SUPER_ADMIN};
+}

+ 10 - 0
backend/src/main/java/com/yimeng/okr/config/DatabaseInitializer.java

@@ -14,6 +14,8 @@ import java.nio.charset.StandardCharsets;
 import java.sql.Connection;
 import java.sql.Statement;
 
+import org.springframework.jdbc.core.JdbcTemplate;
+
 @Slf4j
 @Component
 @RequiredArgsConstructor
@@ -21,6 +23,7 @@ import java.sql.Statement;
 public class DatabaseInitializer implements CommandLineRunner {
 
     private final DataSource dataSource;
+    private final JdbcTemplate jdbcTemplate;
 
     @Override
     public void run(String... args) throws Exception {
@@ -53,6 +56,13 @@ public class DatabaseInitializer implements CommandLineRunner {
                 }
             }
             log.info("Database schema initialized successfully");
+
+            // Migration: ensure scopes column exists
+            try {
+                jdbcTemplate.execute("ALTER TABLE sys_user ADD COLUMN scopes TEXT DEFAULT '[]'");
+            } catch (Exception ignored) {
+                // column already exists
+            }
         }
     }
 }

+ 2 - 0
backend/src/main/java/com/yimeng/okr/entity/SysUser.java

@@ -24,6 +24,8 @@ public class SysUser {
     @TableField("role")
     private UserRole role;
 
+    private String scopes;  // JSON array: ["dept:3","dept:5"]
+
     @TableLogic
     private Integer deleted;
 

+ 15 - 0
backend/src/main/java/com/yimeng/okr/enums/UserRole.java

@@ -5,6 +5,9 @@ import lombok.Getter;
 @Getter
 public enum UserRole {
     EMPLOYEE("普通员工"),
+    TEAM_LEADER("团队主管"),
+    DEPT_LEADER("部门负责人"),
+    HR_ADMIN("HR管理员"),
     SUPER_ADMIN("超级管理员");
 
     private final String label;
@@ -12,4 +15,16 @@ public enum UserRole {
     UserRole(String label) {
         this.label = label;
     }
+
+    public static boolean isManagerOrAbove(UserRole role) {
+        return role == TEAM_LEADER || role == DEPT_LEADER || role == HR_ADMIN || role == SUPER_ADMIN;
+    }
+
+    public static boolean isDeptLeaderOrAbove(UserRole role) {
+        return role == DEPT_LEADER || role == HR_ADMIN || role == SUPER_ADMIN;
+    }
+
+    public static boolean isHrAdminOrAbove(UserRole role) {
+        return role == HR_ADMIN || role == SUPER_ADMIN;
+    }
 }

+ 26 - 0
backend/src/main/java/com/yimeng/okr/security/SecurityUtils.java

@@ -3,6 +3,8 @@ package com.yimeng.okr.security;
 import org.springframework.security.core.Authentication;
 import org.springframework.security.core.context.SecurityContextHolder;
 
+import com.yimeng.okr.enums.UserRole;
+
 public class SecurityUtils {
 
     private SecurityUtils() {}
@@ -23,4 +25,28 @@ public class SecurityUtils {
         }
         return false;
     }
+
+    public static boolean hasRole(UserRole requiredRole) {
+        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
+        if (auth == null || auth.getAuthorities() == null) return false;
+        String roleName = auth.getAuthorities().stream()
+                .map(a -> a.getAuthority().replace("ROLE_", ""))
+                .findFirst().orElse("EMPLOYEE");
+        try {
+            UserRole current = UserRole.valueOf(roleName);
+            return current.ordinal() >= requiredRole.ordinal();
+        } catch (IllegalArgumentException e) {
+            return false;
+        }
+    }
+
+    public static String getCurrentUserRole() {
+        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
+        if (auth != null && auth.getAuthorities() != null) {
+            return auth.getAuthorities().stream()
+                    .map(a -> a.getAuthority().replace("ROLE_", ""))
+                    .findFirst().orElse("EMPLOYEE");
+        }
+        return "EMPLOYEE";
+    }
 }