mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2024-12-23 06:30:35 +03:00
437 lines
12 KiB
Go
437 lines
12 KiB
Go
|
// Copyright 2024 The Forgejo Authors. All rights reserved.
|
||
|
// SPDX-License-Identifier: MIT
|
||
|
|
||
|
package admin
|
||
|
|
||
|
import (
|
||
|
go_context "context"
|
||
|
"net/http"
|
||
|
|
||
|
"code.gitea.io/gitea/models/db"
|
||
|
quota_model "code.gitea.io/gitea/models/quota"
|
||
|
api "code.gitea.io/gitea/modules/structs"
|
||
|
"code.gitea.io/gitea/modules/web"
|
||
|
"code.gitea.io/gitea/services/context"
|
||
|
"code.gitea.io/gitea/services/convert"
|
||
|
)
|
||
|
|
||
|
// ListQuotaGroups returns all the quota groups
|
||
|
func ListQuotaGroups(ctx *context.APIContext) {
|
||
|
// swagger:operation GET /admin/quota/groups admin adminListQuotaGroups
|
||
|
// ---
|
||
|
// summary: List the available quota groups
|
||
|
// produces:
|
||
|
// - application/json
|
||
|
// responses:
|
||
|
// "200":
|
||
|
// "$ref": "#/responses/QuotaGroupList"
|
||
|
// "403":
|
||
|
// "$ref": "#/responses/forbidden"
|
||
|
|
||
|
groups, err := quota_model.ListGroups(ctx)
|
||
|
if err != nil {
|
||
|
ctx.Error(http.StatusInternalServerError, "quota_model.ListGroups", err)
|
||
|
return
|
||
|
}
|
||
|
for _, group := range groups {
|
||
|
if err = group.LoadRules(ctx); err != nil {
|
||
|
ctx.Error(http.StatusInternalServerError, "quota_model.group.LoadRules", err)
|
||
|
return
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ctx.JSON(http.StatusOK, convert.ToQuotaGroupList(groups, true))
|
||
|
}
|
||
|
|
||
|
func createQuotaGroupWithRules(ctx go_context.Context, opts *api.CreateQuotaGroupOptions) (*quota_model.Group, error) {
|
||
|
ctx, committer, err := db.TxContext(ctx)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
defer committer.Close()
|
||
|
|
||
|
group, err := quota_model.CreateGroup(ctx, opts.Name)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
for _, rule := range opts.Rules {
|
||
|
exists, err := quota_model.DoesRuleExist(ctx, rule.Name)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
if !exists {
|
||
|
var limit int64
|
||
|
if rule.Limit != nil {
|
||
|
limit = *rule.Limit
|
||
|
}
|
||
|
|
||
|
subjects, err := toLimitSubjects(rule.Subjects)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
_, err = quota_model.CreateRule(ctx, rule.Name, limit, *subjects)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
}
|
||
|
if err = group.AddRuleByName(ctx, rule.Name); err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if err = group.LoadRules(ctx); err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
return group, committer.Commit()
|
||
|
}
|
||
|
|
||
|
// CreateQuotaGroup creates a new quota group
|
||
|
func CreateQuotaGroup(ctx *context.APIContext) {
|
||
|
// swagger:operation POST /admin/quota/groups admin adminCreateQuotaGroup
|
||
|
// ---
|
||
|
// summary: Create a new quota group
|
||
|
// produces:
|
||
|
// - application/json
|
||
|
// parameters:
|
||
|
// - name: group
|
||
|
// in: body
|
||
|
// description: Definition of the quota group
|
||
|
// schema:
|
||
|
// "$ref": "#/definitions/CreateQuotaGroupOptions"
|
||
|
// required: true
|
||
|
// responses:
|
||
|
// "201":
|
||
|
// "$ref": "#/responses/QuotaGroup"
|
||
|
// "400":
|
||
|
// "$ref": "#/responses/error"
|
||
|
// "403":
|
||
|
// "$ref": "#/responses/forbidden"
|
||
|
// "409":
|
||
|
// "$ref": "#/responses/error"
|
||
|
// "422":
|
||
|
// "$ref": "#/responses/validationError"
|
||
|
|
||
|
form := web.GetForm(ctx).(*api.CreateQuotaGroupOptions)
|
||
|
|
||
|
group, err := createQuotaGroupWithRules(ctx, form)
|
||
|
if err != nil {
|
||
|
if quota_model.IsErrGroupAlreadyExists(err) {
|
||
|
ctx.Error(http.StatusConflict, "", err)
|
||
|
} else if quota_model.IsErrParseLimitSubjectUnrecognized(err) {
|
||
|
ctx.Error(http.StatusUnprocessableEntity, "", err)
|
||
|
} else {
|
||
|
ctx.Error(http.StatusInternalServerError, "quota_model.CreateGroup", err)
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
ctx.JSON(http.StatusCreated, convert.ToQuotaGroup(*group, true))
|
||
|
}
|
||
|
|
||
|
// ListUsersInQuotaGroup lists all the users in a quota group
|
||
|
func ListUsersInQuotaGroup(ctx *context.APIContext) {
|
||
|
// swagger:operation GET /admin/quota/groups/{quotagroup}/users admin adminListUsersInQuotaGroup
|
||
|
// ---
|
||
|
// summary: List users in a quota group
|
||
|
// produces:
|
||
|
// - application/json
|
||
|
// parameters:
|
||
|
// - name: quotagroup
|
||
|
// in: path
|
||
|
// description: quota group to list members of
|
||
|
// type: string
|
||
|
// required: true
|
||
|
// responses:
|
||
|
// "200":
|
||
|
// "$ref": "#/responses/UserList"
|
||
|
// "400":
|
||
|
// "$ref": "#/responses/error"
|
||
|
// "403":
|
||
|
// "$ref": "#/responses/forbidden"
|
||
|
// "404":
|
||
|
// "$ref": "#/responses/notFound"
|
||
|
|
||
|
users, err := quota_model.ListUsersInGroup(ctx, ctx.QuotaGroup.Name)
|
||
|
if err != nil {
|
||
|
ctx.Error(http.StatusInternalServerError, "quota_model.ListUsersInGroup", err)
|
||
|
return
|
||
|
}
|
||
|
ctx.JSON(http.StatusOK, convert.ToUsers(ctx, ctx.Doer, users))
|
||
|
}
|
||
|
|
||
|
// AddUserToQuotaGroup adds a user to a quota group
|
||
|
func AddUserToQuotaGroup(ctx *context.APIContext) {
|
||
|
// swagger:operation PUT /admin/quota/groups/{quotagroup}/users/{username} admin adminAddUserToQuotaGroup
|
||
|
// ---
|
||
|
// summary: Add a user to a quota group
|
||
|
// produces:
|
||
|
// - application/json
|
||
|
// parameters:
|
||
|
// - name: quotagroup
|
||
|
// in: path
|
||
|
// description: quota group to add the user to
|
||
|
// type: string
|
||
|
// required: true
|
||
|
// - name: username
|
||
|
// in: path
|
||
|
// description: username of the user to add to the quota group
|
||
|
// type: string
|
||
|
// required: true
|
||
|
// responses:
|
||
|
// "204":
|
||
|
// "$ref": "#/responses/empty"
|
||
|
// "400":
|
||
|
// "$ref": "#/responses/error"
|
||
|
// "403":
|
||
|
// "$ref": "#/responses/forbidden"
|
||
|
// "404":
|
||
|
// "$ref": "#/responses/notFound"
|
||
|
// "409":
|
||
|
// "$ref": "#/responses/error"
|
||
|
// "422":
|
||
|
// "$ref": "#/responses/validationError"
|
||
|
|
||
|
err := ctx.QuotaGroup.AddUserByID(ctx, ctx.ContextUser.ID)
|
||
|
if err != nil {
|
||
|
if quota_model.IsErrUserAlreadyInGroup(err) {
|
||
|
ctx.Error(http.StatusConflict, "", err)
|
||
|
} else {
|
||
|
ctx.Error(http.StatusInternalServerError, "quota_group.group.AddUserByID", err)
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
ctx.Status(http.StatusNoContent)
|
||
|
}
|
||
|
|
||
|
// RemoveUserFromQuotaGroup removes a user from a quota group
|
||
|
func RemoveUserFromQuotaGroup(ctx *context.APIContext) {
|
||
|
// swagger:operation DELETE /admin/quota/groups/{quotagroup}/users/{username} admin adminRemoveUserFromQuotaGroup
|
||
|
// ---
|
||
|
// summary: Remove a user from a quota group
|
||
|
// produces:
|
||
|
// - application/json
|
||
|
// parameters:
|
||
|
// - name: quotagroup
|
||
|
// in: path
|
||
|
// description: quota group to remove a user from
|
||
|
// type: string
|
||
|
// required: true
|
||
|
// - name: username
|
||
|
// in: path
|
||
|
// description: username of the user to add to the quota group
|
||
|
// type: string
|
||
|
// required: true
|
||
|
// responses:
|
||
|
// "204":
|
||
|
// "$ref": "#/responses/empty"
|
||
|
// "400":
|
||
|
// "$ref": "#/responses/error"
|
||
|
// "403":
|
||
|
// "$ref": "#/responses/forbidden"
|
||
|
// "404":
|
||
|
// "$ref": "#/responses/notFound"
|
||
|
|
||
|
err := ctx.QuotaGroup.RemoveUserByID(ctx, ctx.ContextUser.ID)
|
||
|
if err != nil {
|
||
|
if quota_model.IsErrUserNotInGroup(err) {
|
||
|
ctx.NotFound()
|
||
|
} else {
|
||
|
ctx.Error(http.StatusInternalServerError, "quota_model.group.RemoveUserByID", err)
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
ctx.Status(http.StatusNoContent)
|
||
|
}
|
||
|
|
||
|
// SetUserQuotaGroups moves the user to specific quota groups
|
||
|
func SetUserQuotaGroups(ctx *context.APIContext) {
|
||
|
// swagger:operation POST /admin/users/{username}/quota/groups admin adminSetUserQuotaGroups
|
||
|
// ---
|
||
|
// summary: Set the user's quota groups to a given list.
|
||
|
// produces:
|
||
|
// - application/json
|
||
|
// parameters:
|
||
|
// - name: username
|
||
|
// in: path
|
||
|
// description: username of the user to add to the quota group
|
||
|
// type: string
|
||
|
// required: true
|
||
|
// - name: groups
|
||
|
// in: body
|
||
|
// description: quota group to remove a user from
|
||
|
// schema:
|
||
|
// "$ref": "#/definitions/SetUserQuotaGroupsOptions"
|
||
|
// required: true
|
||
|
// responses:
|
||
|
// "204":
|
||
|
// "$ref": "#/responses/empty"
|
||
|
// "400":
|
||
|
// "$ref": "#/responses/error"
|
||
|
// "403":
|
||
|
// "$ref": "#/responses/forbidden"
|
||
|
// "404":
|
||
|
// "$ref": "#/responses/notFound"
|
||
|
// "422":
|
||
|
// "$ref": "#/responses/validationError"
|
||
|
|
||
|
form := web.GetForm(ctx).(*api.SetUserQuotaGroupsOptions)
|
||
|
|
||
|
err := quota_model.SetUserGroups(ctx, ctx.ContextUser.ID, form.Groups)
|
||
|
if err != nil {
|
||
|
if quota_model.IsErrGroupNotFound(err) {
|
||
|
ctx.Error(http.StatusUnprocessableEntity, "", err)
|
||
|
} else {
|
||
|
ctx.Error(http.StatusInternalServerError, "quota_model.SetUserGroups", err)
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
|
||
|
ctx.Status(http.StatusNoContent)
|
||
|
}
|
||
|
|
||
|
// DeleteQuotaGroup deletes a quota group
|
||
|
func DeleteQuotaGroup(ctx *context.APIContext) {
|
||
|
// swagger:operation DELETE /admin/quota/groups/{quotagroup} admin adminDeleteQuotaGroup
|
||
|
// ---
|
||
|
// summary: Delete a quota group
|
||
|
// produces:
|
||
|
// - application/json
|
||
|
// parameters:
|
||
|
// - name: quotagroup
|
||
|
// in: path
|
||
|
// description: quota group to delete
|
||
|
// type: string
|
||
|
// required: true
|
||
|
// responses:
|
||
|
// "204":
|
||
|
// "$ref": "#/responses/empty"
|
||
|
// "400":
|
||
|
// "$ref": "#/responses/error"
|
||
|
// "403":
|
||
|
// "$ref": "#/responses/forbidden"
|
||
|
// "404":
|
||
|
// "$ref": "#/responses/notFound"
|
||
|
|
||
|
err := quota_model.DeleteGroupByName(ctx, ctx.QuotaGroup.Name)
|
||
|
if err != nil {
|
||
|
ctx.Error(http.StatusInternalServerError, "quota_model.DeleteGroupByName", err)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
ctx.Status(http.StatusNoContent)
|
||
|
}
|
||
|
|
||
|
// GetQuotaGroup returns information about a quota group
|
||
|
func GetQuotaGroup(ctx *context.APIContext) {
|
||
|
// swagger:operation GET /admin/quota/groups/{quotagroup} admin adminGetQuotaGroup
|
||
|
// ---
|
||
|
// summary: Get information about the quota group
|
||
|
// produces:
|
||
|
// - application/json
|
||
|
// parameters:
|
||
|
// - name: quotagroup
|
||
|
// in: path
|
||
|
// description: quota group to query
|
||
|
// type: string
|
||
|
// required: true
|
||
|
// responses:
|
||
|
// "200":
|
||
|
// "$ref": "#/responses/QuotaGroup"
|
||
|
// "400":
|
||
|
// "$ref": "#/responses/error"
|
||
|
// "403":
|
||
|
// "$ref": "#/responses/forbidden"
|
||
|
// "404":
|
||
|
// "$ref": "#/responses/notFound"
|
||
|
|
||
|
ctx.JSON(http.StatusOK, convert.ToQuotaGroup(*ctx.QuotaGroup, true))
|
||
|
}
|
||
|
|
||
|
// AddRuleToQuotaGroup adds a rule to a quota group
|
||
|
func AddRuleToQuotaGroup(ctx *context.APIContext) {
|
||
|
// swagger:operation PUT /admin/quota/groups/{quotagroup}/rules/{quotarule} admin adminAddRuleToQuotaGroup
|
||
|
// ---
|
||
|
// summary: Adds a rule to a quota group
|
||
|
// produces:
|
||
|
// - application/json
|
||
|
// parameters:
|
||
|
// - name: quotagroup
|
||
|
// in: path
|
||
|
// description: quota group to add a rule to
|
||
|
// type: string
|
||
|
// required: true
|
||
|
// - name: quotarule
|
||
|
// in: path
|
||
|
// description: the name of the quota rule to add to the group
|
||
|
// type: string
|
||
|
// required: true
|
||
|
// responses:
|
||
|
// "204":
|
||
|
// "$ref": "#/responses/empty"
|
||
|
// "400":
|
||
|
// "$ref": "#/responses/error"
|
||
|
// "403":
|
||
|
// "$ref": "#/responses/forbidden"
|
||
|
// "404":
|
||
|
// "$ref": "#/responses/notFound"
|
||
|
// "409":
|
||
|
// "$ref": "#/responses/error"
|
||
|
// "422":
|
||
|
// "$ref": "#/responses/validationError"
|
||
|
|
||
|
err := ctx.QuotaGroup.AddRuleByName(ctx, ctx.QuotaRule.Name)
|
||
|
if err != nil {
|
||
|
if quota_model.IsErrRuleAlreadyInGroup(err) {
|
||
|
ctx.Error(http.StatusConflict, "", err)
|
||
|
} else if quota_model.IsErrRuleNotFound(err) {
|
||
|
ctx.Error(http.StatusUnprocessableEntity, "", err)
|
||
|
} else {
|
||
|
ctx.Error(http.StatusInternalServerError, "quota_model.group.AddRuleByName", err)
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
ctx.Status(http.StatusNoContent)
|
||
|
}
|
||
|
|
||
|
// RemoveRuleFromQuotaGroup removes a rule from a quota group
|
||
|
func RemoveRuleFromQuotaGroup(ctx *context.APIContext) {
|
||
|
// swagger:operation DELETE /admin/quota/groups/{quotagroup}/rules/{quotarule} admin adminRemoveRuleFromQuotaGroup
|
||
|
// ---
|
||
|
// summary: Removes a rule from a quota group
|
||
|
// produces:
|
||
|
// - application/json
|
||
|
// parameters:
|
||
|
// - name: quotagroup
|
||
|
// in: path
|
||
|
// description: quota group to add a rule to
|
||
|
// type: string
|
||
|
// required: true
|
||
|
// - name: quotarule
|
||
|
// in: path
|
||
|
// description: the name of the quota rule to remove from the group
|
||
|
// type: string
|
||
|
// required: true
|
||
|
// responses:
|
||
|
// "201":
|
||
|
// "$ref": "#/responses/empty"
|
||
|
// "400":
|
||
|
// "$ref": "#/responses/error"
|
||
|
// "403":
|
||
|
// "$ref": "#/responses/forbidden"
|
||
|
// "404":
|
||
|
// "$ref": "#/responses/notFound"
|
||
|
|
||
|
err := ctx.QuotaGroup.RemoveRuleByName(ctx, ctx.QuotaRule.Name)
|
||
|
if err != nil {
|
||
|
if quota_model.IsErrRuleNotInGroup(err) {
|
||
|
ctx.NotFound()
|
||
|
} else {
|
||
|
ctx.Error(http.StatusInternalServerError, "quota_model.group.RemoveRuleByName", err)
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
ctx.Status(http.StatusNoContent)
|
||
|
}
|