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/add migration scripts #603

Merged
merged 9 commits into from
Nov 23, 2023
4 changes: 2 additions & 2 deletions backend/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@
</dependency>
<dependency>
<groupId>com.tngtech.archunit</groupId>
<artifactId>archunit</artifactId>
<version>1.0.1</version>
<artifactId>archunit-junit5</artifactId>
<version>1.2.0</version>
<scope>test</scope>
</dependency>
<dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public TeamController(TeamAuthorizationService teamAuthorizationService, TeamMap
@Content(mediaType = "application/json", schema = @Schema(implementation = TeamDto.class)) }), })
@GetMapping
public List<TeamDto> getAllTeams(@RequestParam(value = "quarterId", required = false) Long quarterId) {
return teamAuthorizationService.getEntities().stream().map(team -> teamMapper.toDto(team, quarterId)).toList();
return teamAuthorizationService.getAllTeams().stream().map(team -> teamMapper.toDto(team, quarterId)).toList();
}

@Operation(summary = "Create Team", description = "Create a new Team")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import ch.puzzle.okr.dto.UserDto;
import ch.puzzle.okr.mapper.UserMapper;
import ch.puzzle.okr.service.business.UserBusinessService;
import ch.puzzle.okr.service.authorization.UserAuthorizationService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
Expand All @@ -18,11 +18,11 @@
@RequestMapping("api/v1/users")
public class UserController {

private final UserBusinessService userBusinessService;
private final UserAuthorizationService userAuthorizationService;
private final UserMapper userMapper;

public UserController(UserBusinessService userBusinessService, UserMapper userMapper) {
this.userBusinessService = userBusinessService;
public UserController(UserAuthorizationService userAuthorizationService, UserMapper userMapper) {
this.userAuthorizationService = userAuthorizationService;
this.userMapper = userMapper;
}

Expand All @@ -31,7 +31,7 @@ public UserController(UserBusinessService userBusinessService, UserMapper userMa
@Content(mediaType = "application/json", schema = @Schema(implementation = UserDto.class)) }), })
@GetMapping
public List<UserDto> getAllUsers() {
return userBusinessService.getAllUsers().stream().map(userMapper::toDto).toList();
return userAuthorizationService.getAllUsers().stream().map(userMapper::toDto).toList();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package ch.puzzle.okr.converter;

import ch.puzzle.okr.models.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.core.convert.converter.Converter;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.stereotype.Component;

import java.util.List;

@Component
public class JwtConverterFactory {

@Autowired
private ApplicationContext appContext;
private Converter<Jwt, List<String>> jwtOrganisationConverter;
private Converter<Jwt, User> jwtUserConverter;

public synchronized Converter<Jwt, List<String>> getJwtOrganisationConverter() {
if (jwtOrganisationConverter == null) {
// place to load configured converter instead of default converter
jwtOrganisationConverter = appContext.getBean(JwtOrganisationConverter.class);
}
return jwtOrganisationConverter;
}

public synchronized Converter<Jwt, User> getJwtUserConverter() {
if (jwtUserConverter == null) {
// place to load configured converter instead of default converter
jwtUserConverter = appContext.getBean(JwtUserConverter.class);
}
return jwtUserConverter;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ public List<String> convert(Jwt token) {
return organisations.stream().filter(o -> o.startsWith(organisationNamePrefix)).toList();
}
}
logger.warn("empty list of realms or organisations {}", realmAccess);
return List.of();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public User convert(Jwt token) {
.withFirstname(claims.get(firstname).toString()).withLastname(claims.get(lastname).toString())
.withEmail(claims.get(email).toString()).build();
} catch (Exception e) {
logger.error("can not convert user from claims {}", claims);
logger.warn("can not convert user from claims {}", claims);
throw new ResponseStatusException(BAD_REQUEST, "can not convert user from token");
}
}
Expand Down
2 changes: 1 addition & 1 deletion backend/src/main/java/ch/puzzle/okr/dto/TeamDto.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@

import java.util.List;

public record TeamDto(Long id, String name, List<OrganisationDto> organisations) {
public record TeamDto(Long id, int version, String name, List<OrganisationDto> organisations) {
}
3 changes: 2 additions & 1 deletion backend/src/main/java/ch/puzzle/okr/dto/UserDto.java
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
package ch.puzzle.okr.dto;

public record UserDto(Long id, String username, String firstname, String lastname, String email) {
public record UserDto(Long id, int version, String username, String firstname, String lastname, String email,
boolean isWriteable) {
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package ch.puzzle.okr.dto.overview;

public record OverviewTeamDto(Long id, String name, boolean writable, boolean hasInActiveOrganisations) {
public record OverviewTeamDto(Long id, int version, String name, boolean writable, boolean hasInActiveOrganisations) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,8 @@ private OverviewDto createOverviewDto(Overview overview) {
objectives.add(createObjectiveDto(overview));
}
return new OverviewDto(
new OverviewTeamDto(overview.getOverviewId().getTeamId(), overview.getTeamName(),
overview.isWriteable(),
new OverviewTeamDto(overview.getOverviewId().getTeamId(), overview.getTeamVersion(),
overview.getTeamName(), overview.isWriteable(),
organisationBusinessService.teamHasInActiveOrganisations(overview.getOverviewId().getTeamId())),
objectives);
}
Expand Down
4 changes: 2 additions & 2 deletions backend/src/main/java/ch/puzzle/okr/mapper/TeamMapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,13 @@ public TeamDto toDto(Team team, Long quarterId) {
long chosenQuarterId = quarterId == null ? quarterBusinessService.getCurrentQuarter().getId() : quarterId;
List<OrganisationDto> organisationDTOs = team.getAuthorizationOrganisation().stream()
.map(organisationMapper::toDto).toList();
return new TeamDto(team.getId(), team.getName(), organisationDTOs);
return new TeamDto(team.getId(), team.getVersion(), team.getName(), organisationDTOs);
}

public Team toTeam(TeamDto teamDto) {
List<Organisation> organisations = teamDto.organisations().stream().map(organisationMapper::toOrganisation)
.toList();
return Team.Builder.builder().withId(teamDto.id()).withName(teamDto.name())
return Team.Builder.builder().withId(teamDto.id()).withVersion(teamDto.version()).withName(teamDto.name())
.withAuthorizationOrganisation(organisations).build();
}
}
3 changes: 2 additions & 1 deletion backend/src/main/java/ch/puzzle/okr/mapper/UserMapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
@Component
public class UserMapper {
public UserDto toDto(User user) {
return new UserDto(user.getId(), user.getUsername(), user.getFirstname(), user.getLastname(), user.getEmail());
return new UserDto(user.getId(), user.getVersion(), user.getUsername(), user.getFirstname(), user.getLastname(),
user.getEmail(), user.isWriteable());
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package ch.puzzle.okr.mapper;
package ch.puzzle.okr.mapper.role;

import ch.puzzle.okr.models.User;
import ch.puzzle.okr.models.authorization.AuthorizationRole;
Expand All @@ -13,7 +13,7 @@
import static ch.puzzle.okr.models.authorization.AuthorizationRole.*;

@Component
public class RoleMapper {
public class DefaultRoleMapper implements RoleMapper {
private static final String DELIMITER = ",";

@Value("${okr.organisation.name.1stLevel}")
Expand All @@ -23,7 +23,8 @@ public class RoleMapper {
@Value("${okr.user.champion.usernames}")
private String okrChampionUsernames;

public List<AuthorizationRole> mapOrganisationNames(List<String> organisationNames, User user) {
@Override
public List<AuthorizationRole> mapAuthorizationRoles(List<String> organisationNames, User user) {
List<AuthorizationRole> roles = new ArrayList<>();
if (hasFirstLevelOrganisationName(organisationNames) || isOkrChampion(user)) {
roles.addAll(List.of(READ_ALL_DRAFT, WRITE_ALL));
Expand Down
10 changes: 10 additions & 0 deletions backend/src/main/java/ch/puzzle/okr/mapper/role/RoleMapper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package ch.puzzle.okr.mapper.role;

import ch.puzzle.okr.models.User;
import ch.puzzle.okr.models.authorization.AuthorizationRole;

import java.util.List;

public interface RoleMapper {
List<AuthorizationRole> mapAuthorizationRoles(List<String> organisationNames, User user);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package ch.puzzle.okr.mapper.role;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

@Component
public class RoleMapperFactory {
@Autowired
private ApplicationContext appContext;
private RoleMapper roleMapper;

public synchronized RoleMapper getRoleMapper() {
if (roleMapper == null) {
// place to load configured role mapper instead of default role mapper
roleMapper = appContext.getBean(DefaultRoleMapper.class);
}
return roleMapper;
}
}
35 changes: 31 additions & 4 deletions backend/src/main/java/ch/puzzle/okr/models/Team.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,14 @@
import java.util.Objects;

@Entity
public class Team {
public class Team implements WriteableInterface {
@Id
@GeneratedValue(strategy = GenerationType.AUTO, generator = "sequence_team")
private Long id;

@Version
private int version;

@NotBlank(message = "Missing attribute name when saving team")
@NotNull(message = "Attribute name can not be null when saving team")
@Size(min = 2, max = 250, message = "Attribute name must have size between 2 and 250 characters when saving team")
Expand All @@ -22,11 +25,14 @@ public class Team {
@JoinTable(name = "team_organisation", joinColumns = @JoinColumn(name = "team_id"), inverseJoinColumns = @JoinColumn(name = "organisation_id"))
private List<Organisation> authorizationOrganisation;

private transient boolean writeable;

public Team() {
}

private Team(Builder builder) {
id = builder.id;
version = builder.version;
setName(builder.name);
setAuthorizationOrganisation(builder.authorizationOrganisation);
}
Expand All @@ -35,6 +41,10 @@ public Long getId() {
return id;
}

public int getVersion() {
return version;
}

public String getName() {
return name;
}
Expand All @@ -51,9 +61,19 @@ public void setAuthorizationOrganisation(List<Organisation> authorizationOrganis
this.authorizationOrganisation = authorizationOrganisation;
}

@Override
public boolean isWriteable() {
return writeable;
}

@Override
public void setWriteable(boolean writeable) {
this.writeable = writeable;
}

@Override
public String toString() {
return "Team{" + "id=" + id + ", name='" + name + '}';
return "Team{" + "id=" + id + ", version=" + version + ", name='" + name + ", writeable=" + writeable + '}';
}

@Override
Expand All @@ -63,16 +83,18 @@ public boolean equals(Object o) {
if (o == null || getClass() != o.getClass())
return false;
Team team = (Team) o;
return Objects.equals(id, team.id) && Objects.equals(name, team.name);
return Objects.equals(id, team.id) && Objects.equals(version, team.version) && Objects.equals(name, team.name)
&& Objects.equals(writeable, team.writeable);
}

@Override
public int hashCode() {
return Objects.hash(id, name);
return Objects.hash(id, version, name, writeable);
}

public static final class Builder {
private Long id;
private int version;
private String name;

private List<Organisation> authorizationOrganisation;
Expand All @@ -89,6 +111,11 @@ public Builder withId(Long id) {
return this;
}

public Builder withVersion(int version) {
this.version = version;
return this;
}

public Builder withName(String name) {
this.name = name;
return this;
Expand Down
Loading
Loading