appview/repo: add secret management forms to repo settings #376

merged
opened by oppi.li targeting master from push-vynsusnqpmus
Changed files
+138
appview
pages
templates
repo
+3
appview/pages/pages.go
···
"strings"
"sync"
"tangled.sh/tangled.sh/core/appview/commitverify"
"tangled.sh/tangled.sh/core/appview/config"
"tangled.sh/tangled.sh/core/appview/db"
···
Branches []types.Branch
Spindles []string
CurrentSpindle string
// TODO: use repoinfo.roles
IsCollaboratorInviteAllowed bool
}
···
"strings"
"sync"
+
"tangled.sh/tangled.sh/core/api/tangled"
"tangled.sh/tangled.sh/core/appview/commitverify"
"tangled.sh/tangled.sh/core/appview/config"
"tangled.sh/tangled.sh/core/appview/db"
···
Branches []types.Branch
Spindles []string
CurrentSpindle string
+
Secrets []*tangled.RepoListSecrets_Secret
+
// TODO: use repoinfo.roles
IsCollaboratorInviteAllowed bool
}
+44
appview/pages/templates/repo/settings.html
···
</form>
{{ end }}
{{ if .RepoInfo.Roles.RepoDeleteAllowed }}
<form
hx-confirm="Are you sure you want to delete this repository?"
···
</form>
{{ end }}
+
{{ if $.CurrentSpindle }}
+
<header class="font-bold text-sm mb-4 uppercase dark:text-white">
+
Secrets
+
</header>
+
+
<div id="secret-list" class="flex flex-col gap-2 mb-2">
+
{{ range $idx, $secret := .Secrets }}
+
{{ with $secret }}
+
<div id="secret-{{$idx}}" class="mb-2">
+
{{ .Key }} created on {{ .CreatedAt }} by {{ .CreatedBy }}
+
</div>
+
{{ end }}
+
{{ end }}
+
</div>
+
<form
+
hx-put="/{{ $.RepoInfo.FullName }}/settings/secrets"
+
class="mt-6"
+
hx-indicator="#add-secret-spinner">
+
<label for="key">secret key</label>
+
<input
+
type="text"
+
id="key"
+
name="key"
+
required
+
class="dark:bg-gray-700 dark:text-white"
+
placeholder="SECRET_KEY" />
+
<label for="value">secret value</label>
+
<input
+
type="text"
+
id="value"
+
name="value"
+
required
+
class="dark:bg-gray-700 dark:text-white"
+
placeholder="SECRET VALUE" />
+
+
<button class="btn my-2 flex items-center" type="text">
+
<span>add</span>
+
<span id="add-secret-spinner" class="group">
+
{{ i "loader-circle" "ml-2 w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
+
</span>
+
</button>
+
</form>
+
{{ end }}
+
{{ if .RepoInfo.Roles.RepoDeleteAllowed }}
<form
hx-confirm="Are you sure you want to delete this repository?"
+89
appview/repo/repo.go
···
w.Write(fmt.Append(nil, "default branch set to: ", branch))
}
func (rp *Repo) RepoSettings(w http.ResponseWriter, r *http.Request) {
f, err := rp.repoResolver.Resolve(r)
if err != nil {
···
return
}
rp.pages.RepoSettings(w, pages.RepoSettingsParams{
LoggedInUser: user,
RepoInfo: f.RepoInfo(user),
···
Branches: result.Branches,
Spindles: spindles,
CurrentSpindle: f.Spindle,
})
}
}
···
w.Write(fmt.Append(nil, "default branch set to: ", branch))
}
+
func (rp *Repo) Secrets(w http.ResponseWriter, r *http.Request) {
+
f, err := rp.repoResolver.Resolve(r)
+
if err != nil {
+
log.Println("failed to get repo and knot", err)
+
return
+
}
+
+
if f.Spindle == "" {
+
log.Println("empty spindle cannot add/rm secret", err)
+
return
+
}
+
+
lxm := tangled.RepoAddSecretNSID
+
if r.Method == http.MethodDelete {
+
lxm = tangled.RepoRemoveSecretNSID
+
}
+
+
spindleClient, err := rp.oauth.ServiceClient(
+
r,
+
oauth.WithService(f.Spindle),
+
oauth.WithLxm(lxm),
+
oauth.WithDev(rp.config.Core.Dev),
+
)
+
if err != nil {
+
log.Println("failed to create spindle client", err)
+
return
+
}
+
+
key := r.FormValue("key")
+
if key == "" {
+
w.WriteHeader(http.StatusBadRequest)
+
return
+
}
+
+
switch r.Method {
+
case http.MethodPut:
+
value := r.FormValue("value")
+
if key == "" {
+
w.WriteHeader(http.StatusBadRequest)
+
return
+
}
+
+
err = tangled.RepoAddSecret(
+
r.Context(),
+
spindleClient,
+
&tangled.RepoAddSecret_Input{
+
Repo: f.RepoAt.String(),
+
Key: key,
+
Value: value,
+
},
+
)
+
if err != nil {
+
log.Println("request didnt run", "err", err)
+
return
+
}
+
+
case http.MethodDelete:
+
err = tangled.RepoRemoveSecret(
+
r.Context(),
+
spindleClient,
+
&tangled.RepoRemoveSecret_Input{
+
Repo: f.RepoAt.String(),
+
Key: key,
+
},
+
)
+
if err != nil {
+
log.Println("request didnt run", "err", err)
+
return
+
}
+
}
+
}
+
func (rp *Repo) RepoSettings(w http.ResponseWriter, r *http.Request) {
f, err := rp.repoResolver.Resolve(r)
if err != nil {
···
return
}
+
var secrets []*tangled.RepoListSecrets_Secret
+
if f.Spindle != "" {
+
if spindleClient, err := rp.oauth.ServiceClient(
+
r,
+
oauth.WithService(f.Spindle),
+
oauth.WithLxm(tangled.RepoListSecretsNSID),
+
oauth.WithDev(rp.config.Core.Dev),
+
); err != nil {
+
log.Println("failed to create spindle client", err)
+
} else if resp, err := tangled.RepoListSecrets(r.Context(), spindleClient, f.RepoAt.String()); err != nil {
+
log.Println("failed to fetch secrets", err)
+
} else {
+
secrets = resp.Secrets
+
}
+
}
+
rp.pages.RepoSettings(w, pages.RepoSettingsParams{
LoggedInUser: user,
RepoInfo: f.RepoInfo(user),
···
Branches: result.Branches,
Spindles: spindles,
CurrentSpindle: f.Spindle,
+
Secrets: secrets,
})
}
}
+2
appview/repo/router.go
···
r.With(mw.RepoPermissionMiddleware("repo:invite")).Put("/collaborator", rp.AddCollaborator)
r.With(mw.RepoPermissionMiddleware("repo:delete")).Delete("/delete", rp.DeleteRepo)
r.Put("/branches/default", rp.SetDefaultBranch)
})
})
···
r.With(mw.RepoPermissionMiddleware("repo:invite")).Put("/collaborator", rp.AddCollaborator)
r.With(mw.RepoPermissionMiddleware("repo:delete")).Delete("/delete", rp.DeleteRepo)
r.Put("/branches/default", rp.SetDefaultBranch)
+
r.Put("/secrets", rp.Secrets)
+
r.Delete("/secrets", rp.Secrets)
})
})