From 98b4545af08043e4069c4b291798e5c826246a48 Mon Sep 17 00:00:00 2001 From: Vinay Venu Date: Fri, 14 Jun 2024 13:06:29 +0530 Subject: [PATCH] #733 | Multiple changes (Refactoring) Split Metabase repositories based on domain. Change some interfaces to use objects instead of ids. Remove RestTemplate class Add stub test class --- .../server/config/RestTemplateConfig.java | 23 ----- .../avni/server/dao/MetabaseRepository.java | 98 ------------------- .../dao/metabase/BaseMetabaseRepository.java | 44 +++++++++ .../dao/metabase/CollectionRepository.java | 20 ++++ .../dao/metabase/DatabaseRepository.java | 21 ++++ .../dao/metabase/MetabaseRepository.java | 53 ++++++++++ .../dao/metabase/PermissionsRepository.java | 4 + .../server/domain/metabase/AvniDatabase.java | 31 ++++++ .../avni/server/domain/metabase/Database.java | 9 ++ .../domain/metabase/DatabaseDetails.java | 6 +- .../domain/metabase/DatabaseResponse.java | 13 --- .../avni/server/service/MetabaseService.java | 49 ++++------ .../avni/server/web/MetabaseController.java | 7 +- .../MetabaseControllerIntegrationTest.java | 4 + .../src/test/resources/application.properties | 5 +- 15 files changed, 218 insertions(+), 169 deletions(-) delete mode 100644 avni-server-api/src/main/java/org/avni/server/config/RestTemplateConfig.java delete mode 100644 avni-server-api/src/main/java/org/avni/server/dao/MetabaseRepository.java create mode 100644 avni-server-api/src/main/java/org/avni/server/dao/metabase/BaseMetabaseRepository.java create mode 100644 avni-server-api/src/main/java/org/avni/server/dao/metabase/CollectionRepository.java create mode 100644 avni-server-api/src/main/java/org/avni/server/dao/metabase/DatabaseRepository.java create mode 100644 avni-server-api/src/main/java/org/avni/server/dao/metabase/MetabaseRepository.java create mode 100644 avni-server-api/src/main/java/org/avni/server/dao/metabase/PermissionsRepository.java create mode 100644 avni-server-api/src/main/java/org/avni/server/domain/metabase/AvniDatabase.java delete mode 100644 avni-server-api/src/main/java/org/avni/server/domain/metabase/DatabaseResponse.java create mode 100644 avni-server-api/src/test/java/org/avni/server/web/MetabaseControllerIntegrationTest.java diff --git a/avni-server-api/src/main/java/org/avni/server/config/RestTemplateConfig.java b/avni-server-api/src/main/java/org/avni/server/config/RestTemplateConfig.java deleted file mode 100644 index dc176f158..000000000 --- a/avni-server-api/src/main/java/org/avni/server/config/RestTemplateConfig.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.avni.server.config; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.http.client.ClientHttpRequestFactory; -import org.springframework.http.client.SimpleClientHttpRequestFactory; -import org.springframework.web.client.RestTemplate; - -@Configuration -public class RestTemplateConfig { - - @Bean - public RestTemplate restTemplate() { - return new RestTemplate(clientHttpRequestFactory()); - } - private ClientHttpRequestFactory clientHttpRequestFactory() { - SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory(); - factory.setConnectTimeout(30000); // 30 seconds connection timeout - factory.setReadTimeout(300000); // 5 minutes read timeout - return factory; - } - -} diff --git a/avni-server-api/src/main/java/org/avni/server/dao/MetabaseRepository.java b/avni-server-api/src/main/java/org/avni/server/dao/MetabaseRepository.java deleted file mode 100644 index f71865c7f..000000000 --- a/avni-server-api/src/main/java/org/avni/server/dao/MetabaseRepository.java +++ /dev/null @@ -1,98 +0,0 @@ -package org.avni.server.dao; - -import org.avni.server.domain.metabase.Collection; -import org.avni.server.domain.metabase.CollectionPermissions; -import org.avni.server.domain.metabase.CollectionResponse; -import org.avni.server.domain.metabase.Database; -import org.avni.server.domain.metabase.DatabaseResponse; -import org.avni.server.domain.metabase.Permissions; -import org.avni.server.domain.metabase.PermissionsGroup; -import org.avni.server.domain.metabase.PermissionsGroupResponse; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpMethod; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.stereotype.Repository; -import org.springframework.web.client.RestTemplate; - -import java.util.Map; - -@Repository -public class MetabaseRepository { - - private final RestTemplate restTemplate; - - @Value("${metabase.api.key}") - private String apiKey; - - @Value("${metabase.api.url}") - private String metabaseApiUrl; - - public MetabaseRepository(RestTemplate restTemplate) { - this.restTemplate = restTemplate; - } - - public int createDatabase(Database database) { - String url = metabaseApiUrl + "/database"; - HttpEntity entity = createHttpEntity(database); - DatabaseResponse response = restTemplate.postForObject(url, entity, DatabaseResponse.class); - return response.getId(); - } - - public int createCollection(Collection collection) { - String url = metabaseApiUrl + "/collection"; - HttpEntity entity = createHttpEntity(collection); - CollectionResponse response = restTemplate.postForObject(url, entity, CollectionResponse.class); - return response.getId(); - } - - public int createPermissionsGroup(PermissionsGroup permissionsGroup) { - String url = metabaseApiUrl + "/permissions/group"; - HttpEntity entity = createHttpEntity(permissionsGroup); - PermissionsGroupResponse response = restTemplate.postForObject(url, entity, PermissionsGroupResponse.class); - return response.getId(); - } - - public Map getPermissionsGraph() { - String url = metabaseApiUrl + "/permissions/graph"; - ResponseEntity response = restTemplate.exchange(url, HttpMethod.GET, createHttpEntity(null), Map.class); - return response.getBody(); - } - - public Map getCollectionPermissionsGraph() { - String url = metabaseApiUrl + "/collection/graph"; - ResponseEntity response = restTemplate.exchange(url, HttpMethod.GET, createHttpEntity(null), Map.class); - return response.getBody(); - } - - public void assignDatabasePermissions(Permissions permissions, int groupId, int databaseId) { - permissions.updatePermissionsGraph(groupId, databaseId); - String url = metabaseApiUrl + "/permissions/graph"; - sendPutRequest(url, permissions.getPermissionsGraph()); - } - - public void updateCollectionPermissions(CollectionPermissions collectionPermissions, int groupId, int collectionId) { - collectionPermissions.updatePermissionsGraph(groupId, collectionId); - String url = metabaseApiUrl + "/collection/graph"; - sendPutRequest(url, collectionPermissions.getPermissionsGraph()); - } - - private HttpHeaders getHeaders() { - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.APPLICATION_JSON); - headers.set("x-api-key", apiKey); - return headers; - } - - private HttpEntity createHttpEntity(T body) { - HttpHeaders headers = getHeaders(); - return new HttpEntity<>(body, headers); - } - - private void sendPutRequest(String url, Map requestBody) { - HttpEntity> entity = createHttpEntity(requestBody); - restTemplate.exchange(url, HttpMethod.PUT, entity, Map.class); - } -} diff --git a/avni-server-api/src/main/java/org/avni/server/dao/metabase/BaseMetabaseRepository.java b/avni-server-api/src/main/java/org/avni/server/dao/metabase/BaseMetabaseRepository.java new file mode 100644 index 000000000..780989568 --- /dev/null +++ b/avni-server-api/src/main/java/org/avni/server/dao/metabase/BaseMetabaseRepository.java @@ -0,0 +1,44 @@ +package org.avni.server.dao.metabase; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.web.client.RestTemplateBuilder; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Repository; +import org.springframework.web.client.RestTemplate; + +import java.util.Map; + +@Repository +public class BaseMetabaseRepository { + protected final RestTemplate restTemplate; + + @Value("${metabase.api.url}") + protected String metabaseApiUrl; + + @Value("${metabase.api.key}") + private String apiKey; + + public BaseMetabaseRepository(RestTemplateBuilder restTemplateBuilder) { + this.restTemplate = restTemplateBuilder.build(); + } + + private HttpHeaders getHeaders() { + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + headers.set("x-api-key", apiKey); + return headers; + } + + protected HttpEntity createHttpEntity(T body) { + HttpHeaders headers = getHeaders(); + return new HttpEntity<>(body, headers); + } + + protected void sendPutRequest(String url, Map requestBody) { + HttpEntity> entity = createHttpEntity(requestBody); + restTemplate.exchange(url, HttpMethod.PUT, entity, Map.class); + } +} diff --git a/avni-server-api/src/main/java/org/avni/server/dao/metabase/CollectionRepository.java b/avni-server-api/src/main/java/org/avni/server/dao/metabase/CollectionRepository.java new file mode 100644 index 000000000..17d709e46 --- /dev/null +++ b/avni-server-api/src/main/java/org/avni/server/dao/metabase/CollectionRepository.java @@ -0,0 +1,20 @@ +package org.avni.server.dao.metabase; + +import org.avni.server.domain.metabase.Collection; +import org.avni.server.domain.metabase.CollectionResponse; +import org.springframework.boot.web.client.RestTemplateBuilder; +import org.springframework.http.HttpEntity; + +public class CollectionRepository extends MetabaseRepository{ + public CollectionRepository(RestTemplateBuilder restTemplateBuilder) { + super(restTemplateBuilder); + } + + public CollectionResponse save(Collection collection) { + String url = metabaseApiUrl + "/collection"; + HttpEntity entity = createHttpEntity(collection); + CollectionResponse response = restTemplate.postForObject(url, entity, CollectionResponse.class); + + return response; + } +} diff --git a/avni-server-api/src/main/java/org/avni/server/dao/metabase/DatabaseRepository.java b/avni-server-api/src/main/java/org/avni/server/dao/metabase/DatabaseRepository.java new file mode 100644 index 000000000..3b5971829 --- /dev/null +++ b/avni-server-api/src/main/java/org/avni/server/dao/metabase/DatabaseRepository.java @@ -0,0 +1,21 @@ +package org.avni.server.dao.metabase; + +import org.avni.server.domain.metabase.Database; +import org.springframework.boot.web.client.RestTemplateBuilder; +import org.springframework.http.HttpEntity; +import org.springframework.stereotype.Repository; + +@Repository +public class DatabaseRepository extends MetabaseRepository{ + public DatabaseRepository(RestTemplateBuilder restTemplateBuilder) { + super(restTemplateBuilder); + } + + public Database save(Database database) { + String url = metabaseApiUrl + "/database"; + HttpEntity entity = createHttpEntity(database); + Database response = restTemplate.postForObject(url, entity, Database.class); + + return new Database(response.getId(), database.getName(), database.getEngine(), database.getDetails()); + } +} diff --git a/avni-server-api/src/main/java/org/avni/server/dao/metabase/MetabaseRepository.java b/avni-server-api/src/main/java/org/avni/server/dao/metabase/MetabaseRepository.java new file mode 100644 index 000000000..f0850a1e8 --- /dev/null +++ b/avni-server-api/src/main/java/org/avni/server/dao/metabase/MetabaseRepository.java @@ -0,0 +1,53 @@ +package org.avni.server.dao.metabase; + +import org.avni.server.domain.metabase.CollectionPermissions; +import org.avni.server.domain.metabase.Permissions; +import org.avni.server.domain.metabase.PermissionsGroup; +import org.avni.server.domain.metabase.PermissionsGroupResponse; +import org.springframework.boot.web.client.RestTemplateBuilder; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Repository; + +import java.util.Map; + +@Repository +public class MetabaseRepository extends BaseMetabaseRepository{ + + public MetabaseRepository(RestTemplateBuilder restTemplateBuilder) { + super(restTemplateBuilder); + } + + public PermissionsGroupResponse createPermissionsGroup(PermissionsGroup permissionsGroup) { + String url = metabaseApiUrl + "/permissions/group"; + HttpEntity entity = createHttpEntity(permissionsGroup); + PermissionsGroupResponse response = restTemplate.postForObject(url, entity, PermissionsGroupResponse.class); + + return response; + } + + public Map getPermissionsGraph() { + String url = metabaseApiUrl + "/permissions/graph"; + ResponseEntity response = restTemplate.exchange(url, HttpMethod.GET, createHttpEntity(null), Map.class); + return response.getBody(); + } + + public Map getCollectionPermissionsGraph() { + String url = metabaseApiUrl + "/collection/graph"; + ResponseEntity response = restTemplate.exchange(url, HttpMethod.GET, createHttpEntity(null), Map.class); + return response.getBody(); + } + + public void assignDatabasePermissions(Permissions permissions, int groupId, int databaseId) { + permissions.updatePermissionsGraph(groupId, databaseId); + String url = metabaseApiUrl + "/permissions/graph"; + sendPutRequest(url, permissions.getPermissionsGraph()); + } + + public void updateCollectionPermissions(CollectionPermissions collectionPermissions, int groupId, int collectionId) { + collectionPermissions.updatePermissionsGraph(groupId, collectionId); + String url = metabaseApiUrl + "/collection/graph"; + sendPutRequest(url, collectionPermissions.getPermissionsGraph()); + } +} diff --git a/avni-server-api/src/main/java/org/avni/server/dao/metabase/PermissionsRepository.java b/avni-server-api/src/main/java/org/avni/server/dao/metabase/PermissionsRepository.java new file mode 100644 index 000000000..58e9fe476 --- /dev/null +++ b/avni-server-api/src/main/java/org/avni/server/dao/metabase/PermissionsRepository.java @@ -0,0 +1,4 @@ +package org.avni.server.dao.metabase; + +public class PermissionsRepository { +} diff --git a/avni-server-api/src/main/java/org/avni/server/domain/metabase/AvniDatabase.java b/avni-server-api/src/main/java/org/avni/server/domain/metabase/AvniDatabase.java new file mode 100644 index 000000000..d06f48b1e --- /dev/null +++ b/avni-server-api/src/main/java/org/avni/server/domain/metabase/AvniDatabase.java @@ -0,0 +1,31 @@ +package org.avni.server.domain.metabase; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +@Component +public class AvniDatabase { + @Value("${avni.database.server}") + private String avniDatabaseServer; + + @Value("${avni.database.port}") + private String avniDatabasePort; + + @Value("${avni.database}") + private String avniDatabaseName; + + public AvniDatabase() { + } + + public String getAvniDatabaseServer() { + return avniDatabaseServer; + } + + public String getAvniDatabasePort() { + return avniDatabasePort; + } + + public String getAvniDatabaseName() { + return avniDatabaseName; + } +} diff --git a/avni-server-api/src/main/java/org/avni/server/domain/metabase/Database.java b/avni-server-api/src/main/java/org/avni/server/domain/metabase/Database.java index c8c60ed44..82e4fd36e 100644 --- a/avni-server-api/src/main/java/org/avni/server/domain/metabase/Database.java +++ b/avni-server-api/src/main/java/org/avni/server/domain/metabase/Database.java @@ -1,16 +1,25 @@ package org.avni.server.domain.metabase; public class Database { + private final Integer id; private String name; private String engine; private DatabaseDetails details; public Database(String name, String engine, DatabaseDetails details) { + this(null, name, engine, details); + } + + public Database(Integer id, String name, String engine, DatabaseDetails details) { + this.id = id; this.name = name; this.engine = engine; this.details = details; } + public Integer getId() { + return id; + } public String getName() { return name; } diff --git a/avni-server-api/src/main/java/org/avni/server/domain/metabase/DatabaseDetails.java b/avni-server-api/src/main/java/org/avni/server/domain/metabase/DatabaseDetails.java index a17b4df3a..9950d988a 100644 --- a/avni-server-api/src/main/java/org/avni/server/domain/metabase/DatabaseDetails.java +++ b/avni-server-api/src/main/java/org/avni/server/domain/metabase/DatabaseDetails.java @@ -13,7 +13,10 @@ public DatabaseDetails(String host, String port, String db, String user) { this.user = user; } - + public DatabaseDetails(AvniDatabase avniDatabase, String dbUser) { + this(avniDatabase.getAvniDatabaseServer(), avniDatabase.getAvniDatabasePort(), avniDatabase.getAvniDatabaseName(), dbUser); + } + public String getHost() { return host; } @@ -32,4 +35,3 @@ public String getUser() { } - \ No newline at end of file diff --git a/avni-server-api/src/main/java/org/avni/server/domain/metabase/DatabaseResponse.java b/avni-server-api/src/main/java/org/avni/server/domain/metabase/DatabaseResponse.java deleted file mode 100644 index 651991747..000000000 --- a/avni-server-api/src/main/java/org/avni/server/domain/metabase/DatabaseResponse.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.avni.server.domain.metabase; - -public class DatabaseResponse { - private int id; - - public int getId() { - return id; - } - - public void setId(int id) { - this.id = id; - } -} diff --git a/avni-server-api/src/main/java/org/avni/server/service/MetabaseService.java b/avni-server-api/src/main/java/org/avni/server/service/MetabaseService.java index 019bc4ea7..b0eac9ab8 100644 --- a/avni-server-api/src/main/java/org/avni/server/service/MetabaseService.java +++ b/avni-server-api/src/main/java/org/avni/server/service/MetabaseService.java @@ -1,14 +1,11 @@ package org.avni.server.service; -import org.avni.server.dao.MetabaseRepository; +import org.avni.server.dao.metabase.CollectionRepository; +import org.avni.server.dao.metabase.DatabaseRepository; +import org.avni.server.dao.metabase.MetabaseRepository; import org.avni.server.domain.Organisation; -import org.avni.server.domain.metabase.Collection; -import org.avni.server.domain.metabase.CollectionPermissions; -import org.avni.server.domain.metabase.Database; -import org.avni.server.domain.metabase.DatabaseDetails; -import org.avni.server.domain.metabase.Permissions; -import org.avni.server.domain.metabase.PermissionsGroup; -import org.springframework.beans.factory.annotation.Value; +import org.avni.server.domain.metabase.*; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service @@ -16,21 +13,18 @@ public class MetabaseService { private final MetabaseRepository metabaseRepository; private final OrganisationService organisationService; + private final AvniDatabase avniDatabase; + private final String POSTGRES = "postgres"; + private DatabaseRepository databaseRepository; + private CollectionRepository collectionRepository; - @Value("${avni.database.server}") - private String avniDatabaseServer; - - @Value("${avni.database.port}") - private String avniDatabasePort; - - @Value("${avni.database}") - private String avniDatabaseName; - - private final String DB_ENGINE = "postgres"; - - public MetabaseService(MetabaseRepository metabaseRepository, OrganisationService organisationService) { + @Autowired + public MetabaseService(MetabaseRepository metabaseRepository, OrganisationService organisationService, AvniDatabase avniDatabase, DatabaseRepository databaseRepository, CollectionRepository collectionRepository) { this.metabaseRepository = metabaseRepository; this.organisationService = organisationService; + this.avniDatabase = avniDatabase; + this.databaseRepository = databaseRepository; + this.collectionRepository = collectionRepository; } public void setupMetabase() { @@ -38,19 +32,16 @@ public void setupMetabase() { String name = currentOrganisation.getName(); String dbUser = currentOrganisation.getDbUser(); - DatabaseDetails databaseDetails = new DatabaseDetails(avniDatabaseServer, avniDatabasePort, avniDatabaseName, dbUser); - Database database = new Database(name, DB_ENGINE, databaseDetails); - Collection collection = new Collection(name, name + " collection"); - PermissionsGroup permissionsGroup = new PermissionsGroup(name); + Database database = databaseRepository.save(new Database(name, POSTGRES, new DatabaseDetails(avniDatabase, dbUser))); + CollectionResponse metabaseCollection = collectionRepository.save(new Collection(name, name + " collection")); - int databaseId = metabaseRepository.createDatabase(database); - int collectionId = metabaseRepository.createCollection(collection); - int groupId = metabaseRepository.createPermissionsGroup(permissionsGroup); + PermissionsGroup permissionsGroup = new PermissionsGroup(name); + PermissionsGroupResponse metabasePermissionsGroup = metabaseRepository.createPermissionsGroup(permissionsGroup); Permissions permissions = new Permissions(metabaseRepository.getPermissionsGraph()); - metabaseRepository.assignDatabasePermissions(permissions, groupId, databaseId); + metabaseRepository.assignDatabasePermissions(permissions, metabasePermissionsGroup.getId(), database.getId()); CollectionPermissions collectionPermissions = new CollectionPermissions(metabaseRepository.getCollectionPermissionsGraph()); - metabaseRepository.updateCollectionPermissions(collectionPermissions, groupId, collectionId); + metabaseRepository.updateCollectionPermissions(collectionPermissions, metabasePermissionsGroup.getId(), metabaseCollection.getId()); } } diff --git a/avni-server-api/src/main/java/org/avni/server/web/MetabaseController.java b/avni-server-api/src/main/java/org/avni/server/web/MetabaseController.java index 0838c146b..4534706f6 100644 --- a/avni-server-api/src/main/java/org/avni/server/web/MetabaseController.java +++ b/avni-server-api/src/main/java/org/avni/server/web/MetabaseController.java @@ -2,9 +2,10 @@ import org.avni.server.domain.accessControl.PrivilegeType; import org.avni.server.service.MetabaseService; -import org.avni.server.service.UserService; import org.avni.server.service.accessControl.AccessControlService; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/api/metabase") @@ -12,7 +13,7 @@ public class MetabaseController { private final MetabaseService metabaseService; private final AccessControlService accessControlService; - public MetabaseController(MetabaseService metabaseService, UserService userService,AccessControlService accessControlService) { + public MetabaseController(MetabaseService metabaseService, AccessControlService accessControlService) { this.metabaseService = metabaseService; this.accessControlService= accessControlService; } diff --git a/avni-server-api/src/test/java/org/avni/server/web/MetabaseControllerIntegrationTest.java b/avni-server-api/src/test/java/org/avni/server/web/MetabaseControllerIntegrationTest.java new file mode 100644 index 000000000..78e829a3b --- /dev/null +++ b/avni-server-api/src/test/java/org/avni/server/web/MetabaseControllerIntegrationTest.java @@ -0,0 +1,4 @@ +package org.avni.server.web; + +public class MetabaseControllerIntegrationTest { +} diff --git a/avni-server-api/src/test/resources/application.properties b/avni-server-api/src/test/resources/application.properties index 019c784d6..53a188d08 100644 --- a/avni-server-api/src/test/resources/application.properties +++ b/avni-server-api/src/test/resources/application.properties @@ -4,7 +4,10 @@ avni.defaultUserName=${OPENCHS_USER_NAME:admin} spring.servlet.multipart.max-file-size=10028KB spring.servlet.multipart.max-request-size=10028KB -spring.datasource.url=${OPENCHS_DATABASE_URL:jdbc:postgresql://localhost:5432/openchs_test} +avni.database=${OPENCHS_DATABASE:openchs} +avni.database.port=${OPENCHS_DATABASE_PORT:5432} +avni.database.server=${OPENCHS_DATABASE_SERVER:localhost} +spring.datasource.url=${OPENCHS_DATABASE_URL:jdbc:postgresql://${avni.database.server}:5432/openchs_test} spring.datasource.username=openchs spring.datasource.password=password spring.datasource.driverClassName=org.postgresql.Driver