diff --git a/.claude/settings.local.json b/.claude/settings.local.json new file mode 100644 index 0000000..5707c58 --- /dev/null +++ b/.claude/settings.local.json @@ -0,0 +1,7 @@ +{ + "permissions": { + "allow": [ + "Bash(git add:*)" + ] + } +} diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..237a0ed --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,66 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Build & Run Commands + +```bash +# Build the project +./mvnw clean package + +# Run the application +./mvnw spring-boot:run + +# Run all tests +./mvnw test + +# Run a single test class +./mvnw test -Dtest=TestClassName + +# Run a single test method +./mvnw test -Dtest=TestClassName#methodName +``` + +## Project Overview + +- **Framework**: Spring Boot 3.2.3 with Java 21 +- **ORM**: MyBatis Plus 3.5.5 +- **Database**: MySQL 8.0.33 +- **Cache**: Redis (Spring Data Redis) +- **API Docs**: Swagger UI at `/swagger-ui.html` +- **Auth**: JWT (jjwt 0.11.5) + +## Architecture + +Base package: `icu.sunway.ai_spring_example` + +This project follows a layered architecture with MyBatis Plus: + +| Layer | Location | Pattern | +|-------|----------|---------| +| Controller | `Controller/{EntityName}Controller/` | One subdirectory per entity | +| Service | `Service/` | Interface `I{Name}Service` extends `IService` | +| Service Impl | `Service/Implements/` | `{Name}ServiceImpl` extends `ServiceImpl` | +| Mapper | `Mapper/` | `{Name}Mapper` extends `BaseMapper` | +| Entity | `Entity/` | Lombok + MyBatis Plus annotations | +| Config | `Config/` | CORS, Security, Redis, OpenAPI | +| Utils | `Utils/` | Utility classes | + +## Key Utilities + +- **ResponseUtils**: Standard API responses - `ResponseUtils.success(data)` / `ResponseUtils.fail(message)` +- **PageUtils**: Pagination - `PageUtils.createPage(page, limit)` returns `Page` for MyBatis Plus +- **RedisUtils**: Redis operations (inject with `@Resource`) +- **JsonUtils**: JSON serialization - `JsonUtils.toJson()` / `JsonUtils.toObject()` +- **ValidationUtils**: Input validation (email, phone, URL, IP, password strength, etc.) + +## Configuration + +- Copy `application-example.yaml` to `application.yaml` and fill in database/Redis credentials +- `application.yaml` is gitignored (contains sensitive data) +- Uses dynamic multi-datasource (primary datasource named "master") + +## Security Notes + +- Current `SecurityConfig` is permissive (all requests allowed) - configure for production +- Stateless session management configured for JWT authentication diff --git a/src/main/java/icu/sunway/ai_spring_example/Controller/PermissionController/PermissionController.java b/src/main/java/icu/sunway/ai_spring_example/Controller/PermissionController/PermissionController.java new file mode 100644 index 0000000..70a4264 --- /dev/null +++ b/src/main/java/icu/sunway/ai_spring_example/Controller/PermissionController/PermissionController.java @@ -0,0 +1,73 @@ +package icu.sunway.ai_spring_example.Controller.PermissionController; + +import icu.sunway.ai_spring_example.Entity.Permission; +import icu.sunway.ai_spring_example.Service.IPermissionService; +import icu.sunway.ai_spring_example.Utils.ResponseUtils; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.springframework.web.bind.annotation.*; + +import jakarta.annotation.Resource; + +@RestController +@RequestMapping("/permission") +public class PermissionController { + + @Resource + private IPermissionService permissionService; + + @GetMapping("/{id}") + public Object getPermissionById(@PathVariable Long id) { + Permission permission = permissionService.getById(id); + return ResponseUtils.success(permission); + } + + @GetMapping + public Object getAllPermissions( + @RequestParam(defaultValue = "1") Integer page, + @RequestParam(defaultValue = "10") Integer limit) { + + Page permissionPage = new Page<>(page, limit); + Page resultPage = permissionService.page(permissionPage); + return ResponseUtils.success(resultPage); + } + + @PostMapping + public Object createPermission(@RequestBody Permission permission) { + boolean result = permissionService.save(permission); + if (result) { + return ResponseUtils.success(permission); + } else { + return ResponseUtils.fail("Failed to create permission"); + } + } + + @PutMapping("/{id}") + public Object updatePermission(@PathVariable Long id, @RequestBody Permission permission) { + permission.setId(id); + boolean result = permissionService.updateById(permission); + if (result) { + return ResponseUtils.success(permission); + } else { + return ResponseUtils.fail("Failed to update permission"); + } + } + + @DeleteMapping("/{id}") + public Object deletePermission(@PathVariable Long id) { + boolean result = permissionService.removeById(id); + if (result) { + return ResponseUtils.success("Permission deleted successfully"); + } else { + return ResponseUtils.fail("Failed to delete permission"); + } + } + + @GetMapping("/name/{name}") + public Object getPermissionByName(@PathVariable String name) { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("name", name); + Permission permission = permissionService.getOne(wrapper); + return ResponseUtils.success(permission); + } +} \ No newline at end of file diff --git a/src/main/java/icu/sunway/ai_spring_example/Controller/RoleController/RoleController.java b/src/main/java/icu/sunway/ai_spring_example/Controller/RoleController/RoleController.java new file mode 100644 index 0000000..52bdb82 --- /dev/null +++ b/src/main/java/icu/sunway/ai_spring_example/Controller/RoleController/RoleController.java @@ -0,0 +1,73 @@ +package icu.sunway.ai_spring_example.Controller.RoleController; + +import icu.sunway.ai_spring_example.Entity.Role; +import icu.sunway.ai_spring_example.Service.IRoleService; +import icu.sunway.ai_spring_example.Utils.ResponseUtils; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.springframework.web.bind.annotation.*; + +import jakarta.annotation.Resource; + +@RestController +@RequestMapping("/role") +public class RoleController { + + @Resource + private IRoleService roleService; + + @GetMapping("/{id}") + public Object getRoleById(@PathVariable Long id) { + Role role = roleService.getById(id); + return ResponseUtils.success(role); + } + + @GetMapping + public Object getAllRoles( + @RequestParam(defaultValue = "1") Integer page, + @RequestParam(defaultValue = "10") Integer limit) { + + Page rolePage = new Page<>(page, limit); + Page resultPage = roleService.page(rolePage); + return ResponseUtils.success(resultPage); + } + + @PostMapping + public Object createRole(@RequestBody Role role) { + boolean result = roleService.save(role); + if (result) { + return ResponseUtils.success(role); + } else { + return ResponseUtils.fail("Failed to create role"); + } + } + + @PutMapping("/{id}") + public Object updateRole(@PathVariable Long id, @RequestBody Role role) { + role.setId(id); + boolean result = roleService.updateById(role); + if (result) { + return ResponseUtils.success(role); + } else { + return ResponseUtils.fail("Failed to update role"); + } + } + + @DeleteMapping("/{id}") + public Object deleteRole(@PathVariable Long id) { + boolean result = roleService.removeById(id); + if (result) { + return ResponseUtils.success("Role deleted successfully"); + } else { + return ResponseUtils.fail("Failed to delete role"); + } + } + + @GetMapping("/name/{name}") + public Object getRoleByName(@PathVariable String name) { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("name", name); + Role role = roleService.getOne(wrapper); + return ResponseUtils.success(role); + } +} \ No newline at end of file diff --git a/src/main/java/icu/sunway/ai_spring_example/Controller/RolePermissionController/RolePermissionController.java b/src/main/java/icu/sunway/ai_spring_example/Controller/RolePermissionController/RolePermissionController.java new file mode 100644 index 0000000..6e2e32b --- /dev/null +++ b/src/main/java/icu/sunway/ai_spring_example/Controller/RolePermissionController/RolePermissionController.java @@ -0,0 +1,82 @@ +package icu.sunway.ai_spring_example.Controller.RolePermissionController; + +import icu.sunway.ai_spring_example.Entity.RolePermission; +import icu.sunway.ai_spring_example.Service.IRolePermissionService; +import icu.sunway.ai_spring_example.Utils.ResponseUtils; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.springframework.web.bind.annotation.*; + +import jakarta.annotation.Resource; +import java.util.List; + +@RestController +@RequestMapping("/role-permission") +public class RolePermissionController { + + @Resource + private IRolePermissionService rolePermissionService; + + @GetMapping("/{id}") + public Object getRolePermissionById(@PathVariable Long id) { + RolePermission rolePermission = rolePermissionService.getById(id); + return ResponseUtils.success(rolePermission); + } + + @GetMapping + public Object getAllRolePermissions( + @RequestParam(defaultValue = "1") Integer page, + @RequestParam(defaultValue = "10") Integer limit) { + + Page rolePermissionPage = new Page<>(page, limit); + Page resultPage = rolePermissionService.page(rolePermissionPage); + return ResponseUtils.success(resultPage); + } + + @PostMapping + public Object createRolePermission(@RequestBody RolePermission rolePermission) { + boolean result = rolePermissionService.save(rolePermission); + if (result) { + return ResponseUtils.success(rolePermission); + } else { + return ResponseUtils.fail("Failed to create role permission relationship"); + } + } + + @PutMapping("/{id}") + public Object updateRolePermission(@PathVariable Long id, @RequestBody RolePermission rolePermission) { + rolePermission.setId(id); + boolean result = rolePermissionService.updateById(rolePermission); + if (result) { + return ResponseUtils.success(rolePermission); + } else { + return ResponseUtils.fail("Failed to update role permission relationship"); + } + } + + @DeleteMapping("/{id}") + public Object deleteRolePermission(@PathVariable Long id) { + boolean result = rolePermissionService.removeById(id); + if (result) { + return ResponseUtils.success("Role permission relationship deleted successfully"); + } else { + return ResponseUtils.fail("Failed to delete role permission relationship"); + } + } + + @GetMapping("/role/{roleId}") + public Object getRolePermissionsByRoleId(@PathVariable Long roleId) { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("role_id", roleId); + List rolePermissions = rolePermissionService.list(wrapper); + return ResponseUtils.success(rolePermissions); + } + + @GetMapping("/permission/{permissionId}") + public Object getRolePermissionsByPermissionId(@PathVariable Long permissionId) { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("permission_id", permissionId); + List rolePermissions = rolePermissionService.list(wrapper); + return ResponseUtils.success(rolePermissions); + } +} \ No newline at end of file diff --git a/src/main/java/icu/sunway/ai_spring_example/Controller/UserController/UserController.java b/src/main/java/icu/sunway/ai_spring_example/Controller/UserController/UserController.java new file mode 100644 index 0000000..8fcd251 --- /dev/null +++ b/src/main/java/icu/sunway/ai_spring_example/Controller/UserController/UserController.java @@ -0,0 +1,73 @@ +package icu.sunway.ai_spring_example.Controller.UserController; + +import icu.sunway.ai_spring_example.Entity.User; +import icu.sunway.ai_spring_example.Service.IUserService; +import icu.sunway.ai_spring_example.Utils.ResponseUtils; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.springframework.web.bind.annotation.*; + +import jakarta.annotation.Resource; + +@RestController +@RequestMapping("/user") +public class UserController { + + @Resource + private IUserService userService; + + @GetMapping("/{id}") + public Object getUserById(@PathVariable Long id) { + User user = userService.getById(id); + return ResponseUtils.success(user); + } + + @GetMapping + public Object getAllUsers( + @RequestParam(defaultValue = "1") Integer page, + @RequestParam(defaultValue = "10") Integer limit) { + + Page userPage = new Page<>(page, limit); + Page resultPage = userService.page(userPage); + return ResponseUtils.success(resultPage); + } + + @PostMapping + public Object createUser(@RequestBody User user) { + boolean result = userService.save(user); + if (result) { + return ResponseUtils.success(user); + } else { + return ResponseUtils.fail("Failed to create user"); + } + } + + @PutMapping("/{id}") + public Object updateUser(@PathVariable Long id, @RequestBody User user) { + user.setId(id); + boolean result = userService.updateById(user); + if (result) { + return ResponseUtils.success(user); + } else { + return ResponseUtils.fail("Failed to update user"); + } + } + + @DeleteMapping("/{id}") + public Object deleteUser(@PathVariable Long id) { + boolean result = userService.removeById(id); + if (result) { + return ResponseUtils.success("User deleted successfully"); + } else { + return ResponseUtils.fail("Failed to delete user"); + } + } + + @GetMapping("/username/{username}") + public Object getUserByUsername(@PathVariable String username) { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("username", username); + User user = userService.getOne(wrapper); + return ResponseUtils.success(user); + } +} \ No newline at end of file diff --git a/src/main/java/icu/sunway/ai_spring_example/Controller/UserRoleController/UserRoleController.java b/src/main/java/icu/sunway/ai_spring_example/Controller/UserRoleController/UserRoleController.java new file mode 100644 index 0000000..21546a0 --- /dev/null +++ b/src/main/java/icu/sunway/ai_spring_example/Controller/UserRoleController/UserRoleController.java @@ -0,0 +1,84 @@ +package icu.sunway.ai_spring_example.Controller.UserRoleController; + +import icu.sunway.ai_spring_example.Entity.UserRole; +import icu.sunway.ai_spring_example.Service.IUserRoleService; +import icu.sunway.ai_spring_example.Utils.ResponseUtils; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; + +import java.util.List; + +import org.springframework.web.bind.annotation.*; + +import jakarta.annotation.Resource; + +@RestController +@RequestMapping("/user-role") +public class UserRoleController { + + @Resource + private IUserRoleService userRoleService; + + @GetMapping("/{id}") + public Object getUserRoleById(@PathVariable Long id) { + UserRole userRole = userRoleService.getById(id); + return ResponseUtils.success(userRole); + } + + @GetMapping + public Object getAllUserRoles( + @RequestParam(defaultValue = "1") Integer page, + @RequestParam(defaultValue = "10") Integer limit) { + + Page userRolePage = new Page<>(page, limit); + Page resultPage = userRoleService.page(userRolePage); + return ResponseUtils.success(resultPage); + } + + @PostMapping + public Object createUserRole(@RequestBody UserRole userRole) { + boolean result = userRoleService.save(userRole); + if (result) { + return ResponseUtils.success(userRole); + } else { + return ResponseUtils.fail("Failed to create user role relationship"); + } + } + + @PutMapping("/{id}") + public Object updateUserRole(@PathVariable Long id, @RequestBody UserRole userRole) { + userRole.setId(id); + boolean result = userRoleService.updateById(userRole); + if (result) { + return ResponseUtils.success(userRole); + } else { + return ResponseUtils.fail("Failed to update user role relationship"); + } + } + + @DeleteMapping("/{id}") + public Object deleteUserRole(@PathVariable Long id) { + boolean result = userRoleService.removeById(id); + if (result) { + return ResponseUtils.success("User role relationship deleted successfully"); + } else { + return ResponseUtils.fail("Failed to delete user role relationship"); + } + } + + @GetMapping("/user/{userId}") + public Object getUserRolesByUserId(@PathVariable Long userId) { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("user_id", userId); + List userRoles = userRoleService.list(wrapper); + return ResponseUtils.success(userRoles); + } + + @GetMapping("/role/{roleId}") + public Object getUserRolesByRoleId(@PathVariable Long roleId) { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("role_id", roleId); + List userRoles = userRoleService.list(wrapper); + return ResponseUtils.success(userRoles); + } +} \ No newline at end of file diff --git a/src/main/java/icu/sunway/ai_spring_example/Entity/Permission.java b/src/main/java/icu/sunway/ai_spring_example/Entity/Permission.java new file mode 100644 index 0000000..e4822fe --- /dev/null +++ b/src/main/java/icu/sunway/ai_spring_example/Entity/Permission.java @@ -0,0 +1,29 @@ +package icu.sunway.ai_spring_example.Entity; + +import java.time.LocalDateTime; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@TableName("permission") +public class Permission { + @TableId(type = IdType.AUTO) + private Long id; + private String name; + private String code; + private String description; + private Long parentId; + private Integer type; // 1: menu, 2: button, 3: api + private String path; + private Integer sort; + private LocalDateTime createTime; + private LocalDateTime updateTime; +} diff --git a/src/main/java/icu/sunway/ai_spring_example/Entity/Role.java b/src/main/java/icu/sunway/ai_spring_example/Entity/Role.java new file mode 100644 index 0000000..7832776 --- /dev/null +++ b/src/main/java/icu/sunway/ai_spring_example/Entity/Role.java @@ -0,0 +1,26 @@ +package icu.sunway.ai_spring_example.Entity; + +import java.time.LocalDateTime; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@TableName("role") +public class Role { + @TableId(type = IdType.AUTO) + private Long id; + private String name; + private String code; + private String description; + private Integer status; // 0: disabled, 1: enabled + private LocalDateTime createTime; + private LocalDateTime updateTime; +} diff --git a/src/main/java/icu/sunway/ai_spring_example/Entity/RolePermission.java b/src/main/java/icu/sunway/ai_spring_example/Entity/RolePermission.java new file mode 100644 index 0000000..cf72801 --- /dev/null +++ b/src/main/java/icu/sunway/ai_spring_example/Entity/RolePermission.java @@ -0,0 +1,20 @@ +package icu.sunway.ai_spring_example.Entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@TableName("role_permission") +public class RolePermission { + @TableId(type = IdType.AUTO) + private Long id; + private Long roleId; + private Long permissionId; +} diff --git a/src/main/java/icu/sunway/ai_spring_example/Entity/User.java b/src/main/java/icu/sunway/ai_spring_example/Entity/User.java new file mode 100644 index 0000000..021959d --- /dev/null +++ b/src/main/java/icu/sunway/ai_spring_example/Entity/User.java @@ -0,0 +1,29 @@ +package icu.sunway.ai_spring_example.Entity; + +import java.time.LocalDateTime; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@TableName("user") +public class User { + @TableId(type = IdType.AUTO) + private Long id; + private String username; + private String password; + private String email; + private String phone; + private String avatar; + private Integer status; // 0: disabled, 1: enabled + private LocalDateTime createTime; + private LocalDateTime updateTime; + private LocalDateTime lastLoginTime; +} diff --git a/src/main/java/icu/sunway/ai_spring_example/Entity/UserRole.java b/src/main/java/icu/sunway/ai_spring_example/Entity/UserRole.java new file mode 100644 index 0000000..c4e1a0e --- /dev/null +++ b/src/main/java/icu/sunway/ai_spring_example/Entity/UserRole.java @@ -0,0 +1,20 @@ +package icu.sunway.ai_spring_example.Entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@TableName("user_role") +public class UserRole { + @TableId(type = IdType.AUTO) + private Long id; + private Long userId; + private Long roleId; +} diff --git a/src/main/java/icu/sunway/ai_spring_example/Entity/example.sql b/src/main/java/icu/sunway/ai_spring_example/Entity/example.sql new file mode 100644 index 0000000..f3035c8 --- /dev/null +++ b/src/main/java/icu/sunway/ai_spring_example/Entity/example.sql @@ -0,0 +1,276 @@ +-- Example Data for User System + +-- Roles +INSERT INTO + `role` ( + `name`, + `code`, + `description`, + `status` + ) +VALUES ( + 'Super Admin', + 'SUPER_ADMIN', + 'Full system access', + 1 + ), + ( + 'Admin', + 'ADMIN', + 'Administrative access', + 1 + ), + ( + 'User', + 'USER', + 'Regular user access', + 1 + ), + ( + 'Guest', + 'GUEST', + 'Limited guest access', + 1 + ); + +-- Permissions +INSERT INTO + `permission` ( + `name`, + `code`, + `description`, + `parent_id`, + `type`, + `path`, + `sort` + ) +VALUES + -- Menu permissions + ( + 'Dashboard', + 'dashboard', + 'Dashboard menu', + 0, + 1, + '/dashboard', + 1 + ), + ( + 'User Management', + 'user:manage', + 'User management menu', + 0, + 1, + '/user', + 2 + ), + ( + 'Role Management', + 'role:manage', + 'Role management menu', + 0, + 1, + '/role', + 3 + ), + ( + 'System Settings', + 'system:settings', + 'System settings menu', + 0, + 1, + '/settings', + 4 + ), + -- User management buttons/actions + ( + 'View Users', + 'user:view', + 'View user list', + 2, + 2, + NULL, + 1 + ), + ( + 'Create User', + 'user:create', + 'Create new user', + 2, + 2, + NULL, + 2 + ), + ( + 'Edit User', + 'user:edit', + 'Edit user info', + 2, + 2, + NULL, + 3 + ), + ( + 'Delete User', + 'user:delete', + 'Delete user', + 2, + 2, + NULL, + 4 + ), + -- Role management buttons/actions + ( + 'View Roles', + 'role:view', + 'View role list', + 3, + 2, + NULL, + 1 + ), + ( + 'Create Role', + 'role:create', + 'Create new role', + 3, + 2, + NULL, + 2 + ), + ( + 'Edit Role', + 'role:edit', + 'Edit role info', + 3, + 2, + NULL, + 3 + ), + ( + 'Delete Role', + 'role:delete', + 'Delete role', + 3, + 2, + NULL, + 4 + ), + -- API permissions + ( + 'User API', + 'api:user', + 'User API access', + 0, + 3, + '/api/user/**', + 1 + ), + ( + 'Role API', + 'api:role', + 'Role API access', + 0, + 3, + '/api/role/**', + 2 + ); + +-- Users (passwords are bcrypt hashed for 'password123') +INSERT INTO + `user` ( + `username`, + `password`, + `email`, + `phone`, + `avatar`, + `status` + ) +VALUES ( + 'admin', + '$2a$10$N.zmdr9k7uOCQb376NoUnuTJ8iAt6Z5EHsM8lE9lBOsl7iKTVKIUi', + 'admin@example.com', + '13800000001', + NULL, + 1 + ), + ( + 'john', + '$2a$10$N.zmdr9k7uOCQb376NoUnuTJ8iAt6Z5EHsM8lE9lBOsl7iKTVKIUi', + 'john@example.com', + '13800000002', + NULL, + 1 + ), + ( + 'jane', + '$2a$10$N.zmdr9k7uOCQb376NoUnuTJ8iAt6Z5EHsM8lE9lBOsl7iKTVKIUi', + 'jane@example.com', + '13800000003', + NULL, + 1 + ), + ( + 'guest', + '$2a$10$N.zmdr9k7uOCQb376NoUnuTJ8iAt6Z5EHsM8lE9lBOsl7iKTVKIUi', + 'guest@example.com', + '13800000004', + NULL, + 1 + ); + +-- User-Role assignments +INSERT INTO + `user_role` (`user_id`, `role_id`) +VALUES (1, 1), -- admin -> SUPER_ADMIN + (2, 2), -- john -> ADMIN + (3, 3), -- jane -> USER + (4, 4); +-- guest -> GUEST + +-- Role-Permission assignments +-- SUPER_ADMIN gets all permissions +INSERT INTO + `role_permission` (`role_id`, `permission_id`) +VALUES (1, 1), + (1, 2), + (1, 3), + (1, 4), + (1, 5), + (1, 6), + (1, 7), + (1, 8), + (1, 9), + (1, 10), + (1, 11), + (1, 12), + (1, 13), + (1, 14); + +-- ADMIN gets user and role management +INSERT INTO + `role_permission` (`role_id`, `permission_id`) +VALUES (2, 1), + (2, 2), + (2, 3), + (2, 5), + (2, 6), + (2, 7), + (2, 9), + (2, 10), + (2, 11), + (2, 13), + (2, 14); + +-- USER gets dashboard and view permissions +INSERT INTO + `role_permission` (`role_id`, `permission_id`) +VALUES (3, 1), + (3, 5), + (3, 9), + (3, 13); + +-- GUEST gets only dashboard +INSERT INTO + `role_permission` (`role_id`, `permission_id`) +VALUES (4, 1); \ No newline at end of file diff --git a/src/main/java/icu/sunway/ai_spring_example/Entity/main.sql b/src/main/java/icu/sunway/ai_spring_example/Entity/main.sql new file mode 100644 index 0000000..5471bb2 --- /dev/null +++ b/src/main/java/icu/sunway/ai_spring_example/Entity/main.sql @@ -0,0 +1,70 @@ +-- User System Tables + +-- User table +CREATE TABLE `user` ( + `id` BIGINT NOT NULL AUTO_INCREMENT, + `username` VARCHAR(50) NOT NULL, + `password` VARCHAR(255) NOT NULL, + `email` VARCHAR(100), + `phone` VARCHAR(20), + `avatar` VARCHAR(255), + `status` INT DEFAULT 1 COMMENT '0: disabled, 1: enabled', + `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP, + `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `last_login_time` DATETIME, + PRIMARY KEY (`id`), + UNIQUE KEY `uk_username` (`username`), + UNIQUE KEY `uk_email` (`email`), + UNIQUE KEY `uk_phone` (`phone`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- Role table +CREATE TABLE `role` ( + `id` BIGINT NOT NULL AUTO_INCREMENT, + `name` VARCHAR(50) NOT NULL, + `code` VARCHAR(50) NOT NULL, + `description` VARCHAR(255), + `status` INT DEFAULT 1 COMMENT '0: disabled, 1: enabled', + `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP, + `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`id`), + UNIQUE KEY `uk_code` (`code`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- Permission table +CREATE TABLE `permission` ( + `id` BIGINT NOT NULL AUTO_INCREMENT, + `name` VARCHAR(50) NOT NULL, + `code` VARCHAR(100) NOT NULL, + `description` VARCHAR(255), + `parent_id` BIGINT DEFAULT 0, + `type` INT NOT NULL COMMENT '1: menu, 2: button, 3: api', + `path` VARCHAR(255), + `sort` INT DEFAULT 0, + `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP, + `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`id`), + UNIQUE KEY `uk_code` (`code`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- User-Role junction table +CREATE TABLE `user_role` ( + `id` BIGINT NOT NULL AUTO_INCREMENT, + `user_id` BIGINT NOT NULL, + `role_id` BIGINT NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `uk_user_role` (`user_id`, `role_id`), + FOREIGN KEY (`user_id`) REFERENCES `user`(`id`) ON DELETE CASCADE, + FOREIGN KEY (`role_id`) REFERENCES `role`(`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- Role-Permission junction table +CREATE TABLE `role_permission` ( + `id` BIGINT NOT NULL AUTO_INCREMENT, + `role_id` BIGINT NOT NULL, + `permission_id` BIGINT NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `uk_role_permission` (`role_id`, `permission_id`), + FOREIGN KEY (`role_id`) REFERENCES `role`(`id`) ON DELETE CASCADE, + FOREIGN KEY (`permission_id`) REFERENCES `permission`(`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; diff --git a/src/main/java/icu/sunway/ai_spring_example/Mapper/PermissionMapper.java b/src/main/java/icu/sunway/ai_spring_example/Mapper/PermissionMapper.java new file mode 100644 index 0000000..fb18b6e --- /dev/null +++ b/src/main/java/icu/sunway/ai_spring_example/Mapper/PermissionMapper.java @@ -0,0 +1,10 @@ +package icu.sunway.ai_spring_example.Mapper; + +import org.apache.ibatis.annotations.Mapper; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +import icu.sunway.ai_spring_example.Entity.Permission; + +@Mapper +public interface PermissionMapper extends BaseMapper { +} diff --git a/src/main/java/icu/sunway/ai_spring_example/Mapper/RoleMapper.java b/src/main/java/icu/sunway/ai_spring_example/Mapper/RoleMapper.java new file mode 100644 index 0000000..820d5c8 --- /dev/null +++ b/src/main/java/icu/sunway/ai_spring_example/Mapper/RoleMapper.java @@ -0,0 +1,10 @@ +package icu.sunway.ai_spring_example.Mapper; + +import org.apache.ibatis.annotations.Mapper; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +import icu.sunway.ai_spring_example.Entity.Role; + +@Mapper +public interface RoleMapper extends BaseMapper { +} diff --git a/src/main/java/icu/sunway/ai_spring_example/Mapper/RolePermissionMapper.java b/src/main/java/icu/sunway/ai_spring_example/Mapper/RolePermissionMapper.java new file mode 100644 index 0000000..c5a4b41 --- /dev/null +++ b/src/main/java/icu/sunway/ai_spring_example/Mapper/RolePermissionMapper.java @@ -0,0 +1,10 @@ +package icu.sunway.ai_spring_example.Mapper; + +import org.apache.ibatis.annotations.Mapper; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +import icu.sunway.ai_spring_example.Entity.RolePermission; + +@Mapper +public interface RolePermissionMapper extends BaseMapper { +} diff --git a/src/main/java/icu/sunway/ai_spring_example/Mapper/UserMapper.java b/src/main/java/icu/sunway/ai_spring_example/Mapper/UserMapper.java new file mode 100644 index 0000000..1276477 --- /dev/null +++ b/src/main/java/icu/sunway/ai_spring_example/Mapper/UserMapper.java @@ -0,0 +1,10 @@ +package icu.sunway.ai_spring_example.Mapper; + +import org.apache.ibatis.annotations.Mapper; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +import icu.sunway.ai_spring_example.Entity.User; + +@Mapper +public interface UserMapper extends BaseMapper { +} diff --git a/src/main/java/icu/sunway/ai_spring_example/Mapper/UserRoleMapper.java b/src/main/java/icu/sunway/ai_spring_example/Mapper/UserRoleMapper.java new file mode 100644 index 0000000..fcbd13e --- /dev/null +++ b/src/main/java/icu/sunway/ai_spring_example/Mapper/UserRoleMapper.java @@ -0,0 +1,10 @@ +package icu.sunway.ai_spring_example.Mapper; + +import org.apache.ibatis.annotations.Mapper; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +import icu.sunway.ai_spring_example.Entity.UserRole; + +@Mapper +public interface UserRoleMapper extends BaseMapper { +} diff --git a/src/main/java/icu/sunway/ai_spring_example/Service/IPermissionService.java b/src/main/java/icu/sunway/ai_spring_example/Service/IPermissionService.java new file mode 100644 index 0000000..06d21fc --- /dev/null +++ b/src/main/java/icu/sunway/ai_spring_example/Service/IPermissionService.java @@ -0,0 +1,7 @@ +package icu.sunway.ai_spring_example.Service; + +import com.baomidou.mybatisplus.extension.service.IService; +import icu.sunway.ai_spring_example.Entity.Permission; + +public interface IPermissionService extends IService { +} \ No newline at end of file diff --git a/src/main/java/icu/sunway/ai_spring_example/Service/IRolePermissionService.java b/src/main/java/icu/sunway/ai_spring_example/Service/IRolePermissionService.java new file mode 100644 index 0000000..ae9ff7e --- /dev/null +++ b/src/main/java/icu/sunway/ai_spring_example/Service/IRolePermissionService.java @@ -0,0 +1,7 @@ +package icu.sunway.ai_spring_example.Service; + +import com.baomidou.mybatisplus.extension.service.IService; +import icu.sunway.ai_spring_example.Entity.RolePermission; + +public interface IRolePermissionService extends IService { +} \ No newline at end of file diff --git a/src/main/java/icu/sunway/ai_spring_example/Service/IRoleService.java b/src/main/java/icu/sunway/ai_spring_example/Service/IRoleService.java new file mode 100644 index 0000000..b70cf96 --- /dev/null +++ b/src/main/java/icu/sunway/ai_spring_example/Service/IRoleService.java @@ -0,0 +1,7 @@ +package icu.sunway.ai_spring_example.Service; + +import com.baomidou.mybatisplus.extension.service.IService; +import icu.sunway.ai_spring_example.Entity.Role; + +public interface IRoleService extends IService { +} \ No newline at end of file diff --git a/src/main/java/icu/sunway/ai_spring_example/Service/IUserRoleService.java b/src/main/java/icu/sunway/ai_spring_example/Service/IUserRoleService.java new file mode 100644 index 0000000..c7c293d --- /dev/null +++ b/src/main/java/icu/sunway/ai_spring_example/Service/IUserRoleService.java @@ -0,0 +1,7 @@ +package icu.sunway.ai_spring_example.Service; + +import com.baomidou.mybatisplus.extension.service.IService; +import icu.sunway.ai_spring_example.Entity.UserRole; + +public interface IUserRoleService extends IService { +} \ No newline at end of file diff --git a/src/main/java/icu/sunway/ai_spring_example/Service/IUserService.java b/src/main/java/icu/sunway/ai_spring_example/Service/IUserService.java new file mode 100644 index 0000000..009a0dd --- /dev/null +++ b/src/main/java/icu/sunway/ai_spring_example/Service/IUserService.java @@ -0,0 +1,7 @@ +package icu.sunway.ai_spring_example.Service; + +import com.baomidou.mybatisplus.extension.service.IService; +import icu.sunway.ai_spring_example.Entity.User; + +public interface IUserService extends IService { +} \ No newline at end of file diff --git a/src/main/java/icu/sunway/ai_spring_example/Service/Implements/PermissionServiceImpl.java b/src/main/java/icu/sunway/ai_spring_example/Service/Implements/PermissionServiceImpl.java new file mode 100644 index 0000000..749522c --- /dev/null +++ b/src/main/java/icu/sunway/ai_spring_example/Service/Implements/PermissionServiceImpl.java @@ -0,0 +1,16 @@ +package icu.sunway.ai_spring_example.Service.Implements; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import icu.sunway.ai_spring_example.Entity.Permission; +import icu.sunway.ai_spring_example.Mapper.PermissionMapper; +import icu.sunway.ai_spring_example.Service.IPermissionService; +import org.springframework.stereotype.Service; + +import jakarta.annotation.Resource; + +@Service +public class PermissionServiceImpl extends ServiceImpl implements IPermissionService { + + @Resource + private PermissionMapper permissionMapper; +} \ No newline at end of file diff --git a/src/main/java/icu/sunway/ai_spring_example/Service/Implements/RolePermissionServiceImpl.java b/src/main/java/icu/sunway/ai_spring_example/Service/Implements/RolePermissionServiceImpl.java new file mode 100644 index 0000000..f1904f6 --- /dev/null +++ b/src/main/java/icu/sunway/ai_spring_example/Service/Implements/RolePermissionServiceImpl.java @@ -0,0 +1,17 @@ +package icu.sunway.ai_spring_example.Service.Implements; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import icu.sunway.ai_spring_example.Entity.RolePermission; +import icu.sunway.ai_spring_example.Mapper.RolePermissionMapper; +import icu.sunway.ai_spring_example.Service.IRolePermissionService; +import org.springframework.stereotype.Service; + +import jakarta.annotation.Resource; + +@Service +public class RolePermissionServiceImpl extends ServiceImpl + implements IRolePermissionService { + + @Resource + private RolePermissionMapper rolePermissionMapper; +} \ No newline at end of file diff --git a/src/main/java/icu/sunway/ai_spring_example/Service/Implements/RoleServiceImpl.java b/src/main/java/icu/sunway/ai_spring_example/Service/Implements/RoleServiceImpl.java new file mode 100644 index 0000000..eed99db --- /dev/null +++ b/src/main/java/icu/sunway/ai_spring_example/Service/Implements/RoleServiceImpl.java @@ -0,0 +1,16 @@ +package icu.sunway.ai_spring_example.Service.Implements; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import icu.sunway.ai_spring_example.Entity.Role; +import icu.sunway.ai_spring_example.Mapper.RoleMapper; +import icu.sunway.ai_spring_example.Service.IRoleService; +import org.springframework.stereotype.Service; + +import jakarta.annotation.Resource; + +@Service +public class RoleServiceImpl extends ServiceImpl implements IRoleService { + + @Resource + private RoleMapper roleMapper; +} \ No newline at end of file diff --git a/src/main/java/icu/sunway/ai_spring_example/Service/Implements/UserRoleServiceImpl.java b/src/main/java/icu/sunway/ai_spring_example/Service/Implements/UserRoleServiceImpl.java new file mode 100644 index 0000000..fdc6e34 --- /dev/null +++ b/src/main/java/icu/sunway/ai_spring_example/Service/Implements/UserRoleServiceImpl.java @@ -0,0 +1,16 @@ +package icu.sunway.ai_spring_example.Service.Implements; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import icu.sunway.ai_spring_example.Entity.UserRole; +import icu.sunway.ai_spring_example.Mapper.UserRoleMapper; +import icu.sunway.ai_spring_example.Service.IUserRoleService; +import org.springframework.stereotype.Service; + +import jakarta.annotation.Resource; + +@Service +public class UserRoleServiceImpl extends ServiceImpl implements IUserRoleService { + + @Resource + private UserRoleMapper userRoleMapper; +} \ No newline at end of file diff --git a/src/main/java/icu/sunway/ai_spring_example/Service/Implements/UserServiceImpl.java b/src/main/java/icu/sunway/ai_spring_example/Service/Implements/UserServiceImpl.java new file mode 100644 index 0000000..35ab09f --- /dev/null +++ b/src/main/java/icu/sunway/ai_spring_example/Service/Implements/UserServiceImpl.java @@ -0,0 +1,16 @@ +package icu.sunway.ai_spring_example.Service.Implements; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import icu.sunway.ai_spring_example.Entity.User; +import icu.sunway.ai_spring_example.Mapper.UserMapper; +import icu.sunway.ai_spring_example.Service.IUserService; +import org.springframework.stereotype.Service; + +import jakarta.annotation.Resource; + +@Service +public class UserServiceImpl extends ServiceImpl implements IUserService { + + @Resource + private UserMapper userMapper; +} \ No newline at end of file