From b92117785a42e337a3e9347c4683f1c960655ce9 Mon Sep 17 00:00:00 2001 From: pomidorry Date: Mon, 15 Jun 2026 23:06:03 +0300 Subject: [PATCH] easy copy --- options/locale/locale_en-US.json | 1 + routers/web/repo/migrate.go | 10 ++++++++++ templates/repo/migrate/ssh_options.tmpl | 8 +++++++- web_src/js/features/repo-migrate.ts | 10 +++++++++- 4 files changed, 27 insertions(+), 2 deletions(-) diff --git a/options/locale/locale_en-US.json b/options/locale/locale_en-US.json index f2819d55ed..28e956cefa 100644 --- a/options/locale/locale_en-US.json +++ b/options/locale/locale_en-US.json @@ -1126,6 +1126,7 @@ "repo.migrate.ssh_key_owner_label": "Authenticate with", "repo.migrate.ssh_key_owner_org_default": "This organization's managed SSH key (default)", "repo.migrate.ssh_key_owner_personal": "Your personal managed SSH key (%s)", + "repo.migrate.ssh_key_manage_link": "View and copy your public key", "repo.migrate.permission_denied": "You are not allowed to import local repositories.", "repo.migrate.permission_denied_blocked": "You cannot import from disallowed hosts. Please ask the admin to check ALLOWED_DOMAINS/ALLOW_LOCALNETWORKS/BLOCKED_DOMAINS settings.", "repo.migrate.invalid_local_path": "The local path is invalid. It doesn't exist or is not a directory.", diff --git a/routers/web/repo/migrate.go b/routers/web/repo/migrate.go index 446cbac8a6..9d781e0c44 100644 --- a/routers/web/repo/migrate.go +++ b/routers/web/repo/migrate.go @@ -89,10 +89,14 @@ func setManagedSSHKeyFingerprints(ctx *context.Context, ctxUser *user_model.User } fingerprints := map[int64]string{} + // keysURLs maps an org owner id to its managed SSH keys settings page, so the + // form links to the right page to copy the key when authenticating as that org. + keysURLs := map[int64]string{} if orgs, ok := ctx.Data["Orgs"].([]*organization.Organization); ok { for _, org := range orgs { if kp, err := ssh_module.GetOrCreateSSHKeypair(ctx, org.ID); err == nil { fingerprints[org.ID] = kp.Fingerprint + keysURLs[org.ID] = org.OrganisationLink() + "/settings/ssh_keys" } } } @@ -100,12 +104,18 @@ func setManagedSSHKeyFingerprints(ctx *context.Context, ctxUser *user_model.User if _, seen := fingerprints[ctxUser.ID]; !seen { if kp, err := ssh_module.GetOrCreateSSHKeypair(ctx, ctxUser.ID); err == nil { fingerprints[ctxUser.ID] = kp.Fingerprint + if ctxUser.IsOrganization() { + keysURLs[ctxUser.ID] = ctxUser.OrganisationLink() + "/settings/ssh_keys" + } } } } if data, err := json.Marshal(fingerprints); err == nil { ctx.Data["OwnerSSHFingerprintsJSON"] = string(data) } + if data, err := json.Marshal(keysURLs); err == nil { + ctx.Data["OwnerSSHKeysURLsJSON"] = string(data) + } } func handleMigrateError(ctx *context.Context, owner *user_model.User, err error, name string, tpl templates.TplName, form *forms.MigrateRepoForm) { diff --git a/templates/repo/migrate/ssh_options.tmpl b/templates/repo/migrate/ssh_options.tmpl index 8cc1f34b6b..95131920b8 100644 --- a/templates/repo/migrate/ssh_options.tmpl +++ b/templates/repo/migrate/ssh_options.tmpl @@ -10,12 +10,15 @@
{{ctx.Locale.Tr "repo.migrate.ssh_key_owner_personal" .SignedUser.Name}} {{.SignedUserSSHFingerprint}} + {{ctx.Locale.Tr "repo.migrate.ssh_key_manage_link"}}
+ data-owner-fingerprints="{{.OwnerSSHFingerprintsJSON}}" + data-owner-keys-links="{{.OwnerSSHKeysURLsJSON}}" + data-personal-keys-link="{{AppSubUrl}}/user/settings/keys">
+ + {{ctx.Locale.Tr "repo.migrate.ssh_key_manage_link"}} + diff --git a/web_src/js/features/repo-migrate.ts b/web_src/js/features/repo-migrate.ts index e2bc3b13b8..956285e0e1 100644 --- a/web_src/js/features/repo-migrate.ts +++ b/web_src/js/features/repo-migrate.ts @@ -113,7 +113,10 @@ function initSSHKeyOwnerSelector(cloneAddrInput: HTMLInputElement) { const signedUserID = selector.getAttribute('data-signed-user-id') ?? ''; const ownerFingerprints: Record = JSON.parse(selector.getAttribute('data-owner-fingerprints') || '{}'); + const ownerKeysURLs: Record = JSON.parse(selector.getAttribute('data-owner-keys-links') || '{}'); + const personalKeysURL = selector.getAttribute('data-personal-keys-link') ?? ''; const orgDefaultFingerprintEl = selector.querySelector('.menu .item[data-value="0"] .item-fingerprint'); + const keysLink = selector.querySelector('.js-ssh-keys-link'); function update() { const isSSH = isSSHURL(cloneAddrInput.value.trim()); @@ -137,10 +140,15 @@ function initSSHKeyOwnerSelector(cloneAddrInput: HTMLInputElement) { // Org target — show dropdown; populate the org-default item's fingerprint. if (fingerprintOnly) hideElem(fingerprintOnly); if (orgDefaultFingerprintEl) orgDefaultFingerprintEl.textContent = ownerFingerprints[targetUid] ?? ''; + // Point the link at the page holding the key that will actually be used: + // the org's keys page for the org default, or the personal keys page. + if (keysLink) { + keysLink.href = hiddenId!.value === signedUserID ? personalKeysURL : (ownerKeysURLs[targetUid] ?? personalKeysURL); + } showElem(selector!); } - for (const item of document.querySelectorAll('.owner.dropdown .menu .item')) { + for (const item of document.querySelectorAll('.owner.dropdown .menu .item, .ssh-key-owner-selector .menu .item')) { item.addEventListener('click', () => setTimeout(update, 0)); }