mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2026-05-14 15:00:25 +00:00
Adds a user interface for creating repo-specific access tokens (#11311). When the new option "Specific repositories" is selected, a search option appears. Each repository in the search result has an "Add" button to include it on the access token, and once included, a repository can be removed with the "Remove" button. This is a JS-free form. ## Checklist The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org). ### Tests for Go changes (can be removed for JavaScript changes) - I added test coverage for Go changes... - [x] in their respective `*_test.go` for unit tests. - [ ] in the `tests/integration` directory if it involves interactions with a live Forgejo server. - I ran... - [x] `make pr-go` before pushing ### Tests for JavaScript changes - I added test coverage for JavaScript changes... - [ ] in `web_src/js/*.test.js` if it can be unit tested. - [x] in `tests/e2e/*.test.e2e.js` if it requires interactions with a live Forgejo server (see also the [developer guide for JavaScript testing](https://codeberg.org/forgejo/forgejo/src/branch/forgejo/tests/e2e/ README.md#end-to-end-tests)). - Technically there are no "JavaScript changes" in this PR, but e2e tests were added for browser interaction testing. ### Documentation - [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change. - TODO: planning to create documentation in https://forgejo.org/docs/next/user/token-scope/; there is none for public only tokens but I think this seems like a good place to add both. - [ ] I did not document these changes and I do not expect someone else to do it. ### Release notes - [x] This change will be noticed by a Forgejo user or admin (feature, bug fix, performance, etc.). I suggest to include a release note for this change. - [ ] This change is not visible to a Forgejo user or admin (refactor, dependency upgrade, etc.). I think there is no need to add a release note for this change. Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11696 Reviewed-by: Andreas Ahlenstorf <aahlenst@noreply.codeberg.org> Co-authored-by: Mathieu Fenniak <mathieu@fenniak.net> Co-committed-by: Mathieu Fenniak <mathieu@fenniak.net>
180 lines
8.8 KiB
Go HTML Template
180 lines
8.8 KiB
Go HTML Template
{{template "user/settings/layout_head" (dict "ctxData" . "pageClass" "user settings applications")}}
|
|
<div class="user-setting-content">
|
|
<h4 class="ui top attached header">
|
|
{{ctx.Locale.Tr "settings.generate_new_token"}}
|
|
</h4>
|
|
|
|
<div class="ui attached bottom segment">
|
|
<form id="scoped-access-form" class="ui form" action="{{.Link}}" method="post">
|
|
<div class="required field {{if .Err_Name}}error{{end}}">
|
|
<label for="name">{{ctx.Locale.Tr "settings.token_name"}}</label>
|
|
<input id="name" name="name" value="{{.name}}" {{if eq .Autofocus "name"}}autofocus{{end}} required maxlength="255">
|
|
</div>
|
|
<div class="field">
|
|
<fieldset>
|
|
<label>{{ctx.Locale.Tr "settings.repo_and_org_access"}}</label>
|
|
<div class="field">
|
|
<div class="field ui radio checkbox">
|
|
<input id="resource-all" class="enable-system" type="radio" name="resource" value="all" {{if eq .resource "all"}}checked{{end}}>
|
|
<label for="resource-all">{{ctx.Locale.Tr "settings.permissions_access_all"}}</label>
|
|
<p class="help">{{ctx.Locale.Tr "settings.access_token.resource_all_help"}}</p>
|
|
</div>
|
|
</div>
|
|
<div class="field">
|
|
<div class="field ui radio checkbox">
|
|
<input id="resource-public-only" class="enable-system" type="radio" name="resource" value="public-only" {{if eq .resource "public-only"}}checked{{end}}>
|
|
<label for="resource-public-only">{{ctx.Locale.Tr "settings.permissions_public_only"}}</label>
|
|
<p class="help">
|
|
{{ctx.Locale.Tr "settings.access_token.resource_public_only_help"}}
|
|
{{if $.IsAdmin}}{{ctx.Locale.Tr "settings.access_token.admin_disabled"}}{{end}}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<div class="field">
|
|
<div class="field ui radio checkbox">
|
|
<input id="resource-repo-specific" class="enable-system" type="radio" name="resource" value="repo-specific" {{if eq .resource "repo-specific"}}checked{{end}}>
|
|
<label for="resource-repo-specific">{{ctx.Locale.Tr "settings.permissions_access_specific_repositories"}}</label>
|
|
<p class="help">
|
|
{{ctx.Locale.Tr "settings.access_token.resource_specific_repo_help"}}
|
|
{{if $.IsAdmin}}{{ctx.Locale.Tr "settings.access_token.admin_disabled"}}{{end}}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</fieldset>
|
|
</div>
|
|
<div id="repo-selector-wrapper" role="group" class="field tw-mt-4">
|
|
<div id="repo-selector" class="tw-flex tw-flex-wrap tw-gap-8">
|
|
|
|
<!-- left-hand side: repo list from a search -->
|
|
<div class="ui tab active list tw-flex-1">
|
|
<h5>
|
|
{{ctx.Locale.Tr "settings.access_token.available_repositories"}}
|
|
</h5>
|
|
|
|
<div class="ui small fluid action left icon input tw-mb-3">
|
|
<input type="search" name="repo_search" spellcheck="false" {{if eq .Autofocus "search"}}autofocus{{end}} placeholder="{{ctx.Locale.Tr "search.repo_kind"}}" value="{{.repo_search}}">
|
|
<i class="icon">{{svg "octicon-search" 16}}</i>
|
|
<button class="ui small icon button" aria-label="{{ctx.Locale.Tr "search.search"}}" type="submit" name="set_page" value="1" formnovalidate="true" formmethod="get">
|
|
{{svg "octicon-search" 16}}
|
|
</button>
|
|
</div>
|
|
|
|
{{if eq (len .Repos) 0}}
|
|
{{ctx.Locale.Tr "settings.access_token.no_repositories_found"}}
|
|
{{else}}
|
|
<div class="tw-grid tw-items-center" style="grid-template-columns: min-content 1fr min-content;">
|
|
{{range .Repos}}
|
|
{{template "user/settings/repo_icon" .}}
|
|
<div class="text truncate">
|
|
{{.FullName}}
|
|
</div>
|
|
<button class="ui primary button tw-ml-2 tw-my-1 tiny" type="submit" aria-label="{{ctx.Locale.Tr "repo.editor.add" .FullName}}" formnovalidate="true" name="add_selected_repo" value="{{.FullName}}" formmethod="get">
|
|
{{ctx.Locale.Tr "add"}}
|
|
</button>
|
|
{{end}}
|
|
</div>
|
|
{{end}}
|
|
|
|
{{/* Can't use base/paginate template include here because all the pagination links in
|
|
that template are simple <a href=...> links. Here, we need to turn them into form
|
|
buttons so that we can submit the current form. If a user just changed a value (eg. set
|
|
the token name, changed a selected permission) and then clicked a pagination button, the
|
|
new value that they changed needs to be submitted. base/paginate would allow preserving
|
|
old values from before the change, but not new updates. Implementing here also allows
|
|
the use of smaller styling. */}}
|
|
{{with .Page.Paginater}}
|
|
<input type="hidden" name="page" value="{{.Current}}">
|
|
<div class="center page buttons">
|
|
<div class="ui borderless pagination menu mini">
|
|
<button class="item navigation {{if .IsFirst}}disabled{{end}}" type="submit" formnovalidate="true" name="set_page" value="1" formmethod="get">
|
|
{{svg "gitea-double-chevron-left" 16 "tw-mr-1"}}
|
|
<span class="navigation_label">{{ctx.Locale.Tr "admin.first_page"}}</span>
|
|
</button>
|
|
<button class="item navigation {{if not .HasPrevious}}disabled{{end}}" type="submit" formnovalidate="true" name="set_page" value="{{.Previous}}" formmethod="get">
|
|
{{svg "octicon-chevron-left" 16 "tw-mr-1"}}
|
|
<span class="navigation_label">{{ctx.Locale.Tr "repo.issues.previous"}}</span>
|
|
</button>
|
|
{{range .Pages}}
|
|
{{if eq .Num -1}}
|
|
<a class="disabled item">...</a>
|
|
{{else}}
|
|
<button class="item navigation {{if .IsCurrent}}active{{end}}" type="submit" formnovalidate="true" name="set_page" value="{{.Num}}" formmethod="get">
|
|
{{.Num}}
|
|
</button>
|
|
{{end}}
|
|
{{end}}
|
|
<button class="item navigation {{if not .HasNext}}disabled{{end}}" type="submit" formnovalidate="true" name="set_page" value="{{.Next}}" formmethod="get">
|
|
<span class="navigation_label">{{ctx.Locale.Tr "repo.issues.next"}}</span>
|
|
{{svg "octicon-chevron-right" 16 "tw-ml-1"}}
|
|
</button>
|
|
<button class="item navigation {{if .IsLast}}disabled{{end}}" type="submit" formnovalidate="true" name="set_page" value="{{.TotalPages}}" formmethod="get">
|
|
<span class="navigation_label">{{ctx.Locale.Tr "admin.last_page"}}</span>
|
|
{{svg "gitea-double-chevron-right" 16 "tw-ml-1"}}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
{{end}}
|
|
</div>
|
|
|
|
<!-- right-hand side: selected repositories -->
|
|
<div class="tw-flex-1">
|
|
<h5>{{ctx.Locale.TrPluralString (len .SelectedRepos) "settings.access_token.selected_repositories" (len .SelectedRepos)}}</h5>
|
|
{{if eq (len .SelectedRepos) 0}}
|
|
<div class="tw-my-2">
|
|
{{ctx.Locale.Tr "settings.access_token.no_repositories_selected"}}
|
|
</div>
|
|
{{else}}
|
|
<div class="tw-grid tw-items-center tw-auto-rows-min" style="grid-template-columns: min-content 1fr min-content;">
|
|
{{range .SelectedRepos}}
|
|
<input type="hidden" name="selected_repo" value="{{.FullName}}">
|
|
{{template "user/settings/repo_icon" .}}
|
|
<div class="text tw-text-nowrap"> <!-- nowrap, !truncate, ensures that this can be fully seen and ensures this side of the control has an appropriate min-width -->
|
|
{{.FullName}}
|
|
</div>
|
|
<button class="ui button tw-ml-2 tw-my-1 tiny" type="submit" aria-label="{{ctx.Locale.Tr "settings.access_token.remove" .FullName}}" formnovalidate="true" name="remove_selected_repo" value="{{.FullName}}" formmethod="get">
|
|
{{ctx.Locale.Tr "remove"}}
|
|
</button>
|
|
{{end}}
|
|
</div>
|
|
{{end}}
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
<div class="field">
|
|
<label>
|
|
{{ctx.Locale.Tr "settings.select_permissions"}}
|
|
</label>
|
|
<p class="activity meta">
|
|
<p>{{ctx.Locale.Tr "settings.access_token_desc" (printf "%s/api/swagger" AppSubUrl) "https://forgejo.org/docs/latest/user/token-scope/"}}</p>
|
|
</p>
|
|
|
|
{{range .Categories}}
|
|
<div class="field tw-pl-1 tw-pb-1 access-token-category">
|
|
<label class="category-label" for="access-token-scope-{{.}}">
|
|
{{.}}
|
|
</label>
|
|
<div class="gitea-select">
|
|
<select class="ui selection access-token-select" name="scope" id="access-token-scope-{{.}}">
|
|
<option value="">
|
|
{{ctx.Locale.Tr "settings.permission_no_access"}}
|
|
</option>
|
|
<option value="read:{{.}}" {{if (SliceUtils.Contains $.scope (printf "read:%s" .))}} selected {{end}}>
|
|
{{ctx.Locale.Tr "settings.permission_read"}}
|
|
</option>
|
|
<option value="write:{{.}}" {{if (SliceUtils.Contains $.scope (printf "write:%s" .))}} selected {{end}}>
|
|
{{ctx.Locale.Tr "settings.permission_write"}}
|
|
</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
{{end}}
|
|
</div>
|
|
<button id="scoped-access-submit" class="ui primary button">
|
|
{{ctx.Locale.Tr "settings.generate_token"}}
|
|
</button>
|
|
</form>
|
|
</div>
|
|
|
|
</div>
|
|
{{template "user/settings/layout_footer" .}}
|