mirror of
https://github.com/valitydev/org-manager.git
synced 2024-11-06 00:15:23 +00:00
JD-710: user organization context (#53)
This commit is contained in:
parent
de838229b6
commit
790b988e55
7
Jenkinsfile
vendored
7
Jenkinsfile
vendored
@ -5,12 +5,11 @@ build('org-manager', 'java-maven') {
|
||||
|
||||
def javaServicePipeline
|
||||
runStage('load JavaService pipeline') {
|
||||
javaServicePipeline = load("build_utils/jenkins_lib/pipeJavaService.groovy")
|
||||
javaServicePipeline = load("build_utils/jenkins_lib/pipeJavaServiceInsideDocker.groovy")
|
||||
}
|
||||
|
||||
def serviceName = env.REPO_NAME
|
||||
def mvnArgs = '-DjvmArgs="-Xmx256m"'
|
||||
def useJava11 = true
|
||||
|
||||
javaServicePipeline(serviceName, useJava11, mvnArgs)
|
||||
}
|
||||
javaServicePipeline(serviceName, mvnArgs)
|
||||
}
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit a7655bc60c877a65cdfe3d9b668021d970d88a76
|
||||
Subproject commit be44d69fc87b22a0bb82d98d6eae7658d1647f98
|
12
pom.xml
12
pom.xml
@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>com.rbkmoney</groupId>
|
||||
<artifactId>service-parent-pom</artifactId>
|
||||
<version>1.2.10</version>
|
||||
<version>2.0.8</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>org-manager</artifactId>
|
||||
@ -18,18 +18,15 @@
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<java.version>11</java.version>
|
||||
<server.port>8022</server.port>
|
||||
<server.rest.port>8080</server.rest.port>
|
||||
<management.port>8023</management.port>
|
||||
<exposed.ports>${server.port} ${server.rest.port} ${management.port}</exposed.ports>
|
||||
<dockerfile.base.service.tag>c0612d6052ac049496b72a23a04acb142035f249</dockerfile.base.service.tag>
|
||||
<dockerfile.registry>dr2.rbkmoney.com</dockerfile.registry>
|
||||
<!--because of https://github.com/spring-projects/spring-security/issues/9787-->
|
||||
<spring-security.version>5.4.6</spring-security.version>
|
||||
<dockerfile.registry>${env.REGISTRY}</dockerfile.registry>
|
||||
<spring-security.version>5.5.2</spring-security.version>
|
||||
<keycloak.version>14.0.0</keycloak.version>
|
||||
<schedlock.version>4.14.0</schedlock.version>
|
||||
<swag.organizations.version>1.18-38ef431-server</swag.organizations.version>
|
||||
<swag.organizations.version>1.19-8707f87-server</swag.organizations.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
@ -280,7 +277,6 @@
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<version>2.1.1.RELEASE</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
|
@ -5,15 +5,15 @@ import com.rbkmoney.orgmanager.service.OrganizationService;
|
||||
import com.rbkmoney.orgmanager.service.ResourceAccessService;
|
||||
import com.rbkmoney.orgmanager.service.dto.ResourceDto;
|
||||
import com.rbkmoney.swag.organizations.api.UserApi;
|
||||
import com.rbkmoney.swag.organizations.model.OrganizationJoinRequest;
|
||||
import com.rbkmoney.swag.organizations.model.OrganizationMembership;
|
||||
import com.rbkmoney.swag.organizations.model.OrganizationSearchResult;
|
||||
import com.rbkmoney.swag.organizations.model.*;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.keycloak.representations.AccessToken;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.validation.Valid;
|
||||
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@ -74,4 +74,32 @@ public class UserController implements UserApi {
|
||||
organizationService.findAllOrganizations(accessToken.getSubject(), limit, continuationToken);
|
||||
return ResponseEntity.ok(organizationSearchResult);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseEntity<MemberContext> getContext(String requestId) {
|
||||
log.info("Get user context. requestId={}", requestId);
|
||||
resourceAccessService.checkRights();
|
||||
AccessToken accessToken = keycloakService.getAccessToken();
|
||||
MemberContext memberContext = organizationService.findMemberContext(accessToken.getSubject());
|
||||
|
||||
return ResponseEntity.ok(memberContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseEntity<Void> switchContext(String requestId,
|
||||
@Valid OrganizationSwitchRequest organizationSwitchRequest) {
|
||||
log.info("Switch user context. requestId={}, body={}", requestId, organizationSwitchRequest);
|
||||
ResourceDto resource = ResourceDto.builder()
|
||||
.orgId(organizationSwitchRequest.getOrganizationId())
|
||||
.build();
|
||||
resourceAccessService.checkRights(resource);
|
||||
AccessToken accessToken = keycloakService.getAccessToken();
|
||||
|
||||
organizationService.switchMemberContext(
|
||||
accessToken.getSubject(),
|
||||
organizationSwitchRequest.getOrganizationId()
|
||||
);
|
||||
|
||||
return ResponseEntity.noContent().build();
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,31 @@
|
||||
package com.rbkmoney.orgmanager.entity;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.io.Serializable;
|
||||
|
||||
@Entity
|
||||
@Builder
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Table(name = "member_context")
|
||||
public class MemberContextEntity implements Serializable {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@OneToOne
|
||||
@JoinColumn(name = "organization_id", referencedColumnName = "id")
|
||||
private OrganizationEntity organizationEntity;
|
||||
|
||||
@OneToOne
|
||||
@JoinColumn(name = "member_id", referencedColumnName = "id")
|
||||
private MemberEntity memberEntity;
|
||||
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
package com.rbkmoney.orgmanager.repository;
|
||||
|
||||
import com.rbkmoney.orgmanager.entity.MemberContextEntity;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@Repository
|
||||
public interface MemberContextRepository extends JpaRepository<MemberContextEntity, String> {
|
||||
|
||||
Optional<MemberContextEntity> findByMemberEntityId(String memberId);
|
||||
|
||||
}
|
@ -57,7 +57,7 @@ public class InvitationService {
|
||||
.build();
|
||||
}
|
||||
|
||||
Invitation invitation = invitationConverter.toDomain(entity.get());
|
||||
Invitation invitation = invitationConverter.toDomain(entity.orElseThrow());
|
||||
return ResponseEntity
|
||||
.status(HttpStatus.OK)
|
||||
.body(invitation);
|
||||
|
@ -47,7 +47,7 @@ public class OrganizationRoleService {
|
||||
.build();
|
||||
}
|
||||
|
||||
List<Role> roles = entity.get().getRoles()
|
||||
List<Role> roles = entity.orElseThrow().getRoles()
|
||||
.stream()
|
||||
.map(organizationRoleConverter::toDomain)
|
||||
.collect(toList());
|
||||
|
@ -3,13 +3,11 @@ package com.rbkmoney.orgmanager.service;
|
||||
import com.rbkmoney.orgmanager.converter.MemberConverter;
|
||||
import com.rbkmoney.orgmanager.converter.MemberRoleConverter;
|
||||
import com.rbkmoney.orgmanager.converter.OrganizationConverter;
|
||||
import com.rbkmoney.orgmanager.entity.InvitationEntity;
|
||||
import com.rbkmoney.orgmanager.entity.MemberEntity;
|
||||
import com.rbkmoney.orgmanager.entity.MemberRoleEntity;
|
||||
import com.rbkmoney.orgmanager.entity.OrganizationEntity;
|
||||
import com.rbkmoney.orgmanager.entity.*;
|
||||
import com.rbkmoney.orgmanager.exception.AccessDeniedException;
|
||||
import com.rbkmoney.orgmanager.exception.LastRoleException;
|
||||
import com.rbkmoney.orgmanager.exception.ResourceNotFoundException;
|
||||
import com.rbkmoney.orgmanager.repository.MemberContextRepository;
|
||||
import com.rbkmoney.orgmanager.repository.MemberRepository;
|
||||
import com.rbkmoney.orgmanager.repository.OrganizationRepository;
|
||||
import com.rbkmoney.orgmanager.service.dto.MemberWithRoleDto;
|
||||
@ -43,6 +41,7 @@ public class OrganizationService {
|
||||
private final MemberConverter memberConverter;
|
||||
private final MemberRoleConverter memberRoleConverter;
|
||||
private final MemberRepository memberRepository;
|
||||
private final MemberContextRepository memberContextRepository;
|
||||
private final InvitationService invitationService;
|
||||
private final MemberRoleService memberRoleService;
|
||||
|
||||
@ -72,15 +71,14 @@ public class OrganizationService {
|
||||
public ResponseEntity<Organization> get(String orgId) {
|
||||
Optional<OrganizationEntity> entity = organizationRepository.findById(orgId);
|
||||
|
||||
if (entity.isEmpty()) {
|
||||
return ResponseEntity
|
||||
.status(HttpStatus.NOT_FOUND)
|
||||
.build();
|
||||
if (entity.isPresent()) {
|
||||
Organization organization = organizationConverter.toDomain(entity.get());
|
||||
|
||||
return ResponseEntity.ok(organization);
|
||||
}
|
||||
|
||||
Organization organization = organizationConverter.toDomain(entity.get());
|
||||
|
||||
return ResponseEntity.ok(organization);
|
||||
return ResponseEntity
|
||||
.status(HttpStatus.NOT_FOUND)
|
||||
.build();
|
||||
}
|
||||
|
||||
|
||||
@ -214,8 +212,10 @@ public class OrganizationService {
|
||||
return ResponseEntity.notFound().build();
|
||||
}
|
||||
|
||||
organizationEntityOptional.get().getMembers()
|
||||
.removeIf(memberEntity -> memberEntity.getId().equals(memberEntityOptional.get().getId()));
|
||||
organizationEntityOptional.ifPresent(organizationEntity -> {
|
||||
organizationEntity.getMembers()
|
||||
.removeIf(memberEntity -> memberEntity.getId().equals(memberEntityOptional.get().getId()));
|
||||
});
|
||||
|
||||
return ResponseEntity.ok().build();
|
||||
}
|
||||
@ -235,8 +235,8 @@ public class OrganizationService {
|
||||
}
|
||||
|
||||
OrganizationMembership organizationMembership = new OrganizationMembership();
|
||||
organizationMembership.setMember(memberConverter.toDomain(memberEntityOptional.get()));
|
||||
organizationMembership.setOrg(organizationConverter.toDomain(organizationEntityOptional.get()));
|
||||
organizationMembership.setMember(memberConverter.toDomain(memberEntityOptional.orElseThrow()));
|
||||
organizationMembership.setOrg(organizationConverter.toDomain(organizationEntityOptional.orElseThrow()));
|
||||
|
||||
return ResponseEntity.ok(organizationMembership);
|
||||
}
|
||||
@ -262,6 +262,36 @@ public class OrganizationService {
|
||||
return organizationMembership;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void switchMemberContext(String userId, String organizationId) {
|
||||
OrganizationEntity organizationEntity = organizationRepository.findById(organizationId)
|
||||
.orElseThrow(ResourceNotFoundException::new);
|
||||
Optional<MemberContextEntity> memberContextEntityOptional =
|
||||
memberContextRepository.findByMemberEntityId(userId);
|
||||
if (memberContextEntityOptional.isPresent()) {
|
||||
MemberContextEntity memberContextEntity = memberContextEntityOptional.get();
|
||||
memberContextEntity.setOrganizationEntity(organizationEntity);
|
||||
memberContextRepository.save(memberContextEntity);
|
||||
} else {
|
||||
MemberEntity memberEntity = memberRepository.findById(userId)
|
||||
.orElseThrow(() -> new IllegalArgumentException("Can't find member. Unknown userId=" + userId));
|
||||
MemberContextEntity memberContextEntity = new MemberContextEntity();
|
||||
memberContextEntity.setOrganizationEntity(organizationEntity);
|
||||
memberContextEntity.setMemberEntity(memberEntity);
|
||||
memberContextRepository.save(memberContextEntity);
|
||||
}
|
||||
}
|
||||
|
||||
public MemberContext findMemberContext(String userId) {
|
||||
MemberContextEntity memberContextEntity = memberContextRepository.findByMemberEntityId(userId)
|
||||
.orElseThrow(ResourceNotFoundException::new);
|
||||
|
||||
MemberContext memberContext = new MemberContext();
|
||||
memberContext.setOrganizationId(memberContextEntity.getOrganizationEntity().getId());
|
||||
|
||||
return memberContext;
|
||||
}
|
||||
|
||||
private MemberEntity findOrCreateMember(String userId, String userEmail) {
|
||||
return memberRepository.findById(userId)
|
||||
.orElseGet(() -> {
|
||||
|
10
src/main/resources/db/migration/V6__member_context.sql
Normal file
10
src/main/resources/db/migration/V6__member_context.sql
Normal file
@ -0,0 +1,10 @@
|
||||
CREATE TABLE IF NOT EXISTS org_manager.member_context
|
||||
(
|
||||
id BIGSERIAL NOT NULL,
|
||||
member_id CHARACTER VARYING NOT NULL,
|
||||
organization_id CHARACTER VARYING NOT NULL,
|
||||
CONSTRAINT member_context_pkey PRIMARY KEY (id),
|
||||
|
||||
CONSTRAINT member_context_to_member_fkey FOREIGN KEY (member_id) REFERENCES org_manager.member (id),
|
||||
CONSTRAINT member_context_to_organization_fkey FOREIGN KEY (organization_id) REFERENCES org_manager.organization (id)
|
||||
);
|
@ -1,9 +1,7 @@
|
||||
package com.rbkmoney.orgmanager.controller;
|
||||
|
||||
import com.rbkmoney.orgmanager.entity.InvitationEntity;
|
||||
import com.rbkmoney.orgmanager.entity.MemberEntity;
|
||||
import com.rbkmoney.orgmanager.entity.MemberRoleEntity;
|
||||
import com.rbkmoney.orgmanager.entity.OrganizationEntity;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.rbkmoney.orgmanager.entity.*;
|
||||
import com.rbkmoney.orgmanager.exception.AccessDeniedException;
|
||||
import com.rbkmoney.orgmanager.exception.ResourceNotFoundException;
|
||||
import com.rbkmoney.orgmanager.service.dto.ResourceDto;
|
||||
@ -16,6 +14,7 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@ -311,4 +310,103 @@ public class UserControllerTest extends AbstractControllerTest {
|
||||
assertEquals(2, organizationSearchResultThird.getResult().size());
|
||||
assertNull(organizationSearchResultThird.getContinuationToken());
|
||||
}
|
||||
|
||||
@Test
|
||||
void switchOrganizationWithNewContextCreation() throws Exception {
|
||||
String userId = getUserFromToken();
|
||||
MemberEntity memberEntity = memberRepository.save(testMemberEntity(userId));
|
||||
OrganizationEntity organizationEntity = organizationRepository.save(buildOrganization());
|
||||
String jwtToken = generateRbkAdminJwt();
|
||||
OrganizationSwitchRequest organizationSwitchRequest = new OrganizationSwitchRequest();
|
||||
organizationSwitchRequest.setOrganizationId(organizationEntity.getId());
|
||||
|
||||
mockMvc.perform(put("/user/context")
|
||||
.accept(MediaType.APPLICATION_JSON)
|
||||
.contentType("application/json")
|
||||
.header("Authorization", "Bearer " + jwtToken)
|
||||
.header("X-Request-ID", "testRequestId")
|
||||
.content(objectMapper.writeValueAsString(organizationSwitchRequest))
|
||||
)
|
||||
.andExpect(status().isNoContent());
|
||||
Optional<MemberContextEntity> memberContextEntityOptional =
|
||||
memberContextRepository.findByMemberEntityId(userId);
|
||||
|
||||
assertTrue(memberContextEntityOptional.isPresent());
|
||||
assertEquals(userId, memberContextEntityOptional.get().getMemberEntity().getId());
|
||||
assertEquals(organizationEntity.getId(), memberContextEntityOptional.get().getOrganizationEntity().getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
void switchOrganizationOnUnknown() throws Exception {
|
||||
String userId = getUserFromToken();
|
||||
MemberEntity memberEntity = memberRepository.save(testMemberEntity(userId));
|
||||
String jwtToken = generateRbkAdminJwt();
|
||||
OrganizationSwitchRequest organizationSwitchRequest = new OrganizationSwitchRequest();
|
||||
organizationSwitchRequest.setOrganizationId("testOrgId");
|
||||
|
||||
mockMvc.perform(put("/user/context")
|
||||
.accept(MediaType.APPLICATION_JSON)
|
||||
.contentType("application/json")
|
||||
.header("Authorization", "Bearer " + jwtToken)
|
||||
.header("X-Request-ID", "testRequestId")
|
||||
.content(objectMapper.writeValueAsString(organizationSwitchRequest))
|
||||
)
|
||||
.andExpect(status().isNotFound());
|
||||
}
|
||||
|
||||
@Test
|
||||
void switchOrganizationWithExistsContext() throws Exception {
|
||||
String userId = getUserFromToken();
|
||||
MemberEntity memberEntity = memberRepository.save(testMemberEntity(userId));
|
||||
OrganizationEntity organizationEntity = organizationRepository.save(buildOrganization());
|
||||
MemberContextEntity memberContextEntity = memberContextRepository.save(
|
||||
MemberContextEntity.builder()
|
||||
.memberEntity(memberEntity)
|
||||
.organizationEntity(organizationEntity)
|
||||
.build()
|
||||
);
|
||||
OrganizationEntity newOrganizationEntity = organizationRepository.save(buildOrganization());
|
||||
String jwtToken = generateRbkAdminJwt();
|
||||
OrganizationSwitchRequest organizationSwitchRequest = new OrganizationSwitchRequest();
|
||||
organizationSwitchRequest.setOrganizationId(newOrganizationEntity.getId());
|
||||
|
||||
mockMvc.perform(put("/user/context")
|
||||
.accept(MediaType.APPLICATION_JSON)
|
||||
.contentType("application/json")
|
||||
.header("Authorization", "Bearer " + jwtToken)
|
||||
.header("X-Request-ID", "testRequestId")
|
||||
.content(objectMapper.writeValueAsString(organizationSwitchRequest))
|
||||
)
|
||||
.andExpect(status().isNoContent());
|
||||
Optional<MemberContextEntity> memberContextEntityOptional =
|
||||
memberContextRepository.findByMemberEntityId(userId);
|
||||
|
||||
assertTrue(memberContextEntityOptional.isPresent());
|
||||
assertEquals(newOrganizationEntity.getId(), memberContextEntityOptional.get().getOrganizationEntity().getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
void getMemberContext() throws Exception {
|
||||
String userId = getUserFromToken();
|
||||
MemberEntity memberEntity = memberRepository.save(testMemberEntity(userId));
|
||||
OrganizationEntity organizationEntity = organizationRepository.save(buildOrganization());
|
||||
MemberContextEntity memberContextEntity = memberContextRepository.save(
|
||||
MemberContextEntity.builder()
|
||||
.memberEntity(memberEntity)
|
||||
.organizationEntity(organizationEntity)
|
||||
.build()
|
||||
);
|
||||
String jwtToken = generateRbkAdminJwt();
|
||||
|
||||
MvcResult mvcResult = mockMvc.perform(get("/user/context")
|
||||
.accept(MediaType.APPLICATION_JSON)
|
||||
.header("Authorization", "Bearer " + jwtToken)
|
||||
.header("X-Request-ID", "testRequestId")
|
||||
)
|
||||
.andExpect(status().isOk())
|
||||
.andReturn();
|
||||
|
||||
System.out.println(mvcResult);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -37,10 +37,14 @@ public abstract class AbstractRepositoryTest {
|
||||
@Autowired
|
||||
protected OrganizationRoleRepository organizationRoleRepository;
|
||||
|
||||
@Autowired
|
||||
protected MemberContextRepository memberContextRepository;
|
||||
|
||||
@Transactional
|
||||
@BeforeEach
|
||||
public void setUp() throws Exception {
|
||||
invitationRepository.deleteAll();
|
||||
memberContextRepository.deleteAll();
|
||||
organizationRepository.deleteAll();
|
||||
var members = memberRepository.findAll();
|
||||
members.forEach(it -> it.getRoles().clear());
|
||||
|
Loading…
Reference in New Issue
Block a user