From b37b3684c5c590884728750f8448d485c7e4aa01 Mon Sep 17 00:00:00 2001 From: sazid Date: Mon, 24 Jun 2019 00:06:49 +0600 Subject: [PATCH 1/4] flyway integration new schema required changes to support new schema --- .idea/modules/sazid1462.ID-Service.main.iml | 4 +- .idea/modules/sazid1462.ID-Service.test.iml | 3 +- build.gradle | 4 +- .../rls/ids/controllers/AppController.java | 17 ++++--- .../java/com/rls/ids/entities/BaseEntity.java | 11 +++-- .../java/com/rls/ids/entities/Company.java | 23 ++++++--- src/main/java/com/rls/ids/entities/User.java | 49 +++++++------------ .../com/rls/ids/models/SubordinateModel.java | 16 +++--- .../ids/models/UserSignUpResponseModel.java | 10 ++-- .../rls/ids/repositories/UserRepository.java | 8 ++- src/main/resources/application-dev.yml | 15 ++---- src/main/resources/application-prod.yml | 16 ++---- src/main/resources/db/migration/V1__init.sql | 28 +++++++++++ 13 files changed, 110 insertions(+), 94 deletions(-) create mode 100644 src/main/resources/db/migration/V1__init.sql diff --git a/.idea/modules/sazid1462.ID-Service.main.iml b/.idea/modules/sazid1462.ID-Service.main.iml index 2e15146..e140c79 100644 --- a/.idea/modules/sazid1462.ID-Service.main.iml +++ b/.idea/modules/sazid1462.ID-Service.main.iml @@ -23,9 +23,9 @@ + - @@ -71,9 +71,9 @@ + - diff --git a/.idea/modules/sazid1462.ID-Service.test.iml b/.idea/modules/sazid1462.ID-Service.test.iml index 08f0c92..b562c69 100644 --- a/.idea/modules/sazid1462.ID-Service.test.iml +++ b/.idea/modules/sazid1462.ID-Service.test.iml @@ -25,6 +25,7 @@ + @@ -84,8 +85,8 @@ - + diff --git a/build.gradle b/build.gradle index b3066e2..93f3c9a 100644 --- a/build.gradle +++ b/build.gradle @@ -60,11 +60,11 @@ dependencies { // Use MySQL Connector-J compile 'mysql:mysql-connector-java' + compile "org.flywaydb:flyway-core:5.2.4" + implementation("org.springframework.data:spring-data-envers") implementation("com.fasterxml.jackson.core:jackson-annotations:2.9.7") implementation("com.fasterxml.jackson.datatype:jackson-datatype-hibernate5:2.9.7") - - developmentOnly("org.springframework.boot:spring-boot-devtools") testCompile("junit:junit") testCompile("org.springframework.boot:spring-boot-starter-test") diff --git a/src/main/java/com/rls/ids/controllers/AppController.java b/src/main/java/com/rls/ids/controllers/AppController.java index 2112ea9..5372f92 100644 --- a/src/main/java/com/rls/ids/controllers/AppController.java +++ b/src/main/java/com/rls/ids/controllers/AppController.java @@ -45,14 +45,17 @@ public ResponseEntity companySignUp(@Valid @RequestBody Co if (isInvalid(secretKey) && !secretKey.equals(this.secretKey)) throw new MissingHeaderException(secretKey + " is missing or invalid."); - companyRepository.save(company); + company.setCid(UUID.randomUUID().toString()); + company = companyRepository.saveAndFlush(company); + // Retrieve the saved company +// company = companyRepository.getCompanyByCid(company.getCid()); KeyGenerator generator = KeyGenerator.getInstance("AES"); generator.init(128); // The AES key size in number of bits - User admin = new User(UUID.randomUUID().toString(), company.getCid(), Role.ADMIN); + User admin = new User(UUID.randomUUID().toString(), company.getId(), Role.ADMIN); admin.setAppKey(Base64.getEncoder().encodeToString(generator.generateKey().getEncoded())); - userRepository.save(admin); + admin = userRepository.save(admin); CompanyResponseModel companyResponseModel = new CompanyResponseModel(company.getDomain(), company.getCid(), admin); return new ResponseEntity<>(companyResponseModel, HttpStatus.OK); @@ -65,8 +68,8 @@ public ResponseEntity userSignUp(@Valid @RequestBody SignUpRequestModel si if (admin == null) throw new InvalidAppKeyException(signUpModel.getAppKey()+" is invalid!"); - User user = new User(signUpModel.getUserId(), admin.getCid(), Role.USER); - userRepository.save(user); + User user = new User(signUpModel.getUserId(), admin.getCompanyId(), Role.USER); + user = userRepository.saveAndFlush(user); return new ResponseEntity<>(user, HttpStatus.OK); } @@ -82,8 +85,8 @@ public ResponseEntity resolveUser(@RequestParam String throw new InvalidAppKeyException(appKey+" is invalid!"); UserSignUpResponseModel model = new UserSignUpResponseModel(admin.getUserId(), admin.getRole(), - admin.getAppKey(), admin.getCid()); - model.setSubordinates(userRepository.findUsersByCidAndRole(admin.getCid(), Role.USER)); + admin.getAppKey(), admin.getCompanyId()); + model.setSubordinates(userRepository.findUsersByCompanyIdAndRole(admin.getCompanyId(), Role.USER)); return new ResponseEntity<>(model, HttpStatus.OK); } diff --git a/src/main/java/com/rls/ids/entities/BaseEntity.java b/src/main/java/com/rls/ids/entities/BaseEntity.java index d3d71b2..cb611c6 100644 --- a/src/main/java/com/rls/ids/entities/BaseEntity.java +++ b/src/main/java/com/rls/ids/entities/BaseEntity.java @@ -2,19 +2,22 @@ import org.hibernate.annotations.CreationTimestamp; import org.hibernate.annotations.UpdateTimestamp; -import org.springframework.data.annotation.CreatedDate; -import org.springframework.data.annotation.LastModifiedDate; import org.springframework.data.jpa.domain.support.AuditingEntityListener; -import javax.persistence.*; -import java.sql.Date; +import javax.persistence.EntityListeners; +import javax.persistence.MappedSuperclass; +import javax.persistence.Temporal; +import javax.persistence.TemporalType; +import java.util.Date; @MappedSuperclass @EntityListeners({AuditingEntityListener.class}) abstract class BaseEntity { @CreationTimestamp + @Temporal(TemporalType.TIMESTAMP) private Date createdAt; @UpdateTimestamp + @Temporal(TemporalType.TIMESTAMP) private Date updatedAt; public Date getCreatedAt() { diff --git a/src/main/java/com/rls/ids/entities/Company.java b/src/main/java/com/rls/ids/entities/Company.java index 0b4755a..456ea1d 100644 --- a/src/main/java/com/rls/ids/entities/Company.java +++ b/src/main/java/com/rls/ids/entities/Company.java @@ -1,22 +1,20 @@ package com.rls.ids.entities; import jdk.jfr.Timestamp; -import org.hibernate.annotations.GenericGenerator; import org.springframework.validation.annotation.Validated; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; +import javax.persistence.*; import javax.validation.constraints.NotBlank; -import java.sql.Date; +import java.util.Date; @Entity @Validated public class Company extends BaseEntity { @Id - @GeneratedValue(generator = "uuid") - @GenericGenerator(name = "uuid", strategy = "uuid2") + @Column(name = "id") + @GeneratedValue(strategy = GenerationType.IDENTITY) + private int id; + private String cid; @Column(unique = true, nullable = false) @@ -25,6 +23,7 @@ public class Company extends BaseEntity { private String name; @Timestamp + @Temporal(TemporalType.TIMESTAMP) private Date deletedAt; public String getDomain() { @@ -58,4 +57,12 @@ public String getCid() { public void setCid(String cid) { this.cid = cid; } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } } diff --git a/src/main/java/com/rls/ids/entities/User.java b/src/main/java/com/rls/ids/entities/User.java index 810d655..3831cf7 100644 --- a/src/main/java/com/rls/ids/entities/User.java +++ b/src/main/java/com/rls/ids/entities/User.java @@ -2,18 +2,16 @@ import org.springframework.validation.annotation.Validated; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.Id; -import javax.persistence.IdClass; +import javax.persistence.*; import javax.validation.constraints.NotNull; -import java.io.Serializable; @Entity // This tells Hibernate to make a table out of this class @Validated -@IdClass(User.CompositeKey.class) public class User extends BaseEntity{ @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private int id; + @NotNull @Column(name = "user_id") private String userId; @@ -23,14 +21,14 @@ public class User extends BaseEntity{ @Column(name = "app_key") private String appKey; - @Id @NotNull - private String cid; + @Column(name = "company_id") + private int companyId; public User() {} - public User(String userId, String cid, String role) { + public User(String userId, int cid, String role) { this.userId = userId; - this.cid = cid; + this.companyId = cid; this.role = role; } @@ -58,32 +56,19 @@ public void setAppKey(String appKey) { this.appKey = appKey; } - public String getCid() { - return cid; + public int getCompanyId() { + return companyId; } - public void setCid(String cid) { - this.cid = cid; + public void setCompanyId(int cid) { + this.companyId = cid; } - static class CompositeKey implements Serializable { - private String cid; - private String userId; - - public String getCid() { - return cid; - } - - public void setCid(String cid) { - this.cid = cid; - } - - public String getUserId() { - return userId; - } + public int getId() { + return id; + } - public void setUserId(String userId) { - this.userId = userId; - } + public void setId(int id) { + this.id = id; } } diff --git a/src/main/java/com/rls/ids/models/SubordinateModel.java b/src/main/java/com/rls/ids/models/SubordinateModel.java index c473f4f..dd0b9af 100644 --- a/src/main/java/com/rls/ids/models/SubordinateModel.java +++ b/src/main/java/com/rls/ids/models/SubordinateModel.java @@ -1,17 +1,19 @@ package com.rls.ids.models; +import com.rls.ids.entities.User; + public class SubordinateModel { - private String userId; + private User user; - SubordinateModel(String userId) { - this.userId = userId; + SubordinateModel(User user) { + this.user = user; } - public String getUserId() { - return userId; + public User getUser() { + return user; } - public void setUserId(String userId) { - this.userId = userId; + public void setUser(User user) { + this.user = user; } } diff --git a/src/main/java/com/rls/ids/models/UserSignUpResponseModel.java b/src/main/java/com/rls/ids/models/UserSignUpResponseModel.java index ec7966a..3a07f11 100644 --- a/src/main/java/com/rls/ids/models/UserSignUpResponseModel.java +++ b/src/main/java/com/rls/ids/models/UserSignUpResponseModel.java @@ -9,12 +9,12 @@ public class UserSignUpResponseModel { private String userId; private String role; private String appKey; - private String companyId; + private int companyId; private List subordinates; public UserSignUpResponseModel(){} - public UserSignUpResponseModel(String userId, String role, String appKey, String companyId) { + public UserSignUpResponseModel(String userId, String role, String appKey, int companyId) { this.userId = userId; this.role = role; this.appKey = appKey; @@ -51,14 +51,14 @@ public List getSubordinates() { public void setSubordinates(List subordinates) { this.subordinates = new LinkedList<>(); - subordinates.forEach((user -> this.subordinates.add(new SubordinateModel(user.getUserId())))); + subordinates.forEach((user -> this.subordinates.add(new SubordinateModel(user)))); } - public String getCompanyId() { + public int getCompanyId() { return companyId; } - public void setCompanyId(String companyId) { + public void setCompanyId(int companyId) { this.companyId = companyId; } } diff --git a/src/main/java/com/rls/ids/repositories/UserRepository.java b/src/main/java/com/rls/ids/repositories/UserRepository.java index e7dfdb6..0029c02 100644 --- a/src/main/java/com/rls/ids/repositories/UserRepository.java +++ b/src/main/java/com/rls/ids/repositories/UserRepository.java @@ -1,19 +1,17 @@ package com.rls.ids.repositories; -import com.rls.ids.entities.Company; import com.rls.ids.entities.User; import org.hibernate.validator.constraints.UniqueElements; import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.transaction.annotation.Transactional; import javax.validation.constraints.NotNull; import java.util.List; public interface UserRepository extends JpaRepository, ExtendedUserRepository { User findUserByUserId(@NotNull @UniqueElements String userId); - User findUserByUserIdAndCid(@NotNull String userId, String cid); - User findUserByCid(String cid); - List findUsersByCidAndRole(String cid, String role); + User findUserByUserIdAndCompanyId(@NotNull String userId, int cid); + User findUserByCompanyId(int cid); + List findUsersByCompanyIdAndRole(int cid, String role); List findUsersByUserIdIsIn(String[] userId); User findUserByAppKey(String appKey); diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index b9ef588..c71e33e 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -17,16 +17,11 @@ spring: password: 12345678 initializationMode: always jpa: - hibernate: - ddl-auto: update - generate-ddl: true + hibernate.ddl-auto: validate show-sql: true - properties: - hibernate: + properties.hibernate: dialect: org.hibernate.dialect.MySQL5InnoDBDialect -logging: - level: - org: - hibernate: - stat: debug \ No newline at end of file +logging.level.org.hibernate: + SQL: debug + type.descriptor.sql.BasicBinder: TRACE diff --git a/src/main/resources/application-prod.yml b/src/main/resources/application-prod.yml index ae9cdbc..c63582a 100644 --- a/src/main/resources/application-prod.yml +++ b/src/main/resources/application-prod.yml @@ -15,17 +15,11 @@ spring: url: jdbc:mysql://localhost:3306/rlsstore username: rls password: 12345678 + initializationMode: always jpa: - hibernate: - ddl-auto: update - generate-ddl: true + hibernate.ddl-auto: validate show-sql: true - properties: - hibernate: - dialect: org.hibernate.dialect.MySQL5InnoDBDialect + properties.hibernate: + dialect: org.hibernate.dialect.MySQL5InnoDBDialect -logging: - level: - org: - hibernate: - stat: debug +logging.level.org.hibernate.stat: debug \ No newline at end of file diff --git a/src/main/resources/db/migration/V1__init.sql b/src/main/resources/db/migration/V1__init.sql new file mode 100644 index 0000000..043da4a --- /dev/null +++ b/src/main/resources/db/migration/V1__init.sql @@ -0,0 +1,28 @@ +CREATE TABLE `company` ( + `id` INT NOT NULL AUTO_INCREMENT COMMENT 'Primary key.', + `cid` varchar(255) NOT NULL COMMENT 'Unique id for this company. This is communicable among different services.', + `domain` varchar(255) NOT NULL COMMENT 'Unique domain for the company', + `name` varchar(255) NOT NULL COMMENT 'Name of the company', + `created_at` timestamp DEFAULT NULL COMMENT 'Time of creation of the entry', + `updated_at` timestamp DEFAULT NULL COMMENT 'Time of last update of any column', + `deleted_at` timestamp DEFAULT NULL COMMENT 'Time of soft delete', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_company_cid` (`cid`), + UNIQUE KEY `uk_company_domain` (`domain`) +) ENGINE=InnoDB CHARSET=utf8; + + +CREATE TABLE `user` ( + `id` INT NOT NULL AUTO_INCREMENT COMMENT 'Primary key.', + `company_id` INT NOT NULL COMMENT 'FK to the company', + `user_id` varchar(255) NOT NULL COMMENT 'Id of a user. Will be unique per company.', + `app_key` varchar(255) DEFAULT NULL, + `role` varchar(255) DEFAULT NULL, + `created_at` timestamp DEFAULT NULL COMMENT 'Time of creation of the entry', + `updated_at` timestamp DEFAULT NULL COMMENT 'Time of last update of any column', + `deleted_at` timestamp DEFAULT NULL COMMENT 'Time of soft delete', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_user_company_id_user_id` (`company_id`, `user_id`), + KEY `idx_user_company_id` (`company_id`), + CONSTRAINT `fk_user_company_id` FOREIGN KEY (`company_id`) REFERENCES `company` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION +) ENGINE=InnoDB CHARSET=utf8; \ No newline at end of file From f87ec91074ff51c8f19dc232edb5f4e35e3c4aea Mon Sep 17 00:00:00 2001 From: sazid Date: Mon, 24 Jun 2019 00:19:50 +0600 Subject: [PATCH 2/4] log level removed --- src/main/resources/application-prod.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/resources/application-prod.yml b/src/main/resources/application-prod.yml index c63582a..11537e8 100644 --- a/src/main/resources/application-prod.yml +++ b/src/main/resources/application-prod.yml @@ -21,5 +21,3 @@ spring: show-sql: true properties.hibernate: dialect: org.hibernate.dialect.MySQL5InnoDBDialect - -logging.level.org.hibernate.stat: debug \ No newline at end of file From a3c73a7b1701e711d737a53c86a7202c8a9da52b Mon Sep 17 00:00:00 2001 From: sazid Date: Tue, 25 Jun 2019 18:40:40 +0600 Subject: [PATCH 3/4] snake case json model. AppKey in header --- .../rls/ids/controllers/AppController.java | 36 ++++--- .../java/com/rls/ids/entities/BaseEntity.java | 3 + .../java/com/rls/ids/entities/Company.java | 13 +-- src/main/java/com/rls/ids/entities/User.java | 4 + .../com/rls/ids/entities/UserWithCompany.java | 45 +++++++++ .../exceptions/UserExceptionController.java | 5 + .../rls/ids/models/CompanyResponseModel.java | 27 +++--- .../rls/ids/models/SignUpRequestModel.java | 5 +- .../com/rls/ids/models/SubordinateModel.java | 19 ---- .../ids/models/UserResolveResponseModel.java | 93 +++++++++++++++++++ .../ids/models/UserSignUpResponseModel.java | 64 ------------- .../ids/repositories/CompanyRepository.java | 4 +- .../repositories/ExtendedUserRepository.java | 1 + .../ids/repositories/UserRepositoryImpl.java | 9 ++ src/main/resources/db/migration/V1__init.sql | 6 +- 15 files changed, 207 insertions(+), 127 deletions(-) create mode 100644 src/main/java/com/rls/ids/entities/UserWithCompany.java delete mode 100644 src/main/java/com/rls/ids/models/SubordinateModel.java create mode 100644 src/main/java/com/rls/ids/models/UserResolveResponseModel.java delete mode 100644 src/main/java/com/rls/ids/models/UserSignUpResponseModel.java diff --git a/src/main/java/com/rls/ids/controllers/AppController.java b/src/main/java/com/rls/ids/controllers/AppController.java index 5372f92..eb90b5a 100644 --- a/src/main/java/com/rls/ids/controllers/AppController.java +++ b/src/main/java/com/rls/ids/controllers/AppController.java @@ -8,7 +8,7 @@ import com.rls.ids.exceptions.MissingRequestParameterException; import com.rls.ids.models.CompanyResponseModel; import com.rls.ids.models.SignUpRequestModel; -import com.rls.ids.models.UserSignUpResponseModel; +import com.rls.ids.models.UserResolveResponseModel; import com.rls.ids.repositories.CompanyRepository; import com.rls.ids.repositories.UserRepository; import org.springframework.beans.factory.annotation.Autowired; @@ -45,7 +45,6 @@ public ResponseEntity companySignUp(@Valid @RequestBody Co if (isInvalid(secretKey) && !secretKey.equals(this.secretKey)) throw new MissingHeaderException(secretKey + " is missing or invalid."); - company.setCid(UUID.randomUUID().toString()); company = companyRepository.saveAndFlush(company); // Retrieve the saved company // company = companyRepository.getCompanyByCid(company.getCid()); @@ -57,13 +56,16 @@ public ResponseEntity companySignUp(@Valid @RequestBody Co admin.setAppKey(Base64.getEncoder().encodeToString(generator.generateKey().getEncoded())); admin = userRepository.save(admin); - CompanyResponseModel companyResponseModel = new CompanyResponseModel(company.getDomain(), company.getCid(), admin); + CompanyResponseModel companyResponseModel = new CompanyResponseModel(company, admin); return new ResponseEntity<>(companyResponseModel, HttpStatus.OK); } @RequestMapping(path="user/signup", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE) // Map ONLY POST Requests - public ResponseEntity userSignUp(@Valid @RequestBody SignUpRequestModel signUpModel) { - User admin = userRepository.getUserByAppKey(signUpModel.getAppKey()); + public ResponseEntity userSignUp(@Valid @RequestBody SignUpRequestModel signUpModel, @RequestHeader("AppKey") String appKey) { + if (appKey.isBlank()) { + appKey = signUpModel.getAppKey(); + } + User admin = userRepository.getUserByAppKey(appKey); if (admin == null) throw new InvalidAppKeyException(signUpModel.getAppKey()+" is invalid!"); @@ -75,19 +77,23 @@ public ResponseEntity userSignUp(@Valid @RequestBody SignUpRequestModel si } @RequestMapping(path="user/resolve", method = RequestMethod.GET) // Map ONLY POST Requests - public ResponseEntity resolveUser(@RequestParam String appKey) { + public ResponseEntity resolveUser(@RequestHeader("AppKey") String appKey) { if (isInvalid(appKey)) throw new MissingRequestParameterException(appKey + " is missing or invalid."); - User admin = userRepository.getUserByAppKey(appKey); - - if (admin == null) - throw new InvalidAppKeyException(appKey+" is invalid!"); - - UserSignUpResponseModel model = new UserSignUpResponseModel(admin.getUserId(), admin.getRole(), - admin.getAppKey(), admin.getCompanyId()); - model.setSubordinates(userRepository.findUsersByCompanyIdAndRole(admin.getCompanyId(), Role.USER)); - return new ResponseEntity<>(model, HttpStatus.OK); + try { +// List adminList = userRepository.getUserWithCompanyByAppKey(appKey); +// List admin = (List) adminList.get(0); + User admin = userRepository.getUserByAppKey(appKey); + Company company = companyRepository.getCompanyById(admin.getCompanyId()); + + UserResolveResponseModel model = new UserResolveResponseModel(admin.getUserId(), admin.getRole(), + company.getName(), company.getDomain()); + model.setSubordinates(userRepository.findUsersByCompanyIdAndRole(company.getId(), Role.USER)); + return new ResponseEntity<>(model, HttpStatus.OK); + } catch (Exception e) { + throw new InvalidAppKeyException(appKey+" is invalid!" + e.toString()); + } } private boolean isInvalid(String value) { diff --git a/src/main/java/com/rls/ids/entities/BaseEntity.java b/src/main/java/com/rls/ids/entities/BaseEntity.java index cb611c6..15c7ef2 100644 --- a/src/main/java/com/rls/ids/entities/BaseEntity.java +++ b/src/main/java/com/rls/ids/entities/BaseEntity.java @@ -1,5 +1,7 @@ package com.rls.ids.entities; +import com.fasterxml.jackson.databind.PropertyNamingStrategy; +import com.fasterxml.jackson.databind.annotation.JsonNaming; import org.hibernate.annotations.CreationTimestamp; import org.hibernate.annotations.UpdateTimestamp; import org.springframework.data.jpa.domain.support.AuditingEntityListener; @@ -12,6 +14,7 @@ @MappedSuperclass @EntityListeners({AuditingEntityListener.class}) +@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class) abstract class BaseEntity { @CreationTimestamp @Temporal(TemporalType.TIMESTAMP) diff --git a/src/main/java/com/rls/ids/entities/Company.java b/src/main/java/com/rls/ids/entities/Company.java index 456ea1d..c0ebc97 100644 --- a/src/main/java/com/rls/ids/entities/Company.java +++ b/src/main/java/com/rls/ids/entities/Company.java @@ -1,5 +1,7 @@ package com.rls.ids.entities; +import com.fasterxml.jackson.databind.PropertyNamingStrategy; +import com.fasterxml.jackson.databind.annotation.JsonNaming; import jdk.jfr.Timestamp; import org.springframework.validation.annotation.Validated; @@ -9,14 +11,13 @@ @Entity @Validated +@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class) public class Company extends BaseEntity { @Id @Column(name = "id") @GeneratedValue(strategy = GenerationType.IDENTITY) private int id; - private String cid; - @Column(unique = true, nullable = false) @NotBlank private String domain; @@ -50,14 +51,6 @@ public void setDeletedAt(Date deletedAt) { this.deletedAt = deletedAt; } - public String getCid() { - return cid; - } - - public void setCid(String cid) { - this.cid = cid; - } - public int getId() { return id; } diff --git a/src/main/java/com/rls/ids/entities/User.java b/src/main/java/com/rls/ids/entities/User.java index 3831cf7..fdb36f6 100644 --- a/src/main/java/com/rls/ids/entities/User.java +++ b/src/main/java/com/rls/ids/entities/User.java @@ -1,5 +1,7 @@ package com.rls.ids.entities; +import com.fasterxml.jackson.databind.PropertyNamingStrategy; +import com.fasterxml.jackson.databind.annotation.JsonNaming; import org.springframework.validation.annotation.Validated; import javax.persistence.*; @@ -7,6 +9,7 @@ @Entity // This tells Hibernate to make a table out of this class @Validated +@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class) public class User extends BaseEntity{ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @@ -23,6 +26,7 @@ public class User extends BaseEntity{ @NotNull @Column(name = "company_id") + @MapKey private int companyId; public User() {} diff --git a/src/main/java/com/rls/ids/entities/UserWithCompany.java b/src/main/java/com/rls/ids/entities/UserWithCompany.java new file mode 100644 index 0000000..e729b42 --- /dev/null +++ b/src/main/java/com/rls/ids/entities/UserWithCompany.java @@ -0,0 +1,45 @@ +package com.rls.ids.entities; + +import com.fasterxml.jackson.databind.PropertyNamingStrategy; +import com.fasterxml.jackson.databind.annotation.JsonNaming; + +@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class) +public class UserWithCompany { + private String userId; + private String role; + + private String domain; + private String companyName; + + public String getUserId() { + return userId; + } + + public void setUserId(String userId) { + this.userId = userId; + } + + public String getRole() { + return role; + } + + public void setRole(String role) { + this.role = role; + } + + public String getDomain() { + return domain; + } + + public void setDomain(String domain) { + this.domain = domain; + } + + public String getCompanyName() { + return companyName; + } + + public void setCompanyName(String companyName) { + this.companyName = companyName; + } +} diff --git a/src/main/java/com/rls/ids/exceptions/UserExceptionController.java b/src/main/java/com/rls/ids/exceptions/UserExceptionController.java index 0e6656e..5e9a142 100644 --- a/src/main/java/com/rls/ids/exceptions/UserExceptionController.java +++ b/src/main/java/com/rls/ids/exceptions/UserExceptionController.java @@ -42,4 +42,9 @@ public ResponseEntity exception(UnsupportedPayloadTypeException exceptio public ResponseEntity exception(UnsupportedSearchParameter exception) { return new ResponseEntity<>(exception.getMessage(), HttpStatus.BAD_REQUEST); } + + @ExceptionHandler(value = InvalidAppKeyException.class) + public ResponseEntity exception(InvalidAppKeyException exception) { + return new ResponseEntity<>(exception.getMessage(), HttpStatus.BAD_REQUEST); + } } diff --git a/src/main/java/com/rls/ids/models/CompanyResponseModel.java b/src/main/java/com/rls/ids/models/CompanyResponseModel.java index 9a88f01..0f1ea96 100644 --- a/src/main/java/com/rls/ids/models/CompanyResponseModel.java +++ b/src/main/java/com/rls/ids/models/CompanyResponseModel.java @@ -1,28 +1,25 @@ package com.rls.ids.models; +import com.fasterxml.jackson.databind.PropertyNamingStrategy; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import com.rls.ids.entities.Company; import com.rls.ids.entities.User; +@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class) public class CompanyResponseModel { private String domain; private String companyId; + private String companyName; private User admin; public CompanyResponseModel() { } - public CompanyResponseModel(String domain, String companyId, User admin) { - this.domain = domain; - this.companyId = companyId; + public CompanyResponseModel(Company company, User admin) { + this.domain = company.getDomain(); + this.companyName = company.getName(); this.admin = admin; } - public String getCompanyId() { - return companyId; - } - - public void setCompanyId(String companyId) { - this.companyId = companyId; - } - public String getDomain() { return domain; } @@ -38,4 +35,12 @@ public User getAdmin() { public void setAdmin(User admin) { this.admin = admin; } + + public String getCompanyName() { + return companyName; + } + + public void setCompanyName(String companyName) { + this.companyName = companyName; + } } diff --git a/src/main/java/com/rls/ids/models/SignUpRequestModel.java b/src/main/java/com/rls/ids/models/SignUpRequestModel.java index 35f3a0c..b01ca7e 100644 --- a/src/main/java/com/rls/ids/models/SignUpRequestModel.java +++ b/src/main/java/com/rls/ids/models/SignUpRequestModel.java @@ -1,9 +1,12 @@ package com.rls.ids.models; +import com.fasterxml.jackson.databind.PropertyNamingStrategy; +import com.fasterxml.jackson.databind.annotation.JsonNaming; + import javax.validation.constraints.NotBlank; +@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class) public class SignUpRequestModel { - @NotBlank private String appKey; @NotBlank private String userId; diff --git a/src/main/java/com/rls/ids/models/SubordinateModel.java b/src/main/java/com/rls/ids/models/SubordinateModel.java deleted file mode 100644 index dd0b9af..0000000 --- a/src/main/java/com/rls/ids/models/SubordinateModel.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.rls.ids.models; - -import com.rls.ids.entities.User; - -public class SubordinateModel { - private User user; - - SubordinateModel(User user) { - this.user = user; - } - - public User getUser() { - return user; - } - - public void setUser(User user) { - this.user = user; - } -} diff --git a/src/main/java/com/rls/ids/models/UserResolveResponseModel.java b/src/main/java/com/rls/ids/models/UserResolveResponseModel.java new file mode 100644 index 0000000..8d355d2 --- /dev/null +++ b/src/main/java/com/rls/ids/models/UserResolveResponseModel.java @@ -0,0 +1,93 @@ +package com.rls.ids.models; + +import com.fasterxml.jackson.databind.PropertyNamingStrategy; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import com.rls.ids.entities.User; + +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class) +public class UserResolveResponseModel { + private String companyName; + private int companyId; + private String domain; + private String userId; + private String role; + private List subordinates; + + public UserResolveResponseModel(){} + + public UserResolveResponseModel(List adminWithCompany) { + for (Map.Entry entry: adminWithCompany){ + if ("company_name".equals(entry.getKey())) { + companyName = (String) entry.getValue(); + } else if ("domain".equals(entry.getKey())) { + domain = (String) entry.getValue(); + } else if ("user_id".equals(entry.getKey())) { + userId = (String) entry.getValue(); + } else if ("role".equals(entry.getKey())) { + role = (String) entry.getValue(); + } else if ("company_id".equals(entry.getKey())) { + companyId = (int) entry.getValue(); + } + } + } + + public UserResolveResponseModel(String userId, String role, String companyName, String domain) { + this.userId = userId; + this.role = role; + this.companyName = companyName; + this.domain = domain; + } + + public String getUserId() { + return userId; + } + + public void setUserId(String userId) { + this.userId = userId; + } + + public String getRole() { + return role; + } + + public void setRole(String role) { + this.role = role; + } + + public List getSubordinates() { + return subordinates; + } + + public void setSubordinates(List subordinates) { + this.subordinates = new LinkedList<>(); + this.subordinates.addAll(subordinates); + } + + public String getCompanyName() { + return companyName; + } + + public void setCompanyName(String companyName) { + this.companyName = companyName; + } + + public String getDomain() { + return domain; + } + + public void setDomain(String domain) { + this.domain = domain; + } + + public int getCompanyId() { + return companyId; + } + + public void setCompanyId(int companyId) { + this.companyId = companyId; + } +} diff --git a/src/main/java/com/rls/ids/models/UserSignUpResponseModel.java b/src/main/java/com/rls/ids/models/UserSignUpResponseModel.java deleted file mode 100644 index 3a07f11..0000000 --- a/src/main/java/com/rls/ids/models/UserSignUpResponseModel.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.rls.ids.models; - -import com.rls.ids.entities.User; - -import java.util.LinkedList; -import java.util.List; - -public class UserSignUpResponseModel { - private String userId; - private String role; - private String appKey; - private int companyId; - private List subordinates; - - public UserSignUpResponseModel(){} - - public UserSignUpResponseModel(String userId, String role, String appKey, int companyId) { - this.userId = userId; - this.role = role; - this.appKey = appKey; - this.companyId = companyId; - } - - public String getUserId() { - return userId; - } - - public void setUserId(String userId) { - this.userId = userId; - } - - public String getRole() { - return role; - } - - public void setRole(String role) { - this.role = role; - } - - public String getAppKey() { - return appKey; - } - - public void setAppKey(String appKey) { - this.appKey = appKey; - } - - public List getSubordinates() { - return subordinates; - } - - public void setSubordinates(List subordinates) { - this.subordinates = new LinkedList<>(); - subordinates.forEach((user -> this.subordinates.add(new SubordinateModel(user)))); - } - - public int getCompanyId() { - return companyId; - } - - public void setCompanyId(int companyId) { - this.companyId = companyId; - } -} diff --git a/src/main/java/com/rls/ids/repositories/CompanyRepository.java b/src/main/java/com/rls/ids/repositories/CompanyRepository.java index 7e1ffa2..a678f15 100644 --- a/src/main/java/com/rls/ids/repositories/CompanyRepository.java +++ b/src/main/java/com/rls/ids/repositories/CompanyRepository.java @@ -1,11 +1,9 @@ package com.rls.ids.repositories; import com.rls.ids.entities.Company; -import com.rls.ids.entities.User; import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.transaction.annotation.Transactional; public interface CompanyRepository extends JpaRepository { // @Transactional(readOnly = true) - Company getCompanyByCid(String cid); + Company getCompanyById(int id); } diff --git a/src/main/java/com/rls/ids/repositories/ExtendedUserRepository.java b/src/main/java/com/rls/ids/repositories/ExtendedUserRepository.java index cec2651..82b269d 100644 --- a/src/main/java/com/rls/ids/repositories/ExtendedUserRepository.java +++ b/src/main/java/com/rls/ids/repositories/ExtendedUserRepository.java @@ -6,4 +6,5 @@ public interface ExtendedUserRepository { List findAllPaged(MultiValueMap requestParams); + List getUserWithCompanyByAppKey(String appKey); } diff --git a/src/main/java/com/rls/ids/repositories/UserRepositoryImpl.java b/src/main/java/com/rls/ids/repositories/UserRepositoryImpl.java index 7f193ba..369f4f5 100644 --- a/src/main/java/com/rls/ids/repositories/UserRepositoryImpl.java +++ b/src/main/java/com/rls/ids/repositories/UserRepositoryImpl.java @@ -6,6 +6,7 @@ import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; +import javax.persistence.Query; import java.util.List; @SuppressWarnings("unused") @@ -20,4 +21,12 @@ public List findAllPaged(MultiValueMap requestParams) { return em.createNativeQuery(query, User.class).getResultList(); } + + @Override + public List getUserWithCompanyByAppKey(String appKey) { + String query = "SELECT u.user_id, u.role, c.name AS company_name, c.id AS company_id, c.domain FROM user u JOIN company c WHERE app_key='"+appKey+"'"; + + Query queryObj = em.createNativeQuery(query); + return queryObj.getResultList(); + } } diff --git a/src/main/resources/db/migration/V1__init.sql b/src/main/resources/db/migration/V1__init.sql index 043da4a..f1aeb7b 100644 --- a/src/main/resources/db/migration/V1__init.sql +++ b/src/main/resources/db/migration/V1__init.sql @@ -1,13 +1,11 @@ CREATE TABLE `company` ( `id` INT NOT NULL AUTO_INCREMENT COMMENT 'Primary key.', - `cid` varchar(255) NOT NULL COMMENT 'Unique id for this company. This is communicable among different services.', `domain` varchar(255) NOT NULL COMMENT 'Unique domain for the company', `name` varchar(255) NOT NULL COMMENT 'Name of the company', `created_at` timestamp DEFAULT NULL COMMENT 'Time of creation of the entry', `updated_at` timestamp DEFAULT NULL COMMENT 'Time of last update of any column', `deleted_at` timestamp DEFAULT NULL COMMENT 'Time of soft delete', PRIMARY KEY (`id`), - UNIQUE KEY `uk_company_cid` (`cid`), UNIQUE KEY `uk_company_domain` (`domain`) ) ENGINE=InnoDB CHARSET=utf8; @@ -16,8 +14,8 @@ CREATE TABLE `user` ( `id` INT NOT NULL AUTO_INCREMENT COMMENT 'Primary key.', `company_id` INT NOT NULL COMMENT 'FK to the company', `user_id` varchar(255) NOT NULL COMMENT 'Id of a user. Will be unique per company.', - `app_key` varchar(255) DEFAULT NULL, - `role` varchar(255) DEFAULT NULL, + `app_key` varchar(255) DEFAULT NULL COMMENT 'AppKey is used to authenticate the user. Can be NULL for regular user. Must be unique and non NULL per admin user.', + `role` varchar(255) DEFAULT NULL COMMENT 'User role is used to authorize the user.', `created_at` timestamp DEFAULT NULL COMMENT 'Time of creation of the entry', `updated_at` timestamp DEFAULT NULL COMMENT 'Time of last update of any column', `deleted_at` timestamp DEFAULT NULL COMMENT 'Time of soft delete', From 44107a9eb4a0070e98a78bdadfa0b7696cb129be Mon Sep 17 00:00:00 2001 From: sazid Date: Tue, 16 Jul 2019 12:06:47 +0600 Subject: [PATCH 4/4] docker-compose and logback configuration --- .idea/modules/rls42.ID-Service.main.iml | 2 +- build.gradle | 2 +- docker-compose.yml | 19 +++++++- src/main/resources/application.yml | 9 ++++ src/main/resources/logback-spring.xml | 64 +++++++++++++++++++++++++ 5 files changed, 92 insertions(+), 4 deletions(-) create mode 100644 src/main/resources/logback-spring.xml diff --git a/.idea/modules/rls42.ID-Service.main.iml b/.idea/modules/rls42.ID-Service.main.iml index 1d782d9..62b2410 100644 --- a/.idea/modules/rls42.ID-Service.main.iml +++ b/.idea/modules/rls42.ID-Service.main.iml @@ -71,8 +71,8 @@ - + diff --git a/build.gradle b/build.gradle index 87ab50f..1e0b148 100644 --- a/build.gradle +++ b/build.gradle @@ -23,7 +23,7 @@ apply plugin: 'com.palantir.docker' bootJar { baseName = 'id-service' - version = '0.1.0' + version = '1.0.0' } repositories { diff --git a/docker-compose.yml b/docker-compose.yml index 47473dc..df5ab74 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -7,8 +7,23 @@ services: - "./db_data:/var/lib/mysql" environment: - "MYSQL_ROOT_PASSWORD=root" - - "MYSQL_DATABASE=rlsstore" - - "MYSQL_USER=rls" + - "MYSQL_DATABASE=ids_db" + - "MYSQL_USER=ids_user" - "MYSQL_PASSWORD=12345678" ports: - "3306:3306" + + id_service: + container_name: id_service + image: rls42/id-service:1.0.0 + volumes: + - "./initdb.sql:/app/initdb.sql" + - - "./logs:/app/lib/logs" + environment: + - "SERVER_PORT=7001" + - "SPRING_PROFILES_ACTIVE=dev" + - "SPRING_DATASOURCE_URL=jdbc:mysql://localhost:3306/ids_db" + - "SPRING_DATASOURCE_USERNAME=ids_user" + - "SPRING_DATASOURCE_PASSWORD=12345678" + ports: + - "7001:7001" diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 3d7808a..2a3f240 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -1,3 +1,12 @@ spring: profiles: active: dev + +logging: + level: + org.springframework: ERROR + com.rls: DEBUG + pattern: + console: "%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" + file: "%d %p %c{1.} [%t] %m%n" + file: logs/app.log \ No newline at end of file diff --git a/src/main/resources/logback-spring.xml b/src/main/resources/logback-spring.xml new file mode 100644 index 0000000..8711f9d --- /dev/null +++ b/src/main/resources/logback-spring.xml @@ -0,0 +1,64 @@ + + +   +      + +   +      + +          + +              + %black(%d{ISO8601}) %highlight(%-5level) [%blue(%t)] %yellow(%C{1.}): %msg%n%throwable +          + +      + +      + +          + ${LOGS}/id-service.log +          + +              + %d %p %C{1.} [%t] %m%n +          + +   +          + +              +              + ${LOGS}/id-service-%d{yyyy-MM-dd}.%i.log +              + +                  + 10MB +              + +          + +      + +       +      +      + +          + +          + +      + +   +      +      + +          + +          + +      + +   + \ No newline at end of file