public gpg key download on management screen

This commit is contained in:
Konstantin Schaper
2020-08-05 21:23:55 +02:00
parent 0ac8b90c2f
commit acaf70feab
10 changed files with 30 additions and 12 deletions

View File

@@ -69,7 +69,6 @@ const SignatureIcon: FC<Props> = ({ signatures, className }) => {
"changeset.signatureStatus" "changeset.signatureStatus"
)}: ${status}`; )}: ${status}`;
console.log(signature.contacts)
if (signature.contacts?.length > 0) { if (signature.contacts?.length > 0) {
message += `\n${t("changeset.keyContacts")}:`; message += `\n${t("changeset.keyContacts")}:`;
signature.contacts.forEach((contact) => { signature.contacts.forEach((contact) => {

View File

@@ -68,6 +68,7 @@
"raw": "Schlüssel", "raw": "Schlüssel",
"created": "Eingetragen an", "created": "Eingetragen an",
"addKey": "Schlüssel hinzufügen", "addKey": "Schlüssel hinzufügen",
"delete": "Löschen" "delete": "Löschen",
"download": "Herunterladen"
} }
} }

View File

@@ -68,6 +68,7 @@
"raw": "Key", "raw": "Key",
"created": "Created on", "created": "Created on",
"addKey": "Add key", "addKey": "Add key",
"delete": "Delete" "delete": "Delete",
"download": "Download"
} }
} }

View File

@@ -23,11 +23,10 @@
*/ */
import React, { FC } from "react"; import React, { FC } from "react";
import { DateFromNow, DeleteButton } from "@scm-manager/ui-components/src"; import {DateFromNow, DeleteButton, DownloadButton} from "@scm-manager/ui-components/src";
import { PublicKey } from "./SetPublicKeys"; import { PublicKey } from "./SetPublicKeys";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Link } from "@scm-manager/ui-types"; import { Link } from "@scm-manager/ui-types";
import { formatPublicKey } from "./formatPublicKey";
type Props = { type Props = {
publicKey: PublicKey; publicKey: PublicKey;
@@ -43,6 +42,12 @@ export const PublicKeyEntry: FC<Props> = ({ publicKey, onDelete }) => {
<DeleteButton label={t("publicKey.delete")} action={() => onDelete((publicKey._links.delete as Link).href)} /> <DeleteButton label={t("publicKey.delete")} action={() => onDelete((publicKey._links.delete as Link).href)} />
); );
} }
let downloadButton;
if (publicKey?._links?.raw) {
downloadButton = (
<DownloadButton displayName={t("publicKey.download")} url={(publicKey?._links?.raw as Link).href} />
);
}
return ( return (
<> <>
@@ -53,6 +58,7 @@ export const PublicKeyEntry: FC<Props> = ({ publicKey, onDelete }) => {
</td> </td>
<td className="is-hidden-mobile">{publicKey.id}</td> <td className="is-hidden-mobile">{publicKey.id}</td>
<td>{deleteButton}</td> <td>{deleteButton}</td>
<td>{downloadButton}</td>
</tr> </tr>
</> </>
); );

View File

@@ -33,7 +33,7 @@ type Props = {
onDelete: (link: string) => void; onDelete: (link: string) => void;
}; };
const PublicKeyTable: FC<Props> = ({ publicKeys, onDelete }) => { const PublicKeyTable: FC<Props> = ({ publicKeys, onDelete, onDownload }) => {
const [t] = useTranslation("users"); const [t] = useTranslation("users");
if (publicKeys?._embedded?.keys?.length === 0) { if (publicKeys?._embedded?.keys?.length === 0) {

View File

@@ -61,6 +61,7 @@ public abstract class PublicKeyMapper {
if (UserPermissions.changePublicKeys(rawGpgKey.getOwner()).isPermitted() && !rawGpgKey.isReadonly()) { if (UserPermissions.changePublicKeys(rawGpgKey.getOwner()).isPermitted() && !rawGpgKey.isReadonly()) {
linksBuilder.single(Link.link("delete", createDeleteLink(rawGpgKey))); linksBuilder.single(Link.link("delete", createDeleteLink(rawGpgKey)));
} }
linksBuilder.single(Link.link("raw", createDownloadLink(rawGpgKey)));
return new RawGpgKeyDto(linksBuilder.build()); return new RawGpgKeyDto(linksBuilder.build());
} }
@@ -77,4 +78,11 @@ public abstract class PublicKeyMapper {
.parameters(rawGpgKey.getOwner(), rawGpgKey.getId()) .parameters(rawGpgKey.getOwner(), rawGpgKey.getId())
.href(); .href();
} }
private String createDownloadLink(RawGpgKey rawGpgKey) {
return new LinkBuilder(scmPathInfoStore.get().get(), PublicKeyResource.class)
.method("findByIdGpg")
.parameters(rawGpgKey.getId())
.href();
}
} }

View File

@@ -90,7 +90,9 @@ public class PublicKeyResource {
public Response findByIdGpg(@PathParam("id") String id) { public Response findByIdGpg(@PathParam("id") String id) {
Optional<RawGpgKey> byId = store.findById(id); Optional<RawGpgKey> byId = store.findById(id);
if (byId.isPresent()) { if (byId.isPresent()) {
return Response.ok(byId.get().getRaw()).build(); return Response.ok(byId.get().getRaw())
.header("Content-Disposition", "attachment; filename=\"" + byId.get().getDisplayName() + ".asc\"")
.build();
} }
return Response.status(Response.Status.NOT_FOUND).build(); return Response.status(Response.Status.NOT_FOUND).build();
} }

View File

@@ -206,7 +206,7 @@ class MeDtoFactoryTest {
when(subject.isPermitted("user:changePublicKeys:trillian")).thenReturn(true); when(subject.isPermitted("user:changePublicKeys:trillian")).thenReturn(true);
MeDto dto = meDtoFactory.create(); MeDto dto = meDtoFactory.create();
assertThat(dto.getLinks().getLinkBy("publicKeys").get().getHref()).isEqualTo("https://scm.hitchhiker.com/scm/v2/public_keys/trillian"); assertThat(dto.getLinks().getLinkBy("publicKeys").get().getHref()).isEqualTo("https://scm.hitchhiker.com/scm/v2/users/trillian/public_keys");
} }
@Test @Test

View File

@@ -86,7 +86,7 @@ class PublicKeyCollectionMapperTest {
List<HalRepresentation> embedded = collection.getEmbedded().getItemsBy("keys"); List<HalRepresentation> embedded = collection.getEmbedded().getItemsBy("keys");
assertThat(embedded).hasSize(2); assertThat(embedded).hasSize(2);
assertThat(collection.getLinks().getLinkBy("self").get().getHref()).isEqualTo("/v2/public_keys/trillian"); assertThat(collection.getLinks().getLinkBy("self").get().getHref()).isEqualTo("/v2/users/trillian/public_keys");
} }
@Test @Test
@@ -94,7 +94,7 @@ class PublicKeyCollectionMapperTest {
when(subject.isPermitted("user:changePublicKeys:trillian")).thenReturn(true); when(subject.isPermitted("user:changePublicKeys:trillian")).thenReturn(true);
HalRepresentation collection = collectionMapper.map("trillian", Lists.newArrayList()); HalRepresentation collection = collectionMapper.map("trillian", Lists.newArrayList());
assertThat(collection.getLinks().getLinkBy("create").get().getHref()).isEqualTo("/v2/public_keys/trillian"); assertThat(collection.getLinks().getLinkBy("create").get().getHref()).isEqualTo("/v2/users/trillian/public_keys");
} }
@Test @Test

View File

@@ -76,8 +76,9 @@ class PublicKeyMapperTest {
assertThat(dto.getDisplayName()).isEqualTo(key.getDisplayName()); assertThat(dto.getDisplayName()).isEqualTo(key.getDisplayName());
assertThat(dto.getCreated()).isEqualTo(key.getCreated()); assertThat(dto.getCreated()).isEqualTo(key.getCreated());
assertThat(dto.getLinks().getLinkBy("self").get().getHref()).isEqualTo("/v2/public_keys/1"); assertThat(dto.getLinks().getLinkBy("self").get().getHref()).isEqualTo("/v2/users/trillian/public_keys/1");
assertThat(dto.getLinks().getLinkBy("delete").get().getHref()).isEqualTo("/v2/public_keys/delete/1"); assertThat(dto.getLinks().getLinkBy("delete").get().getHref()).isEqualTo("/v2/users/trillian/public_keys/1");
assertThat(dto.getLinks().getLinkBy("raw").get().getHref()).isEqualTo("/v2/public_keys/1");
} }
@Test @Test