From e0bba33d03cda618c6cbb7ecf92028ce49feaa4c Mon Sep 17 00:00:00 2001 From: Damien Trouillet Date: Mon, 28 Jun 2021 11:54:39 +0200 Subject: [PATCH] Feature/identity (#120) * add table identity * add crud identity * add available on application * Add identity in environment * fix unit test * Add unit test * Add identity resource predicate support --- .../java/fr/icdc/ebad/config/Constants.java | 1 + .../fr/icdc/ebad/domain/Environnement.java | 31 +-- .../java/fr/icdc/ebad/domain/Identity.java | 56 ++++ .../ebad/repository/IdentityRepository.java | 20 ++ .../fr/icdc/ebad/security/SecurityUtils.java | 7 + .../permission/PermissionIdentity.java | 71 +++++ .../icdc/ebad/service/ApplicationService.java | 11 +- .../ebad/service/EnvironnementService.java | 3 +- .../fr/icdc/ebad/service/IdentityService.java | 98 +++++++ .../fr/icdc/ebad/service/ShellService.java | 36 ++- .../ebad/web/rest/EnvironnementResource.java | 5 +- .../icdc/ebad/web/rest/IdentityResource.java | 112 ++++++++ .../web/rest/dto/AbstractAuditingDto.java | 5 +- .../web/rest/dto/CompleteIdentityDto.java | 26 ++ .../rest/dto/EnvironnementCreationDto.java | 9 +- .../ebad/web/rest/dto/EnvironnementDto.java | 9 +- .../ebad/web/rest/dto/PublicIdentityDto.java | 14 + .../ebad/web/rest/mapper/IdentityMapper.java | 55 ++++ .../resources/config/application-local.yml | 4 +- src/main/resources/config/application.yml | 2 +- .../changeset/2.7.0-0-changeset.yaml | 125 +++++++++ .../permission/PermissionIdentityTest.java | 244 ++++++++++++++++++ .../ebad/service/ApplicationServiceTest.java | 8 +- .../service/EnvironnementServiceTest.java | 16 +- .../ebad/service/IdentityServiceTest.java | 164 ++++++++++++ .../icdc/ebad/service/ShellServiceTest.java | 14 +- .../ebad/service/jpa/BatchServiceJpaTest.java | 18 +- .../ebad/web/rest/IdentityResourceTest.java | 227 ++++++++++++++++ .../resources/fakekeys/fake_key_bad_format | 38 +++ .../fakekeys/fake_key_bad_format.pub | 1 + .../resources/fakekeys/fake_key_no_password | 39 +++ .../fakekeys/fake_key_no_password.pub | 1 + src/test/resources/fakekeys/fake_key_password | 42 +++ .../resources/fakekeys/fake_key_password.pub | 1 + 34 files changed, 1416 insertions(+), 97 deletions(-) create mode 100644 src/main/java/fr/icdc/ebad/domain/Identity.java create mode 100644 src/main/java/fr/icdc/ebad/repository/IdentityRepository.java create mode 100644 src/main/java/fr/icdc/ebad/security/permission/PermissionIdentity.java create mode 100644 src/main/java/fr/icdc/ebad/service/IdentityService.java create mode 100644 src/main/java/fr/icdc/ebad/web/rest/IdentityResource.java create mode 100644 src/main/java/fr/icdc/ebad/web/rest/dto/CompleteIdentityDto.java create mode 100644 src/main/java/fr/icdc/ebad/web/rest/dto/PublicIdentityDto.java create mode 100644 src/main/java/fr/icdc/ebad/web/rest/mapper/IdentityMapper.java create mode 100644 src/main/resources/db/changelog/changeset/2.7.0-0-changeset.yaml create mode 100644 src/test/java/fr/icdc/ebad/security/permission/PermissionIdentityTest.java create mode 100644 src/test/java/fr/icdc/ebad/service/IdentityServiceTest.java create mode 100644 src/test/java/fr/icdc/ebad/web/rest/IdentityResourceTest.java create mode 100644 src/test/resources/fakekeys/fake_key_bad_format create mode 100644 src/test/resources/fakekeys/fake_key_bad_format.pub create mode 100644 src/test/resources/fakekeys/fake_key_no_password create mode 100644 src/test/resources/fakekeys/fake_key_no_password.pub create mode 100644 src/test/resources/fakekeys/fake_key_password create mode 100644 src/test/resources/fakekeys/fake_key_password.pub diff --git a/src/main/java/fr/icdc/ebad/config/Constants.java b/src/main/java/fr/icdc/ebad/config/Constants.java index 7774b69c..4cf65a31 100644 --- a/src/main/java/fr/icdc/ebad/config/Constants.java +++ b/src/main/java/fr/icdc/ebad/config/Constants.java @@ -10,6 +10,7 @@ public final class Constants { public static final String SPRING_PROFILE_PRODUCTION = "prod"; public static final String SPRING_PROFILE_FAST = "fast"; public static final String ROLE_ADMIN = "ROLE_ADMIN"; + public static final String ROLE_USER = "ROLE_USER"; private Constants() { } diff --git a/src/main/java/fr/icdc/ebad/domain/Environnement.java b/src/main/java/fr/icdc/ebad/domain/Environnement.java index aaf649a1..2fe46976 100644 --- a/src/main/java/fr/icdc/ebad/domain/Environnement.java +++ b/src/main/java/fr/icdc/ebad/domain/Environnement.java @@ -3,32 +3,14 @@ import com.fasterxml.jackson.annotation.JsonBackReference; import com.fasterxml.jackson.annotation.JsonIgnore; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.NoArgsConstructor; -import lombok.ToString; +import lombok.*; import org.hibernate.annotations.Cache; -import org.hibernate.annotations.CacheConcurrencyStrategy; -import org.hibernate.annotations.Cascade; -import org.hibernate.annotations.ColumnDefault; -import org.hibernate.annotations.Fetch; -import org.hibernate.annotations.FetchMode; +import org.hibernate.annotations.*; import javax.annotation.Nullable; -import javax.persistence.Column; import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.JoinTable; -import javax.persistence.ManyToMany; -import javax.persistence.ManyToOne; -import javax.persistence.OneToMany; import javax.persistence.Table; -import javax.persistence.Transient; +import javax.persistence.*; import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; import java.util.Date; @@ -76,9 +58,10 @@ public class Environnement extends AbstractAuditingEntity { private String host; @NotNull - @Size(min = 1, max = 255) - @Column(length = 255, nullable = false) - private String login; + @ManyToOne + @JoinColumn(name = "identity_id") + @JsonBackReference + private Identity identity; @Nullable @Size(min = 1, max = 255) diff --git a/src/main/java/fr/icdc/ebad/domain/Identity.java b/src/main/java/fr/icdc/ebad/domain/Identity.java new file mode 100644 index 00000000..6913cc91 --- /dev/null +++ b/src/main/java/fr/icdc/ebad/domain/Identity.java @@ -0,0 +1,56 @@ +package fr.icdc.ebad.domain; + +import com.fasterxml.jackson.annotation.JsonBackReference; +import lombok.*; +import org.hibernate.annotations.Cache; +import org.hibernate.annotations.CacheConcurrencyStrategy; + +import javax.persistence.*; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; + +@Data +@EqualsAndHashCode(callSuper = false) +@Entity +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Table(name = "t_identity") +@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) +public class Identity extends AbstractAuditingEntity { + @Id + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "identity_generator") + @SequenceGenerator(name = "identity_generator", sequenceName = "t_identity_id_seq") + private Long id; + + @NotNull + @Size(min = 1, max = 255) + @Column(nullable = false) + private String name; + + @NotNull + @Size(min = 1, max = 255) + @Column(nullable = false) + private String login; + + @Size(min = 1, max = 255) + @Column + private String password; + + @Size(min = 1, max = 2048) + @Column + private String privatekey; + + @Size(min = 1, max = 2048) + @Column(name = "privatekey_path") + private String privatekeyPath; + + @Size(min = 1, max = 255) + @Column + private String passphrase; + + @ManyToOne + @JoinColumn(name = "available_application_id") + @JsonBackReference + private Application availableApplication; +} diff --git a/src/main/java/fr/icdc/ebad/repository/IdentityRepository.java b/src/main/java/fr/icdc/ebad/repository/IdentityRepository.java new file mode 100644 index 00000000..4b5701ec --- /dev/null +++ b/src/main/java/fr/icdc/ebad/repository/IdentityRepository.java @@ -0,0 +1,20 @@ +package fr.icdc.ebad.repository; + +import com.querydsl.core.types.dsl.StringExpression; +import com.querydsl.core.types.dsl.StringPath; +import fr.icdc.ebad.domain.Identity; +import fr.icdc.ebad.domain.QIdentity; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.querydsl.QuerydslPredicateExecutor; +import org.springframework.data.querydsl.binding.QuerydslBinderCustomizer; +import org.springframework.data.querydsl.binding.QuerydslBindings; +import org.springframework.data.querydsl.binding.SingleValueBinding; + +public interface IdentityRepository extends JpaRepository, QuerydslPredicateExecutor, QuerydslBinderCustomizer { + @Override + default void customize(QuerydslBindings bindings, QIdentity root) { + bindings + .bind(String.class) + .first((SingleValueBinding) StringExpression::containsIgnoreCase); + } +} diff --git a/src/main/java/fr/icdc/ebad/security/SecurityUtils.java b/src/main/java/fr/icdc/ebad/security/SecurityUtils.java index 66b723cd..459f1986 100644 --- a/src/main/java/fr/icdc/ebad/security/SecurityUtils.java +++ b/src/main/java/fr/icdc/ebad/security/SecurityUtils.java @@ -41,4 +41,11 @@ public static boolean isAdmin() { authority -> authority.getAuthority().equals(Constants.ROLE_ADMIN) ); } + + public static boolean isUser() { + + return SecurityContextHolder.getContext().getAuthentication().getAuthorities().stream().anyMatch( + authority -> authority.getAuthority().equals(Constants.ROLE_USER) + ); + } } diff --git a/src/main/java/fr/icdc/ebad/security/permission/PermissionIdentity.java b/src/main/java/fr/icdc/ebad/security/permission/PermissionIdentity.java new file mode 100644 index 00000000..5799d542 --- /dev/null +++ b/src/main/java/fr/icdc/ebad/security/permission/PermissionIdentity.java @@ -0,0 +1,71 @@ +package fr.icdc.ebad.security.permission; + +import fr.icdc.ebad.domain.Identity; +import fr.icdc.ebad.repository.IdentityRepository; +import fr.icdc.ebad.security.SecurityUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.stereotype.Service; + +import java.util.Optional; + +@Service +public class PermissionIdentity { + private static final Logger LOGGER = LoggerFactory.getLogger(PermissionIdentity.class); + + private final PermissionApplication permissionApplication; + private final IdentityRepository identityRepository; + + public PermissionIdentity(PermissionApplication permissionApplication, IdentityRepository identityRepository) { + this.permissionApplication = permissionApplication; + this.identityRepository = identityRepository; + } + + + public boolean canReadByApplication(Long applicationId, UserDetails userDetails) { + LOGGER.debug("PermissionIdentity canReadByApplication"); + if (applicationId == null) { + return SecurityUtils.isAdmin() || SecurityUtils.isUser(); + } + return permissionApplication.canWrite(applicationId, userDetails); + } + + public boolean canRead(Long identityId, UserDetails userDetails) { + LOGGER.debug("PermissionIdentity canRead"); + if (identityId == null) { + return false; + } + Optional identityOptional = identityRepository.findById(identityId); + if(identityOptional.isEmpty()){ + return false; + } + if(identityOptional.get().getAvailableApplication() == null){ + return SecurityUtils.isAdmin() || SecurityUtils.isUser(); + } + return canReadByApplication(identityOptional.get().getAvailableApplication().getId(), userDetails); + } + + public boolean canWriteByApplication(Long applicationId, UserDetails userDetails) { + LOGGER.debug("PermissionIdentity canWriteByApplication"); + if (applicationId == null) { + return SecurityUtils.isAdmin(); + } + return permissionApplication.canWrite(applicationId, userDetails); + } + + public boolean canWrite(Long identityId, UserDetails userDetails) { + LOGGER.debug("PermissionIdentity canWrite"); + if (identityId == null) { + return false; + } + Optional identityOptional = identityRepository.findById(identityId); + if(identityOptional.isEmpty()){ + return false; + } + if(identityOptional.get().getAvailableApplication() == null){ + return SecurityUtils.isAdmin(); + } + return canWriteByApplication(identityOptional.get().getAvailableApplication().getId(), userDetails); + } +} diff --git a/src/main/java/fr/icdc/ebad/service/ApplicationService.java b/src/main/java/fr/icdc/ebad/service/ApplicationService.java index fc5a0c22..610c4f79 100644 --- a/src/main/java/fr/icdc/ebad/service/ApplicationService.java +++ b/src/main/java/fr/icdc/ebad/service/ApplicationService.java @@ -2,14 +2,12 @@ import com.querydsl.core.types.Predicate; import fr.icdc.ebad.domain.Application; +import fr.icdc.ebad.domain.QIdentity; import fr.icdc.ebad.domain.UsageApplication; import fr.icdc.ebad.domain.User; import fr.icdc.ebad.plugin.dto.ApplicationDiscoverDto; import fr.icdc.ebad.plugin.plugin.ApplicationConnectorPlugin; -import fr.icdc.ebad.repository.AccreditationRequestRepository; -import fr.icdc.ebad.repository.ApplicationRepository; -import fr.icdc.ebad.repository.TypeFichierRepository; -import fr.icdc.ebad.repository.UsageApplicationRepository; +import fr.icdc.ebad.repository.*; import fr.icdc.ebad.service.util.EbadServiceException; import org.pf4j.PluginRuntimeException; import org.pf4j.PluginWrapper; @@ -42,8 +40,9 @@ public class ApplicationService { private final List applicationConnectorPlugins; private final SpringPluginManager springPluginManager; private final AccreditationRequestRepository accreditationRequestRepository; + private final IdentityRepository identityRepository; - public ApplicationService(ApplicationRepository applicationRepository, TypeFichierRepository typeFichierRepository, UsageApplicationRepository usageApplicationRepository, EnvironnementService environnementService, List applicationConnectorPlugins, SpringPluginManager springPluginManager, AccreditationRequestRepository accreditationRequestRepository) { + public ApplicationService(ApplicationRepository applicationRepository, TypeFichierRepository typeFichierRepository, UsageApplicationRepository usageApplicationRepository, EnvironnementService environnementService, List applicationConnectorPlugins, SpringPluginManager springPluginManager, AccreditationRequestRepository accreditationRequestRepository, IdentityRepository identityRepository) { this.applicationRepository = applicationRepository; this.typeFichierRepository = typeFichierRepository; this.usageApplicationRepository = usageApplicationRepository; @@ -51,6 +50,7 @@ public ApplicationService(ApplicationRepository applicationRepository, TypeFichi this.applicationConnectorPlugins = applicationConnectorPlugins; this.springPluginManager = springPluginManager; this.accreditationRequestRepository = accreditationRequestRepository; + this.identityRepository = identityRepository; } @@ -81,6 +81,7 @@ public void deleteApplication(Long appId) { accreditationRequestRepository.deleteByApplication(application); typeFichierRepository.deleteByApplication(application); application.getEnvironnements().forEach(environnement -> environnementService.deleteEnvironnement(environnement, true)); + identityRepository.deleteAll(identityRepository.findAll(QIdentity.identity.availableApplication.id.eq(appId), Pageable.unpaged())); applicationRepository.delete(application); } diff --git a/src/main/java/fr/icdc/ebad/service/EnvironnementService.java b/src/main/java/fr/icdc/ebad/service/EnvironnementService.java index 8ac3fefa..5dbec2d3 100644 --- a/src/main/java/fr/icdc/ebad/service/EnvironnementService.java +++ b/src/main/java/fr/icdc/ebad/service/EnvironnementService.java @@ -7,6 +7,7 @@ import fr.icdc.ebad.plugin.dto.NormeDiscoverDto; import fr.icdc.ebad.plugin.plugin.EnvironnementConnectorPlugin; import fr.icdc.ebad.repository.*; +import fr.icdc.ebad.security.permission.PermissionIdentity; import fr.icdc.ebad.service.util.EbadServiceException; import ma.glasnost.orika.MapperFacade; import org.jobrunr.scheduling.JobScheduler; @@ -191,13 +192,13 @@ public Set importEnvironments(Long applicationId) throws EbadServ environnement.setName(environnementDiscoverDto.getName()); environnement.setHost(environnementDiscoverDto.getHost()); - environnement.setLogin(environnementDiscoverDto.getLogin()); environnement.setHomePath(environnementDiscoverDto.getHome()); environnement.setPrefix(environnementDiscoverDto.getPrefix()); environnement.setNorme(mapper.map(environnementDiscoverDto.getNorme(), Norme.class)); environnement.setExternalId(environnementDiscoverDto.getId()); environnement.setPluginId(pluginId); environnement.setApplication(application); + //FIXME DTROUILLET ADD DEFAULT IDENTITY try { environnementRepository.save(environnement); diff --git a/src/main/java/fr/icdc/ebad/service/IdentityService.java b/src/main/java/fr/icdc/ebad/service/IdentityService.java new file mode 100644 index 00000000..fcd114be --- /dev/null +++ b/src/main/java/fr/icdc/ebad/service/IdentityService.java @@ -0,0 +1,98 @@ +package fr.icdc.ebad.service; + +import com.querydsl.core.types.Predicate; +import fr.icdc.ebad.domain.Identity; +import fr.icdc.ebad.domain.QIdentity; +import fr.icdc.ebad.repository.IdentityRepository; +import fr.icdc.ebad.service.util.EbadServiceException; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.openssl.PEMDecryptorProvider; +import org.bouncycastle.openssl.PEMEncryptedKeyPair; +import org.bouncycastle.openssl.PEMKeyPair; +import org.bouncycastle.openssl.PEMParser; +import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter; +import org.bouncycastle.openssl.jcajce.JcePEMDecryptorProviderBuilder; +import org.bouncycastle.util.io.pem.PemReader; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.io.*; +import java.security.KeyPair; +import java.security.Security; +import java.util.Optional; + +@Service +public class IdentityService { + private final IdentityRepository identityRepository; + + public IdentityService(IdentityRepository identityRepository) { + this.identityRepository = identityRepository; + } + + @Transactional + public Identity saveIdentity(Identity identity) { + return identityRepository.save(identity); + } + + @Transactional(readOnly = true) + public Optional getIdentity(Long id) { + return identityRepository.findById(id); + } + + @Transactional + public void deleteIdentity(Long id) { + identityRepository.deleteById(id); + } + + @Transactional(readOnly = true) + public Page findWithoutApp(Predicate predicate, Pageable pageable) { + Predicate predicateAll = QIdentity.identity.availableApplication.isNull().and(predicate); + return identityRepository.findAll(predicateAll, pageable); + } + + @Transactional(readOnly = true) + public Page findAllByApplication(Long applicationId, Predicate predicate, Pageable pageable) { + Predicate predicateAll = QIdentity.identity.availableApplication.id.eq(applicationId).and(predicate); + return identityRepository.findAll(predicateAll, pageable); + } + + + public KeyPair createKeyPair(Identity identity) throws EbadServiceException { + Security.addProvider(new BouncyCastleProvider()); + String password = identity.getPassphrase(); + + try( + PemReader pemReader = new PemReader(openReader(identity)); + PEMParser pemParser = new PEMParser(pemReader) + ) { + Object pemKeyPair = pemParser.readObject(); + + if (pemKeyPair instanceof PEMEncryptedKeyPair) { + if (password == null) { + throw new EbadServiceException("Unable to import private key. Key is encrypted, but no password was provided."); + } + PEMDecryptorProvider decryptor = new JcePEMDecryptorProviderBuilder().build(password.toCharArray()); + PEMKeyPair decryptedKeyPair = ((PEMEncryptedKeyPair) pemKeyPair).decryptKeyPair(decryptor); + return new JcaPEMKeyConverter().getKeyPair(decryptedKeyPair); + } else { + return new JcaPEMKeyConverter().getKeyPair((PEMKeyPair) pemKeyPair); + } + }catch (IOException e){ + throw new EbadServiceException("Error when trying to read ssh key file\n" + + "Make sur use RSA keys, try to convert your key with \n" + + "ssh-keygen -p -P \"old passphrase\" -N \"new passphrase\" -m pem -f path/to/key \n" + + "THIS OVERWRITE YOUR KEY SO MAKE A BACKUP BEFORE", e); + } + } + + private Reader openReader(Identity identity) throws FileNotFoundException, EbadServiceException { + if(identity.getPrivatekeyPath() != null) + return new FileReader(identity.getPrivatekeyPath()); + if(identity.getPrivatekey() != null) + return new StringReader(identity.getPrivatekey()); + + throw new EbadServiceException("No key is provided"); + } +} diff --git a/src/main/java/fr/icdc/ebad/service/ShellService.java b/src/main/java/fr/icdc/ebad/service/ShellService.java index f84daf37..d2ba740e 100644 --- a/src/main/java/fr/icdc/ebad/service/ShellService.java +++ b/src/main/java/fr/icdc/ebad/service/ShellService.java @@ -18,11 +18,9 @@ import org.springframework.stereotype.Service; import java.io.*; -import java.security.KeyPair; import java.util.ArrayList; import java.util.EnumSet; import java.util.List; -import java.util.Optional; /** * Created by dtrouillet on 03/03/2016. @@ -33,11 +31,11 @@ public class ShellService { private static final String PATH_SEPARATOR = "/"; private final EbadProperties ebadProperties; - private final KeyPair keyPairEbad; + private final IdentityService identityService; - public ShellService(EbadProperties ebadProperties, Optional keyPairEbad) { + public ShellService(EbadProperties ebadProperties, IdentityService identityService) { this.ebadProperties = ebadProperties; - this.keyPairEbad = keyPairEbad.orElse(null); + this.identityService = identityService; } public RetourBatch runCommandNew(Environnement environnement, String command) throws EbadServiceException { @@ -49,7 +47,7 @@ public RetourBatch runCommandNew(Environnement environnement, String command) th SshClient sshClient = SshClient.setUpDefaultClient(); sshClient.start(); - try (ClientSession session = createSession(sshClient, environnement.getHost())) { + try (ClientSession session = createSession(sshClient, environnement)) { try (ByteArrayOutputStream responseStream = new ByteArrayOutputStream(); ClientChannel channel = session.createChannel(org.apache.sshd.common.channel.Channel.CHANNEL_EXEC, commandWithInterpreteur)) { channel.setOut(responseStream); @@ -86,7 +84,7 @@ public List getListFiles(Directory directory, String subDir SshClient sshClient = SshClient.setUpDefaultClient(); sshClient.start(); - try (ClientSession session = createSession(sshClient, directory.getEnvironnement().getHost())) { + try (ClientSession session = createSession(sshClient, directory.getEnvironnement())) { SftpClientFactory factory = SftpClientFactory.instance(); try (SftpClient client = factory.createSftpClient(session)) { @@ -107,7 +105,7 @@ public void removeFile(Directory directory, String filename, String subDirectory SshClient sshClient = SshClient.setUpDefaultClient(); sshClient.start(); - try (ClientSession session = createSession(sshClient, directory.getEnvironnement().getHost())) { + try (ClientSession session = createSession(sshClient, directory.getEnvironnement())) { SftpClientFactory factory = SftpClientFactory.instance(); try (SftpClient client = factory.createSftpClient(session)) { @@ -125,7 +123,7 @@ public InputStream getFile(Directory directory, String filename, String subDirec SshClient sshClient = SshClient.setUpDefaultClient(); sshClient.start(); - try (ClientSession session = createSession(sshClient, directory.getEnvironnement().getHost())) { + try (ClientSession session = createSession(sshClient, directory.getEnvironnement())) { SftpClientFactory factory = SftpClientFactory.instance(); try (SftpClient client = factory.createSftpClient(session); @@ -144,25 +142,23 @@ public InputStream getFile(Directory directory, String filename, String subDirec } } - private ClientSession createSession(SshClient sshClient, String host) throws IOException { + private ClientSession createSession(SshClient sshClient, Environnement environnement) throws IOException, EbadServiceException { ClientSession session = sshClient .connect( - ebadProperties.getSsh().getLogin(), - host, + environnement.getIdentity().getLogin(), + environnement.getHost(), ebadProperties.getSsh().getPort()) .verify() .getSession(); - if(null != keyPairEbad) - session.addPublicKeyIdentity(keyPairEbad); - if (null != ebadProperties.getSsh().getPassphrase()) - session.addPasswordIdentity(ebadProperties.getSsh().getPassphrase()); + if(null != environnement.getIdentity().getPassword()) + session.addPasswordIdentity(environnement.getIdentity().getPassword()); + if(null != environnement.getIdentity().getPrivatekey() || null != environnement.getIdentity().getPrivatekeyPath()) + session.addPublicKeyIdentity(identityService.createKeyPair(environnement.getIdentity())); + session.auth().verify(); return session; - - - } public void uploadFile(Directory directory, InputStream inputStream, String filename, String subDirectory) throws EbadServiceException { @@ -170,7 +166,7 @@ public void uploadFile(Directory directory, InputStream inputStream, String file SshClient sshClient = SshClient.setUpDefaultClient(); sshClient.start(); - try (ClientSession session = createSession(sshClient, directory.getEnvironnement().getHost())) { + try (ClientSession session = createSession(sshClient, directory.getEnvironnement())) { SftpClientFactory factory = SftpClientFactory.instance(); try ( diff --git a/src/main/java/fr/icdc/ebad/web/rest/EnvironnementResource.java b/src/main/java/fr/icdc/ebad/web/rest/EnvironnementResource.java index 6c7d6957..2c5322cd 100644 --- a/src/main/java/fr/icdc/ebad/web/rest/EnvironnementResource.java +++ b/src/main/java/fr/icdc/ebad/web/rest/EnvironnementResource.java @@ -98,12 +98,13 @@ public ResponseEntity changeDateTraitement(@PathVariable Long env, @Requ */ @PutMapping(produces = MediaType.APPLICATION_JSON_VALUE) @Timed - @PreAuthorize("@permissionApplication.canWrite(#env.application, principal) && @permissionServiceOpen.canCreateEnvironment()") + @PreAuthorize("@permissionApplication.canWrite(#env.application, principal) && @permissionServiceOpen.canCreateEnvironment() && @permissionIdentity.canRead(#env.identity.id, principal)") public ResponseEntity addEnvironnement(@RequestBody EnvironnementCreationDto env) { LOGGER.debug("REST request to add a new environnement {}", env); if (env.getPrefix() == null) { env.setPrefix(""); } + Environnement environnement = environnementService.saveEnvironnement(mapper.map(env, Environnement.class)); return new ResponseEntity<>(mapper.map(environnement, EnvironnementDto.class), HttpStatus.OK); } @@ -113,7 +114,7 @@ public ResponseEntity addEnvironnement(@RequestBody Environnem */ @PatchMapping(produces = MediaType.APPLICATION_JSON_VALUE) @Timed - @PreAuthorize("@permissionEnvironnement.canWrite(#env, principal)") + @PreAuthorize("@permissionEnvironnement.canWrite(#env, principal) && @permissionIdentity.canRead(#env.identity.id, principal)") public ResponseEntity updateEnvironnement(@RequestBody EnvironnementDto env) { LOGGER.debug("REST request to update an environnement {}", env.getId()); Environnement result = environnementService.updateEnvironnement(mapper.map(env, Environnement.class)); diff --git a/src/main/java/fr/icdc/ebad/web/rest/IdentityResource.java b/src/main/java/fr/icdc/ebad/web/rest/IdentityResource.java new file mode 100644 index 00000000..eba88826 --- /dev/null +++ b/src/main/java/fr/icdc/ebad/web/rest/IdentityResource.java @@ -0,0 +1,112 @@ +package fr.icdc.ebad.web.rest; + +import com.querydsl.core.types.Predicate; +import fr.icdc.ebad.domain.Identity; +import fr.icdc.ebad.service.IdentityService; +import fr.icdc.ebad.web.ResponseUtil; +import fr.icdc.ebad.web.rest.dto.CompleteIdentityDto; +import fr.icdc.ebad.web.rest.dto.PublicIdentityDto; +import fr.icdc.ebad.web.rest.util.PaginationUtil; +import io.micrometer.core.annotation.Timed; +import io.swagger.v3.oas.annotations.tags.Tag; +import ma.glasnost.orika.MapperFacade; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.querydsl.binding.QuerydslPredicate; +import org.springframework.data.repository.query.Param; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; +import java.util.Optional; + +@RestController +@RequestMapping("/identities") +@Tag(name = "Identity", description = "the identity API") +public class IdentityResource { + + private static final Logger LOGGER = LoggerFactory.getLogger(IdentityResource.class); + + private final IdentityService identityService; + private final MapperFacade mapper; + + public IdentityResource(IdentityService identityService, MapperFacade mapper) { + this.identityService = identityService; + this.mapper = mapper; + } + + /** + * PUT /identities to add a new identity + */ + @PutMapping(produces = MediaType.APPLICATION_JSON_VALUE) + @Timed + @PreAuthorize("@permissionIdentity.canWriteByApplication(#identityDto.availableApplication, principal)") + public ResponseEntity addIdentity(@RequestBody @Valid CompleteIdentityDto identityDto) { + LOGGER.debug("REST request to add a new identity"); + Identity identity = identityService.saveIdentity(mapper.map(identityDto, Identity.class)); + return new ResponseEntity<>(mapper.map(identity, CompleteIdentityDto.class), HttpStatus.OK); + } + + /** + * GET /identities/:id to get an identity + */ + @GetMapping(value = "/{id}", produces = MediaType.APPLICATION_JSON_VALUE) + @Timed + @PreAuthorize("@permissionIdentity.canWrite(#id, principal)") + public ResponseEntity getOneIdentity(@PathVariable Long id) { + LOGGER.debug("REST request to get an identity"); + Optional optionalCompleteIdentityDto = identityService.getIdentity(id) + .map(identity -> mapper.map(identity, CompleteIdentityDto.class)); + return ResponseUtil.wrapOrNotFound(optionalCompleteIdentityDto); + } + + /** + * GET /identities to get all identities + */ + @GetMapping(produces = MediaType.APPLICATION_JSON_VALUE) + @Timed + @PreAuthorize("@permissionIdentity.canReadByApplication(#applicationId, principal)") + public ResponseEntity> getAllIdentities(@Param("applicationId") Long applicationId, @QuerydslPredicate(root = Identity.class) Predicate predicate, Pageable pageable) { + LOGGER.debug("REST request to get all identities"); + Page identities; + + if(applicationId == null){ + identities = identityService.findWithoutApp(predicate, PaginationUtil.generatePageRequestOrDefault(pageable)); + }else{ + identities = identityService.findAllByApplication(applicationId, predicate, PaginationUtil.generatePageRequestOrDefault(pageable)); + } + + return new ResponseEntity<>(identities.map(identity -> mapper.map(identity, PublicIdentityDto.class)), HttpStatus.OK); + } + + + /** + * PATCH /identities to update an identity + */ + + @PatchMapping(produces = MediaType.APPLICATION_JSON_VALUE) + @Timed + @PreAuthorize("@permissionIdentity.canWrite(#identityDto.id, principal) && @permissionIdentity.canWriteByApplication(#identityDto.availableApplication, principal)") + public ResponseEntity updateIdentity(@RequestBody CompleteIdentityDto identityDto) { + LOGGER.debug("REST request to update an identity"); + Identity identity = identityService.saveIdentity(mapper.map(identityDto, Identity.class)); + return new ResponseEntity<>(mapper.map(identity, CompleteIdentityDto.class), HttpStatus.OK); + } + + /** + * DELETE /identities/id to delete an identity + */ + @DeleteMapping(value = "/{identityId}", produces = MediaType.APPLICATION_JSON_VALUE) + @Timed + @PreAuthorize("@permissionIdentity.canWrite(#identityId, principal)") + public ResponseEntity deleteIdentity(@PathVariable Long identityId) { + LOGGER.debug("REST request to delete an identity"); + identityService.deleteIdentity(identityId); + return ResponseEntity.ok().build(); + } +} diff --git a/src/main/java/fr/icdc/ebad/web/rest/dto/AbstractAuditingDto.java b/src/main/java/fr/icdc/ebad/web/rest/dto/AbstractAuditingDto.java index 642d3574..f8f492ac 100644 --- a/src/main/java/fr/icdc/ebad/web/rest/dto/AbstractAuditingDto.java +++ b/src/main/java/fr/icdc/ebad/web/rest/dto/AbstractAuditingDto.java @@ -3,15 +3,14 @@ import lombok.Data; import lombok.EqualsAndHashCode; -import javax.validation.constraints.NotNull; import java.time.LocalDateTime; @Data @EqualsAndHashCode(callSuper = false) public class AbstractAuditingDto { - @NotNull +// @NotNull private String createdBy; - @NotNull +// @NotNull private LocalDateTime createdDate = LocalDateTime.now(); private String lastModifiedBy; private LocalDateTime lastModifiedDate = LocalDateTime.now(); diff --git a/src/main/java/fr/icdc/ebad/web/rest/dto/CompleteIdentityDto.java b/src/main/java/fr/icdc/ebad/web/rest/dto/CompleteIdentityDto.java new file mode 100644 index 00000000..7c26b11e --- /dev/null +++ b/src/main/java/fr/icdc/ebad/web/rest/dto/CompleteIdentityDto.java @@ -0,0 +1,26 @@ +package fr.icdc.ebad.web.rest.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotNull; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class CompleteIdentityDto extends AbstractAuditingDto { + private Long id; + + @NotNull + private String login; + @NotNull + private String name; + private String password; + private String privatekey; + private String privatekeyPath; + private String passphrase; + private Long availableApplication; +} diff --git a/src/main/java/fr/icdc/ebad/web/rest/dto/EnvironnementCreationDto.java b/src/main/java/fr/icdc/ebad/web/rest/dto/EnvironnementCreationDto.java index 24fd9998..fcdab14b 100644 --- a/src/main/java/fr/icdc/ebad/web/rest/dto/EnvironnementCreationDto.java +++ b/src/main/java/fr/icdc/ebad/web/rest/dto/EnvironnementCreationDto.java @@ -3,12 +3,7 @@ import com.fasterxml.jackson.annotation.JsonBackReference; import fr.icdc.ebad.domain.AbstractAuditingEntity; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.NoArgsConstructor; -import lombok.ToString; +import lombok.*; /** * Environnement. @@ -24,7 +19,7 @@ public class EnvironnementCreationDto extends AbstractAuditingEntity { @JsonBackReference private ApplicationDto application; private String host; - private String login; + private PublicIdentityDto identity; private String homePath; private String prefix; private NormeDto norme; diff --git a/src/main/java/fr/icdc/ebad/web/rest/dto/EnvironnementDto.java b/src/main/java/fr/icdc/ebad/web/rest/dto/EnvironnementDto.java index 7c0505b4..d4231d11 100644 --- a/src/main/java/fr/icdc/ebad/web/rest/dto/EnvironnementDto.java +++ b/src/main/java/fr/icdc/ebad/web/rest/dto/EnvironnementDto.java @@ -2,12 +2,7 @@ import fr.icdc.ebad.domain.AbstractAuditingEntity; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.NoArgsConstructor; -import lombok.ToString; +import lombok.*; import java.util.Date; @@ -24,7 +19,7 @@ public class EnvironnementDto extends AbstractAuditingEntity { private Long id; private String name; private String host; - private String login; + private PublicIdentityDto identity; private String homePath; private String prefix; private float diskSpace; diff --git a/src/main/java/fr/icdc/ebad/web/rest/dto/PublicIdentityDto.java b/src/main/java/fr/icdc/ebad/web/rest/dto/PublicIdentityDto.java new file mode 100644 index 00000000..54fb24a5 --- /dev/null +++ b/src/main/java/fr/icdc/ebad/web/rest/dto/PublicIdentityDto.java @@ -0,0 +1,14 @@ +package fr.icdc.ebad.web.rest.dto; + +import lombok.Data; + +import javax.validation.constraints.NotNull; + +@Data +public class PublicIdentityDto { + private Long id; + @NotNull + private String name; + @NotNull + private String login; +} diff --git a/src/main/java/fr/icdc/ebad/web/rest/mapper/IdentityMapper.java b/src/main/java/fr/icdc/ebad/web/rest/mapper/IdentityMapper.java new file mode 100644 index 00000000..a1d12f1e --- /dev/null +++ b/src/main/java/fr/icdc/ebad/web/rest/mapper/IdentityMapper.java @@ -0,0 +1,55 @@ +package fr.icdc.ebad.web.rest.mapper; + +import fr.icdc.ebad.domain.Application; +import fr.icdc.ebad.domain.Identity; +import fr.icdc.ebad.web.rest.dto.CompleteIdentityDto; +import ma.glasnost.orika.MapperFactory; +import ma.glasnost.orika.MappingContext; +import ma.glasnost.orika.converter.BidirectionalConverter; +import ma.glasnost.orika.converter.ConverterFactory; +import ma.glasnost.orika.metadata.Type; +import net.rakugakibox.spring.boot.orika.OrikaMapperFactoryConfigurer; +import org.springframework.stereotype.Component; + +@Component +public class IdentityMapper implements OrikaMapperFactoryConfigurer { + private static final String CONVERTER_NAME = "applicationLongIdConverter"; + private static final String AVAILABLE_APPLICATION_FIELD = "availableApplication"; + @Override + public void configure(MapperFactory orikaMapperFactory) { + ConverterFactory converterFactory = orikaMapperFactory.getConverterFactory(); + converterFactory.registerConverter(CONVERTER_NAME, new ApplicationLongIdConverter()); + + orikaMapperFactory.classMap(Identity.class, CompleteIdentityDto.class) + .fieldMap(AVAILABLE_APPLICATION_FIELD, AVAILABLE_APPLICATION_FIELD).converter(CONVERTER_NAME).add() + .byDefault() + .register(); + orikaMapperFactory.classMap(CompleteIdentityDto.class, Identity.class) + .fieldMap(AVAILABLE_APPLICATION_FIELD, AVAILABLE_APPLICATION_FIELD).converter(CONVERTER_NAME).add() + .byDefault() + .register(); + } + + static class ApplicationLongIdConverter extends BidirectionalConverter { + + @Override + public Long convertTo(Application application, Type type, MappingContext mappingContext) { + if (application == null) { + return null; + } + return application.getId(); + } + + @Override + public Application convertFrom(Long aLong, Type type, MappingContext mappingContext) { + if (aLong == null) { + return null; + } + return Application.builder().id(aLong).build(); + } + } + + +} + + diff --git a/src/main/resources/config/application-local.yml b/src/main/resources/config/application-local.yml index 78e4e259..3cc3ae58 100644 --- a/src/main/resources/config/application-local.yml +++ b/src/main/resources/config/application-local.yml @@ -1,6 +1,6 @@ spring: datasource: - url: jdbc:h2:mem:db1;MODE=PostgreSQL + url: jdbc:h2:~/ebad;MODE=PostgreSQL #url: jdbc:h2:file:/data/demo driverClassName: org.h2.Driver username: sa @@ -17,4 +17,4 @@ ebad: jwt: secret: my-secret-token-to-change-in-production token-validity-in-seconds: 86400 - token-validity-in-seconds-for-remember-me: 2592000 \ No newline at end of file + token-validity-in-seconds-for-remember-me: 2592000 diff --git a/src/main/resources/config/application.yml b/src/main/resources/config/application.yml index bac97976..013fa6d5 100644 --- a/src/main/resources/config/application.yml +++ b/src/main/resources/config/application.yml @@ -24,7 +24,7 @@ spring: show_sql: false generate-ddl: false hibernate: - ddl-auto: update + ddl-auto: validate naming: physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl properties: diff --git a/src/main/resources/db/changelog/changeset/2.7.0-0-changeset.yaml b/src/main/resources/db/changelog/changeset/2.7.0-0-changeset.yaml new file mode 100644 index 00000000..4bac1d87 --- /dev/null +++ b/src/main/resources/db/changelog/changeset/2.7.0-0-changeset.yaml @@ -0,0 +1,125 @@ +databaseChangeLog: + - changeSet: + id: creation_identity + author: dtrouillet + changes: + - createSequence: + cacheSize: 1 + cycle: false + incrementBy: 50 + maxValue: 9223372036854775807 + minValue: 1 + sequenceName: t_identity_id_seq + startValue: 1 + - createTable: + columns: + - column: + constraints: + nullable: false + primaryKey: true + primaryKeyName: t_identity_pkey + name: id + type: BIGINT + defaultValueSequenceNext: t_identity_id_seq + - column: + name: name + type: VARCHAR(255) + constraints: + nullable: false + - column: + name: login + type: VARCHAR(255) + constraints: + nullable: false + - column: + name: password + type: VARCHAR(255) + - column: + name: privatekey + type: VARCHAR(2048) + - column: + name: privatekey_path + type: VARCHAR(2048) + - column: + name: passphrase + type: VARCHAR(255) + - column: + name: available_application_id + type: BIGINT + - column: + constraints: + nullable: false + name: created_by + type: VARCHAR(50) + - column: + constraints: + nullable: false + name: created_date + type: TIMESTAMP WITHOUT TIME ZONE + - column: + name: last_modified_by + type: VARCHAR(50) + - column: + name: last_modified_date + type: TIMESTAMP WITHOUT TIME ZONE + - addForeignKeyConstraint: + baseColumnNames: available_application_id + baseTableName: t_identity + constraintName: t_identity_application_id + deferrable: false + initiallyDeferred: false + onDelete: CASCADE + onUpdate: NO ACTION + referencedColumnNames: id + referencedTableName: t_application + validate: true + tableName: t_identity + - insert: + tableName: t_identity + columns: + - column: + name: created_by + value: SYSTEM + - column: + name: created_date + value: NOW() + - column: + name: name + value: default + - column: + name: login + value: default_login + - column: + name: password + value: changeme + - dropColumn: + tableName: t_environnement + columns: + - column: + name: login + - addColumn: + tableName: t_environnement + columns: + - column: + name: identity_id + type: BIGINT + - addForeignKeyConstraint: + baseColumnNames: identity_id + baseTableName: t_environnement + constraintName: t_environnement_identity_id + deferrable: false + initiallyDeferred: false + onDelete: NO ACTION + onUpdate: NO ACTION + referencedColumnNames: id + referencedTableName: t_identity + validate: true + - update: + tableName: t_environnement + columns: + - column: + name: identity_id + valueComputed: (SELECT id from t_identity where name = 'default') + - addNotNullConstraint: + tableName: t_environnement + columnName: identity_id \ No newline at end of file diff --git a/src/test/java/fr/icdc/ebad/security/permission/PermissionIdentityTest.java b/src/test/java/fr/icdc/ebad/security/permission/PermissionIdentityTest.java new file mode 100644 index 00000000..3f3250ea --- /dev/null +++ b/src/test/java/fr/icdc/ebad/security/permission/PermissionIdentityTest.java @@ -0,0 +1,244 @@ +package fr.icdc.ebad.security.permission; + +import fr.icdc.ebad.domain.Application; +import fr.icdc.ebad.domain.Identity; +import fr.icdc.ebad.repository.IdentityRepository; +import liquibase.pro.packaged.A; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.context.SecurityContext; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.UserDetails; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Optional; + +import static fr.icdc.ebad.config.Constants.ROLE_ADMIN; +import static fr.icdc.ebad.config.Constants.ROLE_USER; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.*; + + +@RunWith(MockitoJUnitRunner.class) +public class PermissionIdentityTest { + @Mock + UserDetails userDetails; + + @InjectMocks + private PermissionIdentity permissionIdentity; + + @Mock + private PermissionApplication permissionApplication; + + @Mock + private IdentityRepository identityRepository; + + @Mock + private Authentication authentication; + + @Mock + private SecurityContext securityContext; + + @Test + public void canReadByApplication() { + Collection authorities = new ArrayList(); + authorities.add(new SimpleGrantedAuthority(ROLE_ADMIN)); + when(authentication.getAuthorities()).thenReturn(authorities); + when(securityContext.getAuthentication()).thenReturn(authentication); + SecurityContextHolder.setContext(securityContext); + + boolean result1 = permissionIdentity.canReadByApplication(null, userDetails); + + assertTrue(result1); + verify(permissionApplication, never()).canWrite(eq(1L), eq(userDetails)); + } + + @Test + public void canReadByApplication2() { + Collection authorities = new ArrayList(); + authorities.add(new SimpleGrantedAuthority(ROLE_USER)); + when(authentication.getAuthorities()).thenReturn(authorities); + when(securityContext.getAuthentication()).thenReturn(authentication); + SecurityContextHolder.setContext(securityContext); + + boolean result1 = permissionIdentity.canReadByApplication(null, userDetails); + + assertTrue(result1); + verify(permissionApplication, never()).canWrite(eq(1L), eq(userDetails)); + } + + @Test + public void canReadByApplication3() { + when(permissionApplication.canWrite(eq(1L), eq(userDetails))).thenReturn(true); + when(permissionApplication.canWrite(eq(2L), eq(userDetails))).thenReturn(false); + + boolean result1 = permissionIdentity.canReadByApplication(1L, userDetails); + assertTrue(result1); + + boolean result2 = permissionIdentity.canReadByApplication(2L, userDetails); + assertFalse(result2); + + verify(permissionApplication, times(1)).canWrite(eq(1L), eq(userDetails)); + verify(permissionApplication, times(1)).canWrite(eq(2L), eq(userDetails)); + } + + @Test + public void canRead1() { + boolean result1 = permissionIdentity.canRead(null, userDetails); + assertFalse(result1); + } + + @Test + public void canRead2() { + when(identityRepository.findById(eq(1L))).thenReturn(Optional.empty()); + boolean result1 = permissionIdentity.canRead(1L, userDetails); + assertFalse(result1); + } + + @Test + public void canRead3() { + Collection authorities = new ArrayList(); + authorities.add(new SimpleGrantedAuthority(ROLE_USER)); + when(authentication.getAuthorities()).thenReturn(authorities); + when(securityContext.getAuthentication()).thenReturn(authentication); + SecurityContextHolder.setContext(securityContext); + + Identity identity = Identity.builder().build(); + when(identityRepository.findById(eq(1L))).thenReturn(Optional.of(identity)); + + boolean result1 = permissionIdentity.canRead(1L, userDetails); + assertTrue(result1); + } + + @Test + public void canRead4() { + Collection authorities = new ArrayList(); + authorities.add(new SimpleGrantedAuthority(ROLE_ADMIN)); + when(authentication.getAuthorities()).thenReturn(authorities); + when(securityContext.getAuthentication()).thenReturn(authentication); + SecurityContextHolder.setContext(securityContext); + + Identity identity = Identity.builder().build(); + when(identityRepository.findById(eq(1L))).thenReturn(Optional.of(identity)); + + boolean result1 = permissionIdentity.canRead(1L, userDetails); + assertTrue(result1); + } + + @Test + public void canRead5() { + Application application = Application.builder().id(2L).build(); + Identity identity = Identity.builder().availableApplication(application).build(); + when(identityRepository.findById(eq(1L))).thenReturn(Optional.of(identity)); + when(permissionApplication.canWrite(eq(2L), eq(userDetails))).thenReturn(true); + + boolean result1 = permissionIdentity.canRead(1L, userDetails); + assertTrue(result1); + verify(permissionApplication, times(1)).canWrite(eq(2L), eq(userDetails)); + + } + + @Test + public void canWriteByApplication() { + Collection authorities = new ArrayList(); + authorities.add(new SimpleGrantedAuthority(ROLE_ADMIN)); + when(authentication.getAuthorities()).thenReturn(authorities); + when(securityContext.getAuthentication()).thenReturn(authentication); + SecurityContextHolder.setContext(securityContext); + + boolean result1 = permissionIdentity.canWriteByApplication(null, userDetails); + assertTrue(result1); + } + + @Test + public void canWriteByApplication2() { + Collection authorities = new ArrayList(); + authorities.add(new SimpleGrantedAuthority(ROLE_USER)); + when(authentication.getAuthorities()).thenReturn(authorities); + when(securityContext.getAuthentication()).thenReturn(authentication); + SecurityContextHolder.setContext(securityContext); + + boolean result1 = permissionIdentity.canWriteByApplication(null, userDetails); + assertFalse(result1); + } + + @Test + public void canWriteByApplication3() { + when(permissionApplication.canWrite(eq(1L), eq(userDetails))).thenReturn(true); + when(permissionApplication.canWrite(eq(2L), eq(userDetails))).thenReturn(false); + boolean result1 = permissionIdentity.canWriteByApplication(1L, userDetails); + assertTrue(result1); + + boolean result2 = permissionIdentity.canWriteByApplication(2L, userDetails); + assertFalse(result2); + + verify(permissionApplication, times(1)).canWrite(eq(1L), eq(userDetails)); + verify(permissionApplication, times(1)).canWrite(eq(2L), eq(userDetails)); + + } + + @Test + public void canWrite1() { + boolean result1 = permissionIdentity.canWrite(null, userDetails); + assertFalse(result1); + } + + @Test + public void canWrite2() { + when(identityRepository.findById(eq(1L))).thenReturn(Optional.empty()); + boolean result1 = permissionIdentity.canWrite(1L, userDetails); + assertFalse(result1); + } + + @Test + public void canWrite3() { + Collection authorities = new ArrayList(); + authorities.add(new SimpleGrantedAuthority(ROLE_USER)); + when(authentication.getAuthorities()).thenReturn(authorities); + when(securityContext.getAuthentication()).thenReturn(authentication); + SecurityContextHolder.setContext(securityContext); + + Identity identity = Identity.builder().build(); + when(identityRepository.findById(eq(1L))).thenReturn(Optional.of(identity)); + + boolean result1 = permissionIdentity.canWrite(1L, userDetails); + assertFalse(result1); + } + + @Test + public void canWrite4() { + Collection authorities = new ArrayList(); + authorities.add(new SimpleGrantedAuthority(ROLE_ADMIN)); + when(authentication.getAuthorities()).thenReturn(authorities); + when(securityContext.getAuthentication()).thenReturn(authentication); + SecurityContextHolder.setContext(securityContext); + + Identity identity = Identity.builder().build(); + when(identityRepository.findById(eq(1L))).thenReturn(Optional.of(identity)); + + boolean result1 = permissionIdentity.canWrite(1L, userDetails); + assertTrue(result1); + } + + @Test + public void canWrite5() { + Application application = Application.builder().id(2L).build(); + Identity identity = Identity.builder().availableApplication(application).build(); + when(identityRepository.findById(eq(1L))).thenReturn(Optional.of(identity)); + when(permissionApplication.canWrite(eq(2L), eq(userDetails))).thenReturn(true); + + boolean result1 = permissionIdentity.canWrite(1L, userDetails); + assertTrue(result1); + verify(permissionApplication, times(1)).canWrite(eq(2L), eq(userDetails)); + + } +} \ No newline at end of file diff --git a/src/test/java/fr/icdc/ebad/service/ApplicationServiceTest.java b/src/test/java/fr/icdc/ebad/service/ApplicationServiceTest.java index 53009344..fe832f19 100644 --- a/src/test/java/fr/icdc/ebad/service/ApplicationServiceTest.java +++ b/src/test/java/fr/icdc/ebad/service/ApplicationServiceTest.java @@ -6,6 +6,7 @@ import fr.icdc.ebad.plugin.plugin.ApplicationConnectorPlugin; import fr.icdc.ebad.repository.AccreditationRequestRepository; import fr.icdc.ebad.repository.ApplicationRepository; +import fr.icdc.ebad.repository.IdentityRepository; import fr.icdc.ebad.repository.TypeFichierRepository; import fr.icdc.ebad.service.util.EbadServiceException; import org.junit.Before; @@ -47,7 +48,8 @@ public class ApplicationServiceTest { private TypeFichierRepository typeFichierRepository; @Mock private AccreditationRequestRepository accreditationRequestRepository; - + @Mock + private IdentityRepository identityRepository; @Spy private List applicationConnectorPlugins = new ArrayList<>(); @@ -73,13 +75,15 @@ public void deleteApplication() { application.setEnvironnements(environnementSet); when(applicationRepository.getById(eq(9L))).thenReturn(application); - + Page pageIdentities = new PageImpl<>(new ArrayList<>()); + when(identityRepository.findAll(any(Predicate.class),any(Pageable.class))).thenReturn(pageIdentities); applicationService.deleteApplication(9L); verify(applicationRepository, times(1)).getById(eq(9L)); verify(environnementService, times(1)).deleteEnvironnement(eq(environnement1), eq(true)); verify(environnementService, times(1)).deleteEnvironnement(eq(environnement2), eq(true)); verify(applicationRepository, times(1)).delete(eq(application)); + verify(identityRepository, times(1)).deleteAll(eq(pageIdentities)); } @Test diff --git a/src/test/java/fr/icdc/ebad/service/EnvironnementServiceTest.java b/src/test/java/fr/icdc/ebad/service/EnvironnementServiceTest.java index 304c3941..99139539 100644 --- a/src/test/java/fr/icdc/ebad/service/EnvironnementServiceTest.java +++ b/src/test/java/fr/icdc/ebad/service/EnvironnementServiceTest.java @@ -340,7 +340,7 @@ public List getDependencies() { && env.getName().equals(environnementDiscoverDto1.getName()) && env.getPrefix().equals(environnementDiscoverDto1.getPrefix()) && env.getExternalId().equals(environnementDiscoverDto1.getId()) - && env.getLogin().equals(environnementDiscoverDto1.getLogin()) +// && env.getLogin().equals(environnementDiscoverDto1.getLogin()) && env.getPluginId().equals("import-plugin"))); verify(environnementRepository).save(argThat((env) -> env.getApplication().equals(application) @@ -349,7 +349,7 @@ public List getDependencies() { && env.getName().equals(environnementDiscoverDto2.getName()) && env.getPrefix().equals(environnementDiscoverDto2.getPrefix()) && env.getExternalId().equals(environnementDiscoverDto2.getId()) - && env.getLogin().equals(environnementDiscoverDto2.getLogin()) +// && env.getLogin().equals(environnementDiscoverDto2.getLogin()) && env.getPluginId().equals("import-plugin"))); @@ -359,7 +359,7 @@ public List getDependencies() { .homePath(environnementDiscoverDto1.getHome()) .name(environnementDiscoverDto1.getName()) .prefix(environnementDiscoverDto1.getPrefix()) - .login(environnementDiscoverDto1.getLogin()) +// .login(environnementDiscoverDto1.getLogin()) .application(application) .pluginId("import-plugin") .build(); @@ -370,7 +370,7 @@ public List getDependencies() { .homePath(environnementDiscoverDto2.getHome()) .name(environnementDiscoverDto2.getName()) .prefix(environnementDiscoverDto2.getPrefix()) - .login(environnementDiscoverDto2.getLogin()) +// .login(environnementDiscoverDto2.getLogin()) .application(application) .pluginId("import-plugin") .build(); @@ -599,7 +599,7 @@ public List getDependencies() { && env.getName().equals(environnementDiscoverDto1.getName()) && env.getPrefix().equals(environnementDiscoverDto1.getPrefix()) && env.getExternalId().equals(environnementDiscoverDto1.getId()) - && env.getLogin().equals(environnementDiscoverDto1.getLogin()) +// && env.getLogin().equals(environnementDiscoverDto1.getLogin()) && env.getPluginId().equals("import-plugin"))); verify(environnementRepository).save(argThat((env) -> env.getApplication().equals(application) @@ -608,7 +608,7 @@ public List getDependencies() { && env.getName().equals(environnementDiscoverDto2.getName()) && env.getPrefix().equals(environnementDiscoverDto2.getPrefix()) && env.getExternalId().equals(environnementDiscoverDto2.getId()) - && env.getLogin().equals(environnementDiscoverDto2.getLogin()) +// && env.getLogin().equals(environnementDiscoverDto2.getLogin()) && env.getPluginId().equals("import-plugin"))); Environnement expectedEnv1 = Environnement.builder() @@ -617,7 +617,7 @@ public List getDependencies() { .homePath(environnementDiscoverDto1.getHome()) .name(environnementDiscoverDto1.getName()) .prefix(environnementDiscoverDto1.getPrefix()) - .login(environnementDiscoverDto1.getLogin()) +// .login(environnementDiscoverDto1.getLogin()) .application(application) .pluginId("import-plugin") .build(); @@ -628,7 +628,7 @@ public List getDependencies() { .homePath(environnementDiscoverDto2.getHome()) .name(environnementDiscoverDto2.getName()) .prefix(environnementDiscoverDto2.getPrefix()) - .login(environnementDiscoverDto2.getLogin()) +// .login(environnementDiscoverDto2.getLogin()) .application(application) .pluginId("import-plugin") .build(); diff --git a/src/test/java/fr/icdc/ebad/service/IdentityServiceTest.java b/src/test/java/fr/icdc/ebad/service/IdentityServiceTest.java new file mode 100644 index 00000000..b337e1a6 --- /dev/null +++ b/src/test/java/fr/icdc/ebad/service/IdentityServiceTest.java @@ -0,0 +1,164 @@ +package fr.icdc.ebad.service; + +import com.querydsl.core.types.Predicate; +import fr.icdc.ebad.domain.Identity; +import fr.icdc.ebad.domain.QIdentity; +import fr.icdc.ebad.repository.IdentityRepository; +import fr.icdc.ebad.service.util.EbadServiceException; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.Pageable; + +import java.security.KeyPair; +import java.util.Collections; +import java.util.Optional; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.*; + +@RunWith(MockitoJUnitRunner.class) +public class IdentityServiceTest { + + @InjectMocks + private IdentityService identityService; + + @Mock + private IdentityRepository identityRepository; + + + @Test + public void saveIdentity() { + Identity identity = Identity.builder().name("testName").login("testLogin").build(); + Identity identitySaved = Identity.builder().id(1L).name("testName").login("testLogin").build(); + + when(identityRepository.save(eq(identity))).thenReturn(identitySaved); + Identity result = identityService.saveIdentity(identity); + assertEquals(identitySaved, result); + verify(identityRepository, times(1)).save(eq(identity)); + } + + @Test + public void getIdentity() { + Identity identity = Identity.builder().id(1L).name("testName").login("testLogin").build(); + + when(identityRepository.findById(eq(1L))).thenReturn(Optional.of(identity)); + Optional result = identityService.getIdentity(1L); + assertEquals(identity, result.get()); + verify(identityRepository, times(1)).findById(eq(1L)); + } + + @Test + public void deleteIdentity() { + identityService.deleteIdentity(1L); + verify(identityRepository, times(1)).deleteById(eq(1L)); + } + + @Test + public void findWithoutApp() { + Pageable pageable = Pageable.unpaged(); + Identity identity = Identity.builder().id(1L).name("testName").login("testLogin").build(); + + Page identities = new PageImpl<>(Collections.singletonList(identity)); + when(identityRepository.findAll(any(Predicate.class), eq(pageable))).thenReturn(identities); + Page result = identityService.findWithoutApp(QIdentity.identity.id.eq(1L), pageable); + assertEquals(identity, result.getContent().get(0)); + } + + @Test + public void findAllByApplication() { + Pageable pageable = Pageable.unpaged(); + Identity identity = Identity.builder().id(1L).name("testName").login("testLogin").build(); + + Page identities = new PageImpl<>(Collections.singletonList(identity)); + when(identityRepository.findAll(any(Predicate.class), eq(pageable))).thenReturn(identities); + Page result = identityService.findAllByApplication(1L, QIdentity.identity.id.eq(1L), pageable); + assertEquals(identity, result.getContent().get(0)); + } + + @Test + public void createKeyPair() throws EbadServiceException { + Identity identity = Identity.builder().id(1L).name("testName").login("testLogin").privatekeyPath("src/test/resources/fakekeys/fake_key_password").passphrase("password").build(); + + KeyPair result = identityService.createKeyPair(identity); + assertNotNull(result); + } + + @Test + public void createKeyPair2() throws EbadServiceException { + Identity identity = Identity.builder().id(1L).name("testName").login("testLogin").privatekeyPath("src/test/resources/fakekeys/fake_key_no_password").build(); + + KeyPair result = identityService.createKeyPair(identity); + assertNotNull(result); + } + + @Test(expected = EbadServiceException.class) + public void createKeyPair3() throws EbadServiceException { + Identity identity = Identity.builder().id(1L).name("testName").login("testLogin").privatekeyPath("src/test/resources/fakekeys/fake_key_bad_format").build(); + identityService.createKeyPair(identity); + } + + @Test(expected = EbadServiceException.class) + public void createKeyPair4() throws EbadServiceException { + Identity identity = Identity.builder().id(1L).name("testName").login("testLogin").build(); + identityService.createKeyPair(identity); + } + + @Test(expected = EbadServiceException.class) + public void createKeyPair5() throws EbadServiceException { + Identity identity = Identity.builder().id(1L).name("testName").login("testLogin").privatekeyPath("src/test/resources/fakekeys/fake_key_password").build(); + identityService.createKeyPair(identity); + } + + @Test + public void createKeyPair6() throws EbadServiceException { + Identity identity = Identity.builder().id(1L).name("testName").login("testLogin").privatekey("-----BEGIN RSA PRIVATE KEY-----\n" + + "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\n" + + "-----END RSA PRIVATE KEY-----").build(); + + KeyPair result = identityService.createKeyPair(identity); + assertNotNull(result); + } +} diff --git a/src/test/java/fr/icdc/ebad/service/ShellServiceTest.java b/src/test/java/fr/icdc/ebad/service/ShellServiceTest.java index dfbccb6f..9d5964f7 100644 --- a/src/test/java/fr/icdc/ebad/service/ShellServiceTest.java +++ b/src/test/java/fr/icdc/ebad/service/ShellServiceTest.java @@ -3,6 +3,7 @@ import fr.icdc.ebad.config.properties.EbadProperties; import fr.icdc.ebad.domain.Directory; import fr.icdc.ebad.domain.Environnement; +import fr.icdc.ebad.domain.Identity; import fr.icdc.ebad.domain.Norme; import fr.icdc.ebad.domain.util.RetourBatch; import fr.icdc.ebad.service.util.EbadServiceException; @@ -22,6 +23,7 @@ import org.junit.Test; import org.junit.rules.TemporaryFolder; import org.junit.runner.RunWith; +import org.mockito.Mock; import org.mockito.Spy; import org.mockito.junit.MockitoJUnitRunner; @@ -31,7 +33,6 @@ import java.security.PublicKey; import java.util.Collections; import java.util.List; -import java.util.Optional; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @@ -43,6 +44,9 @@ public class ShellServiceTest { @Spy private EbadProperties ebadProperties; + @Mock + private IdentityService identityService; + @Rule public TemporaryFolder testFolder = new TemporaryFolder(); @@ -53,7 +57,7 @@ public class ShellServiceTest { @Before public void setup() throws IOException { - shellService = new ShellService(ebadProperties, Optional.empty()); + shellService = new ShellService(ebadProperties, identityService); EbadProperties.SshProperties sshProperties = ebadProperties.getSsh(); sshProperties.setPrivateKeyPath("/key"); sshProperties.setPrivateKeyPassphrase("test"); @@ -96,7 +100,8 @@ public boolean authenticate(String username, PublicKey key, ServerSession sessio @Test public void runCommand() throws EbadServiceException { Norme norme = Norme.builder().commandLine("$1").build(); - Environnement environnement = Environnement.builder().id(1L).host("localhost").norme(norme).build(); + Identity identity = Identity.builder().id(1L).login(USERNAME).password(PASSWORD).name("identityName").build(); + Environnement environnement = Environnement.builder().id(1L).identity(identity).host("localhost").norme(norme).build(); RetourBatch retourBatch = shellService.runCommandNew(environnement, "echo hello"); assertEquals("hello", retourBatch.getLogOut().trim()); assertEquals(0, retourBatch.getReturnCode()); @@ -113,7 +118,8 @@ public void listFile() throws EbadServiceException, IOException { fileWriter.close(); Norme norme = Norme.builder().commandLine("$1").build(); - Environnement environnement = Environnement.builder().homePath("").id(1L).host("localhost").norme(norme).build(); + Identity identity = Identity.builder().id(1L).login(USERNAME).password(PASSWORD).name("identityName").build(); + Environnement environnement = Environnement.builder().homePath("").id(1L).identity(identity).host("localhost").norme(norme).build(); Directory directory = new Directory(); directory.setPath(""); directory.setEnvironnement(environnement); diff --git a/src/test/java/fr/icdc/ebad/service/jpa/BatchServiceJpaTest.java b/src/test/java/fr/icdc/ebad/service/jpa/BatchServiceJpaTest.java index 3500113b..045c8a00 100644 --- a/src/test/java/fr/icdc/ebad/service/jpa/BatchServiceJpaTest.java +++ b/src/test/java/fr/icdc/ebad/service/jpa/BatchServiceJpaTest.java @@ -2,15 +2,7 @@ import com.querydsl.core.types.dsl.BooleanExpression; import fr.icdc.ebad.config.Constants; -import fr.icdc.ebad.domain.Application; -import fr.icdc.ebad.domain.Authority; -import fr.icdc.ebad.domain.Batch; -import fr.icdc.ebad.domain.Environnement; -import fr.icdc.ebad.domain.Norme; -import fr.icdc.ebad.domain.QBatch; -import fr.icdc.ebad.domain.UsageApplication; -import fr.icdc.ebad.domain.UsageApplicationId; -import fr.icdc.ebad.domain.User; +import fr.icdc.ebad.domain.*; import fr.icdc.ebad.repository.BatchRepository; import fr.icdc.ebad.service.BatchService; import org.junit.Test; @@ -65,16 +57,20 @@ public void testGetAllBatchWithPredicate() { Norme norme = Norme.builder().name("UNIX").commandLine("$1").pathShell("/").ctrlMDate("ctr").build(); entityManager.persist(norme); + Identity identity = Identity.builder().name("IdentityName").login("myLogin").build(); + entityManager.persist(identity); + Environnement environnement1 = Environnement.builder().application(application1) - .login("login") + .identity(identity) .norme(norme) .host("localhost") .prefix("") .name("dev").build(); entityManager.persist(environnement1); + Environnement environnement2 = Environnement.builder().application(application1) - .login("login") + .identity(identity) .norme(norme) .host("localhost") .prefix("") diff --git a/src/test/java/fr/icdc/ebad/web/rest/IdentityResourceTest.java b/src/test/java/fr/icdc/ebad/web/rest/IdentityResourceTest.java new file mode 100644 index 00000000..b5836311 --- /dev/null +++ b/src/test/java/fr/icdc/ebad/web/rest/IdentityResourceTest.java @@ -0,0 +1,227 @@ +package fr.icdc.ebad.web.rest; + +import com.querydsl.core.types.Predicate; +import fr.icdc.ebad.config.Constants; +import fr.icdc.ebad.domain.Application; +import fr.icdc.ebad.domain.Identity; +import fr.icdc.ebad.security.permission.PermissionIdentity; +import fr.icdc.ebad.service.IdentityService; +import fr.icdc.ebad.util.TestUtil; +import fr.icdc.ebad.web.rest.dto.CompleteIdentityDto; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.Pageable; +import org.springframework.data.web.PageableHandlerMethodArgumentResolver; +import org.springframework.data.web.querydsl.QuerydslPredicateArgumentResolver; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +import static org.hamcrest.Matchers.hasSize; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@RunWith(SpringRunner.class) +@ActiveProfiles(Constants.SPRING_PROFILE_TEST) +@SpringBootTest +public class IdentityResourceTest { + private MockMvc restMvc; + + @MockBean + private IdentityService identityService; + + @MockBean + private PermissionIdentity permissionIdentity; + + @Autowired + private IdentityResource identityResource; + + @Autowired + private QuerydslPredicateArgumentResolver querydslPredicateArgumentResolver; + + @Before + public void setup() { + this.restMvc = MockMvcBuilders + .standaloneSetup(identityResource) + .setCustomArgumentResolvers(querydslPredicateArgumentResolver, new PageableHandlerMethodArgumentResolver()) + .build(); + } + + @Test + @WithMockUser + public void addIdentity() throws Exception { + when(permissionIdentity.canWriteByApplication(isNull(), any())).thenReturn(true); + + MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.put("/identities"); + + CompleteIdentityDto identityDto = CompleteIdentityDto.builder().name("nameTest").login("loginTest").build(); + Identity identity = Identity.builder().id(1L).name("nameTest").login("loginTest").build(); + when(identityService.saveIdentity(any(Identity.class))).thenReturn(identity); + restMvc.perform( + builder + .contentType(TestUtil.APPLICATION_JSON_UTF8) + .content(TestUtil.convertObjectToJsonBytes(identityDto))) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id", is(1))) + .andExpect(jsonPath("$.name", is("nameTest"))) + .andExpect(jsonPath("$.login", is("loginTest"))); + + ArgumentCaptor identityArgumentCaptor = ArgumentCaptor.forClass(Identity.class); + verify(identityService, times(1)).saveIdentity(identityArgumentCaptor.capture()); + assertEquals("nameTest", identityArgumentCaptor.getValue().getName()); + assertEquals("loginTest", identityArgumentCaptor.getValue().getLogin()); + } + + @Test + @WithMockUser + public void getOneIdentity() throws Exception { + when(permissionIdentity.canWrite(eq(1L), any())).thenReturn(true); + MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get("/identities/1"); + + Identity identity = Identity.builder().id(1L).name("nameTest").login("loginTest").build(); + when(identityService.getIdentity(eq(1L))).thenReturn(Optional.of(identity)); + restMvc.perform( + builder + .contentType(TestUtil.APPLICATION_JSON_UTF8)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id", is(1))) + .andExpect(jsonPath("$.name", is("nameTest"))) + .andExpect(jsonPath("$.login", is("loginTest"))); + + verify(identityService, times(1)).getIdentity(eq(1L)); + } + + @Test + @WithMockUser + public void getAllIdentities() throws Exception { + when(permissionIdentity.canReadByApplication(isNull(), any())).thenReturn(true); + + MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get("/identities"); + + Identity identity1 = Identity.builder().id(1L).name("nameTest1").login("loginTest1").build(); + Identity identity2 = Identity.builder().id(2L).name("nameTest2").login("loginTest2").build(); + Identity identity3 = Identity.builder().id(3L).name("nameTest3").login("loginTest3").build(); + + List identities = new ArrayList<>(); + identities.add(identity1); + identities.add(identity2); + identities.add(identity3); + + Page identityPage = new PageImpl<>(identities); + when(identityService.findWithoutApp(any(Predicate.class), any(Pageable.class))).thenReturn(identityPage); + + restMvc.perform( + builder + .contentType(TestUtil.APPLICATION_JSON_UTF8)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.content").isArray()) + .andExpect(jsonPath("$.content", hasSize(3))) + .andExpect(jsonPath("$.content[0].id", is(1))) + .andExpect(jsonPath("$.content[0].name", is("nameTest1"))) + .andExpect(jsonPath("$.content[0].login", is("loginTest1"))) + .andExpect(jsonPath("$.content[1].id", is(2))) + .andExpect(jsonPath("$.content[1].name", is("nameTest2"))) + .andExpect(jsonPath("$.content[1].login", is("loginTest2"))) + .andExpect(jsonPath("$.content[2].id", is(3))) + .andExpect(jsonPath("$.content[2].name", is("nameTest3"))) + .andExpect(jsonPath("$.content[2].login", is("loginTest3"))); + } + + @Test + @WithMockUser + public void getAllIdentitiesWithApplication() throws Exception { + when(permissionIdentity.canReadByApplication(eq(1L), any())).thenReturn(true); + + MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get("/identities?applicationId=1"); + + Identity identity1 = Identity.builder().id(1L).name("nameTest1").login("loginTest1").build(); + Identity identity2 = Identity.builder().id(2L).name("nameTest2").login("loginTest2").build(); + Identity identity3 = Identity.builder().id(3L).name("nameTest3").login("loginTest3").build(); + + List identities = new ArrayList<>(); + identities.add(identity1); + identities.add(identity2); + identities.add(identity3); + + Page identityPage = new PageImpl<>(identities); + when(identityService.findAllByApplication(eq(1L), any(Predicate.class), any(Pageable.class))).thenReturn(identityPage); + + restMvc.perform( + builder + .contentType(TestUtil.APPLICATION_JSON_UTF8)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.content").isArray()) + .andExpect(jsonPath("$.content", hasSize(3))) + .andExpect(jsonPath("$.content[0].id", is(1))) + .andExpect(jsonPath("$.content[0].name", is("nameTest1"))) + .andExpect(jsonPath("$.content[0].login", is("loginTest1"))) + .andExpect(jsonPath("$.content[1].id", is(2))) + .andExpect(jsonPath("$.content[1].name", is("nameTest2"))) + .andExpect(jsonPath("$.content[1].login", is("loginTest2"))) + .andExpect(jsonPath("$.content[2].id", is(3))) + .andExpect(jsonPath("$.content[2].name", is("nameTest3"))) + .andExpect(jsonPath("$.content[2].login", is("loginTest3"))); + } + + @Test + @WithMockUser + public void updateIdentity() throws Exception { + when(permissionIdentity.canWriteByApplication(eq(2L), any())).thenReturn(true); + when(permissionIdentity.canWrite(eq(1L), any())).thenReturn(true); + MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.patch("/identities"); + + CompleteIdentityDto identityDto = CompleteIdentityDto.builder().id(1L).availableApplication(2L).name("nameTestNew").login("loginTestNew").build(); + + Application application = Application.builder().id(2L).build(); + Identity identity = Identity.builder().id(1L).availableApplication(application).name("nameTestNew").login("loginTestNew").build(); + when(identityService.saveIdentity(any(Identity.class))).thenReturn(identity); + + restMvc.perform( + builder + .contentType(TestUtil.APPLICATION_JSON_UTF8) + .content(TestUtil.convertObjectToJsonBytes(identityDto))) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id", is(1))) + .andExpect(jsonPath("$.availableApplication", is(2))) + .andExpect(jsonPath("$.name", is("nameTestNew"))) + .andExpect(jsonPath("$.login", is("loginTestNew"))); + + ArgumentCaptor identityArgumentCaptor = ArgumentCaptor.forClass(Identity.class); + verify(identityService, times(1)).saveIdentity(identityArgumentCaptor.capture()); + assertEquals("nameTestNew", identityArgumentCaptor.getValue().getName()); + assertEquals("loginTestNew", identityArgumentCaptor.getValue().getLogin()); + assertEquals(2L, identityArgumentCaptor.getValue().getAvailableApplication().getId(),0); + + } + + @Test + @WithMockUser + public void deleteIdentity() throws Exception { + when(permissionIdentity.canWrite(eq(1L), any())).thenReturn(true); + MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.delete("/identities/1"); + restMvc.perform( + builder + .contentType(TestUtil.APPLICATION_JSON_UTF8)) + .andExpect(status().isOk()); + verify(identityService, times(1)).deleteIdentity(eq(1L)); + } +} diff --git a/src/test/resources/fakekeys/fake_key_bad_format b/src/test/resources/fakekeys/fake_key_bad_format new file mode 100644 index 00000000..5d58da86 --- /dev/null +++ b/src/test/resources/fakekeys/fake_key_bad_format @@ -0,0 +1,38 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +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 +-----END OPENSSH PRIVATE KEY----- diff --git a/src/test/resources/fakekeys/fake_key_bad_format.pub b/src/test/resources/fakekeys/fake_key_bad_format.pub new file mode 100644 index 00000000..f9fd5e71 --- /dev/null +++ b/src/test/resources/fakekeys/fake_key_bad_format.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDGdKg1i35iCvUQMwfSa6xu1yzVGGD2g3/ScU87Y/hQvGpljpAgmg+e7DWOkk+goR8n2UlHXyQ3K8GQObN7eqRY1neexw3+vNBkg6dYOncfmsTfxJyHiGYMVodOiBcxTqUGWrxyJDqr9X2tkXkJAqMa1L/nODJFKb/TvBdTtrIHPWGjzTV/rc88274yBWyOv1HwDUqB8WNWtdYWXk2UzDGMHyYSZUyZiUhLXGzMxe1qfmbbzG4fMWsDVK0sHXu0JG6Mi0D4GyGXpKY5uUnEc3Y4JVciQ6JJF9VrK8l8zZ929XupcCt1zlHVkJbkLuJpAaFpDIV+eHdUFqltC0r/PIbGWA3xiOLCOEXi1S0TK4l59YVSyeEODgeoOADlEuFOWuvdnRMVMBv1RFucwQjNLkufh9a2nCC3VVV9ablxgmhl6sZPaEl+9G7YzubofW05SV+bDOJySPlQcsFNE77AYjCJa2O8k1UEtVz0840uTAqmPFuTVoQSK928a+J5/Vk2uaM= dtrouillet@DESKTOP-8M0GEEF diff --git a/src/test/resources/fakekeys/fake_key_no_password b/src/test/resources/fakekeys/fake_key_no_password new file mode 100644 index 00000000..00742187 --- /dev/null +++ b/src/test/resources/fakekeys/fake_key_no_password @@ -0,0 +1,39 @@ +-----BEGIN RSA PRIVATE KEY----- +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 +-----END RSA PRIVATE KEY----- diff --git a/src/test/resources/fakekeys/fake_key_no_password.pub b/src/test/resources/fakekeys/fake_key_no_password.pub new file mode 100644 index 00000000..6b7f4b53 --- /dev/null +++ b/src/test/resources/fakekeys/fake_key_no_password.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDHXl4K2jnIEoqryms4zCEaoUN7w4zvLRBzXq+FdzlrHz9ZVVZLoSLcFnNDxN7pC7d8Ondnaeuj+nZBvhEBjZkFp2iupjOkazgwPqsi/WXZbP9775Lk8d338pKEZr+FKgenAvlOAho1PQ+1FjhdFPh/b9kXBNP3aF7iY0cLNGV38rCLmuRCAtB7XxkIQKqUFcOx7p+9aUlpBlKzMaZQ5+n47hxnTTMgjDQDH3/fAO5SweSMueUk6WzcxJhjzD4w2q4OHleyWuv0h297scUihLgJPNszvNeVshCJhkhYQEESSGKTscEVki5TSxOP+X7kcYXTc0tF/uXOTKeZ9JqzKvu72VfJwv6NV6TZIEWi4Zaa4E/Y0G9C6WFe/LG50x62u5/ZIfe8BFtp+BlfMSwSUNegUDsk/QnFuNiWl9+QIPkwMEMLlVQBCcMOcCrTvx/it1/pbxK2cvwmLCIdrUsZ6GF7t+afa0jKnyA/134a6oMGacCrKOVy9AxwxHEb00KrWos= dtrouillet@DESKTOP-8M0GEEF diff --git a/src/test/resources/fakekeys/fake_key_password b/src/test/resources/fakekeys/fake_key_password new file mode 100644 index 00000000..56a80ae3 --- /dev/null +++ b/src/test/resources/fakekeys/fake_key_password @@ -0,0 +1,42 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-128-CBC,8673152E9BE10CFE4E25B1FB8280B646 + +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 +-----END RSA PRIVATE KEY----- diff --git a/src/test/resources/fakekeys/fake_key_password.pub b/src/test/resources/fakekeys/fake_key_password.pub new file mode 100644 index 00000000..8ecddea2 --- /dev/null +++ b/src/test/resources/fakekeys/fake_key_password.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDWuFs9a5puDKJ2xoDy+jijMD9kOUkv6UhonwKdjyuypwAejh9uTBgdpCpvsZL8sLagoTR/RksMcP4bvEWPFyUkQYD9kuBT5tHlkrabu9oqz4ftCg2VwYQejOQTi345uLtQe1kuvvmwbxqMPnR8a7lWsJR8BoT3ImW11DvY6IAcx2Y/RrKA5U/aCTX1gor2UFyterCGGN2rRpkEo7nybG24v7hQZyH+vAr51xDnFeyoFcw1d0t/0b9a1D80xe+JDSC3e5gBmGvsTXXvbVz7gBdCVMe1+HDZ9kIDPcy43DlHI43mgBNBEC8xg3VS3iZV+71H+IzHX2bqdEaD+KBg0qeTs7shHzuFylDrY3eB6vCwQ71HFF8O/6xUeK2BAcgxql6YkQnxY6QHLSZlkZt5N7M54pVm6kuXQZeGbXK0kBorhi6nDg9DQXFRCXoKtT9d862uW+TkNSAIMXy2PLXVjMwtAAwetWMv+Gq9dU3nAnJdWDemC7pRasYA0zD84oLi88M= dtrouillet@DESKTOP-8M0GEEF