Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Corrected the metabase setup code #787

Merged
merged 4 commits into from
Oct 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import org.avni.server.domain.metabase.*;
import org.avni.server.util.ObjectMapperSingleton;
import org.avni.server.util.S;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.stereotype.Repository;
Expand All @@ -17,7 +18,7 @@ public class DatabaseRepository extends MetabaseConnector {
private final ObjectMapper objectMapper;
public DatabaseRepository(RestTemplateBuilder restTemplateBuilder) {
super(restTemplateBuilder);
this.objectMapper = new ObjectMapper();
this.objectMapper = ObjectMapperSingleton.getObjectMapper();
}

public Database save(Database database) {
Expand All @@ -33,7 +34,6 @@ public Database getDatabaseByName(Database database) {
String jsonResponse = getForObject(url, String.class);

try {
ObjectMapper objectMapper = new ObjectMapper();
JsonNode rootNode = objectMapper.readTree(jsonResponse);
JsonNode dataArray = rootNode.path("data");

Expand All @@ -43,7 +43,7 @@ public Database getDatabaseByName(Database database) {
return db;
}
}
throw new RuntimeException("Database with name " + database.getName() + " not found.");
return null;
} catch (Exception e) {
throw new RuntimeException("Failed to retrieve database", e);
}
Expand Down Expand Up @@ -74,16 +74,14 @@ public CollectionInfoResponse getCollectionByName(Database database) {
String url = metabaseApiUrl + "/collection";
try {
String jsonResponse = getForObject(url, String.class);

ObjectMapper objectMapper = new ObjectMapper();
List<CollectionInfoResponse> collections = objectMapper.readValue(
jsonResponse, new TypeReference<List<CollectionInfoResponse>>() {}
);

return collections.stream()
.filter(collection -> collection.getName().equals(database.getName()))
.findFirst()
.orElseThrow(() -> new RuntimeException("Collection with name " + database.getName() + " not found."));
.orElseThrow(null);
} catch (Exception e) {
throw new RuntimeException("Failed to retrieve collection", e);
}
Expand All @@ -94,7 +92,7 @@ public void createQuestionForTable(Database database, TableDetails tableDetails,
FieldDetails joinField2 = getFieldDetailsByName(database, tableDetails, destinationField);

ArrayNode joinsArray = objectMapper.createArrayNode();
MetabaseQuery query = new MetabaseQueryBuilder(database, joinsArray, objectMapper)
MetabaseQuery query = new MetabaseQueryBuilder(database, joinsArray)
.forTable(tableDetails)
.joinWith(addressTableDetails, joinField1, joinField2)
.build();
Expand All @@ -108,11 +106,11 @@ public void createQuestionForTable(Database database, TableDetails tableDetails,
getCollectionByName(database).getIdAsInt()
);

postForObject(metabaseApiUrl + "/card", requestBody.toJson(objectMapper), JsonNode.class);
postForObject(metabaseApiUrl + "/card", requestBody.toJson(), JsonNode.class);
}

public void createQuestionForASingleTable(Database database, TableDetails tableDetails) {
MetabaseQuery query = new MetabaseQueryBuilder(database, objectMapper.createArrayNode(), objectMapper)
MetabaseQuery query = new MetabaseQueryBuilder(database, objectMapper.createArrayNode())
.forTable(tableDetails)
.build();

Expand All @@ -125,7 +123,7 @@ public void createQuestionForASingleTable(Database database, TableDetails tableD
getCollectionByName(database).getIdAsInt()
);

postForObject(metabaseApiUrl + "/card", requestBody.toJson(objectMapper), JsonNode.class);
postForObject(metabaseApiUrl + "/card", requestBody.toJson(), JsonNode.class);
}

public FieldDetails getFieldDetailsByName(Database database, TableDetails tableDetails, FieldDetails fieldDetails) {
Expand Down Expand Up @@ -180,7 +178,7 @@ public DatabaseSyncStatus getInitialSyncStatus(Database database) {

public DatasetResponse getDataset(DatasetRequestBody requestBody) {
String url = metabaseApiUrl + "/dataset";
String jsonRequestBody = requestBody.toJson(objectMapper).toString();
String jsonRequestBody = requestBody.toJson().toString();
String jsonResponse = postForObject(url, jsonRequestBody, String.class);
try {
return objectMapper.readValue(jsonResponse, DatasetResponse.class);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
package org.avni.server.dao.metabase;

import org.avni.server.domain.metabase.GroupPermissionsService;
import org.avni.server.domain.metabase.GroupPermissionsGraphResponse;
import org.avni.server.domain.metabase.Group;
import org.avni.server.domain.metabase.GroupPermissionsBody;
import org.avni.server.domain.metabase.*;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.http.HttpEntity;
import org.springframework.stereotype.Repository;

import java.util.Arrays;
import java.util.List;
import java.util.Map;

@Repository
Expand All @@ -21,7 +20,6 @@ public Group save(Group permissionsGroup) {
String url = metabaseApiUrl + "/permissions/group";
GroupPermissionsBody body = new GroupPermissionsBody(permissionsGroup.getName());
HttpEntity<Map<String, Object>> entity = createJsonEntity(body);

Group response = restTemplate.postForObject(url, entity, Group.class);
return response;
}
Expand All @@ -31,9 +29,36 @@ public GroupPermissionsGraphResponse getPermissionsGraph() {
return getForObject(url, GroupPermissionsGraphResponse.class);
}

public void updatePermissionsGraph(GroupPermissionsService permissions, int groupId, int databaseId) {
public void updatePermissionsGraph(GroupPermissionsService permissions) {
String url = metabaseApiUrl + "/permissions/graph";
Map<String, Object> requestBody = permissions.getUpdatedPermissionsGraph();
sendPutRequest(url, requestBody);
}

public List<GroupPermissionResponse> getAllGroups() {
String url = metabaseApiUrl + "/permissions/group";
GroupPermissionResponse[] response = getForObject(url, GroupPermissionResponse[].class);
return Arrays.asList(response);
}

public void updateGroupPermissions(int groupId, int databaseId) {
GroupPermissionsService groupPermissions = new GroupPermissionsService(getPermissionsGraph());
groupPermissions.updatePermissions(groupId, databaseId);
updatePermissionsGraph(groupPermissions);
}


public Group findOrCreateGroup(String name, int databaseId, int collectionId) {
List<GroupPermissionResponse> existingGroups = getAllGroups();

for (GroupPermissionResponse group : existingGroups) {
if (group.getName().equals(name)) {
return new Group(group.getName(), group.getId());
}
}

Group newGroup = save(new Group(name));
updateGroupPermissions(newGroup.getId(), databaseId);
return newGroup;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import java.util.HashMap;
import java.util.Map;

import org.avni.server.dao.metabase.CollectionPermissionsRepository;
import org.springframework.stereotype.Component;

@Component
Expand Down Expand Up @@ -55,4 +56,9 @@ public Map<String, Object> getUpdatedPermissionsGraph() {
public CollectionPermissionsGraphResponse getPermissionsGraph() {
return permissionsGraph;
}

public void updateAndSavePermissions(CollectionPermissionsRepository collectionPermissionsRepository, int groupId, int collectionId) {
updatePermissions(groupId, collectionId);
collectionPermissionsRepository.updateCollectionPermissions(this, groupId, collectionId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.avni.server.util.ObjectMapperSingleton;

public class DatasetRequestBody {

Expand All @@ -13,16 +14,16 @@ public DatasetRequestBody(Database database, TableDetails table) {
this.table = table;
}

public ObjectNode toJson(ObjectMapper objectMapper) {
ObjectNode rootNode = objectMapper.createObjectNode();
public ObjectNode toJson() {
ObjectNode rootNode = ObjectMapperSingleton.getObjectMapper().createObjectNode();
rootNode.put("database", database.getId());

ObjectNode queryNode = objectMapper.createObjectNode();
ObjectNode queryNode = ObjectMapperSingleton.getObjectMapper().createObjectNode();
queryNode.put("source-table", table.getId());

rootNode.set("query", queryNode);
rootNode.put("type", "query");
rootNode.set("parameters", objectMapper.createArrayNode());
rootNode.set("parameters", ObjectMapperSingleton.getObjectMapper().createArrayNode());

return rootNode;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.avni.server.util.ObjectMapperSingleton;

public enum FieldAttribute {
ALL("all"),
Expand All @@ -24,8 +25,8 @@ public String getAttributeName() {
return attributeName;
}

public ObjectNode toJson(ObjectMapper objectMapper, Object value) {
ObjectNode attributeNode = objectMapper.createObjectNode();
public ObjectNode toJson(Object value) {
ObjectNode attributeNode = ObjectMapperSingleton.getObjectMapper().createObjectNode();
attributeNode.put(attributeName, value.toString());
return attributeNode;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package org.avni.server.domain.metabase;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

@JsonIgnoreProperties(ignoreUnknown = true)
public class GroupPermissionResponse {
private int id;
private String name;
private int memberCount;

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getMemberCount() {
return memberCount;
}

public void setMemberCount(int memberCount) {
this.memberCount = memberCount;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,18 @@
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.avni.server.util.ObjectMapperSingleton;

public class MetabaseQueryBuilder {
private final Database database;
private final ArrayNode joinsArray;
private final ObjectMapper objectMapper;
private ObjectNode queryNode;

public MetabaseQueryBuilder(Database database, ArrayNode joinsArray, ObjectMapper objectMapper) {
public MetabaseQueryBuilder(Database database, ArrayNode joinsArray) {
this.database = database;
this.joinsArray = joinsArray;
this.objectMapper = objectMapper;
this.objectMapper = ObjectMapperSingleton.getObjectMapper();
this.queryNode = objectMapper.createObjectNode();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package org.avni.server.domain.metabase;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.avni.server.util.ObjectMapperSingleton;

// Refer docs : https://www.metabase.com/docs/latest/api/card#post-apicard
public class MetabaseRequestBody {
Expand All @@ -24,11 +24,11 @@ public MetabaseRequestBody(String name, MetabaseQuery datasetQuery, Visualizatio
this.collectionId = collectionId;
}

public ObjectNode toJson(ObjectMapper objectMapper) {
ObjectNode rootNode = objectMapper.createObjectNode();
public ObjectNode toJson() {
ObjectNode rootNode = ObjectMapperSingleton.getObjectMapper().createObjectNode();
rootNode.put("name", name);

ObjectNode datasetQueryNode = objectMapper.createObjectNode();
ObjectNode datasetQueryNode = ObjectMapperSingleton.getObjectMapper().createObjectNode();
datasetQueryNode.put("database", datasetQuery.getDatabaseId());
datasetQueryNode.put("type", "query");
datasetQueryNode.set("query", datasetQuery.toJson());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,14 @@
import org.avni.server.domain.metabase.*;
import org.avni.server.service.OrganisationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;


@Service
public class MetabaseService {

private final OrganisationService organisationService;
private final AvniDatabase avniDatabase;
private final DatabaseRepository databaseRepository;
private final DatabaseService databaseService;
private final GroupPermissionsRepository groupPermissionsRepository;
private final CollectionPermissionsRepository collectionPermissionsRepository;
private final CollectionRepository collectionRepository;
Expand All @@ -29,14 +26,12 @@ public class MetabaseService {
public MetabaseService(OrganisationService organisationService,
AvniDatabase avniDatabase,
DatabaseRepository databaseRepository,
@Lazy DatabaseService databaseService,
GroupPermissionsRepository groupPermissionsRepository,
CollectionPermissionsRepository collectionPermissionsRepository,
CollectionRepository collectionRepository) {
this.organisationService = organisationService;
this.avniDatabase = avniDatabase;
this.databaseRepository = databaseRepository;
this.databaseService = databaseService;
this.groupPermissionsRepository = groupPermissionsRepository;
this.collectionPermissionsRepository = collectionPermissionsRepository;
this.collectionRepository = collectionRepository;
Expand All @@ -47,36 +42,47 @@ public void setupMetabase() {
String name = currentOrganisation.getName();
String dbUser = currentOrganisation.getDbUser();

Database database = databaseRepository.save(new Database(name, "postgres", new DatabaseDetails(avniDatabase, dbUser)));
this.globalDatabase = database;

CollectionResponse metabaseCollection = collectionRepository.save(new CreateCollectionRequest(name, name + " collection"));
this.globalCollection = new CollectionInfoResponse(null, metabaseCollection.getId(), false);
globalDatabase = databaseRepository.getDatabaseByName(new Database(name));
if (globalDatabase == null) {
Database newDatabase = new Database(name, "postgres", new DatabaseDetails(avniDatabase, dbUser));
globalDatabase = databaseRepository.save(newDatabase);
}

Group metabaseGroup = groupPermissionsRepository.save(new Group(name));
globalCollection = databaseRepository.getCollectionByName(globalDatabase);
if (globalCollection == null) {
CollectionResponse metabaseCollection = collectionRepository.save(new CreateCollectionRequest(name, name + " collection"));
globalCollection = new CollectionInfoResponse(null, metabaseCollection.getId(), false);
}

GroupPermissionsService groupPermissions = new GroupPermissionsService(groupPermissionsRepository.getPermissionsGraph());
groupPermissions.updatePermissions(metabaseGroup.getId(), database.getId());
groupPermissionsRepository.updatePermissionsGraph(groupPermissions, metabaseGroup.getId(), database.getId());
Group metabaseGroup = groupPermissionsRepository.findOrCreateGroup(name, globalDatabase.getId(), globalCollection.getIdAsInt());

CollectionPermissionsService collectionPermissions = new CollectionPermissionsService(collectionPermissionsRepository.getCollectionPermissionsGraph());
collectionPermissions.updatePermissions(metabaseGroup.getId(), metabaseCollection.getId());
collectionPermissionsRepository.updateCollectionPermissions(collectionPermissions, metabaseGroup.getId(), metabaseCollection.getId());
CollectionPermissionsService collectionPermissions = new CollectionPermissionsService(
collectionPermissionsRepository.getCollectionPermissionsGraph()
);
collectionPermissions.updateAndSavePermissions(collectionPermissionsRepository, metabaseGroup.getId(), globalCollection.getIdAsInt());
}

public Database getGlobalDatabase() {
if (globalDatabase == null) {
Organisation currentOrganisation = organisationService.getCurrentOrganisation();
globalDatabase = databaseRepository.getDatabaseByName(new Database(currentOrganisation.getName()));
if (globalDatabase == null) {
throw new RuntimeException("Global database not found.");
}
}
return globalDatabase;
}


public CollectionInfoResponse getGlobalCollection() {
if (globalCollection == null) {
Organisation currentOrganisation = organisationService.getCurrentOrganisation();
globalCollection = databaseRepository.getCollectionByName(new Database(currentOrganisation.getName()));
if (globalCollection == null) {
throw new RuntimeException("Global database not found.");
}
}
return globalCollection;
}
}

}
Loading