mirror of
				https://codeberg.org/forgejo/forgejo.git
				synced 2025-10-31 06:21:11 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			436 lines
		
	
	
	
		
			12 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			436 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 remove from 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 modify the quota groups from
 | |
| 	//   type: string
 | |
| 	//   required: true
 | |
| 	// - name: groups
 | |
| 	//   in: body
 | |
| 	//   description: list of groups that the user should be a member of
 | |
| 	//   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 remove a rule from
 | |
| 	//   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)
 | |
| }
 |