mirror of
https://github.com/theonedev/onedev.git
synced 2025-12-08 18:26:30 +00:00
Fix issue #747 - Support verify signing with sub key
This commit is contained in:
parent
cbd5656b5b
commit
18b0b23b8a
@ -2,12 +2,13 @@ package io.onedev.server.entitymanager;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import io.onedev.server.git.signature.SignatureVerificationKey;
|
||||
import io.onedev.server.model.GpgKey;
|
||||
import io.onedev.server.persistence.dao.EntityManager;
|
||||
|
||||
public interface GpgKeyManager extends EntityManager<GpgKey> {
|
||||
|
||||
@Nullable
|
||||
GpgKey findByKeyId(long keyId);
|
||||
SignatureVerificationKey findSignatureVerificationKey(long keyId);
|
||||
|
||||
}
|
||||
|
||||
@ -2,18 +2,21 @@ package io.onedev.server.entitymanager.impl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.bouncycastle.openpgp.PGPPublicKey;
|
||||
|
||||
import io.onedev.commons.loader.Listen;
|
||||
import io.onedev.server.entitymanager.GpgKeyManager;
|
||||
import io.onedev.server.event.entity.EntityPersisted;
|
||||
import io.onedev.server.event.entity.EntityRemoved;
|
||||
import io.onedev.server.event.system.SystemStarted;
|
||||
import io.onedev.server.git.signature.SignatureVerificationKey;
|
||||
import io.onedev.server.model.EmailAddress;
|
||||
import io.onedev.server.model.GpgKey;
|
||||
import io.onedev.server.model.User;
|
||||
@ -22,13 +25,14 @@ import io.onedev.server.persistence.annotation.Sessional;
|
||||
import io.onedev.server.persistence.annotation.Transactional;
|
||||
import io.onedev.server.persistence.dao.BaseEntityManager;
|
||||
import io.onedev.server.persistence.dao.Dao;
|
||||
import io.onedev.server.util.GpgUtils;
|
||||
|
||||
@Singleton
|
||||
public class DefaultGpgKeyManager extends BaseEntityManager<GpgKey> implements GpgKeyManager {
|
||||
|
||||
private final TransactionManager transactionManager;
|
||||
|
||||
private final Map<Long, Long> idCache = new ConcurrentHashMap<>();
|
||||
private final Map<Long, Long> entityIdCache = new ConcurrentHashMap<>();
|
||||
|
||||
@Inject
|
||||
public DefaultGpgKeyManager(Dao dao, TransactionManager transactionManager) {
|
||||
@ -36,43 +40,38 @@ public class DefaultGpgKeyManager extends BaseEntityManager<GpgKey> implements G
|
||||
this.transactionManager = transactionManager;
|
||||
}
|
||||
|
||||
@Sessional
|
||||
@Override
|
||||
public GpgKey findByKeyId(long keyId) {
|
||||
Long id = idCache.get(keyId);
|
||||
return id != null? load(id): null;
|
||||
}
|
||||
|
||||
@Listen
|
||||
@Sessional
|
||||
public void on(SystemStarted event) {
|
||||
for (GpgKey key: query())
|
||||
idCache.put(key.getKeyId(), key.getId());
|
||||
for (GpgKey key: query()) {
|
||||
for (Long keyId: key.getKeyIds())
|
||||
entityIdCache.put(keyId, key.getId());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Transactional
|
||||
@Listen
|
||||
public void on(EntityRemoved event) {
|
||||
if (event.getEntity() instanceof GpgKey) {
|
||||
long keyId = ((GpgKey)event.getEntity()).getKeyId();
|
||||
List<Long> keyIds = ((GpgKey)event.getEntity()).getKeyIds();
|
||||
transactionManager.runAfterCommit(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
idCache.remove(keyId);
|
||||
entityIdCache.keySet().removeAll(keyIds);
|
||||
}
|
||||
|
||||
});
|
||||
} else if (event.getEntity() instanceof EmailAddress) {
|
||||
EmailAddress emailAddress = (EmailAddress) event.getEntity();
|
||||
Collection<Long> keyIds = emailAddress.getGpgKeys().stream()
|
||||
.map(it->it.getKeyId())
|
||||
.collect(Collectors.toList());
|
||||
Collection<Long> keyIds = new ArrayList<>();
|
||||
for (GpgKey key: emailAddress.getGpgKeys())
|
||||
keyIds.addAll(key.getKeyIds());
|
||||
transactionManager.runAfterCommit(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
idCache.keySet().removeAll(keyIds);
|
||||
entityIdCache.keySet().removeAll(keyIds);
|
||||
}
|
||||
|
||||
});
|
||||
@ -80,15 +79,14 @@ public class DefaultGpgKeyManager extends BaseEntityManager<GpgKey> implements G
|
||||
User user = (User) event.getEntity();
|
||||
Collection<Long> keyIds = new ArrayList<>();
|
||||
for (EmailAddress emailAddress: user.getEmailAddresses()) {
|
||||
keyIds.addAll(emailAddress.getGpgKeys().stream()
|
||||
.map(it->it.getKeyId())
|
||||
.collect(Collectors.toList()));
|
||||
for (GpgKey key: emailAddress.getGpgKeys())
|
||||
keyIds.addAll(key.getKeyIds());
|
||||
}
|
||||
transactionManager.runAfterCommit(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
idCache.keySet().removeAll(keyIds);
|
||||
entityIdCache.keySet().removeAll(keyIds);
|
||||
}
|
||||
|
||||
});
|
||||
@ -100,17 +98,50 @@ public class DefaultGpgKeyManager extends BaseEntityManager<GpgKey> implements G
|
||||
public void on(EntityPersisted event) {
|
||||
if (event.getEntity() instanceof GpgKey) {
|
||||
GpgKey gpgKey = (GpgKey) event.getEntity();
|
||||
long keyId = gpgKey.getKeyId();
|
||||
Long id = gpgKey.getId();
|
||||
List<Long> keyIds = gpgKey.getKeyIds();
|
||||
Long entityId = gpgKey.getId();
|
||||
transactionManager.runAfterCommit(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
idCache.put(keyId, id);
|
||||
for (Long keyId: keyIds)
|
||||
entityIdCache.put(keyId, entityId);
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Sessional
|
||||
@Override
|
||||
public SignatureVerificationKey findSignatureVerificationKey(long keyId) {
|
||||
Long entityId = entityIdCache.get(keyId);
|
||||
if (entityId != null) {
|
||||
return new SignatureVerificationKey() {
|
||||
|
||||
@Override
|
||||
public boolean shouldVerifyDataWriter() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PGPPublicKey getPublicKey() {
|
||||
for (PGPPublicKey publicKey: load(entityId).getPublicKeys()) {
|
||||
if (keyId == publicKey.getKeyID())
|
||||
return publicKey;
|
||||
}
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEmailAddress() {
|
||||
return GpgUtils.getEmailAddress(load(entityId).getPublicKeys().get(0));
|
||||
}
|
||||
|
||||
};
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -683,8 +683,7 @@ public class GitUtils {
|
||||
key.getPublicKey());
|
||||
signature.update(data);
|
||||
if (signature.verify()) {
|
||||
String signer = GpgUtils.getEmailAddress(key.getPublicKey());
|
||||
if (!key.shouldVerifyDataWriter() || signer.equals(dataWriter))
|
||||
if (!key.shouldVerifyDataWriter() || key.getEmailAddress().equals(dataWriter))
|
||||
return new SignatureVerified(key);
|
||||
else
|
||||
return new SignatureUnverified(key, "Email address of signing key and committer is different");
|
||||
@ -696,7 +695,7 @@ public class GitUtils {
|
||||
return new SignatureUnverified(key, "Signature verification failed");
|
||||
}
|
||||
} else {
|
||||
return new SignatureUnverified(null, "Signature is signed with an unkown key "
|
||||
return new SignatureUnverified(null, "Signature is signed with an unknown key "
|
||||
+ "(key ID: " + GpgUtils.getKeyIDString(signature.getKeyID()) + ")");
|
||||
}
|
||||
} else {
|
||||
|
||||
@ -1,25 +1,31 @@
|
||||
package io.onedev.server.git.signature;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import io.onedev.server.OneDev;
|
||||
import io.onedev.server.entitymanager.GpgKeyManager;
|
||||
import io.onedev.server.entitymanager.SettingManager;
|
||||
import io.onedev.server.model.GpgKey;
|
||||
import io.onedev.server.model.support.administration.GpgSetting;
|
||||
|
||||
@Singleton
|
||||
public class DefaultSignatureVerificationKeyLoader implements SignatureVerificationKeyLoader {
|
||||
|
||||
private final SettingManager settingManager;
|
||||
|
||||
private final GpgKeyManager gpgKeyManager;
|
||||
|
||||
@Inject
|
||||
public DefaultSignatureVerificationKeyLoader(SettingManager settingManager, GpgKeyManager gpgKeyManager) {
|
||||
this.settingManager = settingManager;
|
||||
this.gpgKeyManager = gpgKeyManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SignatureVerificationKey getSignatureVerificationKey(long keyId) {
|
||||
GpgSetting gpgSetting = OneDev.getInstance(SettingManager.class).getGpgSetting();
|
||||
GpgSetting gpgSetting = settingManager.getGpgSetting();
|
||||
SignatureVerificationKey verificationKey = gpgSetting.findSignatureVerificationKey(keyId);
|
||||
if (verificationKey == null) {
|
||||
GpgKey gpgKey = OneDev.getInstance(GpgKeyManager.class).findByKeyId(keyId);
|
||||
if (gpgKey != null)
|
||||
verificationKey = gpgKey.getSignatureVerificationKey();
|
||||
}
|
||||
if (verificationKey == null)
|
||||
verificationKey = gpgKeyManager.findSignatureVerificationKey(keyId);
|
||||
return verificationKey;
|
||||
}
|
||||
|
||||
|
||||
@ -8,4 +8,6 @@ public interface SignatureVerificationKey {
|
||||
|
||||
PGPPublicKey getPublicKey();
|
||||
|
||||
String getEmailAddress();
|
||||
|
||||
}
|
||||
|
||||
@ -10,13 +10,11 @@ import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.bouncycastle.openpgp.PGPPublicKey;
|
||||
import org.hibernate.annotations.Cache;
|
||||
import org.hibernate.annotations.CacheConcurrencyStrategy;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
|
||||
import io.onedev.server.git.signature.SignatureVerificationKey;
|
||||
import io.onedev.server.model.support.BaseGpgKey;
|
||||
import io.onedev.server.web.editable.annotation.Editable;
|
||||
|
||||
@ -66,19 +64,4 @@ public class GpgKey extends BaseGpgKey {
|
||||
this.createdAt = createdAt;
|
||||
}
|
||||
|
||||
public SignatureVerificationKey getSignatureVerificationKey() {
|
||||
return new SignatureVerificationKey() {
|
||||
|
||||
@Override
|
||||
public boolean shouldVerifyDataWriter() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PGPPublicKey getPublicKey() {
|
||||
return GpgKey.this.getPublicKey();
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
package io.onedev.server.model.support;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.MappedSuperclass;
|
||||
import javax.validation.ConstraintValidatorContext;
|
||||
@ -27,7 +30,7 @@ public class BaseGpgKey extends AbstractEntity implements Validatable {
|
||||
@Column(nullable=false, length=5000)
|
||||
private String content;
|
||||
|
||||
private transient PGPPublicKey publicKey;
|
||||
private transient List<PGPPublicKey> publicKeys;
|
||||
|
||||
@Editable(name="GPG Public Key", placeholder="GPG public key begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'")
|
||||
@NotEmpty
|
||||
@ -41,10 +44,14 @@ public class BaseGpgKey extends AbstractEntity implements Validatable {
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
public PGPPublicKey getPublicKey() {
|
||||
if (publicKey == null)
|
||||
publicKey = GpgUtils.parse(content);
|
||||
return publicKey;
|
||||
public List<PGPPublicKey> getPublicKeys() {
|
||||
if (publicKeys == null)
|
||||
publicKeys = GpgUtils.parse(content);
|
||||
return publicKeys;
|
||||
}
|
||||
|
||||
public List<Long> getKeyIds() {
|
||||
return getPublicKeys().stream().map(it->it.getKeyID()).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -4,6 +4,7 @@ import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
@ -26,7 +27,9 @@ public class GpgSetting implements Serializable {
|
||||
|
||||
private Map<Long, String> encodedTrustedKeys = new LinkedHashMap<>();
|
||||
|
||||
private transient Map<Long, PGPPublicKey> trustedKeys;
|
||||
private transient Map<Long, SignatureVerificationKey> trustedSignatureVerificationKeys;
|
||||
|
||||
private transient Map<Long, List<PGPPublicKey>> trustedKeys;
|
||||
|
||||
public GpgSetting() {
|
||||
// Add GitHub public GPG key
|
||||
@ -74,20 +77,53 @@ public class GpgSetting implements Serializable {
|
||||
public Map<Long, String> getEncodedTrustedKeys() {
|
||||
return encodedTrustedKeys;
|
||||
}
|
||||
|
||||
public void encodedTrustedKeysUpdated() {
|
||||
trustedKeys = null;
|
||||
trustedSignatureVerificationKeys = null;
|
||||
}
|
||||
|
||||
public Map<Long, List<PGPPublicKey>> getTrustedKeys() {
|
||||
if (trustedKeys == null) {
|
||||
trustedKeys = new HashMap<>();
|
||||
for (Map.Entry<Long, String> entry: encodedTrustedKeys.entrySet())
|
||||
trustedKeys.put(entry.getKey(), GpgUtils.parse(entry.getValue()));
|
||||
}
|
||||
return trustedKeys;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PGPPublicKey getTrustedKey(long keyId) {
|
||||
if (trustedKeys == null)
|
||||
trustedKeys = new HashMap<>();
|
||||
PGPPublicKey trustedKey = trustedKeys.get(keyId);
|
||||
if (trustedKey == null) {
|
||||
String encodedTrustedKey = encodedTrustedKeys.get(keyId);
|
||||
if (encodedTrustedKey != null) {
|
||||
trustedKey = GpgUtils.parse(encodedTrustedKey);
|
||||
trustedKeys.put(keyId, trustedKey);
|
||||
public SignatureVerificationKey getTrustedSignatureVerificationKey(long keyId) {
|
||||
return getTrustedSignatureVerificationKeys().get(keyId);
|
||||
}
|
||||
|
||||
private Map<Long, SignatureVerificationKey> getTrustedSignatureVerificationKeys() {
|
||||
if (trustedSignatureVerificationKeys == null) {
|
||||
trustedSignatureVerificationKeys = new HashMap<>();
|
||||
for (List<PGPPublicKey> publicKeys: getTrustedKeys().values()) {
|
||||
for (PGPPublicKey publicKey: publicKeys) {
|
||||
trustedSignatureVerificationKeys.put(publicKey.getKeyID(), new SignatureVerificationKey() {
|
||||
|
||||
@Override
|
||||
public boolean shouldVerifyDataWriter() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PGPPublicKey getPublicKey() {
|
||||
return publicKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEmailAddress() {
|
||||
return GpgUtils.getEmailAddress(publicKeys.get(0));
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
return trustedKey;
|
||||
return trustedSignatureVerificationKeys;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@ -104,27 +140,15 @@ public class GpgSetting implements Serializable {
|
||||
public PGPPublicKey getPublicKey() {
|
||||
return getSigningKey().getPublicKey();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEmailAddress() {
|
||||
return GpgUtils.getEmailAddress(getPublicKey());
|
||||
}
|
||||
|
||||
};
|
||||
} else {
|
||||
PGPPublicKey trustedKey = getTrustedKey(keyId);
|
||||
if (trustedKey != null) {
|
||||
return new SignatureVerificationKey() {
|
||||
|
||||
@Override
|
||||
public boolean shouldVerifyDataWriter() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PGPPublicKey getPublicKey() {
|
||||
return trustedKey;
|
||||
}
|
||||
|
||||
};
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
return getTrustedSignatureVerificationKey(keyId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -6,8 +6,10 @@ import java.io.InputStream;
|
||||
import java.math.BigInteger;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.bouncycastle.bcpg.HashAlgorithmTags;
|
||||
import org.bouncycastle.bcpg.SymmetricKeyAlgorithmTags;
|
||||
@ -37,18 +39,20 @@ import io.onedev.commons.utils.StringUtils;
|
||||
|
||||
public class GpgUtils {
|
||||
|
||||
public static PGPPublicKey parse(String publicKeyString) {
|
||||
public static List<PGPPublicKey> parse(String publicKeyString) {
|
||||
try (InputStream in = PGPUtil
|
||||
.getDecoderStream(new ByteArrayInputStream(publicKeyString.getBytes(StandardCharsets.UTF_8)))) {
|
||||
List<PGPPublicKey> publicKeys = new ArrayList<>();
|
||||
JcaPGPPublicKeyRingCollection ringCollection = new JcaPGPPublicKeyRingCollection(in);
|
||||
Iterator<PGPPublicKeyRing> itRing = ringCollection.getKeyRings();
|
||||
if (!itRing.hasNext())
|
||||
throw new ExplicitException("No key ring found");
|
||||
PGPPublicKeyRing ring = itRing.next();
|
||||
Iterator<PGPPublicKey> itKey = ring.getPublicKeys();
|
||||
if (!itKey.hasNext())
|
||||
while (itRing.hasNext()) {
|
||||
Iterator<PGPPublicKey> itKey = itRing.next().getPublicKeys();
|
||||
while (itKey.hasNext())
|
||||
publicKeys.add(itKey.next());
|
||||
}
|
||||
if (publicKeys.isEmpty())
|
||||
throw new ExplicitException("No public key found");
|
||||
return itKey.next();
|
||||
return publicKeys;
|
||||
} catch (IOException | PGPException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
@ -35,7 +35,7 @@ abstract class GitSignatureDetailPanel extends Panel {
|
||||
message = "Signature verified successfully with committer's GPG key";
|
||||
else
|
||||
message = "Signature verified successfully with tagger's GPG key";
|
||||
} else if (getGpgSetting().getTrustedKey(key.getPublicKey().getKeyID()) != null) {
|
||||
} else if (getGpgSetting().getTrustedSignatureVerificationKey(key.getPublicKey().getKeyID()) != null) {
|
||||
message = "Signature verified successfully with trusted GPG key";
|
||||
} else {
|
||||
message = "Signature verified successfully with OneDev GPG key";
|
||||
@ -54,7 +54,7 @@ abstract class GitSignatureDetailPanel extends Panel {
|
||||
|
||||
if (key != null) {
|
||||
add(new Label("keyId", GpgUtils.getKeyIDString(key.getPublicKey().getKeyID())));
|
||||
add(new Label("emailAddress", GpgUtils.getEmailAddress(key.getPublicKey())));
|
||||
add(new Label("emailAddress", key.getEmailAddress()));
|
||||
} else {
|
||||
add(new WebMarkupContainer("keyId").setVisible(false));
|
||||
add(new WebMarkupContainer("emailAddress").setVisible(false));
|
||||
|
||||
@ -3,6 +3,7 @@ package io.onedev.server.web.component.user.gpgkey;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.wicket.Session;
|
||||
import org.apache.wicket.ajax.AjaxRequestTarget;
|
||||
@ -26,7 +27,6 @@ import org.apache.wicket.model.Model;
|
||||
import io.onedev.server.OneDev;
|
||||
import io.onedev.server.entitymanager.GpgKeyManager;
|
||||
import io.onedev.server.model.GpgKey;
|
||||
import io.onedev.server.util.DateUtils;
|
||||
import io.onedev.server.util.GpgUtils;
|
||||
import io.onedev.server.web.ajaxlistener.ConfirmClickListener;
|
||||
import io.onedev.server.web.component.datatable.DefaultDataTable;
|
||||
@ -67,12 +67,12 @@ public class GpgKeyListPanel extends GenericPanel<List<GpgKey>> {
|
||||
public void populateItem(Item<ICellPopulator<GpgKey>> cellItem, String componentId,
|
||||
IModel<GpgKey> rowModel) {
|
||||
cellItem.add(new Label(componentId,
|
||||
GpgUtils.getKeyIDString(rowModel.getObject().getPublicKey().getKeyID())));
|
||||
GpgUtils.getKeyIDString(rowModel.getObject().getKeyId())));
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
columns.add(new AbstractColumn<GpgKey, Void>(Model.of("Created At")) {
|
||||
columns.add(new AbstractColumn<GpgKey, Void>(Model.of("Sub Keys")) {
|
||||
|
||||
@Override
|
||||
public String getCssClass() {
|
||||
@ -82,7 +82,15 @@ public class GpgKeyListPanel extends GenericPanel<List<GpgKey>> {
|
||||
@Override
|
||||
public void populateItem(Item<ICellPopulator<GpgKey>> cellItem, String componentId,
|
||||
IModel<GpgKey> rowModel) {
|
||||
cellItem.add(new Label(componentId, DateUtils.formatDateTime(rowModel.getObject().getCreatedAt())));
|
||||
GpgKey key = rowModel.getObject();
|
||||
String subKeyIds = key.getKeyIds().stream()
|
||||
.filter(it->it!=key.getKeyId())
|
||||
.map(it->GpgUtils.getKeyIDString(it))
|
||||
.collect(Collectors.joining(", "));
|
||||
if (subKeyIds.length() != 0)
|
||||
cellItem.add(new Label(componentId, subKeyIds));
|
||||
else
|
||||
cellItem.add(new Label(componentId, "<i>None</i>").setEscapeModelStrings(false));
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
@ -56,13 +56,13 @@ public abstract class InsertGpgKeyPanel extends Panel {
|
||||
|
||||
GpgKeyManager gpgKeyManager = OneDev.getInstance(GpgKeyManager.class);
|
||||
GpgKey gpgKey = (GpgKey) editor.getModelObject();
|
||||
gpgKey.setKeyId(gpgKey.getPublicKey().getKeyID());
|
||||
gpgKey.setKeyId(gpgKey.getKeyIds().get(0));
|
||||
|
||||
if (gpgKeyManager.findByKeyId(gpgKey.getKeyId()) != null) {
|
||||
editor.error(new Path(new PathNode.Named("content")), "This key is already in use");
|
||||
if (gpgKey.getKeyIds().stream().anyMatch(it->gpgKeyManager.findSignatureVerificationKey(it)!=null)) {
|
||||
editor.error(new Path(new PathNode.Named("content")), "This key or one of its subkey is already in use");
|
||||
target.add(form);
|
||||
} else {
|
||||
String emailAddressValue = GpgUtils.getEmailAddress(gpgKey.getPublicKey());
|
||||
String emailAddressValue = GpgUtils.getEmailAddress(gpgKey.getPublicKeys().get(0));
|
||||
EmailAddress emailAddress = OneDev.getInstance(EmailAddressManager.class).findByValue(emailAddressValue);
|
||||
if (emailAddress != null && emailAddress.isVerified() && emailAddress.getOwner().equals(getUser())) {
|
||||
gpgKey.setEmailAddress(emailAddress);
|
||||
|
||||
@ -3,6 +3,7 @@ package io.onedev.server.web.page.admin.gpgtrustedkeys;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.wicket.Component;
|
||||
import org.apache.wicket.Session;
|
||||
@ -89,10 +90,14 @@ public class GpgTrustedKeysPage extends AdministrationPage {
|
||||
BaseGpgKey bean = (BaseGpgKey) editor.getModelObject();
|
||||
|
||||
GpgSetting setting = getSettingManager().getGpgSetting();
|
||||
if (setting.getEncodedTrustedKeys().put(bean.getPublicKey().getKeyID(), bean.getContent()) != null) {
|
||||
editor.error(new Path(new PathNode.Named(BaseGpgKey.PROP_CONTENT)), "This key is already added");
|
||||
if (bean.getKeyIds().stream().anyMatch(it-> setting.getTrustedSignatureVerificationKey(it) != null)) {
|
||||
editor.error(
|
||||
new Path(new PathNode.Named(BaseGpgKey.PROP_CONTENT)),
|
||||
"This key or one of its sub key is already added");
|
||||
target.add(form);
|
||||
} else {
|
||||
setting.getEncodedTrustedKeys().put(bean.getKeyIds().get(0), bean.getContent());
|
||||
setting.encodedTrustedKeysUpdated();
|
||||
getSettingManager().saveGpgSetting(setting);
|
||||
target.add(trustedKeysTable);
|
||||
modal.close();
|
||||
@ -130,8 +135,8 @@ public class GpgTrustedKeysPage extends AdministrationPage {
|
||||
@Override
|
||||
public void populateItem(Item<ICellPopulator<Long>> cellItem, String componentId,
|
||||
IModel<Long> rowModel) {
|
||||
cellItem.add(new Label(componentId,
|
||||
GpgUtils.getEmailAddress(getPublicKey(rowModel.getObject()))));
|
||||
List<PGPPublicKey> trustedKey = getTrustedKey(rowModel.getObject());
|
||||
cellItem.add(new Label(componentId, GpgUtils.getEmailAddress(trustedKey.get(0))));
|
||||
}
|
||||
|
||||
});
|
||||
@ -141,8 +146,33 @@ public class GpgTrustedKeysPage extends AdministrationPage {
|
||||
@Override
|
||||
public void populateItem(Item<ICellPopulator<Long>> cellItem, String componentId,
|
||||
IModel<Long> rowModel) {
|
||||
cellItem.add(new Label(componentId,
|
||||
GpgUtils.getKeyIDString(getPublicKey(rowModel.getObject()).getKeyID())));
|
||||
List<PGPPublicKey> trustedKey = getTrustedKey(rowModel.getObject());
|
||||
cellItem.add(new Label(componentId, GpgUtils.getKeyIDString(trustedKey.get(0).getKeyID())));
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
columns.add(new AbstractColumn<Long, Void>(Model.of("Sub Keys")) {
|
||||
|
||||
@Override
|
||||
public void populateItem(Item<ICellPopulator<Long>> cellItem, String componentId,
|
||||
IModel<Long> rowModel) {
|
||||
List<PGPPublicKey> trustedKey = getTrustedKey(rowModel.getObject());
|
||||
long keyId = trustedKey.get(0).getKeyID();
|
||||
String subKeyIds = trustedKey.stream()
|
||||
.map(it->it.getKeyID())
|
||||
.filter(it->it!=keyId)
|
||||
.map(it->GpgUtils.getKeyIDString(it))
|
||||
.collect(Collectors.joining(", "));
|
||||
if (subKeyIds.length() != 0)
|
||||
cellItem.add(new Label(componentId, subKeyIds));
|
||||
else
|
||||
cellItem.add(new Label(componentId, "<i>None</i>").setEscapeModelStrings(false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCssClass() {
|
||||
return "expanded";
|
||||
}
|
||||
|
||||
});
|
||||
@ -160,6 +190,7 @@ public class GpgTrustedKeysPage extends AdministrationPage {
|
||||
public void onClick(AjaxRequestTarget target) {
|
||||
GpgSetting setting = getSettingManager().getGpgSetting();
|
||||
setting.getEncodedTrustedKeys().remove(rowModel.getObject());
|
||||
setting.encodedTrustedKeysUpdated();
|
||||
getSettingManager().saveGpgSetting(setting);
|
||||
Session.get().success("GPG key deleted");
|
||||
target.add(trustedKeysTable);
|
||||
@ -206,8 +237,8 @@ public class GpgTrustedKeysPage extends AdministrationPage {
|
||||
Integer.MAX_VALUE, null));
|
||||
}
|
||||
|
||||
private PGPPublicKey getPublicKey(long keyId) {
|
||||
return getSettingManager().getGpgSetting().getTrustedKey(keyId);
|
||||
private List<PGPPublicKey> getTrustedKey(long keyId) {
|
||||
return getSettingManager().getGpgSetting().getTrustedKeys().get(keyId);
|
||||
}
|
||||
|
||||
private SettingManager getSettingManager() {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user