diff --git a/models/group.go b/models/group.go index c190975..d2e6490 100644 --- a/models/group.go +++ b/models/group.go @@ -13,7 +13,6 @@ type Group struct { MaxStorage uint64 ShareEnabled bool WebDAVEnabled bool - Color string SpeedLimit int Options string `json:"-",gorm:"type:text"` diff --git a/models/migration.go b/models/migration.go index 823e55b..6eccdac 100644 --- a/models/migration.go +++ b/models/migration.go @@ -203,7 +203,6 @@ func addDefaultGroups() { PolicyList: []uint{1}, MaxStorage: 1 * 1024 * 1024 * 1024, ShareEnabled: true, - Color: "danger", WebDAVEnabled: true, OptionsSerialized: GroupOption{ ArchiveDownload: true, @@ -227,8 +226,10 @@ func addDefaultGroups() { PolicyList: []uint{1}, MaxStorage: 1 * 1024 * 1024 * 1024, ShareEnabled: true, - Color: "danger", WebDAVEnabled: true, + OptionsSerialized: GroupOption{ + ShareDownload: true, + }, } if err := DB.Create(&defaultAdminGroup).Error; err != nil { util.Log().Panic("无法创建初始注册会员用户组, %s", err) @@ -240,8 +241,12 @@ func addDefaultGroups() { // 未找到初始游客用户组时,则创建 if gorm.IsRecordNotFoundError(err) { defaultAdminGroup := Group{ - Name: "游客", - Policies: "[]", + Name: "游客", + PolicyList: []uint{}, + Policies: "[]", + OptionsSerialized: GroupOption{ + ShareDownload: true, + }, } if err := DB.Create(&defaultAdminGroup).Error; err != nil { util.Log().Panic("无法创建初始游客用户组, %s", err) diff --git a/routers/controllers/admin.go b/routers/controllers/admin.go index 6fc4e1e..68db9d2 100644 --- a/routers/controllers/admin.go +++ b/routers/controllers/admin.go @@ -227,3 +227,47 @@ func AdminDeletePolicy(c *gin.Context) { c.JSON(200, ErrorResponse(err)) } } + +// AdminListGroup 列出用户组 +func AdminListGroup(c *gin.Context) { + var service admin.AdminListService + if err := c.ShouldBindJSON(&service); err == nil { + res := service.Groups() + c.JSON(200, res) + } else { + c.JSON(200, ErrorResponse(err)) + } +} + +// AdminAddGroup 新建用户组 +func AdminAddGroup(c *gin.Context) { + var service admin.AddGroupService + if err := c.ShouldBindJSON(&service); err == nil { + res := service.Add() + c.JSON(200, res) + } else { + c.JSON(200, ErrorResponse(err)) + } +} + +// AdminDeleteGroup 删除用户组 +func AdminDeleteGroup(c *gin.Context) { + var service admin.GroupService + if err := c.ShouldBindUri(&service); err == nil { + res := service.Delete() + c.JSON(200, res) + } else { + c.JSON(200, ErrorResponse(err)) + } +} + +// AdminGetGroup 获取用户组详情 +func AdminGetGroup(c *gin.Context) { + var service admin.GroupService + if err := c.ShouldBindUri(&service); err == nil { + res := service.Get() + c.JSON(200, res) + } else { + c.JSON(200, ErrorResponse(err)) + } +} diff --git a/routers/router.go b/routers/router.go index 9f1c1f5..5e49c70 100644 --- a/routers/router.go +++ b/routers/router.go @@ -329,6 +329,7 @@ func InitMasterRouter() *gin.Engine { aria2.POST("test", controllers.AdminTestAria2) } + // 存储策略管理 policy := admin.Group("policy") { // 列出存储策略 @@ -351,6 +352,19 @@ func InitMasterRouter() *gin.Engine { policy.DELETE(":id", controllers.AdminDeletePolicy) } + // 用户组管理 + group := admin.Group("group") + { + // 列出用户组 + group.POST("list", controllers.AdminListGroup) + // 获取用户组 + group.GET(":id", controllers.AdminGetGroup) + // 创建/保存用户组 + group.POST("", controllers.AdminAddGroup) + // 删除 + group.DELETE(":id", controllers.AdminDeleteGroup) + } + } // 用户 diff --git a/service/admin/group.go b/service/admin/group.go new file mode 100644 index 0000000..0968b3a --- /dev/null +++ b/service/admin/group.go @@ -0,0 +1,117 @@ +package admin + +import ( + "fmt" + model "github.com/HFO4/cloudreve/models" + "github.com/HFO4/cloudreve/pkg/serializer" +) + +// AddGroupService 用户组添加服务 +type AddGroupService struct { + Group model.Group `json:"group" binding:"required"` +} + +// GroupService 用户组ID服务 +type GroupService struct { + ID uint `uri:"id" json:"id" binding:"required"` +} + +// Get 获取用户组详情 +func (service *GroupService) Get() serializer.Response { + group, err := model.GetGroupByID(service.ID) + if err != nil { + return serializer.Err(serializer.CodeNotFound, "存储策略不存在", err) + } + + return serializer.Response{Data: group} +} + +// Delete 删除用户组 +func (service *GroupService) Delete() serializer.Response { + // 查找用户组 + group, err := model.GetGroupByID(service.ID) + if err != nil { + return serializer.Err(serializer.CodeNotFound, "用户组不存在", err) + } + + // 是否为系统用户组 + if group.ID <= 3 { + return serializer.Err(serializer.CodeNoPermissionErr, "系统用户组无法删除", err) + } + + // 检查是否有用户使用 + total := 0 + row := model.DB.Model(&model.User{}).Where("group_id = ?", service.ID). + Select("count(id)").Row() + row.Scan(&total) + if total > 0 { + return serializer.ParamErr(fmt.Sprintf("有 %d 位用户仍属于此用户组,请先删除这些用户或者更改用户组", total), nil) + } + + model.DB.Delete(&group) + + return serializer.Response{} +} + +// Add 添加用户组 +func (service *AddGroupService) Add() serializer.Response { + if service.Group.ID > 0 { + if err := model.DB.Save(&service.Group).Error; err != nil { + return serializer.ParamErr("用户组保存失败", err) + } + } else { + if err := model.DB.Create(&service.Group).Error; err != nil { + return serializer.ParamErr("用户组添加失败", err) + } + } + + return serializer.Response{Data: service.Group.ID} +} + +// Groups 列出用户组 +func (service *AdminListService) Groups() serializer.Response { + var res []model.Group + total := 0 + + tx := model.DB.Model(&model.Group{}) + if service.OrderBy != "" { + tx = tx.Order(service.OrderBy) + } + + for k, v := range service.Conditions { + tx = tx.Where(k+" = ?", v) + } + + // 计算总数用于分页 + tx.Count(&total) + + // 查询记录 + tx.Limit(service.PageSize).Offset((service.Page - 1) * service.PageSize).Find(&res) + + // 统计每个用户组的用户总数 + statics := make(map[uint]int, len(res)) + for i := 0; i < len(res); i++ { + total := 0 + row := model.DB.Model(&model.User{}).Where("group_id = ?", res[i].ID). + Select("count(id)").Row() + row.Scan(&total) + statics[res[i].ID] = total + } + + // 汇总用户组存储策略 + policies := make(map[uint]model.Policy) + for i := 0; i < len(res); i++ { + for _, p := range res[i].PolicyList { + if _, ok := policies[p]; !ok { + policies[p], _ = model.GetPolicyByID(p) + } + } + } + + return serializer.Response{Data: map[string]interface{}{ + "total": total, + "items": res, + "statics": statics, + "policies": policies, + }} +}