0
0
mirror of https://github.com/go-gitea/gitea.git synced 2025-03-09 16:43:25 +01:00
Chongyi Zheng de484e86bc
Support scoped access tokens ()
This PR adds the support for scopes of access tokens, mimicking the
design of GitHub OAuth scopes.

The changes of the core logic are in `models/auth` that `AccessToken`
struct will have a `Scope` field. The normalized (no duplication of
scope), comma-separated scope string will be stored in `access_token`
table in the database.
In `services/auth`, the scope will be stored in context, which will be
used by `reqToken` middleware in API calls. Only OAuth2 tokens will have
granular token scopes, while others like BasicAuth will default to scope
`all`.
A large amount of work happens in `routers/api/v1/api.go` and the
corresponding `tests/integration` tests, that is adding necessary scopes
to each of the API calls as they fit.


- [x] Add `Scope` field to `AccessToken`
- [x] Add access control to all API endpoints
- [x] Update frontend & backend for when creating tokens
- [x] Add a database migration for `scope` column (enable 'all' access
to past tokens)

I'm aiming to complete it before Gitea 1.19 release.

Fixes 
2023-01-17 15:46:03 -06:00

280 lines
9.5 KiB
Handlebars

{{template "base/head" .}}
<div class="page-content user settings applications">
{{template "user/settings/navbar" .}}
<div class="ui container">
{{template "base/alert" .}}
<h4 class="ui top attached header">
{{.locale.Tr "settings.manage_access_token"}}
</h4>
<div class="ui attached segment">
<div class="ui key list">
<div class="item">
{{.locale.Tr "settings.tokens_desc"}}
</div>
{{range .Tokens}}
<div class="item">
<div class="right floated content">
<button class="ui red tiny button delete-button" data-modal-id="delete-token" data-url="{{$.Link}}/delete" data-id="{{.ID}}">
{{svg "octicon-trash" 16 "mr-2"}}
{{$.locale.Tr "settings.delete_token"}}
</button>
</div>
<i class="icon tooltip{{if .HasRecentActivity}} green{{end}}" {{if .HasRecentActivity}}data-content="{{$.locale.Tr "settings.token_state_desc"}}"{{end}}>{{svg "fontawesome-send" 36}}</i>
<div class="content">
<strong>{{.Name}}</strong>
<div class="activity meta">
<i>{{$.locale.Tr "settings.add_on"}} <span><time data-format="short-date" datetime="{{.CreatedUnix.FormatLong}}">{{.CreatedUnix.FormatShort}}</time></span> — {{svg "octicon-info"}} {{if .HasUsed}}{{$.locale.Tr "settings.last_used"}} <span {{if .HasRecentActivity}}class="green"{{end}}><time data-format="short-date" datetime="{{.UpdatedUnix.FormatLong}}">{{.UpdatedUnix.FormatShort}}</time></span>{{else}}{{$.locale.Tr "settings.no_activity"}}{{end}}</i>
</div>
</div>
</div>
{{end}}
</div>
</div>
<div class="ui attached bottom segment">
<h5 class="ui top header">
{{.locale.Tr "settings.generate_new_token"}}
</h5>
<p>{{.locale.Tr "settings.new_token_desc"}}</p>
<form class="ui form ignore-dirty" action="{{.Link}}" method="post">
{{.CsrfTokenHtml}}
<div class="field {{if .Err_Name}}error{{end}}">
<label for="name">{{.locale.Tr "settings.token_name"}}</label>
<input id="name" name="name" value="{{.name}}" autofocus required>
</div>
<details class="ui optional field">
<summary class="p-2">
{{.locale.Tr "settings.select_scopes"}}
</summary>
<div class="field pl-2">
<div class="ui checkbox">
<input class="enable-system" type="checkbox" name="scope" value="repo">
<label>repo</label>
</div>
</div>
<div class="field pl-4">
<div class="field">
<div class="ui checkbox">
<input class="enable-system" type="checkbox" name="scope" value="repo:status">
<label>repo:status</label>
</div>
</div>
<div class="field">
<div class="ui checkbox">
<input class="enable-system" type="checkbox" name="scope" value="public:repo">
<label>public_repo</label>
</div>
</div>
</div>
<div class="field">
<div class="ui checkbox">
<input class="enable-system" type="checkbox" name="scope" value="admin:org">
<label>admin:org</label>
</div>
</div>
<div class="field pl-4">
<div class="field">
<div class="ui checkbox">
<input class="enable-system" type="checkbox" name="scope" value="write:org">
<label>write:org</label>
</div>
</div>
<div class="field">
<div class="ui checkbox">
<input class="enable-system" type="checkbox" name="scope" value="read:public_key">
<label>read:public_key</label>
</div>
</div>
</div>
<div class="field">
<div class="ui checkbox">
<input class="enable-system" type="checkbox" name="scope" value="admin:public_key">
<label>admin:public_key</label>
</div>
</div>
<div class="field pl-4">
<div class="field">
<div class="ui checkbox">
<input class="enable-system" type="checkbox" name="scope" value="write:public_key">
<label>write:public_key</label>
</div>
</div>
<div class="field">
<div class="ui checkbox">
<input class="enable-system" type="checkbox" name="scope" value="read:public_key">
<label>read:public_key</label>
</div>
</div>
</div>
<div class="field">
<div class="ui checkbox">
<input class="enable-system" type="checkbox" name="scope" value="admin:repo_hook">
<label>admin:repo_hook</label>
</div>
</div>
<div class="field pl-4">
<div class="field">
<div class="ui checkbox">
<input class="enable-system" type="checkbox" name="scope" value="write:repo_hook">
<label>write:repo_hook</label>
</div>
</div>
<div class="field">
<div class="ui checkbox">
<input class="enable-system" type="checkbox" name="scope" value="read:repo_hook">
<label>read:repo_hook</label>
</div>
</div>
</div>
<div class="field">
<div class="ui checkbox">
<input class="enable-system" type="checkbox" name="scope" value="admin:org_hook">
<label>admin:org_hook</label>
</div>
</div>
<div class="field">
<div class="ui checkbox">
<input class="enable-system" type="checkbox" name="scope" value="notification">
<label>notification</label>
</div>
</div>
<div class="field">
<div class="ui checkbox">
<input class="enable-system" type="checkbox" name="scope" value="user">
<label>user</label>
</div>
</div>
<div class="field pl-4">
<div class="field">
<div class="ui checkbox">
<input class="enable-system" type="checkbox" name="scope" value="read:user">
<label>read:user</label>
</div>
</div>
<div class="field">
<div class="ui checkbox">
<input class="enable-system" type="checkbox" name="scope" value="user:email">
<label>user:email</label>
</div>
</div>
<div class="field">
<div class="ui checkbox">
<input class="enable-system" type="checkbox" name="scope" value="user:follow">
<label>user:follow</label>
</div>
</div>
</div>
<div class="field">
<div class="ui checkbox">
<input class="enable-system" type="checkbox" name="scope" value="delete:repo">
<label>delete_repo</label>
</div>
</div>
<div class="field">
<div class="ui checkbox">
<input class="enable-system" type="checkbox" name="scope" value="package">
<label>package</label>
</div>
</div>
<div class="field pl-4">
<div class="field">
<div class="ui checkbox">
<input class="enable-system" type="checkbox" name="scope" value="write:package">
<label>write:package</label>
</div>
</div>
<div class="field">
<div class="ui checkbox">
<input class="enable-system" type="checkbox" name="scope" value="read:package">
<label>read:package</label>
</div>
</div>
<div class="field">
<div class="ui checkbox">
<input class="enable-system" type="checkbox" name="scope" value="delete:package">
<label>delete:package</label>
</div>
</div>
</div>
<div class="field">
<div class="ui checkbox">
<input class="enable-system" type="checkbox" name="scope" value="admin:gpg_key">
<label>admin:gpg_key</label>
</div>
</div>
<div class="field pl-4">
<div class="field">
<div class="ui checkbox">
<input class="enable-system" type="checkbox" name="scope" value="write:gpg_key">
<label>write:gpg_key</label>
</div>
</div>
<div class="field">
<div class="ui checkbox">
<input class="enable-system" type="checkbox" name="scope" value="read:gpg_key">
<label>read:gpg_key</label>
</div>
</div>
</div>
<div class="field">
<div class="ui checkbox">
<input class="enable-system" type="checkbox" name="scope" value="admin:application">
<label>admin:application</label>
</div>
</div>
<div class="field pl-4">
<div class="field">
<div class="ui checkbox">
<input class="enable-system" type="checkbox" name="scope" value="write:application">
<label>write:application</label>
</div>
</div>
<div class="field">
<div class="ui checkbox">
<input class="enable-system" type="checkbox" name="scope" value="read:application">
<label>read:application</label>
</div>
</div>
</div>
<div class="field">
<div class="ui checkbox">
<input class="enable-system" type="checkbox" name="scope" value="sudo">
<label>sudo</label>
</div>
</div>
</details>
<button class="ui green button">
{{.locale.Tr "settings.generate_token"}}
</button>
</form>
</div>
{{if .EnableOAuth2}}
{{template "user/settings/grants_oauth2" .}}
{{template "user/settings/applications_oauth2" .}}
{{end}}
</div>
</div>
<div class="ui small basic delete modal" id="delete-token">
<div class="ui icon header">
{{svg "octicon-trash"}}
{{.locale.Tr "settings.access_token_deletion"}}
</div>
<div class="content">
<p>{{.locale.Tr "settings.access_token_deletion_desc"}}</p>
</div>
<div class="actions">
<div class="ui cancel button">
<i class="remove icon"></i>
{{.locale.Tr "settings.access_token_deletion_cancel_action"}}
</div>
<div class="ui red basic inverted ok button">
<i class="checkmark icon"></i>
{{.locale.Tr "settings.access_token_deletion_confirm_action"}}
</div>
</div>
</div>
{{template "base/footer" .}}