-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
f7bb13e
commit 4a03ccb
Showing
12 changed files
with
279 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
37 changes: 37 additions & 0 deletions
37
backend/src/main/java/ch/puzzle/okr/SpringSecurityAuditorAware.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
package ch.puzzle.okr; | ||
|
||
import ch.puzzle.okr.models.User; | ||
import ch.puzzle.okr.security.JwtHelper; | ||
import ch.puzzle.okr.service.authorization.AuthorizationService; | ||
import org.springframework.data.domain.AuditorAware; | ||
import org.springframework.security.core.Authentication; | ||
import org.springframework.security.core.context.SecurityContext; | ||
import org.springframework.security.core.context.SecurityContextHolder; | ||
import org.springframework.security.oauth2.jwt.Jwt; | ||
import org.springframework.stereotype.Component; | ||
|
||
import java.util.Optional; | ||
|
||
@Component | ||
class SpringSecurityAuditorAware implements AuditorAware<User> { | ||
|
||
private final JwtHelper jwtHelper; | ||
private final AuthorizationService authorizationService; | ||
|
||
public SpringSecurityAuditorAware(JwtHelper jwtHelper, AuthorizationService authorizationService) { | ||
this.jwtHelper = jwtHelper; | ||
this.authorizationService = authorizationService; | ||
} | ||
|
||
@Override | ||
public Optional<User> getCurrentAuditor() { | ||
return Optional | ||
.ofNullable(SecurityContextHolder.getContext()) | ||
.map(SecurityContext::getAuthentication) | ||
.filter(Authentication::isAuthenticated) | ||
.map(Authentication::getPrincipal) | ||
.map(e -> (Jwt) e) | ||
.map(jwtHelper::getUserFromJwt) | ||
.map(e -> authorizationService.updateOrAddAuthorizationUser().user()); | ||
} | ||
} |
58 changes: 58 additions & 0 deletions
58
backend/src/main/java/ch/puzzle/okr/controller/UnitController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
package ch.puzzle.okr.controller; | ||
|
||
import ch.puzzle.okr.dto.ActionDto; | ||
import ch.puzzle.okr.dto.UnitDto; | ||
import ch.puzzle.okr.mapper.UnitMapper; | ||
import ch.puzzle.okr.models.Unit; | ||
import ch.puzzle.okr.service.authorization.UnitAuthorizationService; | ||
import io.swagger.v3.oas.annotations.Operation; | ||
import io.swagger.v3.oas.annotations.media.Content; | ||
import io.swagger.v3.oas.annotations.media.Schema; | ||
import io.swagger.v3.oas.annotations.responses.ApiResponse; | ||
import io.swagger.v3.oas.annotations.responses.ApiResponses; | ||
import org.springframework.web.bind.annotation.*; | ||
|
||
@RestController | ||
@RequestMapping("api/v2/unit") | ||
public class UnitController { | ||
private final UnitAuthorizationService unitAuthorizationService; | ||
private final UnitMapper unitMapper; | ||
|
||
public UnitController(UnitAuthorizationService unitAuthorizationService, UnitMapper unitMapper) { | ||
this.unitAuthorizationService = unitAuthorizationService; | ||
this.unitMapper = unitMapper; | ||
} | ||
|
||
@Operation(summary = "Update Actions", description = "Update Actions of KeyResult") | ||
@ApiResponses(value = { | ||
@ApiResponse(responseCode = "200", description = "Updated Actions of KeyResult", content = { | ||
@Content(mediaType = "application/json", schema = @Schema(implementation = ActionDto.class)) }), | ||
@ApiResponse(responseCode = "400", description = "Can't update Actions, attributes are not set", content = @Content) }) | ||
@PostMapping | ||
public UnitDto createUnit(@io.swagger.v3.oas.annotations.parameters.RequestBody(description = "The Action as json to update existing Actions.", required = true) | ||
@RequestBody UnitDto unitDto) { | ||
Unit unit = unitMapper.toUnit(unitDto); | ||
return unitMapper.toDto(unitAuthorizationService.createUnit(unit)); | ||
} | ||
|
||
|
||
// @Operation(summary = "Update Actions", description = "Update Actions of KeyResult") | ||
// @ApiResponses(value = { | ||
// @ApiResponse(responseCode = "200", description = "Updated Actions of KeyResult", content = { | ||
// @Content(mediaType = "application/json", schema = @Schema(implementation = ActionDto.class)) }), | ||
// @ApiResponse(responseCode = "400", description = "Can't update Actions, attributes are not set", content = @Content) }) | ||
// @PutMapping | ||
// public void updateUnit(@io.swagger.v3.oas.annotations.parameters.RequestBody(description = "The Action as json to update existing Actions.", required = true) | ||
// @RequestBody List<ActionDto> actionDtoList) { | ||
// List<Action> actionList = unitMapper.toActions(actionDtoList); | ||
// unitAuthorizationService.updateEntities(actionList); | ||
// } | ||
// | ||
// @Operation(summary = "Delete Action by Id", description = "Delete Action by Id") | ||
// @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "Deleted Action by Id"), | ||
// @ApiResponse(responseCode = "404", description = "Did not find the Action with requested id") }) | ||
// @DeleteMapping("/{unitId}") | ||
// public void deleteUnitById(@PathVariable long unitId) { | ||
// unitAuthorizationService.deleteActionByActionId(actionId); | ||
// } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
package ch.puzzle.okr.dto; | ||
|
||
public record UnitDto(Long id, String unitName, UserDto owner) { | ||
} |
37 changes: 37 additions & 0 deletions
37
backend/src/main/java/ch/puzzle/okr/mapper/UnitMapper.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
package ch.puzzle.okr.mapper; | ||
|
||
import ch.puzzle.okr.dto.ObjectiveDto; | ||
import ch.puzzle.okr.dto.UnitDto; | ||
import ch.puzzle.okr.dto.UserDto; | ||
import ch.puzzle.okr.models.Objective; | ||
import ch.puzzle.okr.models.Unit; | ||
import ch.puzzle.okr.service.business.QuarterBusinessService; | ||
import ch.puzzle.okr.service.business.TeamBusinessService; | ||
import org.springframework.stereotype.Component; | ||
|
||
import java.time.LocalDateTime; | ||
import java.util.List; | ||
|
||
@Component | ||
public class UnitMapper { | ||
|
||
private final UserMapper userMapper; | ||
|
||
public UnitMapper(UserMapper userMapper) { | ||
this.userMapper = userMapper; | ||
} | ||
|
||
public UnitDto toDto(Unit unit) { | ||
return new UnitDto(unit.getId(), | ||
unit.getUnitName(), | ||
userMapper.toDto(unit.getCreatedBy())); | ||
} | ||
|
||
public Unit toUnit(UnitDto objectiveDto) { | ||
return Unit.Builder | ||
.builder() | ||
.id(objectiveDto.id()) | ||
.unitName(objectiveDto.unitName()) | ||
.build(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
38 changes: 38 additions & 0 deletions
38
backend/src/main/java/ch/puzzle/okr/service/authorization/UnitAuthorizationService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
package ch.puzzle.okr.service.authorization; | ||
|
||
import ch.puzzle.okr.Constants; | ||
import ch.puzzle.okr.ErrorKey; | ||
import ch.puzzle.okr.exception.OkrResponseStatusException; | ||
import ch.puzzle.okr.models.Unit; | ||
import ch.puzzle.okr.models.authorization.AuthorizationUser; | ||
import ch.puzzle.okr.service.business.UnitBusinessService; | ||
import org.springframework.http.HttpStatus; | ||
import org.springframework.stereotype.Service; | ||
|
||
@Service | ||
public class UnitAuthorizationService { | ||
private final UnitBusinessService unitBusinessService; | ||
private final AuthorizationService authorizationService; | ||
|
||
public UnitAuthorizationService(UnitBusinessService unitBusinessService, | ||
AuthorizationService authorizationService) { | ||
this.unitBusinessService = unitBusinessService; | ||
this.authorizationService = authorizationService; | ||
} | ||
|
||
public Unit createUnit(Unit unit) { | ||
return unitBusinessService.createEntity(unit); | ||
} | ||
|
||
public Unit editUnit(Unit unit) { | ||
AuthorizationUser authorizationUser = authorizationService.updateOrAddAuthorizationUser(); | ||
if(!isOwner(unit, authorizationUser)) { | ||
throw new OkrResponseStatusException(HttpStatus.FORBIDDEN, ErrorKey.NOT_AUTHORIZED_TO_WRITE, Constants.UNIT); | ||
} | ||
return unitBusinessService.updateEntity(unit.getId(), unit); | ||
} | ||
|
||
private boolean isOwner(Unit unit, AuthorizationUser authorizationUser) { | ||
return unitBusinessService.getEntityById(unit.getId()).getCreatedBy().getId().equals(authorizationUser.user().getId()); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
55 changes: 55 additions & 0 deletions
55
backend/src/test/java/ch/puzzle/okr/controller/UnitControllerIT.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
package ch.puzzle.okr.controller; | ||
|
||
import ch.puzzle.okr.multitenancy.TenantConfigProvider; | ||
import ch.puzzle.okr.multitenancy.TenantContext; | ||
import ch.puzzle.okr.service.persistence.UnitPersistenceService; | ||
import ch.puzzle.okr.test.SpringIntegrationTest; | ||
import ch.puzzle.okr.test.TestHelper; | ||
import com.nimbusds.jwt.JWT; | ||
import jdk.jfr.ContentType; | ||
import org.hamcrest.Matchers; | ||
import org.hamcrest.core.Is; | ||
import org.junit.jupiter.api.Test; | ||
import org.junit.jupiter.api.extension.ExtendWith; | ||
import org.mockito.ArgumentMatchers; | ||
import org.mockito.Mockito; | ||
import org.mockito.junit.jupiter.MockitoExtension; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; | ||
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; | ||
import org.springframework.security.oauth2.jwt.Jwt; | ||
import org.springframework.security.oauth2.jwt.JwtDecoder; | ||
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken; | ||
import org.springframework.security.test.context.support.WithMockUser; | ||
import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors; | ||
import org.springframework.test.context.bean.override.mockito.MockitoBean; | ||
import org.springframework.test.web.servlet.MockMvc; | ||
import org.springframework.test.web.servlet.result.MockMvcResultMatchers; | ||
|
||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; | ||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; | ||
|
||
@WithMockUser | ||
@AutoConfigureMockMvc | ||
@SpringIntegrationTest | ||
class UnitControllerIT { | ||
@Autowired | ||
private MockMvc mvc; | ||
private final String URL_BASE = "/api/v2/unit"; | ||
String CREATE_UNIT_BODY = "{\"unitName\":\"TestUnit\"}"; | ||
|
||
@Autowired | ||
private UnitPersistenceService unitPersistenceService; | ||
|
||
@Test | ||
void test() throws Exception { | ||
Jwt jwt = TestHelper.mockJwtToken("Jaya", "Norris", "[email protected]"); | ||
|
||
TenantContext.setCurrentTenant("pitc"); | ||
mvc | ||
.perform(post(URL_BASE).with(SecurityMockMvcRequestPostProcessors.csrf()). with(SecurityMockMvcRequestPostProcessors.jwt().jwt(jwt)) | ||
.content(CREATE_UNIT_BODY).contentType("application/json")) | ||
.andExpect(MockMvcResultMatchers.status().isOk()) | ||
.andExpect(jsonPath("$.owner.email", Is.is("[email protected]"))); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters