mirror of https://github.com/go-gitea/gitea
Add user secrets (#22191)
Fixes #22183 Replaces #22187 This PR adds secrets for users. I refactored the files for organizations and repos to use the same logic and templates. I splitted the secrets from deploy keys again and reverted the fix from #22187. --------- Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>pull/22262/head^2
parent
9f9a1ce922
commit
5882e179a9
@ -0,0 +1,48 @@ |
||||
// Copyright 2022 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package org |
||||
|
||||
import ( |
||||
"net/http" |
||||
|
||||
"code.gitea.io/gitea/modules/base" |
||||
"code.gitea.io/gitea/modules/context" |
||||
shared "code.gitea.io/gitea/routers/web/shared/secrets" |
||||
) |
||||
|
||||
const ( |
||||
tplSettingsSecrets base.TplName = "org/settings/secrets" |
||||
) |
||||
|
||||
// Secrets render organization secrets page
|
||||
func Secrets(ctx *context.Context) { |
||||
ctx.Data["Title"] = ctx.Tr("secrets.secrets") |
||||
ctx.Data["PageIsOrgSettings"] = true |
||||
ctx.Data["PageIsOrgSettingsSecrets"] = true |
||||
|
||||
shared.SetSecretsContext(ctx, ctx.ContextUser.ID, 0) |
||||
if ctx.Written() { |
||||
return |
||||
} |
||||
|
||||
ctx.HTML(http.StatusOK, tplSettingsSecrets) |
||||
} |
||||
|
||||
// SecretsPost add secrets
|
||||
func SecretsPost(ctx *context.Context) { |
||||
shared.PerformSecretsPost( |
||||
ctx, |
||||
ctx.ContextUser.ID, |
||||
0, |
||||
ctx.Org.OrgLink+"/settings/secrets", |
||||
) |
||||
} |
||||
|
||||
// SecretsDelete delete secrets
|
||||
func SecretsDelete(ctx *context.Context) { |
||||
shared.PerformSecretsDelete( |
||||
ctx, |
||||
ctx.Org.OrgLink+"/settings/secrets", |
||||
) |
||||
} |
@ -0,0 +1,46 @@ |
||||
// Copyright 2022 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package repo |
||||
|
||||
import ( |
||||
"net/http" |
||||
|
||||
"code.gitea.io/gitea/modules/base" |
||||
"code.gitea.io/gitea/modules/context" |
||||
"code.gitea.io/gitea/modules/setting" |
||||
shared "code.gitea.io/gitea/routers/web/shared/secrets" |
||||
) |
||||
|
||||
const ( |
||||
tplSecrets base.TplName = "repo/settings/secrets" |
||||
) |
||||
|
||||
func Secrets(ctx *context.Context) { |
||||
ctx.Data["Title"] = ctx.Tr("secrets.secrets") |
||||
ctx.Data["PageIsSettingsSecrets"] = true |
||||
ctx.Data["DisableSSH"] = setting.SSH.Disabled |
||||
|
||||
shared.SetSecretsContext(ctx, 0, ctx.Repo.Repository.ID) |
||||
if ctx.Written() { |
||||
return |
||||
} |
||||
|
||||
ctx.HTML(http.StatusOK, tplSecrets) |
||||
} |
||||
|
||||
func SecretsPost(ctx *context.Context) { |
||||
shared.PerformSecretsPost( |
||||
ctx, |
||||
0, |
||||
ctx.Repo.Repository.ID, |
||||
ctx.Repo.RepoLink+"/settings/secrets", |
||||
) |
||||
} |
||||
|
||||
func DeleteSecret(ctx *context.Context) { |
||||
shared.PerformSecretsDelete( |
||||
ctx, |
||||
ctx.Repo.RepoLink+"/settings/secrets", |
||||
) |
||||
} |
@ -0,0 +1,54 @@ |
||||
// Copyright 2022 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package secrets |
||||
|
||||
import ( |
||||
"net/http" |
||||
|
||||
"code.gitea.io/gitea/models/db" |
||||
secret_model "code.gitea.io/gitea/models/secret" |
||||
"code.gitea.io/gitea/modules/context" |
||||
"code.gitea.io/gitea/modules/log" |
||||
"code.gitea.io/gitea/modules/web" |
||||
"code.gitea.io/gitea/services/forms" |
||||
) |
||||
|
||||
func SetSecretsContext(ctx *context.Context, ownerID, repoID int64) { |
||||
secrets, err := secret_model.FindSecrets(ctx, secret_model.FindSecretsOptions{OwnerID: ownerID, RepoID: repoID}) |
||||
if err != nil { |
||||
ctx.ServerError("FindSecrets", err) |
||||
return |
||||
} |
||||
|
||||
ctx.Data["Secrets"] = secrets |
||||
} |
||||
|
||||
func PerformSecretsPost(ctx *context.Context, ownerID, repoID int64, redirectURL string) { |
||||
form := web.GetForm(ctx).(*forms.AddSecretForm) |
||||
|
||||
s, err := secret_model.InsertEncryptedSecret(ctx, ownerID, repoID, form.Title, form.Content) |
||||
if err != nil { |
||||
log.Error("InsertEncryptedSecret: %v", err) |
||||
ctx.Flash.Error(ctx.Tr("secrets.creation.failed")) |
||||
} else { |
||||
ctx.Flash.Success(ctx.Tr("secrets.creation.success", s.Name)) |
||||
} |
||||
|
||||
ctx.Redirect(redirectURL) |
||||
} |
||||
|
||||
func PerformSecretsDelete(ctx *context.Context, redirectURL string) { |
||||
id := ctx.FormInt64("id") |
||||
|
||||
if _, err := db.DeleteByBean(ctx, &secret_model.Secret{ID: id}); err != nil { |
||||
log.Error("Delete secret %d failed: %v", id, err) |
||||
ctx.Flash.Error(ctx.Tr("secrets.deletion.failed")) |
||||
} else { |
||||
ctx.Flash.Success(ctx.Tr("secrets.deletion.success")) |
||||
} |
||||
|
||||
ctx.JSON(http.StatusOK, map[string]interface{}{ |
||||
"redirect": redirectURL, |
||||
}) |
||||
} |
@ -0,0 +1,45 @@ |
||||
// Copyright 2022 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package setting |
||||
|
||||
import ( |
||||
"net/http" |
||||
|
||||
"code.gitea.io/gitea/modules/base" |
||||
"code.gitea.io/gitea/modules/context" |
||||
"code.gitea.io/gitea/modules/setting" |
||||
shared "code.gitea.io/gitea/routers/web/shared/secrets" |
||||
) |
||||
|
||||
const ( |
||||
tplSettingsSecrets base.TplName = "user/settings/secrets" |
||||
) |
||||
|
||||
func Secrets(ctx *context.Context) { |
||||
ctx.Data["Title"] = ctx.Tr("secrets.secrets") |
||||
ctx.Data["PageIsSettingsSecrets"] = true |
||||
|
||||
shared.SetSecretsContext(ctx, ctx.Doer.ID, 0) |
||||
if ctx.Written() { |
||||
return |
||||
} |
||||
|
||||
ctx.HTML(http.StatusOK, tplSettingsSecrets) |
||||
} |
||||
|
||||
func SecretsPost(ctx *context.Context) { |
||||
shared.PerformSecretsPost( |
||||
ctx, |
||||
ctx.Doer.ID, |
||||
0, |
||||
setting.AppSubURL+"/user/settings/secrets", |
||||
) |
||||
} |
||||
|
||||
func SecretsDelete(ctx *context.Context) { |
||||
shared.PerformSecretsDelete( |
||||
ctx, |
||||
setting.AppSubURL+"/user/settings/secrets", |
||||
) |
||||
} |
@ -1,80 +1,10 @@ |
||||
<div class="ui container"> |
||||
<h4 class="ui top attached header"> |
||||
{{.locale.Tr "secrets.secrets"}} |
||||
<div class="ui right"> |
||||
<div class="ui primary tiny show-panel button" data-panel="#add-secret-panel">{{.locale.Tr "secrets.creation"}}</div> |
||||
</div> |
||||
</h4> |
||||
<div class="ui attached segment"> |
||||
<div class="{{if not .HasError}}hide {{end}}mb-4" id="add-secret-panel"> |
||||
<form class="ui form" action="{{.Link}}/secrets" method="post"> |
||||
{{.CsrfTokenHtml}} |
||||
<div class="field"> |
||||
{{.locale.Tr "secrets.description"}} |
||||
</div> |
||||
<div class="field{{if .Err_Title}} error{{end}}"> |
||||
<label for="secret-title">{{.locale.Tr "secrets.name"}}</label> |
||||
<input id="secret-title" name="title" value="{{.title}}" autofocus required pattern="^[a-zA-Z_][a-zA-Z0-9_]*$" placeholder="{{.locale.Tr "secrets.creation.name_placeholder"}}"> |
||||
</div> |
||||
<div class="field{{if .Err_Content}} error{{end}}"> |
||||
<label for="secret-content">{{.locale.Tr "secrets.value"}}</label> |
||||
<textarea id="secret-content" name="content" required placeholder="{{.locale.Tr "secrets.creation.value_placeholder"}}">{{.content}}</textarea> |
||||
</div> |
||||
<button class="ui green button"> |
||||
{{.locale.Tr "secrets.creation"}} |
||||
</button> |
||||
<button class="ui hide-panel button" data-panel="#add-secret-panel"> |
||||
{{.locale.Tr "cancel"}} |
||||
</button> |
||||
</form> |
||||
</div> |
||||
{{if .Secrets}} |
||||
<div class="ui key list"> |
||||
{{range .Secrets}} |
||||
<div class="item"> |
||||
<div class="right floated content"> |
||||
<button class="ui red tiny button delete-button" data-modal-id="delete-secret-modal" data-url="{{$.Link}}/secrets/delete" data-id="{{.ID}}"> |
||||
{{$.locale.Tr "settings.delete_key"}} |
||||
</button> |
||||
</div> |
||||
<div class="left floated content"> |
||||
<i>{{svg "octicon-key" 32}}</i> |
||||
</div> |
||||
<div class="content"> |
||||
<strong>{{.Name}}</strong> |
||||
<div class="print meta">******</div> |
||||
<div class="activity meta"> |
||||
<i> |
||||
{{$.locale.Tr "settings.add_on"}} |
||||
<span>{{.CreatedUnix.FormatShort}}</span> |
||||
</i> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
{{end}} |
||||
</div> |
||||
{{else}} |
||||
{{.locale.Tr "secrets.none"}} |
||||
{{end}} |
||||
</div> |
||||
</div> |
||||
|
||||
<div class="ui small basic delete modal" id="delete-secret-modal"> |
||||
<div class="ui icon header"> |
||||
{{svg "octicon-trash"}} |
||||
{{.locale.Tr "secrets.deletion"}} |
||||
</div> |
||||
<div class="content"> |
||||
<p>{{.locale.Tr "secrets.deletion.description"}}</p> |
||||
</div> |
||||
<div class="actions"> |
||||
<div class="ui red basic inverted cancel button"> |
||||
<i class="remove icon"></i> |
||||
{{.locale.Tr "modal.no"}} |
||||
</div> |
||||
<div class="ui green basic inverted ok button"> |
||||
<i class="checkmark icon"></i> |
||||
{{.locale.Tr "modal.yes"}} |
||||
</div> |
||||
{{template "base/head" .}} |
||||
<div class="page-content repository settings"> |
||||
{{template "repo/header" .}} |
||||
{{template "repo/settings/navbar" .}} |
||||
<div class="ui container"> |
||||
{{template "base/alert" .}} |
||||
{{template "shared/secrets/add_list" .}} |
||||
</div> |
||||
</div> |
||||
{{template "base/footer" .}} |
||||
|
@ -0,0 +1,68 @@ |
||||
<h4 class="ui top attached header"> |
||||
{{.locale.Tr "secrets.secrets"}} |
||||
<div class="ui right"> |
||||
<div class="ui primary tiny show-panel button" data-panel="#add-secret-panel">{{.locale.Tr "secrets.creation"}}</div> |
||||
</div> |
||||
</h4> |
||||
<div class="ui attached segment"> |
||||
<div class="{{if not .HasError}}hide {{end}}mb-4" id="add-secret-panel"> |
||||
<form class="ui form" action="{{.Link}}" method="post"> |
||||
{{.CsrfTokenHtml}} |
||||
<div class="field"> |
||||
{{.locale.Tr "secrets.description"}} |
||||
</div> |
||||
<div class="field{{if .Err_Title}} error{{end}}"> |
||||
<label for="secret-title">{{.locale.Tr "secrets.name"}}</label> |
||||
<input id="secret-title" name="title" value="{{.title}}" autofocus required pattern="^[a-zA-Z_][a-zA-Z0-9_]*$" placeholder="{{.locale.Tr "secrets.creation.name_placeholder"}}"> |
||||
</div> |
||||
<div class="field{{if .Err_Content}} error{{end}}"> |
||||
<label for="secret-content">{{.locale.Tr "secrets.value"}}</label> |
||||
<textarea id="secret-content" name="content" required placeholder="{{.locale.Tr "secrets.creation.value_placeholder"}}">{{.content}}</textarea> |
||||
</div> |
||||
<button class="ui green button"> |
||||
{{.locale.Tr "secrets.creation"}} |
||||
</button> |
||||
<button class="ui hide-panel button" data-panel="#add-secret-panel"> |
||||
{{.locale.Tr "cancel"}} |
||||
</button> |
||||
</form> |
||||
</div> |
||||
{{if .Secrets}} |
||||
<div class="ui key list"> |
||||
{{range .Secrets}} |
||||
<div class="item"> |
||||
<div class="right floated content"> |
||||
<button class="ui red tiny button delete-button" data-url="{{$.Link}}/delete" data-id="{{.ID}}"> |
||||
{{$.locale.Tr "settings.delete_key"}} |
||||
</button> |
||||
</div> |
||||
<div class="left floated content"> |
||||
<i>{{svg "octicon-key" 32}}</i> |
||||
</div> |
||||
<div class="content"> |
||||
<strong>{{.Name}}</strong> |
||||
<div class="print meta">******</div> |
||||
<div class="activity meta"> |
||||
<i> |
||||
{{$.locale.Tr "settings.add_on"}} |
||||
<span>{{.CreatedUnix.FormatShort}}</span> |
||||
</i> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
{{end}} |
||||
</div> |
||||
{{else}} |
||||
{{.locale.Tr "secrets.none"}} |
||||
{{end}} |
||||
</div> |
||||
<div class="ui small basic delete modal"> |
||||
<div class="ui header"> |
||||
{{svg "octicon-trash" 16 "mr-2"}} |
||||
{{.locale.Tr "secrets.deletion"}} |
||||
</div> |
||||
<div class="content"> |
||||
<p>{{.locale.Tr "secrets.deletion.description"}}</p> |
||||
</div> |
||||
{{template "base/delete_modal_actions" .}} |
||||
</div> |
@ -0,0 +1,10 @@ |
||||
{{template "base/head" .}} |
||||
<div class="page-content user settings secrets"> |
||||
{{template "user/settings/navbar" .}} |
||||
<div class="ui container"> |
||||
{{template "base/alert" .}} |
||||
{{template "shared/secrets/add_list" .}} |
||||
</div> |
||||
</div> |
||||
|
||||
{{template "base/footer" .}} |
Loading…
Reference in new issue