diff --git a/options/locale/locale_en-US.json b/options/locale/locale_en-US.json index 321a0666bb..1ca87c1d1e 100644 --- a/options/locale/locale_en-US.json +++ b/options/locale/locale_en-US.json @@ -2660,6 +2660,9 @@ "repo.licenses.key_revoked": "License key revoked.", "repo.licenses.master_key_created": "Master License Key Created", "repo.licenses.master_key_created_copy": "This is your organization master key with unlimited access to all update channels. Copy it now — it will not be shown again.", + "repo.licenses.regenerate_master_key": "Regenerate", + "repo.licenses.regenerate_master_key_help": "Deactivates the current master key and generates a new one. The new key will be shown once.", + "repo.licenses.master_key_regenerated": "Master key regenerated. Copy the new key below — it will not be shown again.", "repo.licenses.update_feeds": "Update Feed URLs", "repo.licenses.edit_key": "Edit License Key", "repo.licenses.licensee_name": "Licensee Name", diff --git a/routers/web/repo/licenses.go b/routers/web/repo/licenses.go index 7f31859bd2..5182ef3257 100644 --- a/routers/web/repo/licenses.go +++ b/routers/web/repo/licenses.go @@ -90,6 +90,10 @@ func Licenses(ctx *context.Context) { } } + // Always load the master key for display (prefix + status). + masterKey, _ := licenses.GetMasterKey(ctx, ownerID) + ctx.Data["MasterKey"] = masterKey + pkgs, err := licenses.ListLicensePackages(ctx, ownerID) if err != nil { ctx.ServerError("ListLicensePackages", err) @@ -203,6 +207,54 @@ func LicensesCreatePackage(ctx *context.Context) { ctx.Redirect(ctx.Repo.RepoLink + "/licenses") } +// LicensesRegenerateMasterKey handles POST to regenerate the master key. +func LicensesRegenerateMasterKey(ctx *context.Context) { + ownerID := ctx.Repo.Repository.OwnerID + + // Deactivate the old master key. + oldKey, _ := licenses.GetMasterKey(ctx, ownerID) + if oldKey != nil { + oldKey.IsActive = false + _ = licenses.UpdateLicenseKey(ctx, oldKey) + } + + // Find the master package. + pkgs, err := licenses.ListLicensePackages(ctx, ownerID) + if err != nil { + ctx.ServerError("ListLicensePackages", err) + return + } + var masterPkg *licenses.LicensePackage + for _, pkg := range pkgs { + if pkg.Name == licenses.MasterPackageName { + masterPkg = pkg + break + } + } + if masterPkg == nil { + ctx.Flash.Error("Master package not found") + ctx.Redirect(ctx.Repo.RepoLink + "/licenses") + return + } + + // Create a new master key. + newKey := &licenses.LicenseKey{ + PackageID: masterPkg.ID, + OwnerID: ownerID, + IsInternal: true, + IsActive: true, + } + rawKey, err := licenses.CreateLicenseKey(ctx, newKey) + if err != nil { + ctx.ServerError("CreateLicenseKey", err) + return + } + + ctx.Flash.Success(ctx.Tr("repo.licenses.master_key_regenerated")) + ctx.Data["NewMasterKey"] = rawKey + Licenses(ctx) +} + // LicensesGenerateKey handles POST to generate a new key from a package. func LicensesGenerateKey(ctx *context.Context) { packageID, _ := strconv.ParseInt(ctx.FormString("package_id"), 10, 64) diff --git a/routers/web/web.go b/routers/web/web.go index 19d71398c5..4a8ecc18ae 100644 --- a/routers/web/web.go +++ b/routers/web/web.go @@ -1549,6 +1549,7 @@ func registerWebRoutes(m *web.Router, webAuth *AuthMiddleware) { m.Post("/packages/{id}/archive", repo.LicensesArchivePackage) m.Post("/packages/{id}/unarchive", repo.LicensesUnarchivePackage) m.Post("/keys/generate", repo.LicensesGenerateKey) + m.Post("/master-key/regenerate", repo.LicensesRegenerateMasterKey) m.Get("/keys/{id}/edit", repo.LicensesEditKey) m.Post("/keys/{id}/edit", repo.LicensesEditKeyPost) m.Post("/keys/{id}/revoke", repo.LicensesRevokeKey) diff --git a/templates/repo/licenses.tmpl b/templates/repo/licenses.tmpl index e67c132935..aebd76106c 100644 --- a/templates/repo/licenses.tmpl +++ b/templates/repo/licenses.tmpl @@ -25,12 +25,32 @@ {{end}} + {{/* ── Master Key Info ── */}} + {{if and .MasterKey .IsRepoAdmin}} +
{{.MasterKey.KeyPrefix}}
+ {{if .MasterKey.IsActive}}
+ {{ctx.Locale.Tr "repo.licenses.active"}}
+ {{else}}
+ {{ctx.Locale.Tr "repo.licenses.inactive"}}
+ {{end}}
+ {{if .KeyRaw}}{{.KeyRaw}}{{else}}{{.KeyPrefix}}{{end}}
- {{if .KeyRaw}}{{end}}
+
{{if .IsInternal}} {{ctx.Locale.Tr "repo.licenses.master_label"}}{{end}}