GuestService.java
package io.featureprobe.api.service;
import io.featureprobe.api.base.enums.OrganizationRoleEnum;
import io.featureprobe.api.config.JWTConfig;
import io.featureprobe.api.base.db.ExcludeTenant;
import io.featureprobe.api.dao.repository.OrganizationRepository;
import io.featureprobe.api.dto.ProjectCreateRequest;
import io.featureprobe.api.dao.entity.Member;
import io.featureprobe.api.dao.entity.Organization;
import io.featureprobe.api.dao.repository.MemberRepository;
import io.featureprobe.api.base.tenant.TenantContext;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.io.ClassPathResource;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.context.SecurityContextImpl;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
@Slf4j
@AllArgsConstructor
@Service
@ExcludeTenant
public class GuestService {
JWTConfig JWTConfig;
private MemberService memberService;
private OrganizationRepository organizationRepository;
@PersistenceContext
public EntityManager entityManager;
private ProjectService projectService;
private static final PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
private static final String GUEST_INIT_PROJECT_KEY = "My_Project";
private static final String DEMO_INIT_DATA_FILE_PATH = "db/demo_init_data.sql";
@Transactional(rollbackFor = Exception.class)
public Member initGuest(String account, String source) {
Organization organization = organizationRepository.save(new Organization(account));
Member guestMember = createGuestMember(account, source, organization);
loginGuestUser(guestMember);
initProjectEnvironment(String.valueOf(organization.getId()), GUEST_INIT_PROJECT_KEY);
initToggles(organization.getId(), guestMember.getId());
return guestMember;
}
private Member createGuestMember(String account, String source, Organization organization) {
Member member = new Member();
member.setAccount(account);
member.setPassword(passwordEncoder.encode(JWTConfig.getGuestDefaultPassword()));
member.setSource(source);
member.addOrganization(organization, OrganizationRoleEnum.OWNER);
return memberService.save(member);
}
private void loginGuestUser(Member member) {
SecurityContextHolder.setContext(new SecurityContextImpl(new JwtAuthenticationToken(Jwt.withTokenValue("_")
.claim("userId", member.getId()).claim("account", member.getAccount())
.claim("role", member.getOrganizationMembers().get(0).getRole())
.header("iss", "")
.build())));
}
private void initProjectEnvironment(String tenantId, String projectName) {
TenantContext.setCurrentTenant(tenantId);
projectService.create(new ProjectCreateRequest(projectName,
projectName, ""));
}
private void initToggles(Long tenantId, Long userId) {
try {
ClassPathResource classPathResource = new ClassPathResource(DEMO_INIT_DATA_FILE_PATH);
BufferedReader br = new BufferedReader(new InputStreamReader(classPathResource.getInputStream()));
String sql;
while (StringUtils.isNotBlank((sql = br.readLine()))) {
sql = sql.replace("${organization_id}", String.valueOf(tenantId))
.replace("${project_key}", GUEST_INIT_PROJECT_KEY)
.replace("${user_id}", String.valueOf(userId));
executeSQL(sql);
}
} catch (IOException e) {
log.error("Demo init toggles error.", e);
}
}
private void executeSQL(String sql) {
Query query = entityManager.createNativeQuery(sql);
query.executeUpdate();
}
}