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
··· 16 "strings" 17 "sync" 18 19 "tangled.sh/tangled.sh/core/appview/commitverify" 20 "tangled.sh/tangled.sh/core/appview/config" 21 "tangled.sh/tangled.sh/core/appview/db" ··· 690 Branches []types.Branch 691 Spindles []string 692 CurrentSpindle string 693 // TODO: use repoinfo.roles 694 IsCollaboratorInviteAllowed bool 695 }
··· 16 "strings" 17 "sync" 18 19 + "tangled.sh/tangled.sh/core/api/tangled" 20 "tangled.sh/tangled.sh/core/appview/commitverify" 21 "tangled.sh/tangled.sh/core/appview/config" 22 "tangled.sh/tangled.sh/core/appview/db" ··· 691 Branches []types.Branch 692 Spindles []string 693 CurrentSpindle string 694 + Secrets []*tangled.RepoListSecrets_Secret 695 + 696 // TODO: use repoinfo.roles 697 IsCollaboratorInviteAllowed bool 698 }
+44
appview/pages/templates/repo/settings.html
··· 115 </form> 116 {{ end }} 117 118 {{ if .RepoInfo.Roles.RepoDeleteAllowed }} 119 <form 120 hx-confirm="Are you sure you want to delete this repository?"
··· 115 </form> 116 {{ end }} 117 118 + {{ if $.CurrentSpindle }} 119 + <header class="font-bold text-sm mb-4 uppercase dark:text-white"> 120 + Secrets 121 + </header> 122 + 123 + <div id="secret-list" class="flex flex-col gap-2 mb-2"> 124 + {{ range $idx, $secret := .Secrets }} 125 + {{ with $secret }} 126 + <div id="secret-{{$idx}}" class="mb-2"> 127 + {{ .Key }} created on {{ .CreatedAt }} by {{ .CreatedBy }} 128 + </div> 129 + {{ end }} 130 + {{ end }} 131 + </div> 132 + <form 133 + hx-put="/{{ $.RepoInfo.FullName }}/settings/secrets" 134 + class="mt-6" 135 + hx-indicator="#add-secret-spinner"> 136 + <label for="key">secret key</label> 137 + <input 138 + type="text" 139 + id="key" 140 + name="key" 141 + required 142 + class="dark:bg-gray-700 dark:text-white" 143 + placeholder="SECRET_KEY" /> 144 + <label for="value">secret value</label> 145 + <input 146 + type="text" 147 + id="value" 148 + name="value" 149 + required 150 + class="dark:bg-gray-700 dark:text-white" 151 + placeholder="SECRET VALUE" /> 152 + 153 + <button class="btn my-2 flex items-center" type="text"> 154 + <span>add</span> 155 + <span id="add-secret-spinner" class="group"> 156 + {{ i "loader-circle" "ml-2 w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }} 157 + </span> 158 + </button> 159 + </form> 160 + {{ end }} 161 + 162 {{ if .RepoInfo.Roles.RepoDeleteAllowed }} 163 <form 164 hx-confirm="Are you sure you want to delete this repository?"
+89
appview/repo/repo.go
··· 912 w.Write(fmt.Append(nil, "default branch set to: ", branch)) 913 } 914 915 func (rp *Repo) RepoSettings(w http.ResponseWriter, r *http.Request) { 916 f, err := rp.repoResolver.Resolve(r) 917 if err != nil { ··· 955 return 956 } 957 958 rp.pages.RepoSettings(w, pages.RepoSettingsParams{ 959 LoggedInUser: user, 960 RepoInfo: f.RepoInfo(user), ··· 963 Branches: result.Branches, 964 Spindles: spindles, 965 CurrentSpindle: f.Spindle, 966 }) 967 } 968 }
··· 912 w.Write(fmt.Append(nil, "default branch set to: ", branch)) 913 } 914 915 + func (rp *Repo) Secrets(w http.ResponseWriter, r *http.Request) { 916 + f, err := rp.repoResolver.Resolve(r) 917 + if err != nil { 918 + log.Println("failed to get repo and knot", err) 919 + return 920 + } 921 + 922 + if f.Spindle == "" { 923 + log.Println("empty spindle cannot add/rm secret", err) 924 + return 925 + } 926 + 927 + lxm := tangled.RepoAddSecretNSID 928 + if r.Method == http.MethodDelete { 929 + lxm = tangled.RepoRemoveSecretNSID 930 + } 931 + 932 + spindleClient, err := rp.oauth.ServiceClient( 933 + r, 934 + oauth.WithService(f.Spindle), 935 + oauth.WithLxm(lxm), 936 + oauth.WithDev(rp.config.Core.Dev), 937 + ) 938 + if err != nil { 939 + log.Println("failed to create spindle client", err) 940 + return 941 + } 942 + 943 + key := r.FormValue("key") 944 + if key == "" { 945 + w.WriteHeader(http.StatusBadRequest) 946 + return 947 + } 948 + 949 + switch r.Method { 950 + case http.MethodPut: 951 + value := r.FormValue("value") 952 + if key == "" { 953 + w.WriteHeader(http.StatusBadRequest) 954 + return 955 + } 956 + 957 + err = tangled.RepoAddSecret( 958 + r.Context(), 959 + spindleClient, 960 + &tangled.RepoAddSecret_Input{ 961 + Repo: f.RepoAt.String(), 962 + Key: key, 963 + Value: value, 964 + }, 965 + ) 966 + if err != nil { 967 + log.Println("request didnt run", "err", err) 968 + return 969 + } 970 + 971 + case http.MethodDelete: 972 + err = tangled.RepoRemoveSecret( 973 + r.Context(), 974 + spindleClient, 975 + &tangled.RepoRemoveSecret_Input{ 976 + Repo: f.RepoAt.String(), 977 + Key: key, 978 + }, 979 + ) 980 + if err != nil { 981 + log.Println("request didnt run", "err", err) 982 + return 983 + } 984 + } 985 + } 986 + 987 func (rp *Repo) RepoSettings(w http.ResponseWriter, r *http.Request) { 988 f, err := rp.repoResolver.Resolve(r) 989 if err != nil { ··· 1027 return 1028 } 1029 1030 + var secrets []*tangled.RepoListSecrets_Secret 1031 + if f.Spindle != "" { 1032 + if spindleClient, err := rp.oauth.ServiceClient( 1033 + r, 1034 + oauth.WithService(f.Spindle), 1035 + oauth.WithLxm(tangled.RepoListSecretsNSID), 1036 + oauth.WithDev(rp.config.Core.Dev), 1037 + ); err != nil { 1038 + log.Println("failed to create spindle client", err) 1039 + } else if resp, err := tangled.RepoListSecrets(r.Context(), spindleClient, f.RepoAt.String()); err != nil { 1040 + log.Println("failed to fetch secrets", err) 1041 + } else { 1042 + secrets = resp.Secrets 1043 + } 1044 + } 1045 + 1046 rp.pages.RepoSettings(w, pages.RepoSettingsParams{ 1047 LoggedInUser: user, 1048 RepoInfo: f.RepoInfo(user), ··· 1051 Branches: result.Branches, 1052 Spindles: spindles, 1053 CurrentSpindle: f.Spindle, 1054 + Secrets: secrets, 1055 }) 1056 } 1057 }
+2
appview/repo/router.go
··· 74 r.With(mw.RepoPermissionMiddleware("repo:invite")).Put("/collaborator", rp.AddCollaborator) 75 r.With(mw.RepoPermissionMiddleware("repo:delete")).Delete("/delete", rp.DeleteRepo) 76 r.Put("/branches/default", rp.SetDefaultBranch) 77 }) 78 }) 79
··· 74 r.With(mw.RepoPermissionMiddleware("repo:invite")).Put("/collaborator", rp.AddCollaborator) 75 r.With(mw.RepoPermissionMiddleware("repo:delete")).Delete("/delete", rp.DeleteRepo) 76 r.Put("/branches/default", rp.SetDefaultBranch) 77 + r.Put("/secrets", rp.Secrets) 78 + r.Delete("/secrets", rp.Secrets) 79 }) 80 }) 81