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

Feature/1135 Apply Formatters #1221

Merged
merged 6 commits into from
Dec 20, 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
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
17 changes: 8 additions & 9 deletions backend/src/main/java/ch/puzzle/okr/Constants.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
package ch.puzzle.okr;

import static java.util.Map.entry;

import ch.puzzle.okr.dto.checkin.*;
import ch.puzzle.okr.dto.keyresult.*;

import java.util.Map;

import static java.util.Map.entry;

public class Constants {
private Constants() {
}
Expand All @@ -29,11 +28,11 @@ private Constants() {
public static final String CHECK_IN_KEY_RESULT_ID_ATTRIBUTE_NAME = "keyResultId";
public static final String KEY_RESULT_TYPE_ATTRIBUTE_NAME = "keyResultType";

public static final Map<String, Class<? extends KeyResultDto>> KEY_RESULT_MAP = Map.ofEntries(
entry(KEY_RESULT_TYPE_METRIC, KeyResultMetricDto.class),
entry(KEY_RESULT_TYPE_ORDINAL, KeyResultOrdinalDto.class));
public static final Map<String, Class<? extends KeyResultDto>> KEY_RESULT_MAP = Map
.ofEntries(entry(KEY_RESULT_TYPE_METRIC, KeyResultMetricDto.class),
entry(KEY_RESULT_TYPE_ORDINAL, KeyResultOrdinalDto.class));

public static final Map<String, Class<? extends CheckInDto>> CHECK_IN_MAP = Map.ofEntries(
entry(KEY_RESULT_TYPE_METRIC, CheckInMetricDto.class),
entry(KEY_RESULT_TYPE_ORDINAL, CheckInOrdinalDto.class));
public static final Map<String, Class<? extends CheckInDto>> CHECK_IN_MAP = Map
.ofEntries(entry(KEY_RESULT_TYPE_METRIC, CheckInMetricDto.class),
entry(KEY_RESULT_TYPE_ORDINAL, CheckInOrdinalDto.class));
}
22 changes: 18 additions & 4 deletions backend/src/main/java/ch/puzzle/okr/ErrorKey.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,22 @@
package ch.puzzle.okr;

public enum ErrorKey {
ATTRIBUTE_NULL, ATTRIBUTE_CHANGED, ATTRIBUTE_SET_FORBIDDEN, ATTRIBUTE_NOT_SET, ATTRIBUTE_CANNOT_CHANGE,
ATTRIBUTE_MUST_BE_DRAFT, KEY_RESULT_CONVERSION, ALREADY_EXISTS_SAME_NAME, CONVERT_TOKEN, DATA_HAS_BEEN_UPDATED,
MODEL_NULL, MODEL_WITH_ID_NOT_FOUND, NOT_AUTHORIZED_TO_READ, NOT_AUTHORIZED_TO_WRITE, NOT_AUTHORIZED_TO_DELETE,
TOKEN_NULL, TRIED_TO_DELETE_LAST_ADMIN, TRIED_TO_REMOVE_LAST_OKR_CHAMPION
ATTRIBUTE_NULL,
ATTRIBUTE_CHANGED,
ATTRIBUTE_SET_FORBIDDEN,
ATTRIBUTE_NOT_SET,
ATTRIBUTE_CANNOT_CHANGE,
ATTRIBUTE_MUST_BE_DRAFT,
KEY_RESULT_CONVERSION,
ALREADY_EXISTS_SAME_NAME,
CONVERT_TOKEN,
DATA_HAS_BEEN_UPDATED,
MODEL_NULL,
MODEL_WITH_ID_NOT_FOUND,
NOT_AUTHORIZED_TO_READ,
NOT_AUTHORIZED_TO_WRITE,
NOT_AUTHORIZED_TO_DELETE,
TOKEN_NULL,
TRIED_TO_DELETE_LAST_ADMIN,
TRIED_TO_REMOVE_LAST_OKR_CHAMPION
}
5 changes: 1 addition & 4 deletions backend/src/main/java/ch/puzzle/okr/ForwardFilter.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,11 @@
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletRequest;
import java.io.IOException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.GenericFilterBean;

import java.io.IOException;
import java.util.Arrays;

public class ForwardFilter extends GenericFilterBean {

private static final Logger logger = LoggerFactory.getLogger(ForwardFilter.class);
Expand Down
3 changes: 1 addition & 2 deletions backend/src/main/java/ch/puzzle/okr/OkrErrorAttributes.java
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
package ch.puzzle.okr;

import ch.puzzle.okr.exception.OkrResponseStatusException;
import java.util.Map;
import org.springframework.boot.web.error.ErrorAttributeOptions;
import org.springframework.boot.web.servlet.error.DefaultErrorAttributes;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.WebRequest;

import java.util.Map;

@Component
public class OkrErrorAttributes extends DefaultErrorAttributes {

Expand Down
12 changes: 9 additions & 3 deletions backend/src/main/java/ch/puzzle/okr/OpenAPI30Configuration.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,15 @@ public class OpenAPI30Configuration {
@Bean
public OpenAPI customizeOpenAPI() {
final String securitySchemeName = "bearerAuth";
return new OpenAPI().addSecurityItem(new SecurityRequirement().addList(securitySchemeName))
.components(new Components().addSecuritySchemes(securitySchemeName, new SecurityScheme()
.name(securitySchemeName).type(SecurityScheme.Type.HTTP).scheme("bearer").bearerFormat("JWT")));
return new OpenAPI()
.addSecurityItem(new SecurityRequirement().addList(securitySchemeName))
.components(new Components()
.addSecuritySchemes(securitySchemeName,
new SecurityScheme()
.name(securitySchemeName)
.type(SecurityScheme.Type.HTTP)
.scheme("bearer")
.bearerFormat("JWT")));
}

}
56 changes: 29 additions & 27 deletions backend/src/main/java/ch/puzzle/okr/SecurityConfig.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package ch.puzzle.okr;

import static org.springframework.security.web.header.writers.CrossOriginEmbedderPolicyHeaderWriter.CrossOriginEmbedderPolicy.REQUIRE_CORP;
import static org.springframework.security.web.header.writers.ReferrerPolicyHeaderWriter.ReferrerPolicy.NO_REFERRER;
import static org.springframework.security.web.header.writers.XXssProtectionHeaderWriter.HeaderValue.ENABLED_MODE_BLOCK;

import com.nimbusds.jose.proc.SecurityContext;
import com.nimbusds.jwt.proc.ConfigurableJWTProcessor;
import com.nimbusds.jwt.proc.DefaultJWTProcessor;
Expand Down Expand Up @@ -33,10 +37,6 @@
import org.springframework.security.web.header.writers.CrossOriginResourcePolicyHeaderWriter;
import org.springframework.security.web.header.writers.StaticHeadersWriter;

import static org.springframework.security.web.header.writers.CrossOriginEmbedderPolicyHeaderWriter.CrossOriginEmbedderPolicy.REQUIRE_CORP;
import static org.springframework.security.web.header.writers.ReferrerPolicyHeaderWriter.ReferrerPolicy.NO_REFERRER;
import static org.springframework.security.web.header.writers.XXssProtectionHeaderWriter.HeaderValue.ENABLED_MODE_BLOCK;

@Configuration
@EnableWebSecurity
@EnableMethodSecurity
Expand All @@ -58,10 +58,12 @@ public SecurityFilterChain apiSecurityFilterChain(HttpSecurity http, @Value("${c
http.addFilterAfter(new ForwardFilter(), BasicAuthenticationFilter.class);
logger.debug("*** apiSecurityFilterChain reached");
setHeaders(http);
return http.cors(Customizer.withDefaults())
return http
.cors(Customizer.withDefaults())
.authorizeHttpRequests(e -> e.requestMatchers("/api/**").authenticated().anyRequest().permitAll())
.exceptionHandling(e -> e.authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED)))
.oauth2ResourceServer(oauth2 -> oauth2.jwt(Customizer.withDefaults())).build();
.oauth2ResourceServer(oauth2 -> oauth2.jwt(Customizer.withDefaults()))
.build();
}

@Bean
Expand All @@ -75,14 +77,15 @@ JWTProcessor<SecurityContext> jwtProcessor(JWTClaimsSetAwareJWSKeySelector<Secur
JwtDecoder jwtDecoder(JWTProcessor<SecurityContext> jwtProcessor, OAuth2TokenValidator<Jwt> jwtValidator) {
NimbusJwtDecoder decoder = new NimbusJwtDecoder(jwtProcessor);
OAuth2TokenValidator<Jwt> validator = new DelegatingOAuth2TokenValidator<>(JwtValidators.createDefault(),
jwtValidator);
jwtValidator);
MasterEvarior marked this conversation as resolved.
Show resolved Hide resolved
decoder.setJwtValidator(validator);
return decoder;
}

private HttpSecurity setHeaders(HttpSecurity http) throws Exception {
return http
.headers(headers -> headers.contentSecurityPolicy(c -> c.policyDirectives(okrContentSecurityPolicy()))
.headers(headers -> headers
.contentSecurityPolicy(c -> c.policyDirectives(okrContentSecurityPolicy()))
.crossOriginEmbedderPolicy(c -> c.policy(REQUIRE_CORP))
.crossOriginOpenerPolicy(c -> c.policy(OPENER_SAME_ORIGIN))
.crossOriginResourcePolicy(c -> c.policy(RESOURCE_SAME_ORIGIN))
Expand All @@ -96,32 +99,31 @@ private HttpSecurity setHeaders(HttpSecurity http) throws Exception {

private String okrContentSecurityPolicy() {
return "default-src 'self';" //
+ "script-src 'self' 'unsafe-inline';" //
+ " style-src 'self' 'unsafe-inline';" //
+ " object-src 'none';" //
+ " base-uri 'self';" //
+ " connect-src 'self' " + connectSrc + ";" //
+ " font-src 'self';" //
+ " frame-src 'self';" //
+ " img-src 'self' data: ;" //
+ " manifest-src 'self';" //
+ " media-src 'self';" //
+ " worker-src 'none';"; //
+ "script-src 'self' 'unsafe-inline';" //
+ " style-src 'self' 'unsafe-inline';" //
+ " object-src 'none';" //
+ " base-uri 'self';" //
+ " connect-src 'self' " + connectSrc + ";" //
+ " font-src 'self';" //
+ " frame-src 'self';" //
+ " img-src 'self' data: ;" //
+ " manifest-src 'self';" //
+ " media-src 'self';" //
+ " worker-src 'none';"; //
}

private String okrPermissionPolicy() {
return "accelerometer=(), ambient-light-sensor=(), autoplay=(), "
+ "battery=(), camera=(), cross-origin-isolated=(), display-capture=(), document-domain=(), encrypted-media=(), "
+ "execution-while-not-rendered=(), execution-while-out-of-viewport=(), fullscreen=(),"
+ " geolocation=(), gyroscope=(), keyboard-map=(), magnetometer=(), microphone=(), "
+ "midi=(), navigation-override=(), payment=(), picture-in-picture=(),"
+ " publickey-credentials-get=(), screen-wake-lock=(), sync-xhr=(self), "
+ "usb=(), web-share=(), xr-spatial-tracking=()";
+ "battery=(), camera=(), cross-origin-isolated=(), display-capture=(), document-domain=(), encrypted-media=(), "
+ "execution-while-not-rendered=(), execution-while-out-of-viewport=(), fullscreen=(),"
+ " geolocation=(), gyroscope=(), keyboard-map=(), magnetometer=(), microphone=(), "
+ "midi=(), navigation-override=(), payment=(), picture-in-picture=(),"
+ " publickey-credentials-get=(), screen-wake-lock=(), sync-xhr=(self), "
+ "usb=(), web-share=(), xr-spatial-tracking=()";
}

@Bean
public AuthenticationEventPublisher authenticationEventPublisher(
ApplicationEventPublisher applicationEventPublisher) {
public AuthenticationEventPublisher authenticationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
return new DefaultAuthenticationEventPublisher(applicationEventPublisher);
}

Expand Down
3 changes: 1 addition & 2 deletions backend/src/main/java/ch/puzzle/okr/UserKeyGenerator.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@

import ch.puzzle.okr.models.User;
import ch.puzzle.okr.multitenancy.TenantContext;
import org.springframework.cache.interceptor.KeyGenerator;

import java.lang.reflect.Method;
import java.text.MessageFormat;
import org.springframework.cache.interceptor.KeyGenerator;

public class UserKeyGenerator implements KeyGenerator {
@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,8 @@
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.*;

import java.util.List;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("api/v2/action")
Expand All @@ -30,8 +29,8 @@ public ActionController(ActionAuthorizationService actionAuthorizationService, A
@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 updateActions(
@io.swagger.v3.oas.annotations.parameters.RequestBody(description = "The Action as json to update existing Actions.", required = true) @RequestBody List<ActionDto> actionDtoList) {
public void updateActions(@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 = actionMapper.toActions(actionDtoList);
actionAuthorizationService.updateEntities(actionList);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,22 @@
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 java.util.List;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
@RequestMapping("api/v2/alignments")
public class AlignmentController {
private final AlignmentSelectionMapper alignmentSelectionMapper;
private final AlignmentSelectionBusinessService alignmentSelectionBusinessService;

public AlignmentController(AlignmentSelectionMapper alignmentSelectionMapper,
AlignmentSelectionBusinessService alignmentSelectionBusinessService) {
AlignmentSelectionBusinessService alignmentSelectionBusinessService) {
this.alignmentSelectionMapper = alignmentSelectionMapper;
this.alignmentSelectionBusinessService = alignmentSelectionBusinessService;
}
Expand All @@ -35,11 +34,12 @@ public AlignmentController(AlignmentSelectionMapper alignmentSelectionMapper,
@Content(mediaType = "application/json", schema = @Schema(implementation = AlignmentObjectiveDto.class)) }),
@ApiResponse(responseCode = "400", description = "Can't return list of objectives with their key results to select the alignment", content = @Content) })
@GetMapping("/selections")
public ResponseEntity<List<AlignmentObjectiveDto>> getAlignmentSelections(
@RequestParam(required = false, defaultValue = "", name = "quarter") Long quarterFilter,
@RequestParam(required = false, defaultValue = "", name = "team") Long teamFilter) {
return ResponseEntity.status(HttpStatus.OK)
.body(alignmentSelectionMapper.toDto(alignmentSelectionBusinessService
.getAlignmentSelectionByQuarterIdAndTeamIdNot(quarterFilter, teamFilter)));
public ResponseEntity<List<AlignmentObjectiveDto>> getAlignmentSelections(@RequestParam(required = false, defaultValue = "", name = "quarter") Long quarterFilter,
@RequestParam(required = false, defaultValue = "", name = "team") Long teamFilter) {
return ResponseEntity
.status(HttpStatus.OK)
.body(alignmentSelectionMapper
.toDto(alignmentSelectionBusinessService
.getAlignmentSelectionByQuarterIdAndTeamIdNot(quarterFilter, teamFilter)));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ public CheckInController(CheckInMapper checkInMapper, CheckInAuthorizationServic
@ApiResponse(responseCode = "404", description = "Did not find a Check-in with a specified ID", content = @Content) })
@GetMapping("/{id}")
public ResponseEntity<CheckInDto> getCheckInById(@PathVariable long id) {
return ResponseEntity.status(HttpStatus.OK)
return ResponseEntity
.status(HttpStatus.OK)
.body(checkInMapper.toDto(this.checkInAuthorizationService.getEntityById(id)));
}

Expand All @@ -47,9 +48,8 @@ public ResponseEntity<CheckInDto> getCheckInById(@PathVariable long id) {
@ApiResponse(responseCode = "404", description = "Given ID of Check-in wasn't found.", content = @Content),
@ApiResponse(responseCode = "422", description = "Can't update Check-in since Check-in was updated or deleted by another user.", content = @Content) })
@PutMapping("/{id}")
public ResponseEntity<CheckInDto> updateCheckIn(
@Parameter(description = "The ID for updating a Check-in.", required = true) @PathVariable Long id,
@io.swagger.v3.oas.annotations.parameters.RequestBody(description = "The Check-in as json to update an existing Check-in.", required = true) @RequestBody CheckInDto checkInDto) {
public ResponseEntity<CheckInDto> updateCheckIn(@Parameter(description = "The ID for updating a Check-in.", required = true)
@PathVariable Long id, @io.swagger.v3.oas.annotations.parameters.RequestBody(description = "The Check-in as json to update an existing Check-in.", required = true) @RequestBody CheckInDto checkInDto) {
CheckIn checkIn = checkInMapper.toCheckIn(checkInDto);
CheckInDto updatedCheckIn = this.checkInMapper
.toDto(this.checkInAuthorizationService.updateEntity(id, checkIn));
Expand All @@ -63,8 +63,8 @@ public ResponseEntity<CheckInDto> updateCheckIn(
@ApiResponse(responseCode = "400", description = "Can't create new Check-in, not allowed to give an ID", content = @Content),
@ApiResponse(responseCode = "401", description = "Not authorized to create Check-in", content = @Content) })
@PostMapping
public ResponseEntity<CheckInDto> createCheckIn(
@io.swagger.v3.oas.annotations.parameters.RequestBody(description = "The Check-in as json to create a new Check-in.", required = true) @RequestBody CheckInDto checkInDto) {
public ResponseEntity<CheckInDto> createCheckIn(@io.swagger.v3.oas.annotations.parameters.RequestBody(description = "The Check-in as json to create a new Check-in.", required = true)
@RequestBody CheckInDto checkInDto) {
CheckIn checkIn = checkInMapper.toCheckIn(checkInDto);
CheckInDto createdCheckIn = checkInMapper.toDto(checkInAuthorizationService.createEntity(checkIn));
return ResponseEntity.status(HttpStatus.CREATED).body(createdCheckIn);
Expand All @@ -75,8 +75,8 @@ public ResponseEntity<CheckInDto> createCheckIn(
@ApiResponse(responseCode = "401", description = "Not authorized to delete Check-in", content = @Content),
@ApiResponse(responseCode = "404", description = "Did not find the Check-in with requested ID") })
@DeleteMapping("/{id}")
public void deleteCheckInById(
@Parameter(description = "The ID of an Check-in to delete it.", required = true) @PathVariable long id) {
public void deleteCheckInById(@Parameter(description = "The ID of an Check-in to delete it.", required = true)
@PathVariable long id) {
this.checkInAuthorizationService.deleteEntityById(id);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ public ClientConfigController(ClientConfigService configService) {

@GetMapping("/config")
public ResponseEntity<ClientConfigDto> getConfig(HttpServletRequest request) {
return ResponseEntity.status(HttpStatus.OK)
return ResponseEntity
.status(HttpStatus.OK)
.body(configService.getConfigBasedOnActiveEnv(request.getServerName()));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public class CompletedController {
private final CompletedMapper completedMapper;

public CompletedController(CompletedAuthorizationService completedAuthorizationService,
CompletedMapper completedMapper) {
CompletedMapper completedMapper) {
this.completedAuthorizationService = completedAuthorizationService;
this.completedMapper = completedMapper;
}
Expand Down
Loading
Loading