diff --git a/build.gradle b/build.gradle index c61339b..25ea948 100644 --- a/build.gradle +++ b/build.gradle @@ -59,9 +59,11 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-security' implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' implementation 'org.springframework.boot:spring-boot-starter-web' - + + compile group: 'org.springframework.boot', name: 'spring-boot-starter-oauth2-client', version: '2.2.5.RELEASE' + implementation 'org.keycloak:keycloak-spring-boot-starter:9.0.0' - implementation 'org.keycloak.bom:keycloak-adapter-bom:3.3.0.Final' + implementation 'org.keycloak.bom:keycloak-adapter-bom:9.0.0' implementation 'mops:styleguide:2.1.0' implementation 'io.springfox:springfox-swagger2:2.9.2' implementation 'io.springfox:springfox-swagger-ui:2.9.2' @@ -73,6 +75,8 @@ dependencies { runtimeOnly 'com.h2database:h2' runtimeOnly 'mysql:mysql-connector-java' + compile group: 'org.springframework.security.oauth', name: 'spring-security-oauth2', version: '2.4.0.RELEASE' + testImplementation 'org.assertj:assertj-core:3.15.0' testImplementation('org.springframework.boot:spring-boot-starter-test') { exclude group: 'org.junit.vintage', module: 'junit-vintage-engine' @@ -80,6 +84,7 @@ dependencies { testImplementation 'org.springframework.security:spring-security-test' testImplementation 'com.tngtech.archunit:archunit-junit5:0.13.1' implementation 'junit:junit:4.12' + implementation 'junit:junit:4.12' } test { diff --git a/src/main/java/mops/gruppen2/controller/APIController.java b/src/main/java/mops/gruppen2/controller/APIController.java index f4d18ef..12591a1 100644 --- a/src/main/java/mops/gruppen2/controller/APIController.java +++ b/src/main/java/mops/gruppen2/controller/APIController.java @@ -11,6 +11,7 @@ import mops.gruppen2.service.APIFormatterService; import mops.gruppen2.service.EventService; import mops.gruppen2.service.GroupService; import mops.gruppen2.service.SerializationService; +import org.springframework.security.access.annotation.Secured; import org.springframework.web.bind.annotation.*; import java.util.List; @@ -33,6 +34,7 @@ public class APIController { } @GetMapping("/updateGroups/{status}") + @Secured("ROLE_api_user") @ApiOperation(value = "Gibt alle Gruppen zurück in denen sich etwas geändert hat") public UpdatedGroupRequestMapper updateGroup(@ApiParam("Letzter Status des Anfragestellers") @PathVariable Long status) throws EventException { List events = eventService.getNewEvents(status); @@ -42,12 +44,14 @@ public class APIController { } @GetMapping("/getGroupIdsOfUser/{teilnehmer}") + @Secured("ROLE_api_user") @ApiOperation(value = "Gibt alle Gruppen zurück in denen sich ein Teilnehmer befindet") public List getGroupsOfUser(@ApiParam("Teilnehmer dessen groupIds zurückgegeben werden sollen") @PathVariable String teilnehmer) throws EventException { return eventService.getGroupsOfUser(teilnehmer); } @GetMapping("/getGroup/{groupId}") + @Secured("ROLE_api_user") @ApiOperation(value = "Gibt die Gruppe mit der als Parameter mitgegebenden groupId zurück") public Group getGroupFromId(@ApiParam("GruppenId der gefordeten Gruppe") @PathVariable Long groupId) throws EventException{ List eventList = eventService.getEventsOfGroup(groupId); diff --git a/src/main/java/mops/gruppen2/controller/Gruppen2Controller.java b/src/main/java/mops/gruppen2/controller/Gruppen2Controller.java index 89a81d2..5883a89 100644 --- a/src/main/java/mops/gruppen2/controller/Gruppen2Controller.java +++ b/src/main/java/mops/gruppen2/controller/Gruppen2Controller.java @@ -3,8 +3,7 @@ package mops.gruppen2.controller; import mops.gruppen2.config.Gruppen2Config; import mops.gruppen2.domain.Exceptions.EventException; import mops.gruppen2.domain.Group; -import mops.gruppen2.domain.GroupType; -import mops.gruppen2.domain.Role; + import mops.gruppen2.domain.User; import mops.gruppen2.domain.event.CreateGroupEvent; import mops.gruppen2.security.Account; @@ -15,12 +14,12 @@ import org.springframework.http.HttpStatus; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.*; +import org.springframework.web.client.RestTemplate; import org.springframework.web.server.ResponseStatusException; import javax.annotation.security.RolesAllowed; import java.util.ArrayList; import java.util.List; -import java.util.Set; @Controller @RequestMapping("/gruppen2") @@ -114,4 +113,16 @@ public class Gruppen2Controller { throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Group not found"); } + @RolesAllowed({"ROLE_orga", "ROLE_studentin", "ROLE_actuator)"}) + @GetMapping("/detailsSearch") + public String showGroupDetailsNoMember (KeycloakAuthenticationToken token, Model model, @RequestParam (value="id") Long id) throws EventException { + model.addAttribute("account", keyCloakService.createAccountFromPrincipal(token)); + Group group = userService.getGroupById(id); + if (group!=null) { + model.addAttribute("group", group); + return "detailsNoMember"; + } + throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Group not found"); + } + } diff --git a/src/main/java/mops/gruppen2/security/KeycloakConfig.java b/src/main/java/mops/gruppen2/security/KeycloakConfig.java index 57032ab..d707be1 100644 --- a/src/main/java/mops/gruppen2/security/KeycloakConfig.java +++ b/src/main/java/mops/gruppen2/security/KeycloakConfig.java @@ -1,8 +1,13 @@ package mops.gruppen2.security; +import org.keycloak.OAuth2Constants; import org.keycloak.adapters.springboot.KeycloakSpringBootConfigResolver; +import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.security.oauth2.client.OAuth2RestTemplate; +import org.springframework.security.oauth2.client.token.grant.client.ClientCredentialsResourceDetails; +import org.springframework.web.client.RestTemplate; /** * WORKAROUND for https://issues.redhat.com/browse/KEYCLOAK-11282 @@ -15,4 +20,35 @@ public class KeycloakConfig { public KeycloakSpringBootConfigResolver keycloakConfigResolver() { return new KeycloakSpringBootConfigResolver(); } + + @Value("${keycloak.resource}") + + private String clientId; + + @Value("${keycloak.credentials.secret}") + + private String clientSecret; + + @Value("${hhu_keycloak.token-uri}") + + private String tokenUri; + + + @Bean + public RestTemplate serviceAccountRestTemplate() { + + ClientCredentialsResourceDetails resourceDetails = new ClientCredentialsResourceDetails(); + + resourceDetails.setGrantType(OAuth2Constants.CLIENT_CREDENTIALS); + + resourceDetails.setAccessTokenUri(tokenUri); + + resourceDetails.setClientId(clientId); + + resourceDetails.setClientSecret(clientSecret); + + + return new OAuth2RestTemplate(resourceDetails); + + } } \ No newline at end of file diff --git a/src/main/java/mops/gruppen2/service/EventService.java b/src/main/java/mops/gruppen2/service/EventService.java index 2bce156..d6fb3da 100644 --- a/src/main/java/mops/gruppen2/service/EventService.java +++ b/src/main/java/mops/gruppen2/service/EventService.java @@ -2,8 +2,6 @@ package mops.gruppen2.service; import com.fasterxml.jackson.core.JsonProcessingException; import mops.gruppen2.domain.EventDTO; -import mops.gruppen2.domain.Exceptions.EventException; -import mops.gruppen2.domain.Group; import mops.gruppen2.domain.Visibility; import mops.gruppen2.domain.event.CreateGroupEvent; import mops.gruppen2.domain.event.Event; @@ -23,17 +21,19 @@ public class EventService { this.eventStore = eventStore; } - /** sichert ein Event Objekt indem es ein EventDTO Objekt erzeugt + /** + * sichert ein Event Objekt indem es ein EventDTO Objekt erzeugt * * @param event */ - public void saveEvent(Event event){ + public void saveEvent(Event event) { EventDTO eventDTO = getDTO(event); eventStore.save(eventDTO); } - /** Erzeugt aus einem Event Objekt ein EventDTO Objekt. - * Ist die Gruppe öffentlich, dann wird die visibility auf true gesetzt. + /** + * Erzeugt aus einem Event Objekt ein EventDTO Objekt. + * Ist die Gruppe öffentlich, dann wird die visibility auf true gesetzt. * * @param event * @return EventDTO @@ -42,24 +42,24 @@ public class EventService { EventDTO eventDTO = new EventDTO(); eventDTO.setGroup_id(event.getGroup_id()); eventDTO.setUser_id(event.getUser_id()); - if(event instanceof CreateGroupEvent) { - if(((CreateGroupEvent) event).getGroupVisibility() == Visibility.PRIVATE) { + if (event instanceof CreateGroupEvent) { + if (((CreateGroupEvent) event).getGroupVisibility() == Visibility.PRIVATE) { eventDTO.setVisibility(false); - }else { + } else { eventDTO.setVisibility(true); } } - try { eventDTO.setEvent_payload(serializationService.serializeEvent(event)); } catch (JsonProcessingException e) { e.printStackTrace(); } - return eventDTO; + return eventDTO; } - /** Sorgt dafür die Group_id immer um 1 zu erhöhen + /** + * Sorgt dafür die Group_id immer um 1 zu erhöhen * * @return Gibt Long zurück */ @@ -77,30 +77,32 @@ public class EventService { return tmpId; } - /** Findet alle Events welche ab dem neuen Status hinzugekommen sind + /** + * Findet alle Events welche ab dem neuen Status hinzugekommen sind * * @param status * @return Liste von Events */ - public List getNewEvents(Long status){ + public List getNewEvents(Long status) { List groupIdsThatChanged = eventStore.findNewEventSinceStatus(status); List groupEventDTOS = eventStore.findAllEventsOfGroups(groupIdsThatChanged); return translateEventDTOs(groupEventDTOS); } - /** Erzeugt aus einer Liste von eventDTOs eine Liste von Events + /** + * Erzeugt aus einer Liste von eventDTOs eine Liste von Events * * @param eventDTOS * @return Liste von Events */ - public List translateEventDTOs(Iterable eventDTOS){ + public List translateEventDTOs(Iterable eventDTOS) { List events = new ArrayList<>(); for (EventDTO eventDTO : eventDTOS) { try { events.add(serializationService.deserializeEvent(eventDTO.getEvent_payload())); - }catch (JsonProcessingException e) { + } catch (JsonProcessingException e) { e.printStackTrace(); } } @@ -113,12 +115,12 @@ public class EventService { * @param createGroupEvents Liste von Event Objekten */ public void saveEventList(List createGroupEvents) { - for(Event event : createGroupEvents) { + for (Event event : createGroupEvents) { saveEvent(event); } } - public Long getMaxEvent_id(){ + public Long getMaxEvent_id() { return eventStore.getHighesEvent_ID(); } diff --git a/src/main/resources/application-dev.properties b/src/main/resources/application-dev.properties index 3ad4107..79a9404 100644 --- a/src/main/resources/application-dev.properties +++ b/src/main/resources/application-dev.properties @@ -12,5 +12,12 @@ spring.jpa.database-platform=org.hibernate.dialect.H2Dialect keycloak.principal-attribute=preferred_username keycloak.auth-server-url=https://keycloak.cs.hhu.de/auth keycloak.realm=MOPS -keycloak.resource=demo -keycloak.public-client=true + +hhu_keycloak.token-uri=https://keycloak.cs.hhu.de/auth/realms/MOPS/protocol/openid-connect/token +keycloak.resource=gruppenfindung +keycloak.credentials.secret= fc6ebf10-8c63-4e71-a667-4eae4e8209a1 +keycloak.verify-token-audience=true +keycloak.use-resource-role-mappings=true + +keycloak.autodetect-bearer-only=true +keycloak.confidential-port= 443 \ No newline at end of file diff --git a/src/main/resources/application-docker.properties b/src/main/resources/application-docker.properties index 99ee878..76fce96 100644 --- a/src/main/resources/application-docker.properties +++ b/src/main/resources/application-docker.properties @@ -10,5 +10,12 @@ spring.datasource.password=geheim keycloak.principal-attribute=preferred_username keycloak.auth-server-url=https://keycloak.cs.hhu.de/auth keycloak.realm=MOPS -keycloak.resource=demo -keycloak.public-client=true + +hhu_keycloak.token-uri=https://keycloak.cs.hhu.de/auth/realms/MOPS/protocol/openid-connect/token +keycloak.resource=gruppenfindung +keycloak.credentials.secret= fc6ebf10-8c63-4e71-a667-4eae4e8209a1 +keycloak.verify-token-audience=true +keycloak.use-resource-role-mappings=true + +keycloak.autodetect-bearer-only=true +keycloak.confidential-port= 443 diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 257b306..7f0e7ec 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1 +1,2 @@ -spring.profiles.active=dev \ No newline at end of file +spring.profiles.active=dev + diff --git a/src/main/resources/templates/detailsNoMember.html b/src/main/resources/templates/detailsNoMember.html index f351207..e12d035 100644 --- a/src/main/resources/templates/detailsNoMember.html +++ b/src/main/resources/templates/detailsNoMember.html @@ -25,7 +25,26 @@
- +
+
+
+
+

+

+ Private Gruppe + Öffentliche Gruppe + Veranstaltung +

+

+
+
+ +
+
+
+
+
+
\ No newline at end of file diff --git a/src/main/resources/templates/errorRenameLater.html b/src/main/resources/templates/errorRenameLater.html new file mode 100644 index 0000000..01fbadc --- /dev/null +++ b/src/main/resources/templates/errorRenameLater.html @@ -0,0 +1,26 @@ + + + + + + + + + Error + + +
+
+

Da ist etwas schiefgelaufen!

+

Die Seite, nach der du suchst, scheint nicht zu existieren.

+
+ +
+
+
+ + \ No newline at end of file diff --git a/src/main/resources/templates/search.html b/src/main/resources/templates/search.html index 832d6c3..4eab94f 100644 --- a/src/main/resources/templates/search.html +++ b/src/main/resources/templates/search.html @@ -35,30 +35,31 @@ - - - -
- - - - - - - - - - - - - - - - - - -
GruppennameBeschreibungÖffentlich/PrivatMitgliederanzahl
GruppennameBeschreibungÖffentlichMitgliederanzahl
- + +
+ + + + + + + + + + + + + + + + + + +
GruppennameBeschreibungÖffentlich/PrivatMitgliederanzahl
+ Gruppenname + BeschreibungÖffentlichMitgliederanzahl
+ +