Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve and fix bugs in runner management page #24366

Open
wants to merge 25 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 47 additions & 6 deletions models/actions/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"time"

"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/models/organization"
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/shared/types"
user_model "code.gitea.io/gitea/models/user"
Expand Down Expand Up @@ -108,15 +109,53 @@ func (r *ActionRunner) IsOnline() bool {
return false
}

// EditLink returns edit runner link
// Should ensure attributes are loaded before call this function
func (r *ActionRunner) EditLink(admin bool) string {
if admin {
return fmt.Sprintf("/admin/actions/runners/%d", r.ID)
}

switch r.BelongsToOwnerType() {
case types.OwnerTypeSystemGlobal:
return fmt.Sprintf("/admin/actions/runners/%d", r.ID)
case types.OwnerTypeIndividual:
return fmt.Sprintf("/user/settings/actions/runners/%d", r.ID)
case types.OwnerTypeRepository:
return fmt.Sprintf("%s/settings/actions/runners/%d", r.Repo.Link(), r.ID)
case types.OwnerTypeOrganization:
return fmt.Sprintf("%s/settings/actions/runners/%d", r.Owner.OrganisationLink(), r.ID)
}
return ""
}

// Editable checks if the runner is editable by the user
func (r *ActionRunner) Editable(ownerID, repoID int64) bool {
if ownerID == 0 && repoID == 0 {
return true
func (r *ActionRunner) Editable(ctx context.Context, doer, owner *user_model.User, repo *repo_model.Repository) (bool, error) {
if doer == nil {
return false, nil
}
if ownerID > 0 && r.OwnerID == ownerID {
return true

// admin can edit all runners
if doer.IsAdmin {
return true, nil
}

switch r.BelongsToOwnerType() {
case types.OwnerTypeIndividual:
return owner != nil && r.Owner.ID == doer.ID, nil
case types.OwnerTypeRepository:
return repo != nil && r.RepoID == repo.ID, nil
case types.OwnerTypeOrganization:
if (repo != nil && r.OwnerID == repo.OwnerID) || (owner != nil && r.OwnerID == owner.ID) {
isOrgAdmin, err := organization.IsOrganizationAdmin(ctx, r.OwnerID, doer.ID)
if err != nil {
return false, err
}
return isOrgAdmin, nil
}
}
return repoID > 0 && r.RepoID == repoID

return false, nil
}

// LoadAttributes loads the attributes of the runner
Expand Down Expand Up @@ -156,7 +195,9 @@ func init() {
type FindRunnerOptions struct {
db.ListOptions
RepoID int64
Repo *repo_model.Repository
OwnerID int64
Owner *user_model.User
Sort string
Filter string
IsOnline util.OptionalBool
Expand Down
2 changes: 2 additions & 0 deletions options/locale/locale_en-US.ini
Original file line number Diff line number Diff line change
Expand Up @@ -3515,6 +3515,7 @@ runners.owner_type = Type
runners.description = Description
runners.labels = Labels
runners.last_online = Last Online Time
runners.no_permission_to_edit = You don't have permission to edit this runner.
runners.runner_title = Runner
runners.task_list = Recent tasks on this runner
runners.task_list.no_tasks = There is no task yet.
Expand All @@ -3523,6 +3524,7 @@ runners.task_list.status = Status
runners.task_list.repository = Repository
runners.task_list.commit = Commit
runners.task_list.done_at = Done At
runners.task_list.no_tasks = No tasks
runners.edit_runner = Edit Runner
runners.update_runner = Update Changes
runners.update_runner_success = Runner updated successfully
Expand Down
18 changes: 15 additions & 3 deletions routers/web/repo/setting/runners.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import (

actions_model "code.gitea.io/gitea/models/actions"
"code.gitea.io/gitea/models/db"
repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/setting"
Expand All @@ -31,7 +33,9 @@ const (

type runnersCtx struct {
OwnerID int64
Owner *user_model.User
RepoID int64
Repo *repo_model.Repository
IsRepo bool
IsOrg bool
IsAdmin bool
Expand All @@ -45,7 +49,9 @@ func getRunnersCtx(ctx *context.Context) (*runnersCtx, error) {
if ctx.Data["PageIsRepoSettings"] == true {
return &runnersCtx{
RepoID: ctx.Repo.Repository.ID,
Repo: ctx.Repo.Repository,
OwnerID: 0,
Owner: nil,
IsRepo: true,
RunnersTemplate: tplRepoRunners,
RunnerEditTemplate: tplRepoRunnerEdit,
Expand All @@ -61,7 +67,9 @@ func getRunnersCtx(ctx *context.Context) (*runnersCtx, error) {
}
return &runnersCtx{
RepoID: 0,
Repo: nil,
OwnerID: ctx.Org.Organization.ID,
Owner: ctx.Org.Organization.AsUser(),
IsOrg: true,
RunnersTemplate: tplOrgRunners,
RunnerEditTemplate: tplOrgRunnerEdit,
Expand All @@ -72,7 +80,9 @@ func getRunnersCtx(ctx *context.Context) (*runnersCtx, error) {
if ctx.Data["PageIsAdmin"] == true {
return &runnersCtx{
RepoID: 0,
Repo: nil,
OwnerID: 0,
Owner: nil,
IsAdmin: true,
RunnersTemplate: tplAdminRunners,
RunnerEditTemplate: tplAdminRunnerEdit,
Expand Down Expand Up @@ -121,9 +131,11 @@ func Runners(ctx *context.Context) {
}
if rCtx.IsRepo {
opts.RepoID = rCtx.RepoID
opts.Repo = rCtx.Repo
opts.WithAvailable = true
} else if rCtx.IsOrg || rCtx.IsUser {
opts.OwnerID = rCtx.OwnerID
opts.Owner = rCtx.Owner
opts.WithAvailable = true
}
actions_shared.RunnersList(ctx, opts)
Expand All @@ -147,7 +159,7 @@ func RunnersEdit(ctx *context.Context) {
}

actions_shared.RunnerDetails(ctx, page,
ctx.ParamsInt64(":runnerid"), rCtx.OwnerID, rCtx.RepoID,
ctx.ParamsInt64(":runnerid"), rCtx.Owner, rCtx.Repo,
)
ctx.HTML(http.StatusOK, rCtx.RunnerEditTemplate)
}
Expand All @@ -159,8 +171,8 @@ func RunnersEditPost(ctx *context.Context) {
return
}
actions_shared.RunnerDetailsEditPost(ctx, ctx.ParamsInt64(":runnerid"),
rCtx.OwnerID, rCtx.RepoID,
rCtx.RedirectLink+url.PathEscape(ctx.Params(":runnerid")))
rCtx.RedirectLink+url.PathEscape(ctx.Params(":runnerid")),
rCtx.Owner, rCtx.Repo)
}

func ResetRunnerRegistrationToken(ctx *context.Context) {
Expand Down
20 changes: 14 additions & 6 deletions routers/web/shared/actions/runners.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import (

actions_model "code.gitea.io/gitea/models/actions"
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/util"
Expand Down Expand Up @@ -46,8 +48,8 @@ func RunnersList(ctx *context.Context, opts actions_model.FindRunnerOptions) {
ctx.Data["Runners"] = runners
ctx.Data["Total"] = count
ctx.Data["RegistrationToken"] = token.Token
ctx.Data["RunnerOwnerID"] = opts.OwnerID
ctx.Data["RunnerRepoID"] = opts.RepoID
ctx.Data["RunnerOwner"] = opts.Owner
ctx.Data["RunnerRepo"] = opts.Repo
ctx.Data["SortType"] = opts.Sort

pager := context.NewPagination(int(count), opts.PageSize, opts.Page, 5)
Expand All @@ -56,7 +58,7 @@ func RunnersList(ctx *context.Context, opts actions_model.FindRunnerOptions) {
}

// RunnerDetails prepares data for runners edit page
func RunnerDetails(ctx *context.Context, page int, runnerID, ownerID, repoID int64) {
func RunnerDetails(ctx *context.Context, page int, runnerID int64, owner *user.User, repo *repo.Repository) {
runner, err := actions_model.GetRunnerByID(ctx, runnerID)
if err != nil {
ctx.ServerError("GetRunnerByID", err)
Expand All @@ -66,7 +68,10 @@ func RunnerDetails(ctx *context.Context, page int, runnerID, ownerID, repoID int
ctx.ServerError("LoadAttributes", err)
return
}
if !runner.Editable(ownerID, repoID) {
if editable, err := runner.Editable(ctx, ctx.Doer, owner, repo); err != nil {
ctx.ServerError("Editable", err)
return
} else if !editable {
err = errors.New("no permission to edit this runner")
ctx.NotFound("RunnerDetails", err)
return
Expand Down Expand Up @@ -101,14 +106,17 @@ func RunnerDetails(ctx *context.Context, page int, runnerID, ownerID, repoID int
}

// RunnerDetailsEditPost response for edit runner details
func RunnerDetailsEditPost(ctx *context.Context, runnerID, ownerID, repoID int64, redirectTo string) {
func RunnerDetailsEditPost(ctx *context.Context, runnerID int64, redirectTo string, owner *user.User, repo *repo.Repository) {
runner, err := actions_model.GetRunnerByID(ctx, runnerID)
if err != nil {
log.Warn("RunnerDetailsEditPost.GetRunnerByID failed: %v, url: %s", err, ctx.Req.URL)
ctx.ServerError("RunnerDetailsEditPost.GetRunnerByID", err)
return
}
if !runner.Editable(ownerID, repoID) {
if editable, err := runner.Editable(ctx, ctx.Doer, owner, repo); err != nil {
ctx.ServerError("Editable", err)
return
} else if !editable {
ctx.NotFound("RunnerDetailsEditPost.Editable", util.NewPermissionDeniedErrorf("no permission to edit this runner"))
return
}
Expand Down
2 changes: 1 addition & 1 deletion templates/shared/actions/runner_edit.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
<h4 class="ui top attached header">
{{ctx.Locale.Tr "actions.runners.task_list"}}
</h4>
<div class="ui attached segment">
<div class="ui attached table segment">
<table class="ui very basic striped table unstackable">
<thead>
<tr>
Expand Down
10 changes: 8 additions & 2 deletions templates/shared/actions/runner_list.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,14 @@
</td>
<td>{{if .LastOnline}}{{TimeSinceUnix .LastOnline ctx.Locale}}{{else}}{{ctx.Locale.Tr "never"}}{{end}}</td>
<td class="runner-ops">
{{if .Editable $.RunnerOwnerID $.RunnerRepoID}}
<a href="{{$.Link}}/{{.ID}}">{{svg "octicon-pencil"}}</a>
{{if .Editable $.Context $.Context.Doer $.RunnerOwner $.RunnerRepo}}
{{if $.PageIsAdmin}}
<a href="{{.EditLink true}}">{{svg "octicon-pencil"}}</a>
{{else}}
<a href="{{.EditLink false}}">{{svg "octicon-pencil"}}</a>
{{end}}
{{else}}
<div class="gt-ml-3" data-tooltip-content="{{ctx.Locale.Tr "actions.runners.no_permission_to_edit"}}">{{svg "octicon-x"}}</div>
{{end}}
</td>
</tr>
Expand Down
Loading