mirror of
https://github.com/go-gitea/gitea.git
synced 2026-07-29 03:34:37 +02:00
Mirror SSH Keys -> Managed SSH Keys
This commit is contained in:
@@ -73,11 +73,11 @@ func GetSSHKeypairForURL(ctx context.Context, repo *repo_model.Repository, url s
|
||||
return GetSSHKeypairForRepository(ctx, repo)
|
||||
}
|
||||
|
||||
// SetupMirrorSSHAgent prepares SSH key-based authentication for a mirror or
|
||||
// SetupManagedSSHAgent prepares SSH key-based authentication for a mirror or
|
||||
// migration git operation against remoteURL on behalf of repo. For non-SSH
|
||||
// URLs (or when no keypair is available) it is a no-op. The returned cleanup
|
||||
// is never nil and must always be called by the caller (typically via defer).
|
||||
func SetupMirrorSSHAgent(ctx context.Context, repo *repo_model.Repository, remoteURL string) (sshAuthSock string, cleanup func(), err error) {
|
||||
func SetupManagedSSHAgent(ctx context.Context, repo *repo_model.Repository, remoteURL string) (sshAuthSock string, cleanup func(), err error) {
|
||||
noop := func() {}
|
||||
if !IsSSHURL(remoteURL) {
|
||||
return "", noop, nil
|
||||
|
||||
@@ -953,15 +953,15 @@
|
||||
"settings.visibility.limited_tooltip": "Visible only to authenticated users",
|
||||
"settings.visibility.private": "Private",
|
||||
"settings.visibility.private_tooltip": "Visible only to members of organizations you have joined",
|
||||
"settings.mirror_ssh_title": "Managed SSH Keys",
|
||||
"settings.mirror_ssh_description": "Managed SSH keys allow you to authenticate with remote Git repositories using SSH for mirroring and migrations. Each user and organization has their own SSH keypair stored securely.",
|
||||
"settings.mirror_ssh_current_key": "Current SSH Public Key",
|
||||
"settings.mirror_ssh_fingerprint": "Fingerprint",
|
||||
"settings.mirror_ssh_generate": "Generate SSH Key",
|
||||
"settings.mirror_ssh_regenerate": "Regenerate SSH Key",
|
||||
"settings.mirror_ssh_regenerated": "SSH keypair has been regenerated successfully.",
|
||||
"settings.mirror_ssh_documentation": "SSH keys are automatically used for SSH-based repository mirrors and migrations. Add the public key to your remote Git service (GitHub, GitLab, etc.) to enable authentication.",
|
||||
"settings.mirror_ssh_org_notice": "This SSH key is only for your personal repositories. For organization repositories, you need to configure SSH keys in the organization's settings.",
|
||||
"settings.managed_ssh_title": "Managed SSH Keys",
|
||||
"settings.managed_ssh_description": "Managed SSH keys allow you to authenticate with remote Git repositories using SSH for mirroring and migrations. Each user and organization has their own SSH keypair stored securely.",
|
||||
"settings.managed_ssh_current_key": "Current SSH Public Key",
|
||||
"settings.managed_ssh_fingerprint": "Fingerprint",
|
||||
"settings.managed_ssh_generate": "Generate SSH Key",
|
||||
"settings.managed_ssh_regenerate": "Regenerate SSH Key",
|
||||
"settings.managed_ssh_regenerated": "SSH keypair has been regenerated successfully.",
|
||||
"settings.managed_ssh_documentation": "SSH keys are automatically used for SSH-based repository mirrors and migrations. Add the public key to your remote Git service (GitHub, GitLab, etc.) to enable authentication.",
|
||||
"settings.managed_ssh_org_notice": "This SSH key is only for your personal repositories. For organization repositories, you need to configure SSH keys in the organization's settings.",
|
||||
"repo.new_repo_helper": "A repository contains all project files, including revision history. Already hosting one elsewhere? <a href=\"%s\">Migrate repository.</a>",
|
||||
"repo.owner": "Owner",
|
||||
"repo.owner_helper": "Some organizations may not show up in the dropdown due to a maximum repository count limit.",
|
||||
|
||||
@@ -1149,9 +1149,9 @@ func Routes() *web.Router {
|
||||
}, context.UserAssignmentAPI(), checkTokenPublicOnly())
|
||||
}, rejectPublicOnly())
|
||||
|
||||
m.Group("/mirror-ssh-key", func() {
|
||||
m.Get("", user.GetMirrorSSHKey)
|
||||
m.Post("/regenerate", user.RegenerateMirrorSSHKey)
|
||||
m.Group("/managed-ssh-key", func() {
|
||||
m.Get("", user.GetManagedSSHKey)
|
||||
m.Post("/regenerate", user.RegenerateManagedSSHKey)
|
||||
})
|
||||
}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryUser), reqToken(), contextAuthenticatedUser(), checkTokenPublicOnly())
|
||||
|
||||
@@ -1695,9 +1695,9 @@ func Routes() *web.Router {
|
||||
})
|
||||
}, reqToken(), reqOrgOwnership())
|
||||
|
||||
m.Group("/mirror-ssh-key", func() {
|
||||
m.Get("", reqToken(), reqOrgOwnership(), org.GetMirrorSSHKey)
|
||||
m.Post("/regenerate", reqToken(), reqOrgOwnership(), org.RegenerateMirrorSSHKey)
|
||||
m.Group("/managed-ssh-key", func() {
|
||||
m.Get("", reqToken(), reqOrgOwnership(), org.GetManagedSSHKey)
|
||||
m.Post("/regenerate", reqToken(), reqOrgOwnership(), org.RegenerateManagedSSHKey)
|
||||
})
|
||||
}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryOrganization), orgAssignment(true), checkTokenPublicOnly())
|
||||
m.Group("/teams/{teamid}", func() {
|
||||
|
||||
@@ -11,9 +11,9 @@ import (
|
||||
mirror_service "gitea.dev/services/mirror"
|
||||
)
|
||||
|
||||
// GetMirrorSSHKey gets the SSH public key for organization mirroring
|
||||
func GetMirrorSSHKey(ctx *context.APIContext) {
|
||||
// swagger:operation GET /orgs/{org}/mirror-ssh-key organization orgGetMirrorSSHKey
|
||||
// GetManagedSSHKey gets the SSH public key for organization mirroring
|
||||
func GetManagedSSHKey(ctx *context.APIContext) {
|
||||
// swagger:operation GET /orgs/{org}/managed-ssh-key organization orgGetManagedSSHKey
|
||||
// ---
|
||||
// summary: Get SSH public key for organization mirroring
|
||||
// produces:
|
||||
@@ -55,9 +55,9 @@ func GetMirrorSSHKey(ctx *context.APIContext) {
|
||||
})
|
||||
}
|
||||
|
||||
// RegenerateMirrorSSHKey regenerates the SSH keypair for organization mirroring
|
||||
func RegenerateMirrorSSHKey(ctx *context.APIContext) {
|
||||
// swagger:operation POST /orgs/{org}/mirror-ssh-key/regenerate organization orgRegenerateMirrorSSHKey
|
||||
// RegenerateManagedSSHKey regenerates the SSH keypair for organization mirroring
|
||||
func RegenerateManagedSSHKey(ctx *context.APIContext) {
|
||||
// swagger:operation POST /orgs/{org}/managed-ssh-key/regenerate organization orgRegenerateManagedSSHKey
|
||||
// ---
|
||||
// summary: Regenerate SSH keypair for organization mirroring
|
||||
// produces:
|
||||
|
||||
@@ -11,9 +11,9 @@ import (
|
||||
mirror_service "gitea.dev/services/mirror"
|
||||
)
|
||||
|
||||
// GetMirrorSSHKey gets the SSH public key for user mirroring
|
||||
func GetMirrorSSHKey(ctx *context.APIContext) {
|
||||
// swagger:operation GET /user/mirror-ssh-key user userGetMirrorSSHKey
|
||||
// GetManagedSSHKey gets the SSH public key for user mirroring
|
||||
func GetManagedSSHKey(ctx *context.APIContext) {
|
||||
// swagger:operation GET /user/managed-ssh-key user userGetManagedSSHKey
|
||||
// ---
|
||||
// summary: Get SSH public key for user mirroring
|
||||
// produces:
|
||||
@@ -47,9 +47,9 @@ func GetMirrorSSHKey(ctx *context.APIContext) {
|
||||
})
|
||||
}
|
||||
|
||||
// RegenerateMirrorSSHKey regenerates the SSH keypair for user mirroring
|
||||
func RegenerateMirrorSSHKey(ctx *context.APIContext) {
|
||||
// swagger:operation POST /user/mirror-ssh-key/regenerate user userRegenerateMirrorSSHKey
|
||||
// RegenerateManagedSSHKey regenerates the SSH keypair for user mirroring
|
||||
func RegenerateManagedSSHKey(ctx *context.APIContext) {
|
||||
// swagger:operation POST /user/managed-ssh-key/regenerate user userRegenerateManagedSSHKey
|
||||
// ---
|
||||
// summary: Regenerate SSH keypair for user mirroring
|
||||
// produces:
|
||||
|
||||
@@ -51,6 +51,6 @@ func RegenerateSSHKey(ctx *context.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Flash.Success(ctx.Tr("settings.mirror_ssh_regenerated"))
|
||||
ctx.Flash.Success(ctx.Tr("settings.managed_ssh_regenerated"))
|
||||
ctx.Redirect(ctx.Org.OrgLink + "/settings/ssh_keys")
|
||||
}
|
||||
|
||||
@@ -346,7 +346,7 @@ func loadKeysData(ctx *context.Context) {
|
||||
// Load SSH mirror keypair if it exists
|
||||
mirrorKeypair, err := mirror_service.GetOrCreateSSHKeypairForUser(ctx, ctx.Doer.ID)
|
||||
if err == nil {
|
||||
ctx.Data["HasMirrorSSHKey"] = true
|
||||
ctx.Data["HasManagedSSHKey"] = true
|
||||
|
||||
// Create a struct with the public key including comment
|
||||
publicKeyWithComment, _ := mirrorKeypair.GetPublicKeyWithComment(ctx)
|
||||
@@ -358,9 +358,9 @@ func loadKeysData(ctx *context.Context) {
|
||||
PublicKeyWithComment: publicKeyWithComment,
|
||||
}
|
||||
|
||||
ctx.Data["MirrorSSHKey"] = mirrorKeyData
|
||||
ctx.Data["ManagedSSHKey"] = mirrorKeyData
|
||||
} else {
|
||||
ctx.Data["HasMirrorSSHKey"] = false
|
||||
ctx.Data["HasManagedSSHKey"] = false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -372,6 +372,6 @@ func RegenerateUserSSHKeypair(ctx *context.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Flash.Success(ctx.Tr("settings.mirror_ssh_regenerated"))
|
||||
ctx.Flash.Success(ctx.Tr("settings.managed_ssh_regenerated"))
|
||||
ctx.Redirect(setting.AppSubURL + "/user/settings/keys")
|
||||
}
|
||||
|
||||
@@ -118,7 +118,7 @@ func runSync(ctx context.Context, m *repo_model.Mirror) ([]*repo_module.SyncResu
|
||||
timeout := time.Duration(setting.Git.Timeout.Mirror) * time.Second
|
||||
|
||||
// Setup SSH authentication if needed
|
||||
sshAuthSock, cleanup, sshErr := SetupMirrorSSHAgent(ctx, m.Repo, remoteURL.String())
|
||||
sshAuthSock, cleanup, sshErr := SetupManagedSSHAgent(ctx, m.Repo, remoteURL.String())
|
||||
if sshErr != nil {
|
||||
log.Error("SyncMirrors [repo: %-v]: SSH setup error %v", m.Repo, sshErr)
|
||||
return nil, false
|
||||
|
||||
@@ -167,7 +167,7 @@ func runPushSync(ctx context.Context, m *repo_model.PushMirror) error {
|
||||
}
|
||||
|
||||
// Setup SSH authentication
|
||||
sshAuthSock, cleanup, err := SetupMirrorSSHAgent(ctx, repo, remoteURL.String())
|
||||
sshAuthSock, cleanup, err := SetupManagedSSHAgent(ctx, repo, remoteURL.String())
|
||||
if err != nil {
|
||||
log.Error("Failed to set up SSH agent for push mirror %s: %v", repo.FullName(), err)
|
||||
return util.SanitizeErrorCredentialURLs(err)
|
||||
|
||||
@@ -51,9 +51,9 @@ func GetSSHKeypairForURL(ctx context.Context, repo *repo_model.Repository, url s
|
||||
return ssh_module.GetSSHKeypairForURL(ctx, repo, url)
|
||||
}
|
||||
|
||||
// SetupMirrorSSHAgent prepares SSH key-based authentication for a mirror or
|
||||
// SetupManagedSSHAgent prepares SSH key-based authentication for a mirror or
|
||||
// migration git operation against url on behalf of repo. The returned cleanup
|
||||
// is never nil and must always be called by the caller (typically via defer).
|
||||
func SetupMirrorSSHAgent(ctx context.Context, repo *repo_model.Repository, url string) (string, func(), error) {
|
||||
return ssh_module.SetupMirrorSSHAgent(ctx, repo, url)
|
||||
func SetupManagedSSHAgent(ctx context.Context, repo *repo_model.Repository, url string) (string, func(), error) {
|
||||
return ssh_module.SetupManagedSSHAgent(ctx, repo, url)
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ import (
|
||||
)
|
||||
|
||||
func cloneExternalRepoWithSSHAuth(ctx context.Context, repo *repo_model.Repository, remoteURL string, storageRepo gitrepo.Repository, cloneOpts git.CloneRepoOptions) error {
|
||||
sshAuthSock, cleanup, err := ssh_module.SetupMirrorSSHAgent(ctx, repo, remoteURL)
|
||||
sshAuthSock, cleanup, err := ssh_module.SetupManagedSSHAgent(ctx, repo, remoteURL)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -2,23 +2,23 @@
|
||||
|
||||
<div class="ui segments org-setting-content">
|
||||
<h4 class="ui top attached header">
|
||||
{{ctx.Locale.Tr "settings.mirror_ssh_title"}}
|
||||
{{ctx.Locale.Tr "settings.managed_ssh_title"}}
|
||||
</h4>
|
||||
<div class="ui attached segment">
|
||||
<div class="ui form">
|
||||
<div class="field">
|
||||
<label>{{ctx.Locale.Tr "settings.mirror_ssh_description"}}</label>
|
||||
<label>{{ctx.Locale.Tr "settings.managed_ssh_description"}}</label>
|
||||
</div>
|
||||
{{if .SSHKeypair}}
|
||||
<div class="field">
|
||||
<label>{{ctx.Locale.Tr "settings.mirror_ssh_current_key"}}</label>
|
||||
<label>{{ctx.Locale.Tr "settings.managed_ssh_current_key"}}</label>
|
||||
<div class="ui action input">
|
||||
<input id="ssh-public-key-content" class="js-ssh-key-content" value="{{.SSHKeypair.PublicKey}}" readonly>
|
||||
<button class="ui compact button" data-clipboard-target="#ssh-public-key-content" data-tooltip-content="{{ctx.Locale.Tr "copy"}}">
|
||||
{{svg "octicon-copy" 14}}
|
||||
</button>
|
||||
</div>
|
||||
<small class="text grey">{{ctx.Locale.Tr "settings.mirror_ssh_fingerprint"}}: {{.SSHKeypair.Fingerprint}}</small>
|
||||
<small class="text grey">{{ctx.Locale.Tr "settings.managed_ssh_fingerprint"}}: {{.SSHKeypair.Fingerprint}}</small>
|
||||
</div>
|
||||
{{end}}
|
||||
<div class="field">
|
||||
@@ -26,9 +26,9 @@
|
||||
{{.CsrfTokenHtml}}
|
||||
<button class="ui primary button" type="submit">
|
||||
{{if .SSHKeypair}}
|
||||
{{ctx.Locale.Tr "settings.mirror_ssh_regenerate"}}
|
||||
{{ctx.Locale.Tr "settings.managed_ssh_regenerate"}}
|
||||
{{else}}
|
||||
{{ctx.Locale.Tr "settings.mirror_ssh_generate"}}
|
||||
{{ctx.Locale.Tr "settings.managed_ssh_generate"}}
|
||||
{{end}}
|
||||
</button>
|
||||
</form>
|
||||
@@ -36,7 +36,7 @@
|
||||
<div class="field">
|
||||
<div class="ui info message">
|
||||
<i class="info icon"></i>
|
||||
{{ctx.Locale.Tr "settings.mirror_ssh_documentation"}}
|
||||
{{ctx.Locale.Tr "settings.managed_ssh_documentation"}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Generated
+8
-8
@@ -3378,7 +3378,7 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/orgs/{org}/mirror-ssh-key": {
|
||||
"/orgs/{org}/managed-ssh-key": {
|
||||
"get": {
|
||||
"produces": [
|
||||
"application/json"
|
||||
@@ -3387,7 +3387,7 @@
|
||||
"organization"
|
||||
],
|
||||
"summary": "Get SSH public key for organization mirroring",
|
||||
"operationId": "orgGetMirrorSSHKey",
|
||||
"operationId": "orgGetManagedSSHKey",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
@@ -3421,7 +3421,7 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/orgs/{org}/mirror-ssh-key/regenerate": {
|
||||
"/orgs/{org}/managed-ssh-key/regenerate": {
|
||||
"post": {
|
||||
"produces": [
|
||||
"application/json"
|
||||
@@ -3430,7 +3430,7 @@
|
||||
"organization"
|
||||
],
|
||||
"summary": "Regenerate SSH keypair for organization mirroring",
|
||||
"operationId": "orgRegenerateMirrorSSHKey",
|
||||
"operationId": "orgRegenerateManagedSSHKey",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
@@ -20524,7 +20524,7 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/user/mirror-ssh-key": {
|
||||
"/user/managed-ssh-key": {
|
||||
"get": {
|
||||
"produces": [
|
||||
"application/json"
|
||||
@@ -20533,7 +20533,7 @@
|
||||
"user"
|
||||
],
|
||||
"summary": "Get SSH public key for user mirroring",
|
||||
"operationId": "userGetMirrorSSHKey",
|
||||
"operationId": "userGetManagedSSHKey",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "SSH public key",
|
||||
@@ -20555,7 +20555,7 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/user/mirror-ssh-key/regenerate": {
|
||||
"/user/managed-ssh-key/regenerate": {
|
||||
"post": {
|
||||
"produces": [
|
||||
"application/json"
|
||||
@@ -20564,7 +20564,7 @@
|
||||
"user"
|
||||
],
|
||||
"summary": "Regenerate SSH keypair for user mirroring",
|
||||
"operationId": "userRegenerateMirrorSSHKey",
|
||||
"operationId": "userRegenerateManagedSSHKey",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "New SSH public key",
|
||||
|
||||
Generated
+8
-8
@@ -14106,9 +14106,9 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"/orgs/{org}/mirror-ssh-key": {
|
||||
"/orgs/{org}/managed-ssh-key": {
|
||||
"get": {
|
||||
"operationId": "orgGetMirrorSSHKey",
|
||||
"operationId": "orgGetManagedSSHKey",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "name of the organization",
|
||||
@@ -14152,9 +14152,9 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"/orgs/{org}/mirror-ssh-key/regenerate": {
|
||||
"/orgs/{org}/managed-ssh-key/regenerate": {
|
||||
"post": {
|
||||
"operationId": "orgRegenerateMirrorSSHKey",
|
||||
"operationId": "orgRegenerateManagedSSHKey",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "name of the organization",
|
||||
@@ -32569,9 +32569,9 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"/user/mirror-ssh-key": {
|
||||
"/user/managed-ssh-key": {
|
||||
"get": {
|
||||
"operationId": "userGetMirrorSSHKey",
|
||||
"operationId": "userGetManagedSSHKey",
|
||||
"responses": {
|
||||
"200": {
|
||||
"content": {
|
||||
@@ -32601,9 +32601,9 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"/user/mirror-ssh-key/regenerate": {
|
||||
"/user/managed-ssh-key/regenerate": {
|
||||
"post": {
|
||||
"operationId": "userRegenerateMirrorSSHKey",
|
||||
"operationId": "userRegenerateManagedSSHKey",
|
||||
"responses": {
|
||||
"200": {
|
||||
"content": {
|
||||
|
||||
@@ -8,6 +8,6 @@
|
||||
{{template "user/settings/keys_gpg" .}}
|
||||
{{end}}
|
||||
<div class="ui divider"></div>
|
||||
{{template "user/settings/keys_mirror_ssh" .}}
|
||||
{{template "user/settings/keys_managed_ssh" .}}
|
||||
</div>
|
||||
{{template "user/settings/layout_footer" .}}
|
||||
|
||||
+11
-11
@@ -1,31 +1,31 @@
|
||||
<h4 class="ui top attached header">
|
||||
{{ctx.Locale.Tr "settings.mirror_ssh_title"}}
|
||||
{{ctx.Locale.Tr "settings.managed_ssh_title"}}
|
||||
</h4>
|
||||
<div class="ui attached segment">
|
||||
<div class="ui form">
|
||||
<div class="field">
|
||||
<label>{{ctx.Locale.Tr "settings.mirror_ssh_description"}}</label>
|
||||
<label>{{ctx.Locale.Tr "settings.managed_ssh_description"}}</label>
|
||||
</div>
|
||||
{{if .HasMirrorSSHKey}}
|
||||
{{if .HasManagedSSHKey}}
|
||||
<div class="field">
|
||||
<label>{{ctx.Locale.Tr "settings.mirror_ssh_current_key"}}</label>
|
||||
<label>{{ctx.Locale.Tr "settings.managed_ssh_current_key"}}</label>
|
||||
<div class="ui action input">
|
||||
<input id="ssh-public-key-content" class="js-ssh-key-content" value="{{.MirrorSSHKey.PublicKeyWithComment}}" readonly>
|
||||
<input id="ssh-public-key-content" class="js-ssh-key-content" value="{{.ManagedSSHKey.PublicKeyWithComment}}" readonly>
|
||||
<button class="ui compact button" data-clipboard-target="#ssh-public-key-content" data-tooltip-content="{{ctx.Locale.Tr "copy"}}">
|
||||
{{svg "octicon-copy" 14}}
|
||||
</button>
|
||||
</div>
|
||||
<small class="text grey">{{ctx.Locale.Tr "settings.mirror_ssh_fingerprint"}}: {{.MirrorSSHKey.Fingerprint}}</small>
|
||||
<small class="text grey">{{ctx.Locale.Tr "settings.managed_ssh_fingerprint"}}: {{.ManagedSSHKey.Fingerprint}}</small>
|
||||
</div>
|
||||
{{end}}
|
||||
<div class="field">
|
||||
<form action="{{.Link}}/mirror-ssh/regenerate" method="post">
|
||||
{{.CsrfTokenHtml}}
|
||||
<button class="ui primary button" type="submit">
|
||||
{{if .HasMirrorSSHKey}}
|
||||
{{ctx.Locale.Tr "settings.mirror_ssh_regenerate"}}
|
||||
{{if .HasManagedSSHKey}}
|
||||
{{ctx.Locale.Tr "settings.managed_ssh_regenerate"}}
|
||||
{{else}}
|
||||
{{ctx.Locale.Tr "settings.mirror_ssh_generate"}}
|
||||
{{ctx.Locale.Tr "settings.managed_ssh_generate"}}
|
||||
{{end}}
|
||||
</button>
|
||||
</form>
|
||||
@@ -33,13 +33,13 @@
|
||||
<div class="field">
|
||||
<div class="ui info message">
|
||||
<i class="info icon"></i>
|
||||
{{ctx.Locale.Tr "settings.mirror_ssh_documentation"}}
|
||||
{{ctx.Locale.Tr "settings.managed_ssh_documentation"}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui warning message">
|
||||
<i class="warning icon"></i>
|
||||
{{ctx.Locale.Tr "settings.mirror_ssh_org_notice"}}
|
||||
{{ctx.Locale.Tr "settings.managed_ssh_org_notice"}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
Reference in New Issue
Block a user