完成租户登录

This commit is contained in:
2025-10-29 23:07:53 +08:00
parent b9938b4c0d
commit ddf90424ba
43 changed files with 7761 additions and 474 deletions
+168 -58
View File
@@ -16,19 +16,21 @@ type AuthController struct {
beego.Controller
}
// Login 处理登录请求
// Login 处理登录请求(支持租户模式,使用租户名称)
func (c *AuthController) Login() {
var username, password string
var username, password, tenantName string
// 优先尝试从URL参数获取(Apifox测试方式)
username = c.GetString("username")
password = c.GetString("password")
tenantName = c.GetString("tenant_name")
// 如果URL参数为空,尝试从JSON请求体获取(前端方式)
if username == "" || password == "" {
if username == "" || password == "" || tenantName == "" {
var loginData struct {
Username string `json:"username"`
Password string `json:"password"`
Username string `json:"username"`
Password string `json:"password"`
TenantName string `json:"tenant_name"`
}
err := json.Unmarshal(c.Ctx.Input.RequestBody, &loginData)
@@ -44,31 +46,43 @@ func (c *AuthController) Login() {
username = loginData.Username
password = loginData.Password
tenantName = loginData.TenantName
}
// 验证参数
if tenantName == "" {
c.Data["json"] = map[string]interface{}{
"code": 1,
"message": "租户名称不能为空",
"data": nil,
}
c.ServeJSON()
return
}
// 添加日志调试
fmt.Println("接收到的登录请求:")
fmt.Println("用户名:", username)
fmt.Println("密码", password)
fmt.Println("租户名称", tenantName)
// 验证用户
fmt.Println("开始验证用户:", username)
user, err := models.ValidateUser(username, password)
// 验证用户(先验证租户,再验证租户下的用户)
fmt.Println("开始验证用户:", username, "租户:", tenantName)
user, err := models.ValidateUser(username, password, tenantName)
fmt.Println("验证结果:", err)
if user != nil {
fmt.Println("用户信息:ID=", user.Id, "Username=", user.Username, "Salt=", user.Salt)
fmt.Println("用户信息:ID=", user.Id, "Username=", user.Username, "TenantId=", user.TenantId)
}
if err != nil {
// 登录失败
c.Data["json"] = map[string]interface{}{
"code": 1,
"message": "用户名或密码错误",
"message": err.Error(),
"data": nil,
}
} else {
// 使用models包中的GenerateToken函数生成token
tokenString, err := models.GenerateToken(user.Id, user.Username)
// 使用models包中的GenerateToken函数生成token(包含租户ID
tokenString, err := models.GenerateToken(user.Id, user.Username, user.TenantId)
if err != nil {
c.Data["json"] = map[string]interface{}{
@@ -85,11 +99,12 @@ func (c *AuthController) Login() {
"accessToken": tokenString,
"token": tokenString, // 兼容性
"user": map[string]interface{}{
"id": user.Id,
"username": user.Username,
"email": user.Email,
"avatar": user.Avatar,
"nickname": user.Nickname,
"id": user.Id,
"username": user.Username,
"email": user.Email,
"avatar": user.Avatar,
"nickname": user.Nickname,
"tenant_id": user.TenantId,
},
},
}
@@ -99,14 +114,35 @@ func (c *AuthController) Login() {
c.ServeJSON()
}
// ResetPassword 重置用户密码
// ResetPassword 重置用户密码(支持租户模式)
func (c *AuthController) ResetPassword() {
// 获取请求参数
username := c.GetString("username")
superPassword := c.GetString("superPassword")
tenantId, _ := c.GetInt("tenant_id", 0)
// 如果URL参数中没有租户ID,尝试从JSON请求体获取
if tenantId == 0 {
var resetData struct {
Username string `json:"username"`
SuperPassword string `json:"superPassword"`
TenantId int `json:"tenant_id"`
}
if err := json.Unmarshal(c.Ctx.Input.RequestBody, &resetData); err == nil {
username = resetData.Username
superPassword = resetData.SuperPassword
tenantId = resetData.TenantId
}
}
if tenantId <= 0 {
c.Data["json"] = map[string]interface{}{"success": false, "message": "租户ID不能为空"}
c.ServeJSON()
return
}
// 调用模型方法
err := models.ResetPassword(username, superPassword)
err := models.ResetPassword(username, superPassword, tenantId)
if err != nil {
c.Data["json"] = map[string]interface{}{"success": false, "message": err.Error()}
@@ -117,15 +153,38 @@ func (c *AuthController) ResetPassword() {
c.ServeJSON()
}
// ChangePassword 修改用户密码
// ChangePassword 修改用户密码(支持租户模式)
func (c *AuthController) ChangePassword() {
// 获取请求参数
username := c.GetString("username")
oldPassword := c.GetString("oldPassword")
newPassword := c.GetString("newPassword")
tenantId, _ := c.GetInt("tenant_id", 0)
// 如果URL参数中没有租户ID,尝试从JSON请求体获取
if tenantId == 0 {
var changeData struct {
Username string `json:"username"`
OldPassword string `json:"oldPassword"`
NewPassword string `json:"newPassword"`
TenantId int `json:"tenant_id"`
}
if err := json.Unmarshal(c.Ctx.Input.RequestBody, &changeData); err == nil {
username = changeData.Username
oldPassword = changeData.OldPassword
newPassword = changeData.NewPassword
tenantId = changeData.TenantId
}
}
if tenantId <= 0 {
c.Data["json"] = map[string]interface{}{"success": false, "message": "租户ID不能为空"}
c.ServeJSON()
return
}
// 调用模型方法
err := models.ChangePassword(username, oldPassword, newPassword)
err := models.ChangePassword(username, oldPassword, newPassword, tenantId)
if err != nil {
c.Data["json"] = map[string]interface{}{"success": false, "message": err.Error()}
} else {
@@ -144,9 +203,11 @@ func (c *AuthController) Logout() {
c.ServeJSON()
}
// FindAllUsers 获取所有用户
// FindAllUsers 获取所有用户(支持按租户过滤)
func (c *AuthController) FindAllUsers() {
users := models.FindAllUsers()
// 从查询参数获取租户ID(可选)
tenantId, _ := c.GetInt("tenant_id", 0)
users := models.FindAllUsers(tenantId)
c.Data["json"] = map[string]interface{}{
"success": true,
"message": "获取用户列表成功",
@@ -155,10 +216,12 @@ func (c *AuthController) FindAllUsers() {
c.ServeJSON()
}
// GetUserByUsername 通过用户名查询用户信息
// GetUserByUsername 通过用户名查询用户信息(支持租户模式)
func (c *AuthController) GetUserByUsername() {
// 获取请求参数中的用户名
// 获取请求参数中的用户名和租户ID
username := c.GetString("username")
tenantId, _ := c.GetInt("tenant_id", 0)
if username == "" {
c.Data["json"] = map[string]interface{}{
"code": 1,
@@ -169,8 +232,18 @@ func (c *AuthController) GetUserByUsername() {
return
}
if tenantId <= 0 {
c.Data["json"] = map[string]interface{}{
"code": 1,
"message": "租户ID不能为空",
"data": nil,
}
c.ServeJSON()
return
}
// 调用模型层方法查询用户
user, err := models.GetUserByUsername(username) // 假设models层有这个方法
user, err := models.GetUserByUsername(username, tenantId)
if err != nil {
c.Data["json"] = map[string]interface{}{
"code": 1,
@@ -188,19 +261,19 @@ func (c *AuthController) GetUserByUsername() {
"code": 0,
"message": "查询成功",
"data": map[string]interface{}{
"id": user.Id,
"username": user.Username,
"email": user.Email,
"avatar": user.Avatar,
"nickname": user.Nickname,
// 其他需要返回的用户字段
"id": user.Id,
"username": user.Username,
"email": user.Email,
"avatar": user.Avatar,
"nickname": user.Nickname,
"tenant_id": user.TenantId,
},
}
}
c.ServeJSON()
}
// AddUser 添加新用户
// AddUser 添加新用户(支持租户模式)
func (c *AuthController) AddUser() {
// 定义接收用户数据的结构体(与JSON请求体对应)
var userData struct {
@@ -209,6 +282,7 @@ func (c *AuthController) AddUser() {
Email string `json:"email"`
Nickname string `json:"nickname"`
Avatar string `json:"avatar"`
TenantId int `json:"tenant_id"`
}
// 解析请求体JSON数据
@@ -242,6 +316,15 @@ func (c *AuthController) AddUser() {
c.ServeJSON()
return
}
if userData.TenantId <= 0 {
c.Data["json"] = map[string]interface{}{
"code": 1,
"message": "租户ID不能为空",
"data": nil,
}
c.ServeJSON()
return
}
// 调用模型层方法添加用户(传递参数,接收新用户对象)
newUser, err := models.AddUser(
@@ -250,6 +333,7 @@ func (c *AuthController) AddUser() {
userData.Email,
userData.Nickname,
userData.Avatar,
userData.TenantId,
)
if err != nil {
c.Data["json"] = map[string]interface{}{
@@ -262,26 +346,28 @@ func (c *AuthController) AddUser() {
"code": 0,
"message": "用户添加成功",
"data": map[string]interface{}{
"id": newUser.Id,
"username": newUser.Username,
"email": newUser.Email,
"nickname": newUser.Nickname,
"avatar": newUser.Avatar,
"id": newUser.Id,
"username": newUser.Username,
"email": newUser.Email,
"nickname": newUser.Nickname,
"avatar": newUser.Avatar,
"tenant_id": newUser.TenantId,
},
}
}
c.ServeJSON()
}
// UpdateUser 更新用户信息
// UpdateUser 更新用户信息(支持租户模式)
func (c *AuthController) UpdateUser() {
// 定义接收更新数据的结构体
var updateData struct {
Id int `json:"id"` // 必须包含用户ID,用于定位要更新的用户
Username string `json:"username"` // 可选更新字段
Email string `json:"email"` // 可选更新字段
Nickname string `json:"nickname"` // 可选更新字段
Avatar string `json:"avatar"` // 可选更新字段
Id int `json:"id"` // 必须包含用户ID,用于定位要更新的用户
Username string `json:"username"` // 可选更新字段
Email string `json:"email"` // 可选更新字段
Nickname string `json:"nickname"` // 可选更新字段
Avatar string `json:"avatar"` // 可选更新字段
TenantId int `json:"tenant_id"` // 必须包含租户ID,用于验证用户归属
}
// 解析请求体JSON
@@ -296,7 +382,7 @@ func (c *AuthController) UpdateUser() {
return
}
// 校验必要参数(用户ID不能为空)
// 校验必要参数(用户ID和租户ID不能为空)
if updateData.Id == 0 {
c.Data["json"] = map[string]interface{}{
"code": 1,
@@ -306,6 +392,15 @@ func (c *AuthController) UpdateUser() {
c.ServeJSON()
return
}
if updateData.TenantId <= 0 {
c.Data["json"] = map[string]interface{}{
"code": 1,
"message": "租户ID不能为空",
"data": nil,
}
c.ServeJSON()
return
}
// 调用模型层方法更新用户
updatedUser, err := models.UpdateUser(
@@ -314,6 +409,7 @@ func (c *AuthController) UpdateUser() {
updateData.Email,
updateData.Nickname,
updateData.Avatar,
updateData.TenantId,
)
if err != nil {
c.Data["json"] = map[string]interface{}{
@@ -326,39 +422,44 @@ func (c *AuthController) UpdateUser() {
"code": 0,
"message": "用户更新成功",
"data": map[string]interface{}{
"id": updatedUser.Id,
"username": updatedUser.Username,
"email": updatedUser.Email,
"nickname": updatedUser.Nickname,
"avatar": updatedUser.Avatar,
"id": updatedUser.Id,
"username": updatedUser.Username,
"email": updatedUser.Email,
"nickname": updatedUser.Nickname,
"avatar": updatedUser.Avatar,
"tenant_id": updatedUser.TenantId,
},
}
}
c.ServeJSON()
}
// DeleteUser 删除用户
// DeleteUser 删除用户(支持租户模式)
func (c *AuthController) DeleteUser() {
// 获取要删除的用户ID(从URL参数或请求体中获取)
// 获取要删除的用户ID和租户ID(从URL参数或请求体中获取)
userId, err := c.GetInt("id") // 从URL参数获取,如 /user?id=1
if err != nil {
tenantId, _ := c.GetInt("tenant_id", 0)
if err != nil || tenantId == 0 {
// 若URL参数获取失败,尝试从JSON请求体获取
var deleteData struct {
Id int `json:"id"`
Id int `json:"id"`
TenantId int `json:"tenant_id"`
}
if err := json.Unmarshal(c.Ctx.Input.RequestBody, &deleteData); err != nil {
c.Data["json"] = map[string]interface{}{
"code": 1,
"message": "用户ID获取失败: " + err.Error(),
"message": "用户ID或租户ID获取失败: " + err.Error(),
"data": nil,
}
c.ServeJSON()
return
}
userId = deleteData.Id
tenantId = deleteData.TenantId
}
// 校验用户ID
// 校验用户ID和租户ID
if userId <= 0 {
c.Data["json"] = map[string]interface{}{
"code": 1,
@@ -368,9 +469,18 @@ func (c *AuthController) DeleteUser() {
c.ServeJSON()
return
}
if tenantId <= 0 {
c.Data["json"] = map[string]interface{}{
"code": 1,
"message": "租户ID不能为空",
"data": nil,
}
c.ServeJSON()
return
}
// 调用模型层方法删除用户
err = models.DeleteUser(userId)
err = models.DeleteUser(userId, tenantId)
if err != nil {
c.Data["json"] = map[string]interface{}{
"code": 1,
+72
View File
@@ -4,6 +4,7 @@ import (
"encoding/json"
"server/models"
"github.com/beego/beego/v2/client/orm"
beego "github.com/beego/beego/v2/server/web"
)
@@ -111,6 +112,77 @@ func (c *MenuController) UpdateMenu() {
c.ServeJSON()
}
// UpdateMenuStatus 更新菜单状态
func (c *MenuController) UpdateMenuStatus() {
id, err := c.GetInt(":id")
if err != nil {
c.Data["json"] = map[string]interface{}{
"success": false,
"message": "参数错误",
}
c.ServeJSON()
return
}
// 解析请求体获取 status 字段
var req struct {
Status int8 `json:"status"`
}
// 尝试从请求体获取数据
requestBody := c.Ctx.Input.RequestBody
if len(requestBody) > 0 {
// 有请求体,从 JSON 解析
if err := json.Unmarshal(requestBody, &req); err != nil {
c.Data["json"] = map[string]interface{}{
"success": false,
"message": "请求参数错误",
}
c.ServeJSON()
return
}
} else {
// 如果请求体为空,尝试从表单参数或查询参数获取
statusValue, err := c.GetInt("status", -1)
if err != nil || statusValue == -1 {
c.Data["json"] = map[string]interface{}{
"success": false,
"message": "请求参数错误:缺少 status 参数",
}
c.ServeJSON()
return
}
req.Status = int8(statusValue)
}
// 先查询该菜单,确保存在
o := orm.NewOrm()
menu := models.Menu{Id: id}
if err = o.Read(&menu); err != nil {
c.Data["json"] = map[string]interface{}{
"success": false,
"message": "菜单不存在",
}
c.ServeJSON()
return
}
// 更新状态
menu.Status = req.Status
if _, err := o.Update(&menu, "Status"); err != nil {
c.Data["json"] = map[string]interface{}{
"success": false,
"message": "更新菜单状态失败",
}
} else {
c.Data["json"] = map[string]interface{}{
"success": true,
"message": "菜单状态更新成功",
}
}
c.ServeJSON()
}
// DeleteMenu 删除菜单
func (c *MenuController) DeleteMenu() {
id, err := c.GetInt(":id")
+208
View File
@@ -0,0 +1,208 @@
package controllers
import (
"encoding/json"
"strconv"
"server/models"
"github.com/beego/beego/v2/server/web"
)
type TenantController struct {
web.Controller
}
// GetAllTenants 获取所有租户
func (c *TenantController) GetAllTenants() {
tenants, err := models.GetTenantList()
if err != nil {
c.Data["json"] = map[string]interface{}{
"success": false,
"message": "获取租户列表失败: " + err.Error(),
}
} else {
c.Data["json"] = map[string]interface{}{
"success": true,
"message": "获取租户列表成功",
"data": tenants,
}
}
c.ServeJSON()
}
// CreateTenant 新增租户
func (c *TenantController) CreateTenant() {
var tenant models.Tenant
if err := json.Unmarshal(c.Ctx.Input.RequestBody, &tenant); err != nil {
c.Data["json"] = map[string]interface{}{
"success": false,
"message": "解析租户数据失败: " + err.Error(),
}
c.ServeJSON()
return
}
err := models.CreateTenant(&tenant)
if err != nil {
c.Data["json"] = map[string]interface{}{
"success": false,
"message": "创建租户失败: " + err.Error(),
}
} else {
c.Data["json"] = map[string]interface{}{
"success": true,
"message": "租户创建成功",
"data": tenant,
}
}
c.ServeJSON()
}
// UpdateTenant 编辑租户
func (c *TenantController) UpdateTenant() {
idStr := c.Ctx.Input.Param(":id")
id, err := strconv.Atoi(idStr)
if err != nil {
c.Data["json"] = map[string]interface{}{
"success": false,
"message": "无效的租户ID",
}
c.ServeJSON()
return
}
var data map[string]interface{}
if err := json.Unmarshal(c.Ctx.Input.RequestBody, &data); err != nil {
c.Data["json"] = map[string]interface{}{
"success": false,
"message": "解析更新数据失败: " + err.Error(),
}
c.ServeJSON()
return
}
err = models.UpdateTenant(id, data)
if err != nil {
c.Data["json"] = map[string]interface{}{
"success": false,
"message": "编辑租户失败: " + err.Error(),
}
} else {
c.Data["json"] = map[string]interface{}{
"success": true,
"message": "租户编辑成功",
}
}
c.ServeJSON()
}
// DeleteTenant 删除租户
func (c *TenantController) DeleteTenant() {
idStr := c.Ctx.Input.Param(":id")
id, err := strconv.Atoi(idStr)
if err != nil {
c.Data["json"] = map[string]interface{}{
"success": false,
"message": "无效的租户ID",
}
c.ServeJSON()
return
}
err = models.DeleteTenant(id)
if err != nil {
c.Data["json"] = map[string]interface{}{
"success": false,
"message": "删除租户失败: " + err.Error(),
}
} else {
c.Data["json"] = map[string]interface{}{
"success": true,
"message": "租户删除成功",
}
}
c.ServeJSON()
}
// AuditTenant 审核租户
func (c *TenantController) AuditTenant() {
idStr := c.Ctx.Input.Param(":id")
id, err := strconv.Atoi(idStr)
if err != nil {
c.Data["json"] = map[string]interface{}{
"success": false,
"message": "无效的租户ID",
}
c.ServeJSON()
return
}
// 解析 JSON 请求体
var auditData struct {
AuditStatus string `json:"audit_status"`
AuditComment string `json:"audit_comment"`
AuditBy string `json:"audit_by"`
}
if err := json.Unmarshal(c.Ctx.Input.RequestBody, &auditData); err != nil {
c.Data["json"] = map[string]interface{}{
"success": false,
"message": "解析审核数据失败: " + err.Error(),
}
c.ServeJSON()
return
}
if auditData.AuditStatus == "" {
c.Data["json"] = map[string]interface{}{
"success": false,
"message": "审核状态不能为空",
}
c.ServeJSON()
return
}
err = models.AuditTenant(id, auditData.AuditStatus, auditData.AuditComment, auditData.AuditBy)
if err != nil {
c.Data["json"] = map[string]interface{}{
"success": false,
"message": "审核租户失败: " + err.Error(),
}
} else {
c.Data["json"] = map[string]interface{}{
"success": true,
"message": "审核成功",
}
}
c.ServeJSON()
}
// GetTenantDetail 查看租户详情
func (c *TenantController) GetTenantDetail() {
idStr := c.Ctx.Input.Param(":id")
id, err := strconv.Atoi(idStr)
if err != nil {
c.Data["json"] = map[string]interface{}{
"success": false,
"message": "无效的租户ID",
}
c.ServeJSON()
return
}
tenant, err := models.GetTenantById(id)
if err != nil {
c.Data["json"] = map[string]interface{}{
"success": false,
"message": "获取租户详情失败: " + err.Error(),
}
} else if tenant == nil {
c.Data["json"] = map[string]interface{}{
"success": false,
"message": "租户不存在",
}
} else {
c.Data["json"] = map[string]interface{}{
"success": true,
"message": "获取租户详情成功",
"data": tenant,
}
}
c.ServeJSON()
}