Skip to content

Commit

Permalink
chore: create default tenant, anonymous user and instance config migr…
Browse files Browse the repository at this point in the history
…ation (#33304)

## Description
Adds migration for generating instance id, adding default tenant and
creating anonymous user

Fixes #`Issue Number`  
_or_  
Fixes `Issue URL`
> [!WARNING]  
> _If no issue exists, please create an issue first, and check with the
maintainers if the issue is valid._

## Automation

/ok-to-test tags=""

### 🔍 Cypress test results
<!-- This is an auto-generated comment: Cypress test results  -->
> [!CAUTION]  
> If you modify the content in this section, you are likely to disrupt
the CI result for your PR.

<!-- end of auto-generated comment: Cypress test results  -->


## Communication
Should the DevRel and Marketing teams inform users about this change?
- [ ] Yes
- [ ] No

---------

Co-authored-by: Abhijeet <[email protected]>
  • Loading branch information
vivonk and abhvsn committed May 13, 2024
1 parent f71f43d commit 6ee7a7c
Show file tree
Hide file tree
Showing 6 changed files with 134 additions and 49 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,12 @@
import com.appsmith.server.constants.FieldName;
import com.appsmith.server.domains.Config;
import com.appsmith.server.domains.PermissionGroup;
import com.appsmith.server.domains.PricingPlan;
import com.appsmith.server.domains.Tenant;
import com.appsmith.server.domains.Theme;
import com.appsmith.server.domains.User;
import com.appsmith.server.dtos.Permission;
import com.appsmith.server.helpers.InMemoryCacheableRepositoryHelper;
import com.appsmith.server.repositories.ConfigRepository;
import com.appsmith.server.repositories.PermissionGroupRepository;
import com.appsmith.server.repositories.TenantRepository;
import com.appsmith.server.repositories.ThemeRepository;
import com.appsmith.server.repositories.UserRepository;
import com.fasterxml.jackson.databind.ObjectMapper;
Expand All @@ -39,7 +36,6 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;

import static com.appsmith.server.acl.AclPermission.ASSIGN_PERMISSION_GROUPS;
Expand All @@ -55,25 +51,6 @@
public class SeedData {
// TODO: Move to separate files in a "seeds" package? Or to migrations?

@Bean
public String instanceId(ConfigRepository configRepository) {
final Object value = configRepository
.findByName("instance-id")
.orElseGet(() -> {
log.debug("Adding instance id");
final String valueStr = UUID.randomUUID().toString();
return configRepository.save(new Config(new JSONObject(Map.of("value", valueStr)), "instance-id"));
})
.getConfig()
.get("value");

if (value instanceof String valueStr) {
return valueStr;
} else {
throw new IllegalStateException("instance-id config value is not a string");
}
}

@Bean
public String instanceAdminPermissionGroupId(
EntityManager entityManager,
Expand Down Expand Up @@ -156,38 +133,13 @@ public String instanceAdminPermissionGroupId(
}
}

@Bean
public Tenant defaultTenant(TenantRepository tenantRepository) {
return tenantRepository.findBySlug("default").orElseGet(() -> {
Tenant defaultTenant = new Tenant();
defaultTenant.setDisplayName("Default");
defaultTenant.setSlug("default");
defaultTenant.setPricingPlan(PricingPlan.FREE);
return tenantRepository.save(defaultTenant);
});
}

@Bean
public User anonymousUser(UserRepository userRepository, Tenant defaultTenant) {
log.debug("Adding anonymous user");
return userRepository.findByEmail(FieldName.ANONYMOUS_USER).orElseGet(() -> {
final User anonymousUser = new User();
anonymousUser.setName(FieldName.ANONYMOUS_USER);
anonymousUser.setEmail(FieldName.ANONYMOUS_USER);
anonymousUser.setWorkspaceIds(new HashSet<>());
anonymousUser.setIsAnonymous(true);
anonymousUser.setTenantId(defaultTenant.getId());
return userRepository.save(anonymousUser);
});
}

public record PublicPermissionInfo(PermissionGroup permissionGroup, Config config) {}

@Bean
public PublicPermissionInfo publicPermissionInfo(
ConfigRepository configRepository,
PermissionGroupRepository permissionGroupRepository,
User anonymousUser) {
UserRepository userRepository) {
return configRepository
.findByName(FieldName.PUBLIC_PERMISSION_GROUP)
.map(config -> {
Expand All @@ -198,10 +150,14 @@ public PublicPermissionInfo publicPermissionInfo(
})
.orElseGet(() -> {
log.debug("Adding anonymous user permission group");
// Find anonymous user
final User anonymousUser =
userRepository.findByEmail(FieldName.ANONYMOUS_USER).orElseThrow();

final PermissionGroup publicPermissionGroup = new PermissionGroup();
publicPermissionGroup.setName(FieldName.PUBLIC_PERMISSION_GROUP);
publicPermissionGroup.setDescription("Role for giving accesses for all objects to anonymous users");
assert anonymousUser.getId() != null : "Anonymous user id is null";
publicPermissionGroup.setAssignedToUserIds(Set.of(anonymousUser.getId()));
permissionGroupRepository.save(publicPermissionGroup);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.appsmith.server.migrations;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

public class JsonHelper {
private static ObjectMapper objectMapper = new ObjectMapper();

public static String convertToString(Object object) throws JsonProcessingException {
if (object == null) {
return null;
}
return objectMapper.writeValueAsString(object);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.appsmith.server.migrations;

import lombok.RequiredArgsConstructor;
import org.springframework.jdbc.core.JdbcTemplate;

@RequiredArgsConstructor
public class RepositoryHelperMethods {
private final JdbcTemplate jdbcTemplate;

public String getDefaultTenantId() {
try {
return jdbcTemplate.queryForObject("SELECT id FROM tenant WHERE slug = 'default' LIMIT 1", String.class);
} catch (Exception e) {
return null;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.appsmith.server.migrations.ce;

import com.appsmith.server.domains.Config;
import com.appsmith.server.migrations.AppsmithJavaMigration;
import com.appsmith.server.migrations.JsonHelper;
import net.minidev.json.JSONObject;
import org.springframework.jdbc.core.JdbcTemplate;

import java.util.Map;
import java.util.UUID;

public class V4__configureInstanceId extends AppsmithJavaMigration {

public static final String INSTANCE_ID = "instance-id";

@Override
public void migrate(JdbcTemplate jdbcTemplate) throws Exception {
String sql = "SELECT COUNT(*) FROM config WHERE name = ?";
Integer count = jdbcTemplate.queryForObject(sql, Integer.class, INSTANCE_ID);
if (count != null && count != 0) {
return;
}
final String valueStr = UUID.randomUUID().toString();

Config instanceIdConfig = new Config(new JSONObject(Map.of("value", valueStr)), INSTANCE_ID);
String jsonConfig = JsonHelper.convertToString(instanceIdConfig.getConfig());
String insertInstanceConfigurationQuery =
"INSERT INTO config (id, name, config, created_at, updated_at) VALUES (gen_random_uuid(), ?, cast(? as jsonb), now(), now())";
jdbcTemplate.update(insertInstanceConfigurationQuery, INSTANCE_ID, jsonConfig);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.appsmith.server.migrations.ce;

import com.appsmith.server.migrations.AppsmithJavaMigration;
import com.appsmith.server.migrations.RepositoryHelperMethods;
import org.apache.commons.lang3.StringUtils;
import org.springframework.jdbc.core.JdbcTemplate;

public class V5__createDefaultTenant extends AppsmithJavaMigration {

private RepositoryHelperMethods helperMethods;

@Override
public void migrate(JdbcTemplate jdbcTemplate) throws Exception {
RepositoryHelperMethods helperMethods = new RepositoryHelperMethods(jdbcTemplate);
if (!StringUtils.isBlank(helperMethods.getDefaultTenantId())) {
return;
}
jdbcTemplate.execute(
"INSERT INTO tenant (id, slug, display_name, pricing_plan, created_at, updated_at) VALUES (gen_random_uuid(), 'default', 'Default', 'FREE', now(), now())");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package com.appsmith.server.migrations.ce;

import com.appsmith.server.constants.FieldName;
import com.appsmith.server.migrations.AppsmithJavaMigration;
import com.appsmith.server.migrations.JsonHelper;
import com.appsmith.server.migrations.RepositoryHelperMethods;
import com.fasterxml.jackson.core.JsonProcessingException;
import org.springframework.jdbc.core.JdbcTemplate;

import java.util.Set;

public class V6__createAnonymousUser extends AppsmithJavaMigration {
private JdbcTemplate jdbcTemplate;
private RepositoryHelperMethods helperMethods;

@Override
public void migrate(JdbcTemplate jdbcTemplate) throws Exception {
this.jdbcTemplate = jdbcTemplate;
helperMethods = new RepositoryHelperMethods(jdbcTemplate);
addAnonymousUser();
}

private void addAnonymousUser() throws JsonProcessingException {
String defaultTenantId = helperMethods.getDefaultTenantId();
if (doesAnonymousUserExist(defaultTenantId)) {
return;
}
String insertUserQuery =
"INSERT INTO \"user\" (id, email, name, current_workspace_id, workspace_ids, is_anonymous, tenant_id, created_at, updated_at) VALUES (gen_random_uuid(), ?, ?, ?, cast(? as jsonb), ?, ?, now() ,now())";
jdbcTemplate.update(
insertUserQuery,
FieldName.ANONYMOUS_USER,
FieldName.ANONYMOUS_USER,
"",
JsonHelper.convertToString(Set.of()),
true,
defaultTenantId);
}

private boolean doesAnonymousUserExist(String tenantId) {
String sql = "SELECT COUNT(*) FROM \"user\" WHERE email = ? and tenant_id = ?";
Integer count = jdbcTemplate.queryForObject(sql, Integer.class, FieldName.ANONYMOUS_USER, tenantId);
return count != null && count != 0;
}
}

0 comments on commit 6ee7a7c

Please sign in to comment.