diff options
Diffstat (limited to 'routers/api/v1/org')
-rw-r--r-- | routers/api/v1/org/action.go | 202 | ||||
-rw-r--r-- | routers/api/v1/org/block.go | 6 | ||||
-rw-r--r-- | routers/api/v1/org/member.go | 33 | ||||
-rw-r--r-- | routers/api/v1/org/org.go | 16 | ||||
-rw-r--r-- | routers/api/v1/org/team.go | 42 |
5 files changed, 244 insertions, 55 deletions
diff --git a/routers/api/v1/org/action.go b/routers/api/v1/org/action.go index b1cd2f0c3c..3ae5e60585 100644 --- a/routers/api/v1/org/action.go +++ b/routers/api/v1/org/action.go @@ -190,6 +190,27 @@ func (Action) GetRegistrationToken(ctx *context.APIContext) { shared.GetRegistrationToken(ctx, ctx.Org.Organization.ID, 0) } +// https://docs.github.com/en/rest/actions/self-hosted-runners?apiVersion=2022-11-28#create-a-registration-token-for-an-organization +// CreateRegistrationToken returns the token to register org runners +func (Action) CreateRegistrationToken(ctx *context.APIContext) { + // swagger:operation POST /orgs/{org}/actions/runners/registration-token organization orgCreateRunnerRegistrationToken + // --- + // summary: Get an organization's actions runner registration token + // produces: + // - application/json + // parameters: + // - name: org + // in: path + // description: name of the organization + // type: string + // required: true + // responses: + // "200": + // "$ref": "#/responses/RegistrationToken" + + shared.GetRegistrationToken(ctx, ctx.Org.Organization.ID, 0) +} + // ListVariables list org-level variables func (Action) ListVariables(ctx *context.APIContext) { // swagger:operation GET /orgs/{org}/actions/variables organization getOrgVariablesList @@ -363,13 +384,13 @@ func (Action) CreateVariable(ctx *context.APIContext) { // "$ref": "#/definitions/CreateVariableOption" // responses: // "201": - // description: response when creating an org-level variable - // "204": - // description: response when creating an org-level variable + // description: successfully created the org-level variable // "400": // "$ref": "#/responses/error" - // "404": - // "$ref": "#/responses/notFound" + // "409": + // description: variable name already exists. + // "500": + // "$ref": "#/responses/error" opt := web.GetForm(ctx).(*api.CreateVariableOption) @@ -398,7 +419,7 @@ func (Action) CreateVariable(ctx *context.APIContext) { return } - ctx.Status(http.StatusNoContent) + ctx.Status(http.StatusCreated) } // UpdateVariable update an org-level variable @@ -470,6 +491,175 @@ func (Action) UpdateVariable(ctx *context.APIContext) { ctx.Status(http.StatusNoContent) } +// ListRunners get org-level runners +func (Action) ListRunners(ctx *context.APIContext) { + // swagger:operation GET /orgs/{org}/actions/runners organization getOrgRunners + // --- + // summary: Get org-level runners + // produces: + // - application/json + // parameters: + // - name: org + // in: path + // description: name of the organization + // type: string + // required: true + // responses: + // "200": + // "$ref": "#/definitions/ActionRunnersResponse" + // "400": + // "$ref": "#/responses/error" + // "404": + // "$ref": "#/responses/notFound" + shared.ListRunners(ctx, ctx.Org.Organization.ID, 0) +} + +// GetRunner get an org-level runner +func (Action) GetRunner(ctx *context.APIContext) { + // swagger:operation GET /orgs/{org}/actions/runners/{runner_id} organization getOrgRunner + // --- + // summary: Get an org-level runner + // produces: + // - application/json + // parameters: + // - name: org + // in: path + // description: name of the organization + // type: string + // required: true + // - name: runner_id + // in: path + // description: id of the runner + // type: string + // required: true + // responses: + // "200": + // "$ref": "#/definitions/ActionRunner" + // "400": + // "$ref": "#/responses/error" + // "404": + // "$ref": "#/responses/notFound" + shared.GetRunner(ctx, ctx.Org.Organization.ID, 0, ctx.PathParamInt64("runner_id")) +} + +// DeleteRunner delete an org-level runner +func (Action) DeleteRunner(ctx *context.APIContext) { + // swagger:operation DELETE /orgs/{org}/actions/runners/{runner_id} organization deleteOrgRunner + // --- + // summary: Delete an org-level runner + // produces: + // - application/json + // parameters: + // - name: org + // in: path + // description: name of the organization + // type: string + // required: true + // - name: runner_id + // in: path + // description: id of the runner + // type: string + // required: true + // responses: + // "204": + // description: runner has been deleted + // "400": + // "$ref": "#/responses/error" + // "404": + // "$ref": "#/responses/notFound" + shared.DeleteRunner(ctx, ctx.Org.Organization.ID, 0, ctx.PathParamInt64("runner_id")) +} + +func (Action) ListWorkflowJobs(ctx *context.APIContext) { + // swagger:operation GET /orgs/{org}/actions/jobs organization getOrgWorkflowJobs + // --- + // summary: Get org-level workflow jobs + // produces: + // - application/json + // parameters: + // - name: org + // in: path + // description: name of the organization + // type: string + // required: true + // - name: status + // in: query + // description: workflow status (pending, queued, in_progress, failure, success, skipped) + // type: string + // required: false + // - name: page + // in: query + // description: page number of results to return (1-based) + // type: integer + // - name: limit + // in: query + // description: page size of results + // type: integer + // responses: + // "200": + // "$ref": "#/responses/WorkflowJobsList" + // "400": + // "$ref": "#/responses/error" + // "404": + // "$ref": "#/responses/notFound" + shared.ListJobs(ctx, ctx.Org.Organization.ID, 0, 0) +} + +func (Action) ListWorkflowRuns(ctx *context.APIContext) { + // swagger:operation GET /orgs/{org}/actions/runs organization getOrgWorkflowRuns + // --- + // summary: Get org-level workflow runs + // produces: + // - application/json + // parameters: + // - name: org + // in: path + // description: name of the organization + // type: string + // required: true + // - name: event + // in: query + // description: workflow event name + // type: string + // required: false + // - name: branch + // in: query + // description: workflow branch + // type: string + // required: false + // - name: status + // in: query + // description: workflow status (pending, queued, in_progress, failure, success, skipped) + // type: string + // required: false + // - name: actor + // in: query + // description: triggered by user + // type: string + // required: false + // - name: head_sha + // in: query + // description: triggering sha of the workflow run + // type: string + // required: false + // - name: page + // in: query + // description: page number of results to return (1-based) + // type: integer + // - name: limit + // in: query + // description: page size of results + // type: integer + // responses: + // "200": + // "$ref": "#/responses/WorkflowRunsList" + // "400": + // "$ref": "#/responses/error" + // "404": + // "$ref": "#/responses/notFound" + shared.ListRuns(ctx, ctx.Org.Organization.ID, 0) +} + var _ actions_service.API = new(Action) // Action implements actions_service.API diff --git a/routers/api/v1/org/block.go b/routers/api/v1/org/block.go index 69a5222a20..6b2f3dc615 100644 --- a/routers/api/v1/org/block.go +++ b/routers/api/v1/org/block.go @@ -47,7 +47,7 @@ func CheckUserBlock(ctx *context.APIContext) { // required: true // - name: username // in: path - // description: user to check + // description: username of the user to check // type: string // required: true // responses: @@ -71,7 +71,7 @@ func BlockUser(ctx *context.APIContext) { // required: true // - name: username // in: path - // description: user to block + // description: username of the user to block // type: string // required: true // - name: note @@ -101,7 +101,7 @@ func UnblockUser(ctx *context.APIContext) { // required: true // - name: username // in: path - // description: user to unblock + // description: username of the user to unblock // type: string // required: true // responses: diff --git a/routers/api/v1/org/member.go b/routers/api/v1/org/member.go index 2663d78b73..1c12b0cc94 100644 --- a/routers/api/v1/org/member.go +++ b/routers/api/v1/org/member.go @@ -8,6 +8,7 @@ import ( "net/url" "code.gitea.io/gitea/models/organization" + user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/routers/api/v1/user" @@ -132,7 +133,7 @@ func IsMember(ctx *context.APIContext) { // required: true // - name: username // in: path - // description: username of the user + // description: username of the user to check for an organization membership // type: string // required: true // responses: @@ -185,7 +186,7 @@ func IsPublicMember(ctx *context.APIContext) { // required: true // - name: username // in: path - // description: username of the user + // description: username of the user to check for a public organization membership // type: string // required: true // responses: @@ -210,6 +211,20 @@ func IsPublicMember(ctx *context.APIContext) { } } +func checkCanChangeOrgUserStatus(ctx *context.APIContext, targetUser *user_model.User) { + // allow user themselves to change their status, and allow admins to change any user + if targetUser.ID == ctx.Doer.ID || ctx.Doer.IsAdmin { + return + } + // allow org owners to change status of members + isOwner, err := ctx.Org.Organization.IsOwnedBy(ctx, ctx.Doer.ID) + if err != nil { + ctx.APIError(http.StatusInternalServerError, err) + } else if !isOwner { + ctx.APIError(http.StatusForbidden, "Cannot change member visibility") + } +} + // PublicizeMember make a member's membership public func PublicizeMember(ctx *context.APIContext) { // swagger:operation PUT /orgs/{org}/public_members/{username} organization orgPublicizeMember @@ -225,7 +240,7 @@ func PublicizeMember(ctx *context.APIContext) { // required: true // - name: username // in: path - // description: username of the user + // description: username of the user whose membership is to be publicized // type: string // required: true // responses: @@ -240,8 +255,8 @@ func PublicizeMember(ctx *context.APIContext) { if ctx.Written() { return } - if userToPublicize.ID != ctx.Doer.ID { - ctx.APIError(http.StatusForbidden, "Cannot publicize another member") + checkCanChangeOrgUserStatus(ctx, userToPublicize) + if ctx.Written() { return } err := organization.ChangeOrgUserStatus(ctx, ctx.Org.Organization.ID, userToPublicize.ID, true) @@ -267,7 +282,7 @@ func ConcealMember(ctx *context.APIContext) { // required: true // - name: username // in: path - // description: username of the user + // description: username of the user whose membership is to be concealed // type: string // required: true // responses: @@ -282,8 +297,8 @@ func ConcealMember(ctx *context.APIContext) { if ctx.Written() { return } - if userToConceal.ID != ctx.Doer.ID { - ctx.APIError(http.StatusForbidden, "Cannot conceal another member") + checkCanChangeOrgUserStatus(ctx, userToConceal) + if ctx.Written() { return } err := organization.ChangeOrgUserStatus(ctx, ctx.Org.Organization.ID, userToConceal.ID, false) @@ -309,7 +324,7 @@ func DeleteMember(ctx *context.APIContext) { // required: true // - name: username // in: path - // description: username of the user + // description: username of the user to remove from the organization // type: string // required: true // responses: diff --git a/routers/api/v1/org/org.go b/routers/api/v1/org/org.go index c9208f4757..cd67686065 100644 --- a/routers/api/v1/org/org.go +++ b/routers/api/v1/org/org.go @@ -26,12 +26,10 @@ import ( func listUserOrgs(ctx *context.APIContext, u *user_model.User) { listOptions := utils.GetListOptions(ctx) - showPrivate := ctx.IsSigned && (ctx.Doer.IsAdmin || ctx.Doer.ID == u.ID) - opts := organization.FindOrgOptions{ - ListOptions: listOptions, - UserID: u.ID, - IncludePrivate: showPrivate, + ListOptions: listOptions, + UserID: u.ID, + IncludeVisibility: organization.DoerViewOtherVisibility(ctx.Doer, u), } orgs, maxResults, err := db.FindAndCount[organization.Organization](ctx, opts) if err != nil { @@ -84,7 +82,7 @@ func ListUserOrgs(ctx *context.APIContext) { // parameters: // - name: username // in: path - // description: username of user + // description: username of the user whose organizations are to be listed // type: string // required: true // - name: page @@ -114,7 +112,7 @@ func GetUserOrgsPermissions(ctx *context.APIContext) { // parameters: // - name: username // in: path - // description: username of user + // description: username of the user whose permissions are to be obtained // type: string // required: true // - name: org @@ -201,7 +199,7 @@ func GetAll(ctx *context.APIContext) { listOptions := utils.GetListOptions(ctx) - publicOrgs, maxResults, err := user_model.SearchUsers(ctx, &user_model.SearchUserOptions{ + publicOrgs, maxResults, err := user_model.SearchUsers(ctx, user_model.SearchUserOptions{ Actor: ctx.Doer, ListOptions: listOptions, Type: user_model.UserTypeOrganization, @@ -393,7 +391,7 @@ func Edit(ctx *context.APIContext) { Description: optional.Some(form.Description), Website: optional.Some(form.Website), Location: optional.Some(form.Location), - Visibility: optional.FromNonDefault(api.VisibilityModes[form.Visibility]), + Visibility: optional.FromMapLookup(api.VisibilityModes, form.Visibility), RepoAdminChangeTeamAccess: optional.FromPtr(form.RepoAdminChangeTeamAccess), } if err := user_service.UpdateUser(ctx, ctx.Org.Organization.AsUser(), opts); err != nil { diff --git a/routers/api/v1/org/team.go b/routers/api/v1/org/team.go index f70e5dd235..1a1710750a 100644 --- a/routers/api/v1/org/team.go +++ b/routers/api/v1/org/team.go @@ -141,26 +141,18 @@ func GetTeam(ctx *context.APIContext) { ctx.JSON(http.StatusOK, apiTeam) } -func attachTeamUnits(team *organization.Team, units []string) { +func attachTeamUnits(team *organization.Team, defaultAccessMode perm.AccessMode, units []string) { unitTypes, _ := unit_model.FindUnitTypes(units...) team.Units = make([]*organization.TeamUnit, 0, len(units)) for _, tp := range unitTypes { team.Units = append(team.Units, &organization.TeamUnit{ OrgID: team.OrgID, Type: tp, - AccessMode: team.AccessMode, + AccessMode: defaultAccessMode, }) } } -func convertUnitsMap(unitsMap map[string]string) map[unit_model.Type]perm.AccessMode { - res := make(map[unit_model.Type]perm.AccessMode, len(unitsMap)) - for unitKey, p := range unitsMap { - res[unit_model.TypeFromKey(unitKey)] = perm.ParseAccessMode(p) - } - return res -} - func attachTeamUnitsMap(team *organization.Team, unitsMap map[string]string) { team.Units = make([]*organization.TeamUnit, 0, len(unitsMap)) for unitKey, p := range unitsMap { @@ -214,24 +206,22 @@ func CreateTeam(ctx *context.APIContext) { // "422": // "$ref": "#/responses/validationError" form := web.GetForm(ctx).(*api.CreateTeamOption) - p := perm.ParseAccessMode(form.Permission) - if p < perm.AccessModeAdmin && len(form.UnitsMap) > 0 { - p = unit_model.MinUnitAccessMode(convertUnitsMap(form.UnitsMap)) - } + teamPermission := perm.ParseAccessMode(form.Permission, perm.AccessModeNone, perm.AccessModeAdmin) team := &organization.Team{ OrgID: ctx.Org.Organization.ID, Name: form.Name, Description: form.Description, IncludesAllRepositories: form.IncludesAllRepositories, CanCreateOrgRepo: form.CanCreateOrgRepo, - AccessMode: p, + AccessMode: teamPermission, } if team.AccessMode < perm.AccessModeAdmin { if len(form.UnitsMap) > 0 { attachTeamUnitsMap(team, form.UnitsMap) } else if len(form.Units) > 0 { - attachTeamUnits(team, form.Units) + unitPerm := perm.ParseAccessMode(form.Permission, perm.AccessModeRead, perm.AccessModeWrite) + attachTeamUnits(team, unitPerm, form.Units) } else { ctx.APIErrorInternal(errors.New("units permission should not be empty")) return @@ -304,15 +294,10 @@ func EditTeam(ctx *context.APIContext) { isAuthChanged := false isIncludeAllChanged := false if !team.IsOwnerTeam() && len(form.Permission) != 0 { - // Validate permission level. - p := perm.ParseAccessMode(form.Permission) - if p < perm.AccessModeAdmin && len(form.UnitsMap) > 0 { - p = unit_model.MinUnitAccessMode(convertUnitsMap(form.UnitsMap)) - } - - if team.AccessMode != p { + teamPermission := perm.ParseAccessMode(form.Permission, perm.AccessModeNone, perm.AccessModeAdmin) + if team.AccessMode != teamPermission { isAuthChanged = true - team.AccessMode = p + team.AccessMode = teamPermission } if form.IncludesAllRepositories != nil { @@ -325,7 +310,8 @@ func EditTeam(ctx *context.APIContext) { if len(form.UnitsMap) > 0 { attachTeamUnitsMap(team, form.UnitsMap) } else if len(form.Units) > 0 { - attachTeamUnits(team, form.Units) + unitPerm := perm.ParseAccessMode(form.Permission, perm.AccessModeRead, perm.AccessModeWrite) + attachTeamUnits(team, unitPerm, form.Units) } } else { attachAdminTeamUnits(team) @@ -440,7 +426,7 @@ func GetTeamMember(ctx *context.APIContext) { // required: true // - name: username // in: path - // description: username of the member to list + // description: username of the user whose data is to be listed // type: string // required: true // responses: @@ -481,7 +467,7 @@ func AddTeamMember(ctx *context.APIContext) { // required: true // - name: username // in: path - // description: username of the user to add + // description: username of the user to add to a team // type: string // required: true // responses: @@ -523,7 +509,7 @@ func RemoveTeamMember(ctx *context.APIContext) { // required: true // - name: username // in: path - // description: username of the user to remove + // description: username of the user to remove from a team // type: string // required: true // responses: |