Skip to content

Commit 5882e17

Browse files
KN4CK3Rlunny
andauthored
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 <[email protected]>
1 parent 9f9a1ce commit 5882e17

File tree

17 files changed

+310
-255
lines changed

17 files changed

+310
-255
lines changed

docs/content/doc/secrets/overview.en-us.md

+8-8
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
date: "2022-12-19T21:26:00+08:00"
3-
title: "Encrypted secrets"
3+
title: "Secrets"
44
slug: "secrets/overview"
55
draft: false
66
toc: false
@@ -12,24 +12,24 @@ menu:
1212
identifier: "overview"
1313
---
1414

15-
# Encrypted secrets
15+
# Secrets
1616

17-
Encrypted secrets allow you to store sensitive information in your organization or repository.
17+
Secrets allow you to store sensitive information in your user, organization or repository.
1818
Secrets are available on Gitea 1.19+.
1919

2020
# Naming your secrets
2121

2222
The following rules apply to secret names:
2323

24-
Secret names can only contain alphanumeric characters (`[a-z]`, `[A-Z]`, `[0-9]`) or underscores (`_`). Spaces are not allowed.
24+
- Secret names can only contain alphanumeric characters (`[a-z]`, `[A-Z]`, `[0-9]`) or underscores (`_`). Spaces are not allowed.
2525

26-
Secret names must not start with the `GITHUB_` and `GITEA_` prefix.
26+
- Secret names must not start with the `GITHUB_` and `GITEA_` prefix.
2727

28-
Secret names must not start with a number.
28+
- Secret names must not start with a number.
2929

30-
Secret names are not case-sensitive.
30+
- Secret names are not case-sensitive.
3131

32-
Secret names must be unique at the level they are created at.
32+
- Secret names must be unique at the level they are created at.
3333

3434
For example, a secret created at the repository level must have a unique name in that repository, and a secret created at the organization level must have a unique name at that level.
3535

options/locale/locale_en-US.ini

+1-1
Original file line numberDiff line numberDiff line change
@@ -3254,7 +3254,7 @@ creation.value_placeholder = Input any content. Whitespace at the start and end
32543254
creation.success = The secret '%s' has been added.
32553255
creation.failed = Failed to add secret.
32563256
deletion = Remove secret
3257-
deletion.description = Removing a secret will revoke its access to repositories. Continue?
3257+
deletion.description = Removing a secret is permanent and cannot be undone. Continue?
32583258
deletion.success = The secret has been removed.
32593259
deletion.failed = Failed to remove secret.
32603260

routers/web/org/setting.go

-51
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import (
1212
"code.gitea.io/gitea/models"
1313
"code.gitea.io/gitea/models/db"
1414
repo_model "code.gitea.io/gitea/models/repo"
15-
secret_model "code.gitea.io/gitea/models/secret"
1615
user_model "code.gitea.io/gitea/models/user"
1716
"code.gitea.io/gitea/models/webhook"
1817
"code.gitea.io/gitea/modules/base"
@@ -38,8 +37,6 @@ const (
3837
tplSettingsHooks base.TplName = "org/settings/hooks"
3938
// tplSettingsLabels template path for render labels settings
4039
tplSettingsLabels base.TplName = "org/settings/labels"
41-
// tplSettingsSecrets template path for render secrets settings
42-
tplSettingsSecrets base.TplName = "org/settings/secrets"
4340
// tplSettingsRunners template path for render runners settings
4441
tplSettingsRunners base.TplName = "org/settings/runners"
4542
// tplSettingsRunnersEdit template path for render runners edit settings
@@ -253,51 +250,3 @@ func Labels(ctx *context.Context) {
253250
ctx.Data["LabelTemplates"] = repo_module.LabelTemplates
254251
ctx.HTML(http.StatusOK, tplSettingsLabels)
255252
}
256-
257-
// Secrets render organization secrets page
258-
func Secrets(ctx *context.Context) {
259-
ctx.Data["Title"] = ctx.Tr("repo.secrets")
260-
ctx.Data["PageIsOrgSettings"] = true
261-
ctx.Data["PageIsOrgSettingsSecrets"] = true
262-
263-
secrets, err := secret_model.FindSecrets(ctx, secret_model.FindSecretsOptions{OwnerID: ctx.Org.Organization.ID})
264-
if err != nil {
265-
ctx.ServerError("FindSecrets", err)
266-
return
267-
}
268-
ctx.Data["Secrets"] = secrets
269-
270-
ctx.HTML(http.StatusOK, tplSettingsSecrets)
271-
}
272-
273-
// SecretsPost add secrets
274-
func SecretsPost(ctx *context.Context) {
275-
form := web.GetForm(ctx).(*forms.AddSecretForm)
276-
277-
_, err := secret_model.InsertEncryptedSecret(ctx, ctx.Org.Organization.ID, 0, form.Title, form.Content)
278-
if err != nil {
279-
ctx.Flash.Error(ctx.Tr("secrets.creation.failed"))
280-
log.Error("validate secret: %v", err)
281-
ctx.Redirect(ctx.Org.OrgLink + "/settings/secrets")
282-
return
283-
}
284-
285-
log.Trace("Org %d: secret added", ctx.Org.Organization.ID)
286-
ctx.Flash.Success(ctx.Tr("secrets.creation.success", form.Title))
287-
ctx.Redirect(ctx.Org.OrgLink + "/settings/secrets")
288-
}
289-
290-
// SecretsDelete delete secrets
291-
func SecretsDelete(ctx *context.Context) {
292-
id := ctx.FormInt64("id")
293-
if _, err := db.DeleteByBean(ctx, &secret_model.Secret{ID: id}); err != nil {
294-
ctx.Flash.Error(ctx.Tr("secrets.deletion.failed"))
295-
log.Error("delete secret %d: %v", id, err)
296-
} else {
297-
ctx.Flash.Success(ctx.Tr("secrets.deletion.success"))
298-
}
299-
300-
ctx.JSON(http.StatusOK, map[string]interface{}{
301-
"redirect": ctx.Org.OrgLink + "/settings/secrets",
302-
})
303-
}

routers/web/org/setting_secrets.go

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// Copyright 2022 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package org
5+
6+
import (
7+
"net/http"
8+
9+
"code.gitea.io/gitea/modules/base"
10+
"code.gitea.io/gitea/modules/context"
11+
shared "code.gitea.io/gitea/routers/web/shared/secrets"
12+
)
13+
14+
const (
15+
tplSettingsSecrets base.TplName = "org/settings/secrets"
16+
)
17+
18+
// Secrets render organization secrets page
19+
func Secrets(ctx *context.Context) {
20+
ctx.Data["Title"] = ctx.Tr("secrets.secrets")
21+
ctx.Data["PageIsOrgSettings"] = true
22+
ctx.Data["PageIsOrgSettingsSecrets"] = true
23+
24+
shared.SetSecretsContext(ctx, ctx.ContextUser.ID, 0)
25+
if ctx.Written() {
26+
return
27+
}
28+
29+
ctx.HTML(http.StatusOK, tplSettingsSecrets)
30+
}
31+
32+
// SecretsPost add secrets
33+
func SecretsPost(ctx *context.Context) {
34+
shared.PerformSecretsPost(
35+
ctx,
36+
ctx.ContextUser.ID,
37+
0,
38+
ctx.Org.OrgLink+"/settings/secrets",
39+
)
40+
}
41+
42+
// SecretsDelete delete secrets
43+
func SecretsDelete(ctx *context.Context) {
44+
shared.PerformSecretsDelete(
45+
ctx,
46+
ctx.Org.OrgLink+"/settings/secrets",
47+
)
48+
}

routers/web/repo/setting.go

-39
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ import (
1919
"code.gitea.io/gitea/models/organization"
2020
"code.gitea.io/gitea/models/perm"
2121
repo_model "code.gitea.io/gitea/models/repo"
22-
secret_model "code.gitea.io/gitea/models/secret"
2322
unit_model "code.gitea.io/gitea/models/unit"
2423
user_model "code.gitea.io/gitea/models/user"
2524
"code.gitea.io/gitea/modules/base"
@@ -1131,33 +1130,9 @@ func DeployKeys(ctx *context.Context) {
11311130
}
11321131
ctx.Data["Deploykeys"] = keys
11331132

1134-
secrets, err := secret_model.FindSecrets(ctx, secret_model.FindSecretsOptions{RepoID: ctx.Repo.Repository.ID})
1135-
if err != nil {
1136-
ctx.ServerError("FindSecrets", err)
1137-
return
1138-
}
1139-
ctx.Data["Secrets"] = secrets
1140-
11411133
ctx.HTML(http.StatusOK, tplDeployKeys)
11421134
}
11431135

1144-
// SecretsPost response for creating a new secret
1145-
func SecretsPost(ctx *context.Context) {
1146-
form := web.GetForm(ctx).(*forms.AddSecretForm)
1147-
1148-
_, err := secret_model.InsertEncryptedSecret(ctx, 0, ctx.Repo.Repository.ID, form.Title, form.Content)
1149-
if err != nil {
1150-
ctx.Flash.Error(ctx.Tr("secrets.creation.failed"))
1151-
log.Error("validate secret: %v", err)
1152-
ctx.Redirect(ctx.Repo.RepoLink + "/settings/keys")
1153-
return
1154-
}
1155-
1156-
log.Trace("Secret added: %d", ctx.Repo.Repository.ID)
1157-
ctx.Flash.Success(ctx.Tr("secrets.creation.success", form.Title))
1158-
ctx.Redirect(ctx.Repo.RepoLink + "/settings/keys")
1159-
}
1160-
11611136
// DeployKeysPost response for adding a deploy key of a repository
11621137
func DeployKeysPost(ctx *context.Context) {
11631138
form := web.GetForm(ctx).(*forms.AddKeyForm)
@@ -1219,20 +1194,6 @@ func DeployKeysPost(ctx *context.Context) {
12191194
ctx.Redirect(ctx.Repo.RepoLink + "/settings/keys")
12201195
}
12211196

1222-
func DeleteSecret(ctx *context.Context) {
1223-
id := ctx.FormInt64("id")
1224-
if _, err := db.DeleteByBean(ctx, &secret_model.Secret{ID: id}); err != nil {
1225-
ctx.Flash.Error(ctx.Tr("secrets.deletion.failed"))
1226-
log.Error("delete secret %d: %v", id, err)
1227-
} else {
1228-
ctx.Flash.Success(ctx.Tr("secrets.deletion.success"))
1229-
}
1230-
1231-
ctx.JSON(http.StatusOK, map[string]interface{}{
1232-
"redirect": ctx.Repo.RepoLink + "/settings/keys",
1233-
})
1234-
}
1235-
12361197
// DeleteDeployKey response for deleting a deploy key
12371198
func DeleteDeployKey(ctx *context.Context) {
12381199
if err := asymkey_service.DeleteDeployKey(ctx.Doer, ctx.FormInt64("id")); err != nil {

routers/web/repo/setting_secrets.go

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// Copyright 2022 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package repo
5+
6+
import (
7+
"net/http"
8+
9+
"code.gitea.io/gitea/modules/base"
10+
"code.gitea.io/gitea/modules/context"
11+
"code.gitea.io/gitea/modules/setting"
12+
shared "code.gitea.io/gitea/routers/web/shared/secrets"
13+
)
14+
15+
const (
16+
tplSecrets base.TplName = "repo/settings/secrets"
17+
)
18+
19+
func Secrets(ctx *context.Context) {
20+
ctx.Data["Title"] = ctx.Tr("secrets.secrets")
21+
ctx.Data["PageIsSettingsSecrets"] = true
22+
ctx.Data["DisableSSH"] = setting.SSH.Disabled
23+
24+
shared.SetSecretsContext(ctx, 0, ctx.Repo.Repository.ID)
25+
if ctx.Written() {
26+
return
27+
}
28+
29+
ctx.HTML(http.StatusOK, tplSecrets)
30+
}
31+
32+
func SecretsPost(ctx *context.Context) {
33+
shared.PerformSecretsPost(
34+
ctx,
35+
0,
36+
ctx.Repo.Repository.ID,
37+
ctx.Repo.RepoLink+"/settings/secrets",
38+
)
39+
}
40+
41+
func DeleteSecret(ctx *context.Context) {
42+
shared.PerformSecretsDelete(
43+
ctx,
44+
ctx.Repo.RepoLink+"/settings/secrets",
45+
)
46+
}

routers/web/shared/secrets/secrets.go

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// Copyright 2022 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package secrets
5+
6+
import (
7+
"net/http"
8+
9+
"code.gitea.io/gitea/models/db"
10+
secret_model "code.gitea.io/gitea/models/secret"
11+
"code.gitea.io/gitea/modules/context"
12+
"code.gitea.io/gitea/modules/log"
13+
"code.gitea.io/gitea/modules/web"
14+
"code.gitea.io/gitea/services/forms"
15+
)
16+
17+
func SetSecretsContext(ctx *context.Context, ownerID, repoID int64) {
18+
secrets, err := secret_model.FindSecrets(ctx, secret_model.FindSecretsOptions{OwnerID: ownerID, RepoID: repoID})
19+
if err != nil {
20+
ctx.ServerError("FindSecrets", err)
21+
return
22+
}
23+
24+
ctx.Data["Secrets"] = secrets
25+
}
26+
27+
func PerformSecretsPost(ctx *context.Context, ownerID, repoID int64, redirectURL string) {
28+
form := web.GetForm(ctx).(*forms.AddSecretForm)
29+
30+
s, err := secret_model.InsertEncryptedSecret(ctx, ownerID, repoID, form.Title, form.Content)
31+
if err != nil {
32+
log.Error("InsertEncryptedSecret: %v", err)
33+
ctx.Flash.Error(ctx.Tr("secrets.creation.failed"))
34+
} else {
35+
ctx.Flash.Success(ctx.Tr("secrets.creation.success", s.Name))
36+
}
37+
38+
ctx.Redirect(redirectURL)
39+
}
40+
41+
func PerformSecretsDelete(ctx *context.Context, redirectURL string) {
42+
id := ctx.FormInt64("id")
43+
44+
if _, err := db.DeleteByBean(ctx, &secret_model.Secret{ID: id}); err != nil {
45+
log.Error("Delete secret %d failed: %v", id, err)
46+
ctx.Flash.Error(ctx.Tr("secrets.deletion.failed"))
47+
} else {
48+
ctx.Flash.Success(ctx.Tr("secrets.deletion.success"))
49+
}
50+
51+
ctx.JSON(http.StatusOK, map[string]interface{}{
52+
"redirect": redirectURL,
53+
})
54+
}

routers/web/user/setting/secrets.go

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Copyright 2022 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package setting
5+
6+
import (
7+
"net/http"
8+
9+
"code.gitea.io/gitea/modules/base"
10+
"code.gitea.io/gitea/modules/context"
11+
"code.gitea.io/gitea/modules/setting"
12+
shared "code.gitea.io/gitea/routers/web/shared/secrets"
13+
)
14+
15+
const (
16+
tplSettingsSecrets base.TplName = "user/settings/secrets"
17+
)
18+
19+
func Secrets(ctx *context.Context) {
20+
ctx.Data["Title"] = ctx.Tr("secrets.secrets")
21+
ctx.Data["PageIsSettingsSecrets"] = true
22+
23+
shared.SetSecretsContext(ctx, ctx.Doer.ID, 0)
24+
if ctx.Written() {
25+
return
26+
}
27+
28+
ctx.HTML(http.StatusOK, tplSettingsSecrets)
29+
}
30+
31+
func SecretsPost(ctx *context.Context) {
32+
shared.PerformSecretsPost(
33+
ctx,
34+
ctx.Doer.ID,
35+
0,
36+
setting.AppSubURL+"/user/settings/secrets",
37+
)
38+
}
39+
40+
func SecretsDelete(ctx *context.Context) {
41+
shared.PerformSecretsDelete(
42+
ctx,
43+
setting.AppSubURL+"/user/settings/secrets",
44+
)
45+
}

0 commit comments

Comments
 (0)