mirror of
https://github.com/go-gitea/gitea.git
synced 2026-08-28 20:25:38 +00:00
feat: add deploy tokens (#37306)
Deploy keys only work over SSH. A deploy token is their counterpart for HTTPS: a repository scoped credential, used as the password of a Git request, with read or read and write access. It covers Git operations and LFS, and can be regenerated in place. Signed-off-by: silverwind <me@silverwind.io> Co-authored-by: Claude Mythos <noreply@anthropic.com> Co-authored-by: silverwind <me@silverwind.io> Co-authored-by: bircni <bircni@icloud.com> Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
{{if .RepoDeployKeys}}
|
||||
<div class="flex-divided-list items-with-main">
|
||||
{{range $key := .RepoDeployKeys}}
|
||||
<div class="item">
|
||||
<div class="item-leading">
|
||||
{{$usedRecently := and $key.HasUsed $key.HasRecentActivity}}
|
||||
<span class="{{if $usedRecently}}tw-text-green{{end}}" {{if $usedRecently}}data-tooltip-content="{{ctx.Locale.Tr "settings.key_state_desc"}}"{{end}}>
|
||||
{{svg (Iif $key.IsKeyTypeToken "octicon-key-asterisk" "octicon-key") 32}}
|
||||
</span>
|
||||
</div>
|
||||
<div class="item-main">
|
||||
<div class="item-title">{{$key.Name}}</div>
|
||||
{{if $key.Fingerprint}}
|
||||
<div class="item-body">{{$key.Fingerprint}}</div>
|
||||
{{end}}
|
||||
<div class="item-body">
|
||||
{{ctx.Locale.Tr "settings.added_on" (DateUtils.AbsoluteShort $key.CreatedUnix)}}
|
||||
·
|
||||
{{if $key.HasUsed}}{{ctx.Locale.Tr "settings.last_used"}}
|
||||
<span {{if $key.HasRecentActivity}}class="tw-text-green"{{end}}>{{DateUtils.AbsoluteShort $key.UpdatedUnix}}</span>
|
||||
{{else}}
|
||||
{{ctx.Locale.Tr "settings.no_activity"}}
|
||||
{{end}}
|
||||
·
|
||||
{{ctx.Locale.Tr "settings.can_read_info"}}
|
||||
{{if not $key.IsReadOnly}} · {{ctx.Locale.Tr "settings.can_write_info"}}{{end}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="item-trailing">
|
||||
{{if $key.IsKeyTypeToken}}
|
||||
<button class="ui tiny button link-action" data-modal-confirm="#repo-deploy-token-regenerate-modal" data-url="{{ctx.RootData.Link}}/regenerate-token?id={{$key.ID}}">
|
||||
{{svg "octicon-sync"}} {{ctx.Locale.Tr "settings.regenerate_token"}}
|
||||
</button>
|
||||
{{end}}
|
||||
<button class="ui red tiny button link-action" data-modal-confirm="#repo-deploy-key-delete-modal" data-url="{{ctx.RootData.Link}}/delete?id={{$key.ID}}">
|
||||
{{ctx.Locale.Tr "settings.delete_key"}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
{{else}}
|
||||
{{ctx.Locale.Tr "repo.settings.no_deploy_keys"}}
|
||||
{{end}}
|
||||
@@ -1,92 +1,75 @@
|
||||
{{template "repo/settings/layout_head" (dict "pageClass" "repository settings")}}
|
||||
<div class="repo-setting-content">
|
||||
<h4 class="ui top attached header">
|
||||
{{ctx.Locale.Tr "repo.settings.deploy_keys"}}
|
||||
<div class="ui right">
|
||||
<div class="repo-setting-content">
|
||||
<h4 class="ui top attached header">
|
||||
{{ctx.Locale.Tr "repo.settings.deploy_keys"}}
|
||||
<div class="ui right">
|
||||
{{if not .DisableSSH}}
|
||||
<button class="ui primary tiny show-panel toggle button" data-panel="#add-deploy-key-panel">{{ctx.Locale.Tr "repo.settings.add_deploy_key"}}</button>
|
||||
<button class="ui primary compact tiny button show-panel toggle" data-panel="#add-deploy-key-ssh-panel" data-panel-hide="#add-deploy-key-token-panel">{{ctx.Locale.Tr "repo.settings.add_deploy_key_ssh"}}</button>
|
||||
{{else}}
|
||||
<button class="ui primary tiny button disabled">{{ctx.Locale.Tr "settings.ssh_disabled"}}</button>
|
||||
{{end}}
|
||||
</div>
|
||||
</h4>
|
||||
<div class="ui attached segment">
|
||||
<div class="tw-hidden tw-mb-4" id="add-deploy-key-panel">
|
||||
<form class="ui form form-fetch-action" action="{{.Link}}" method="post">
|
||||
<div class="field">
|
||||
{{ctx.Locale.Tr "repo.settings.deploy_key_desc"}}
|
||||
</div>
|
||||
<div class="field">
|
||||
<label for="ssh-key-title">{{ctx.Locale.Tr "repo.settings.title"}}</label>
|
||||
<input id="ssh-key-title" name="title" value="{{.title}}" autofocus required>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label for="ssh-key-content">{{ctx.Locale.Tr "repo.settings.deploy_key_content"}}</label>
|
||||
<textarea id="ssh-key-content" name="content" placeholder="{{ctx.Locale.Tr "settings.key_content_ssh_placeholder"}}" required>{{.content}}</textarea>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input id="ssh-key-is-writable" name="is_writable" type="checkbox" value="1">
|
||||
<label for="ssh-key-is-writable">
|
||||
{{ctx.Locale.Tr "repo.settings.is_writable"}}
|
||||
</label>
|
||||
<small class="tw-pl-[26px]">{{ctx.Locale.Tr "repo.settings.is_writable_info"}}</small>
|
||||
</div>
|
||||
</div>
|
||||
<button class="ui primary button">
|
||||
{{ctx.Locale.Tr "repo.settings.add_deploy_key"}}
|
||||
</button>
|
||||
<button class="ui hide-panel button" data-panel="#add-deploy-key-panel">
|
||||
{{ctx.Locale.Tr "cancel"}}
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
{{if .RepoDeployKeys}}
|
||||
<div class="flex-divided-list items-with-main">
|
||||
{{range $deployKey := .RepoDeployKeys}}
|
||||
<div class="item">
|
||||
<div class="item-leading">
|
||||
<span class="{{if $deployKey.HasRecentActivity}}tw-text-green{{end}}"
|
||||
{{if $deployKey.HasRecentActivity}}data-tooltip-content="{{ctx.Locale.Tr "settings.key_state_desc"}}"{{end}}
|
||||
>{{svg "octicon-key" 32}}</span>
|
||||
</div>
|
||||
<div class="item-main">
|
||||
<div class="item-title">{{$deployKey.Name}}</div>
|
||||
<div class="item-body">
|
||||
{{$deployKey.Fingerprint}}
|
||||
</div>
|
||||
<div class="item-body">
|
||||
{{ctx.Locale.Tr "settings.added_on" (DateUtils.AbsoluteShort $deployKey.CreatedUnix)}}
|
||||
<span class="tw-mx-2">-</span>
|
||||
{{svg "octicon-info"}}
|
||||
{{if $deployKey.HasUsed}}
|
||||
{{ctx.Locale.Tr "settings.last_used"}}
|
||||
<span {{if $deployKey.HasRecentActivity}}class="tw-text-green"{{end}}>{{DateUtils.AbsoluteShort $deployKey.UpdatedUnix}}</span>
|
||||
{{else}}
|
||||
{{ctx.Locale.Tr "settings.no_activity"}}
|
||||
{{end}}
|
||||
<span class="tw-mx-2">-</span>
|
||||
<span>{{ctx.Locale.Tr "settings.can_read_info"}}{{if not $deployKey.IsReadOnly}} / {{ctx.Locale.Tr "settings.can_write_info"}} {{end}}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item-trailing">
|
||||
<button class="ui red tiny button link-action" data-modal-confirm="#repo-deploy-key-delete-modal" data-url="{{$.Link}}/delete?id={{$deployKey.ID}}">
|
||||
{{ctx.Locale.Tr "settings.delete_key"}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
{{else}}
|
||||
{{ctx.Locale.Tr "repo.settings.no_deploy_keys"}}
|
||||
<button class="ui primary compact tiny button disabled">{{ctx.Locale.Tr "settings.ssh_disabled"}}</button>
|
||||
{{end}}
|
||||
<button class="ui primary compact tiny button show-panel toggle" data-panel="#add-deploy-key-token-panel" data-panel-hide="#add-deploy-key-ssh-panel">{{ctx.Locale.Tr "repo.settings.generate_deploy_token"}}</button>
|
||||
</div>
|
||||
</h4>
|
||||
<div class="ui attached segment">
|
||||
<div class="tw-hidden tw-mb-4" id="add-deploy-key-ssh-panel">
|
||||
<form class="ui form form-fetch-action" action="{{.Link}}" method="post">
|
||||
<div class="field">{{ctx.Locale.Tr "repo.settings.deploy_key_ssh_desc"}}</div>
|
||||
<div class="field">
|
||||
<label>{{ctx.Locale.Tr "repo.settings.title"}}</label>
|
||||
<input name="title" autofocus required>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>{{ctx.Locale.Tr "settings.key_content"}}</label>
|
||||
<textarea name="content" placeholder="{{ctx.Locale.Tr "settings.key_content_ssh_placeholder"}}" required></textarea>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input name="is_writable" type="checkbox" value="1">
|
||||
<label>{{ctx.Locale.Tr "repo.settings.is_writable"}}</label>
|
||||
<small class="tw-pl-[20px]">{{ctx.Locale.Tr "repo.settings.is_writable_info"}}</small>
|
||||
</div>
|
||||
</div>
|
||||
<button class="ui primary button">{{ctx.Locale.Tr "repo.settings.add_deploy_key_ssh"}}</button>
|
||||
<button class="ui hide-panel button" data-panel="#add-deploy-key-ssh-panel">{{ctx.Locale.Tr "cancel"}}</button>
|
||||
</form>
|
||||
<div class="divider"></div>
|
||||
</div>
|
||||
|
||||
<div class="tw-hidden tw-mb-4" id="add-deploy-key-token-panel">
|
||||
<form class="ui form form-fetch-action" action="{{.Link}}/generate-token" method="post">
|
||||
<div class="field">{{ctx.Locale.Tr "repo.settings.deploy_key_token_desc"}}</div>
|
||||
<div class="field">
|
||||
<label>{{ctx.Locale.Tr "repo.settings.title"}}</label>
|
||||
<input name="title" autofocus required>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input name="is_writable" type="checkbox" value="1">
|
||||
<label>{{ctx.Locale.Tr "repo.settings.is_writable"}}</label>
|
||||
<small class="tw-pl-[20px]">{{ctx.Locale.Tr "repo.settings.is_writable_info"}}</small>
|
||||
</div>
|
||||
</div>
|
||||
<button class="ui primary button">{{ctx.Locale.Tr "repo.settings.generate_deploy_token"}}</button>
|
||||
<button class="ui hide-panel button" data-panel="#add-deploy-key-token-panel">{{ctx.Locale.Tr "cancel"}}</button>
|
||||
</form>
|
||||
<div class="divider"></div>
|
||||
</div>
|
||||
|
||||
{{template "repo/settings/deploy_key_list" dict "RepoDeployKeys" .RepoDeployKeys}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ui small modal" id="repo-deploy-key-delete-modal">
|
||||
<div class="header">{{svg "octicon-trash"}} {{ctx.Locale.Tr "repo.settings.deploy_key_deletion"}}</div>
|
||||
<div class="header">{{svg "octicon-trash"}} {{ctx.Locale.Tr "remove"}}</div>
|
||||
<div class="content"><p>{{ctx.Locale.Tr "repo.settings.deploy_key_deletion_desc"}}</p></div>
|
||||
{{template "base/modal_actions_confirm" .}}
|
||||
</div>
|
||||
|
||||
<div class="ui small modal" id="repo-deploy-token-regenerate-modal">
|
||||
<div class="header">{{svg "octicon-sync"}} {{ctx.Locale.Tr "settings.regenerate_token"}}</div>
|
||||
<div class="content"><p>{{ctx.Locale.Tr "repo.settings.regenerate_deploy_token_desc"}}</p></div>
|
||||
{{template "base/modal_actions_confirm" .}}
|
||||
</div>
|
||||
|
||||
{{template "repo/settings/layout_footer" .}}
|
||||
|
||||
+87
-5
@@ -3973,6 +3973,26 @@
|
||||
"type": "object",
|
||||
"x-go-package": "gitea.dev/modules/structs"
|
||||
},
|
||||
"CreateDeployKeyTokenOption": {
|
||||
"properties": {
|
||||
"read_only": {
|
||||
"description": "Describe if the token has only read access or read/write",
|
||||
"type": "boolean",
|
||||
"x-go-name": "ReadOnly"
|
||||
},
|
||||
"title": {
|
||||
"description": "Title of the token to add",
|
||||
"type": "string",
|
||||
"uniqueItems": true,
|
||||
"x-go-name": "Title"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"title"
|
||||
],
|
||||
"type": "object",
|
||||
"x-go-package": "gitea.dev/modules/structs"
|
||||
},
|
||||
"CreateEmailOption": {
|
||||
"description": "CreateEmailOption options when creating email addresses",
|
||||
"properties": {
|
||||
@@ -4227,7 +4247,6 @@
|
||||
"x-go-package": "gitea.dev/modules/structs"
|
||||
},
|
||||
"CreateKeyOption": {
|
||||
"description": "CreateKeyOption options when creating a key",
|
||||
"properties": {
|
||||
"key": {
|
||||
"description": "An armored SSH key to add",
|
||||
@@ -5195,10 +5214,9 @@
|
||||
"x-go-package": "gitea.dev/modules/structs"
|
||||
},
|
||||
"DeployKey": {
|
||||
"description": "DeployKey a deploy key",
|
||||
"properties": {
|
||||
"created_at": {
|
||||
"description": "Created is the time when the deploy key was added",
|
||||
"description": "Created is the time when the deploy-key was added",
|
||||
"format": "date-time",
|
||||
"type": "string",
|
||||
"x-go-name": "Created"
|
||||
@@ -5209,7 +5227,7 @@
|
||||
"x-go-name": "Fingerprint"
|
||||
},
|
||||
"id": {
|
||||
"description": "ID is the unique identifier for the deploy key",
|
||||
"description": "ID is the unique identifier for the deploy-key",
|
||||
"format": "int64",
|
||||
"type": "integer",
|
||||
"x-go-name": "ID"
|
||||
@@ -5225,6 +5243,15 @@
|
||||
"type": "integer",
|
||||
"x-go-name": "KeyID"
|
||||
},
|
||||
"key_type": {
|
||||
"description": "Type tells whether the key authenticates over SSH or with a token over HTTPS",
|
||||
"enum": [
|
||||
"ssh",
|
||||
"token"
|
||||
],
|
||||
"type": "string",
|
||||
"x-go-name": "KeyType"
|
||||
},
|
||||
"read_only": {
|
||||
"description": "ReadOnly indicates if the key has read-only access",
|
||||
"type": "boolean",
|
||||
@@ -5238,8 +5265,13 @@
|
||||
"type": "string",
|
||||
"x-go-name": "Title"
|
||||
},
|
||||
"token": {
|
||||
"description": "Token is the plaintext token of an HTTPS key, only returned when it is created",
|
||||
"type": "string",
|
||||
"x-go-name": "Token"
|
||||
},
|
||||
"url": {
|
||||
"description": "URL is the API URL for this deploy key",
|
||||
"description": "URL is the API URL for this deploy-key",
|
||||
"format": "uri",
|
||||
"type": "string",
|
||||
"x-go-name": "URL"
|
||||
@@ -26543,6 +26575,56 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"/repos/{owner}/{repo}/keys/tokens": {
|
||||
"post": {
|
||||
"operationId": "repoCreateDeployToken",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "owner of the repo",
|
||||
"in": "path",
|
||||
"name": "owner",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "name of the repo",
|
||||
"in": "path",
|
||||
"name": "repo",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/CreateDeployKeyTokenOption"
|
||||
}
|
||||
}
|
||||
},
|
||||
"x-originalParamName": "body"
|
||||
},
|
||||
"responses": {
|
||||
"201": {
|
||||
"$ref": "#/components/responses/DeployKey"
|
||||
},
|
||||
"404": {
|
||||
"$ref": "#/components/responses/notFound"
|
||||
},
|
||||
"422": {
|
||||
"$ref": "#/components/responses/validationError"
|
||||
}
|
||||
},
|
||||
"summary": "Add a deploy token to a repository, it authenticates git over HTTPS",
|
||||
"tags": [
|
||||
"repository"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/repos/{owner}/{repo}/keys/{id}": {
|
||||
"delete": {
|
||||
"operationId": "repoDeleteKey",
|
||||
|
||||
+86
-5
@@ -14457,6 +14457,55 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/repos/{owner}/{repo}/keys/tokens": {
|
||||
"post": {
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"repository"
|
||||
],
|
||||
"summary": "Add a deploy token to a repository, it authenticates git over HTTPS",
|
||||
"operationId": "repoCreateDeployToken",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "owner of the repo",
|
||||
"name": "owner",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "name of the repo",
|
||||
"name": "repo",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "body",
|
||||
"in": "body",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/CreateDeployKeyTokenOption"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"201": {
|
||||
"$ref": "#/responses/DeployKey"
|
||||
},
|
||||
"404": {
|
||||
"$ref": "#/responses/notFound"
|
||||
},
|
||||
"422": {
|
||||
"$ref": "#/responses/validationError"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/repos/{owner}/{repo}/keys/{id}": {
|
||||
"get": {
|
||||
"produces": [
|
||||
@@ -26937,6 +26986,26 @@
|
||||
},
|
||||
"x-go-package": "gitea.dev/modules/structs"
|
||||
},
|
||||
"CreateDeployKeyTokenOption": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"title"
|
||||
],
|
||||
"properties": {
|
||||
"read_only": {
|
||||
"description": "Describe if the token has only read access or read/write",
|
||||
"type": "boolean",
|
||||
"x-go-name": "ReadOnly"
|
||||
},
|
||||
"title": {
|
||||
"description": "Title of the token to add",
|
||||
"type": "string",
|
||||
"uniqueItems": true,
|
||||
"x-go-name": "Title"
|
||||
}
|
||||
},
|
||||
"x-go-package": "gitea.dev/modules/structs"
|
||||
},
|
||||
"CreateEmailOption": {
|
||||
"description": "CreateEmailOption options when creating email addresses",
|
||||
"type": "object",
|
||||
@@ -27190,7 +27259,6 @@
|
||||
"x-go-package": "gitea.dev/modules/structs"
|
||||
},
|
||||
"CreateKeyOption": {
|
||||
"description": "CreateKeyOption options when creating a key",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"title",
|
||||
@@ -28186,11 +28254,10 @@
|
||||
"x-go-package": "gitea.dev/modules/structs"
|
||||
},
|
||||
"DeployKey": {
|
||||
"description": "DeployKey a deploy key",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"created_at": {
|
||||
"description": "Created is the time when the deploy key was added",
|
||||
"description": "Created is the time when the deploy-key was added",
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"x-go-name": "Created"
|
||||
@@ -28201,7 +28268,7 @@
|
||||
"x-go-name": "Fingerprint"
|
||||
},
|
||||
"id": {
|
||||
"description": "ID is the unique identifier for the deploy key",
|
||||
"description": "ID is the unique identifier for the deploy-key",
|
||||
"type": "integer",
|
||||
"format": "int64",
|
||||
"x-go-name": "ID"
|
||||
@@ -28217,6 +28284,15 @@
|
||||
"format": "int64",
|
||||
"x-go-name": "KeyID"
|
||||
},
|
||||
"key_type": {
|
||||
"description": "Type tells whether the key authenticates over SSH or with a token over HTTPS",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"ssh",
|
||||
"token"
|
||||
],
|
||||
"x-go-name": "KeyType"
|
||||
},
|
||||
"read_only": {
|
||||
"description": "ReadOnly indicates if the key has read-only access",
|
||||
"type": "boolean",
|
||||
@@ -28230,8 +28306,13 @@
|
||||
"type": "string",
|
||||
"x-go-name": "Title"
|
||||
},
|
||||
"token": {
|
||||
"description": "Token is the plaintext token of an HTTPS key, only returned when it is created",
|
||||
"type": "string",
|
||||
"x-go-name": "Token"
|
||||
},
|
||||
"url": {
|
||||
"description": "URL is the API URL for this deploy key",
|
||||
"description": "URL is the API URL for this deploy-key",
|
||||
"type": "string",
|
||||
"x-go-name": "URL"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user