Unverified Commit a91cb7b8 authored by Cristina Yenyxe Gonzalez Garcia's avatar Cristina Yenyxe Gonzalez Garcia Committed by GitHub
Browse files

Merge pull request #10 from selvaebi/T2D-262

T2D-262 Created separate schemas for staging and prod. Auto notification for updates in registry.
parents ce54994b c63e0750
...@@ -6,14 +6,16 @@ pipeline { ...@@ -6,14 +6,16 @@ pipeline {
} }
environment { environment {
stagingPostgresDbUrl = credentials('STAGINGPROPERTYREGISTRYDBURL') stagingPostgresDbUrl = credentials('STAGINGPROPERTYREGISTRYDBURL')
fallBackPostgresDbUrl = credentials('STAGINGPROPERTYREGISTRYDBURL') fallBackPostgresDbUrl = credentials('PRODUCTIONPROPERTYREGISTRYDBURL')
productionPostgresDbUrl = credentials('STAGINGPROPERTYREGISTRYDBURL') productionPostgresDbUrl = credentials('PRODUCTIONPROPERTYREGISTRYDBURL')
postgresDBUserName = credentials('POSTGRESDBUSERNAME') postgresDBUserName = credentials('POSTGRESDBUSERNAME')
postgresDBPassword = credentials('POSTGRESDBPASSWORD') postgresDBPassword = credentials('POSTGRESDBPASSWORD')
tomcatCredentials = credentials('TOMCATCREDENTIALS') tomcatCredentials = credentials('TOMCATCREDENTIALS')
stagingHost = credentials('STAGINGHOST') stagingHost = credentials('STAGINGHOST')
fallbackHost = credentials('FALLBACKHOST') fallbackHost = credentials('FALLBACKHOST')
productionHost = credentials('PRODUCTIONHOST') productionHost = credentials('PRODUCTIONHOST')
smtpHost = credentials('SMTPHOST')
ampt2dEmailId = credentials('AMPT2DEMAILID')
} }
parameters { parameters {
booleanParam(name: 'DeployToStaging' , defaultValue: false , description: '') booleanParam(name: 'DeployToStaging' , defaultValue: false , description: '')
...@@ -22,7 +24,7 @@ pipeline { ...@@ -22,7 +24,7 @@ pipeline {
stages { stages {
stage('Default Build pointing to Staging DB') { stage('Default Build pointing to Staging DB') {
steps { steps {
sh "mvn clean package -DskipTests -DbuildDirectory=staging/target -Dampt2d-property-registry-db.url=${stagingPostgresDbUrl} -Dampt2d-property-registry-db.username=${postgresDBUserName} -Dampt2d-property-registry-db.password=${postgresDBPassword}" sh "mvn clean package -DskipTests -DbuildDirectory=staging/target -Dampt2d-property-registry-db.url=${stagingPostgresDbUrl} -Dampt2d-property-registry-db.username=${postgresDBUserName} -Dampt2d-property-registry-db.password=${postgresDBPassword} -Dsmtp-host=${smtpHost} -Damp-t2d-email-id=${ampt2dEmailId}"
} }
} }
stage('Build For FallBack And Production') { stage('Build For FallBack And Production') {
...@@ -33,9 +35,9 @@ pipeline { ...@@ -33,9 +35,9 @@ pipeline {
} }
steps { steps {
echo 'Build pointing to FallBack DB' echo 'Build pointing to FallBack DB'
sh "mvn clean package -DskipTests -DbuildDirectory=fallback/target -Dampt2d-property-registry-db.url=${fallBackPostgresDbUrl} -Dampt2d-property-registry-db.username=${postgresDBUserName} -Dampt2d-property-registry-db.password=${postgresDBPassword}" sh "mvn clean package -DskipTests -DbuildDirectory=fallback/target -Dampt2d-property-registry-db.url=${fallBackPostgresDbUrl} -Dampt2d-property-registry-db.username=${postgresDBUserName} -Dampt2d-property-registry-db.password=${postgresDBPassword} -Dsmtp-host=${smtpHost} -Damp-t2d-email-id=${ampt2dEmailId}"
echo 'Build pointing to Production DB' echo 'Build pointing to Production DB'
sh "mvn clean package -DskipTests -DbuildDirectory=production/target -Dampt2d-property-registry-db.url=${productionPostgresDbUrl} -Dampt2d-property-registry-db.username=${postgresDBUserName} -Dampt2d-property-registry-db.password=${postgresDBPassword}" sh "mvn clean package -DskipTests -DbuildDirectory=production/target -Dampt2d-property-registry-db.url=${productionPostgresDbUrl} -Dampt2d-property-registry-db.username=${postgresDBUserName} -Dampt2d-property-registry-db.password=${postgresDBPassword} -Dsmtp-host=${smtpHost} -Damp-t2d-email-id=${ampt2dEmailId}"
} }
} }
stage('Deploy To Staging') { stage('Deploy To Staging') {
...@@ -46,7 +48,7 @@ pipeline { ...@@ -46,7 +48,7 @@ pipeline {
} }
steps { steps {
echo 'Deploying to Staging' echo 'Deploying to Staging'
sh "curl --upload-file staging/target/amp-t2d-property-registry-*.war 'http://'${tomcatCredentials}'@'${stagingHost}':8080/manager/text/deploy?path=/registry&update=true' | grep 'OK - Deployed application at context path '" sh "curl --upload-file staging/target/amp-t2d-property-registry-*.war 'http://'${tomcatCredentials}'@'${stagingHost}':8080/manager/text/deploy?path=/dev/registry&update=true' | grep 'OK - Deployed application at context path '"
} }
} }
stage('Deploy To FallBack And Production') { stage('Deploy To FallBack And Production') {
......
...@@ -31,6 +31,10 @@ ...@@ -31,6 +31,10 @@
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId> <artifactId>spring-boot-starter-web</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId> <artifactId>spring-boot-starter-data-jpa</artifactId>
......
...@@ -20,8 +20,8 @@ package uk.ac.ebi.ampt2d.registry.config.security; ...@@ -20,8 +20,8 @@ package uk.ac.ebi.ampt2d.registry.config.security;
import org.springframework.boot.autoconfigure.security.oauth2.resource.AuthoritiesExtractor; import org.springframework.boot.autoconfigure.security.oauth2.resource.AuthoritiesExtractor;
import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority;
import uk.ac.ebi.ampt2d.registry.entities.User; import uk.ac.ebi.ampt2d.registry.entities.RegistryUser;
import uk.ac.ebi.ampt2d.registry.repositories.UserRepository; import uk.ac.ebi.ampt2d.registry.repositories.RegistryUserRepository;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
...@@ -29,21 +29,21 @@ import java.util.Map; ...@@ -29,21 +29,21 @@ import java.util.Map;
public class CustomAuthoritiesExtractor implements AuthoritiesExtractor { public class CustomAuthoritiesExtractor implements AuthoritiesExtractor {
private UserRepository userRepository; private RegistryUserRepository registryUserRepository;
public CustomAuthoritiesExtractor(UserRepository userRepository) { public CustomAuthoritiesExtractor(RegistryUserRepository registryUserRepository) {
this.userRepository = userRepository; this.registryUserRepository = registryUserRepository;
} }
@Override @Override
public List<GrantedAuthority> extractAuthorities(Map<String, Object> map) { public List<GrantedAuthority> extractAuthorities(Map<String, Object> map) {
String email = (String) map.get("email"); String email = (String) map.get("email");
User user = userRepository.findByEmail(email); RegistryUser registryUser = registryUserRepository.findByEmail(email);
if (user == null) { if (registryUser == null) {
user = new User(email, User.Role.ROLE_USER); registryUser = new RegistryUser(email, RegistryUser.Role.ROLE_USER);
userRepository.save(user); registryUserRepository.save(registryUser);
return Arrays.asList(new SimpleGrantedAuthority(User.Role.ROLE_USER.name())); return Arrays.asList(new SimpleGrantedAuthority(RegistryUser.Role.ROLE_USER.name()));
} }
return Arrays.asList(new SimpleGrantedAuthority(user.getRole().toString())); return Arrays.asList(new SimpleGrantedAuthority(registryUser.getRole().toString()));
} }
} }
...@@ -17,7 +17,6 @@ ...@@ -17,7 +17,6 @@
*/ */
package uk.ac.ebi.ampt2d.registry.config.security; package uk.ac.ebi.ampt2d.registry.config.security;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.security.oauth2.resource.AuthoritiesExtractor; import org.springframework.boot.autoconfigure.security.oauth2.resource.AuthoritiesExtractor;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
...@@ -26,7 +25,7 @@ import org.springframework.http.HttpMethod; ...@@ -26,7 +25,7 @@ import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer; import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter; import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import uk.ac.ebi.ampt2d.registry.repositories.UserRepository; import uk.ac.ebi.ampt2d.registry.repositories.RegistryUserRepository;
@ConditionalOnProperty(value = "security.enabled", havingValue = "true") @ConditionalOnProperty(value = "security.enabled", havingValue = "true")
@Configuration @Configuration
...@@ -57,7 +56,7 @@ public class EnableSecurityConfig extends ResourceServerConfigurerAdapter { ...@@ -57,7 +56,7 @@ public class EnableSecurityConfig extends ResourceServerConfigurerAdapter {
} }
@Bean @Bean
public AuthoritiesExtractor authoritiesExtractor(UserRepository userRepository) { public AuthoritiesExtractor authoritiesExtractor(RegistryUserRepository registryUserRepository) {
return new CustomAuthoritiesExtractor(userRepository); return new CustomAuthoritiesExtractor(registryUserRepository);
} }
} }
\ No newline at end of file
/*
*
* Copyright 2018 EMBL - European Bioinformatics Institute
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package uk.ac.ebi.ampt2d.registry.entities;
import uk.ac.ebi.ampt2d.registry.util.BeanUtil;
import uk.ac.ebi.ampt2d.registry.service.mail.MailService;
import javax.persistence.PostPersist;
import javax.persistence.PostRemove;
import javax.persistence.PostUpdate;
public class EntityEventListener {
private enum Event {
CREATED,
UPDATED,
REMOVED
}
@PostPersist
public void onPersistEntity(IdentifiableEntity entity) {
sendNotification(entity, Event.CREATED);
}
@PostUpdate
public void onUpdateEntity(IdentifiableEntity entity) {
sendNotification(entity, Event.UPDATED);
}
@PostRemove
public void onRemoveEntity(IdentifiableEntity entity) {
sendNotification(entity, Event.REMOVED);
}
private void sendNotification(IdentifiableEntity entity, Event event) {
BeanUtil.getBean(MailService.class).send(entity.getClass().getSimpleName() + " " + entity.getId() + " " + event);
}
}
/*
*
* Copyright 2018 EMBL - European Bioinformatics Institute
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package uk.ac.ebi.ampt2d.registry.entities;
public interface IdentifiableEntity<ENTITY_ID> {
ENTITY_ID getId();
}
\ No newline at end of file
...@@ -34,8 +34,8 @@ import javax.validation.constraints.Size; ...@@ -34,8 +34,8 @@ import javax.validation.constraints.Size;
import java.time.ZonedDateTime; import java.time.ZonedDateTime;
@Entity @Entity
@EntityListeners(AuditingEntityListener.class) @EntityListeners({AuditingEntityListener.class, EntityEventListener.class})
public class Phenotype { public class Phenotype implements IdentifiableEntity<String> {
public enum Group { public enum Group {
...@@ -68,4 +68,8 @@ public class Phenotype { ...@@ -68,4 +68,8 @@ public class Phenotype {
@LastModifiedDate @LastModifiedDate
private ZonedDateTime lastModifiedDate; private ZonedDateTime lastModifiedDate;
public String getId() {
return id;
}
} }
...@@ -35,8 +35,8 @@ import javax.validation.constraints.Size; ...@@ -35,8 +35,8 @@ import javax.validation.constraints.Size;
import java.time.ZonedDateTime; import java.time.ZonedDateTime;
@Entity @Entity
@EntityListeners(AuditingEntityListener.class) @EntityListeners({AuditingEntityListener.class, EntityEventListener.class})
public class Property { public class Property implements IdentifiableEntity<String> {
public enum Type { public enum Type {
...@@ -102,4 +102,7 @@ public class Property { ...@@ -102,4 +102,7 @@ public class Property {
@LastModifiedDate @LastModifiedDate
private ZonedDateTime lastModifiedDate; private ZonedDateTime lastModifiedDate;
public String getId() {
return id;
}
} }
\ No newline at end of file
...@@ -24,8 +24,11 @@ import javax.persistence.EnumType; ...@@ -24,8 +24,11 @@ import javax.persistence.EnumType;
import javax.persistence.Enumerated; import javax.persistence.Enumerated;
import javax.persistence.Id; import javax.persistence.Id;
/*
User is a reserved word in PostgreSQL. Hence using class name RegistryUser
*/
@Entity @Entity
public class User { public class RegistryUser {
public enum Role { public enum Role {
...@@ -43,10 +46,10 @@ public class User { ...@@ -43,10 +46,10 @@ public class User {
@Enumerated(EnumType.STRING) @Enumerated(EnumType.STRING)
private Role role; private Role role;
public User() { public RegistryUser() {
} }
public User(String email, Role role) { public RegistryUser(String email, Role role) {
this.email = email; this.email = email;
this.role = role; this.role = role;
} }
......
/*
*
* Copyright 2018 EMBL - European Bioinformatics Institute
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package uk.ac.ebi.ampt2d.registry.exceptionhandling;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.mail.MailSendException;
import org.springframework.transaction.TransactionSystemException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import java.util.logging.Level;
import java.util.logging.Logger;
@ControllerAdvice
public class ExceptionHandlers {
private static final Logger exceptionLogger = Logger.getLogger(ExceptionHandlers.class.getSimpleName());
@Value("${mail.from}")
private String mailFrom;
@ExceptionHandler(value = TransactionSystemException.class)
public ResponseEntity<String> handleMailSendException(TransactionSystemException ex) {
if (ex.getOriginalException().getCause().getClass().equals(MailSendException.class)) {
exceptionLogger.log(Level.SEVERE, ex.getOriginalException().getCause().getMessage());
return new ResponseEntity("An automated email could not be sent, please contact " + mailFrom,
HttpStatus.INTERNAL_SERVER_ERROR);
}
throw ex;
}
}
...@@ -19,11 +19,11 @@ package uk.ac.ebi.ampt2d.registry.repositories; ...@@ -19,11 +19,11 @@ package uk.ac.ebi.ampt2d.registry.repositories;
import org.springframework.data.repository.PagingAndSortingRepository; import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.data.repository.query.Param; import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository; import org.springframework.data.rest.core.annotation.RepositoryRestResource;
import uk.ac.ebi.ampt2d.registry.entities.User; import uk.ac.ebi.ampt2d.registry.entities.RegistryUser;
@Repository @RepositoryRestResource(collectionResourceRel = "users", path = "users")
public interface UserRepository extends PagingAndSortingRepository<User, String> { public interface RegistryUserRepository extends PagingAndSortingRepository<RegistryUser, String> {
User findByEmail(@Param("email") String email); RegistryUser findByEmail(@Param("email") String email);
} }
/*
*
* Copyright 2018 EMBL - European Bioinformatics Institute
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package uk.ac.ebi.ampt2d.registry.service.mail;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Service;
@Service
public class MailService {
@Autowired
private JavaMailSender javaMailSender;
@Value("${mail.notify:false}")
private Boolean nofify;
@Value("${mail.to}")
private String to;
@Value("${mail.from}")
private String from;
@Value("${mail.subject}")
private String subject;
public void send(String text) {
if (nofify == true) {
SimpleMailMessage message = new SimpleMailMessage();
message.setTo(to);
message.setFrom(from);
message.setSubject(subject);
message.setText(text);
javaMailSender.send(message);
}
}
}
\ No newline at end of file
/*
*
* Copyright 2018 EMBL - European Bioinformatics Institute
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package uk.ac.ebi.ampt2d.registry.util;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Service;
@Service
public class BeanUtil implements ApplicationContextAware {
private static ApplicationContext context;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
context = applicationContext;
}
public static <T> T getBean(Class<T> beanClass) {
return context.getBean(beanClass);
}
}
\ No newline at end of file
...@@ -21,4 +21,14 @@ security.enabled=true ...@@ -21,4 +21,14 @@ security.enabled=true
security.oauth2.resource.userInfoUri=https://www.googleapis.com/userinfo/v2/me security.oauth2.resource.userInfoUri=https://www.googleapis.com/userinfo/v2/me
security.oauth2.resource.filter-order=3 security.oauth2.resource.filter-order=3
registry.protocols=https spring.mail.host=@smtp-host@
spring.mail.port=587
spring.mail.test-connection=false
spring.mail.properties.mail.smtp.auth=false
spring.mail.properties.mail.smtp.ssl.enable=false
mail.from=@amp-t2d-email-id@
mail.to=@amp-t2d-email-id@
mail.subject=AMP-T2D Registry Update
registry.protocols=https
\ No newline at end of file
insert into user VALUES ('selva@ebi.ac.uk','ROLE_ADMIN');
insert into user VALUES ('zl@ebi.ac.uk','ROLE_ADMIN');
insert into user VALUES ('iyangar@ebi.ac.uk','ROLE_ADMIN');
\ No newline at end of file
...@@ -14,7 +14,7 @@ CREATE TABLE IF NOT EXISTS property ( ...@@ -14,7 +14,7 @@ CREATE TABLE IF NOT EXISTS property (
type VARCHAR(255) NOT NULL, type VARCHAR(255) NOT NULL,
PRIMARY KEY (id) PRIMARY KEY (id)
); );
CREATE TABLE IF NOT EXISTS user ( CREATE TABLE IF NOT EXISTS registry_user (
email VARCHAR(255) NOT NULL, email VARCHAR(255) NOT NULL,
role VARCHAR(255), role VARCHAR(255),
PRIMARY KEY (email) PRIMARY KEY (email)
......
...@@ -35,7 +35,7 @@ import org.springframework.security.oauth2.provider.token.AuthorizationServerTok ...@@ -35,7 +35,7 @@ import org.springframework.security.oauth2.provider.token.AuthorizationServerTok
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.test.web.servlet.request.RequestPostProcessor; import org.springframework.test.web.servlet.request.RequestPostProcessor;
import uk.ac.ebi.ampt2d.registry.config.security.CustomAuthoritiesExtractor; import uk.ac.ebi.ampt2d.registry.config.security.CustomAuthoritiesExtractor;
import uk.ac.ebi.ampt2d.registry.repositories.UserRepository; import uk.ac.ebi.ampt2d.registry.repositories.RegistryUserRepository;
import java.io.Serializable; import java.io.Serializable;
import java.util.Collection; import java.util.Collection;
...@@ -55,7 +55,7 @@ public class OAuthHelper extends AuthorizationServerConfigurerAdapter { ...@@ -55,7 +55,7 @@ public class OAuthHelper extends AuthorizationServerConfigurerAdapter {
private ClientDetailsService clientDetailsService; private ClientDetailsService clientDetailsService;
@Autowired @Autowired
private UserRepository userRepository; private RegistryUserRepository registryUserRepository;
public RequestPostProcessor bearerToken(final String clientid) { public RequestPostProcessor bearerToken(final String clientid) {