Skip to content

Commit

Permalink
feat: ZO-191 - UUID and PIN should be different for each meeting
Browse files Browse the repository at this point in the history
feat: ZO-191 - UUID and PIN should be different for each meeting
  • Loading branch information
wagner-wutzke authored Feb 27, 2025
2 parents d720965 + 8e3240c commit 6cdc316
Show file tree
Hide file tree
Showing 23 changed files with 174 additions and 89 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@
ovc-backend.iml

.env
src/main/resources/application-dev.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ public MeetingController(
content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE,
schema = @Schema(implementation = ApiErrorDTO.class)))
})
@PreAuthorize("hasAuthority('default-roles-vk-bund')")
@PreAuthorize("@rolesAuthorization.hasBasicAccessRole")
public ResponseEntity<MeetingsPageDTO> findMeetings(
@Parameter(description = "The type of meeting to be retrieved: 'normal', 'static', 'instant'")
@RequestParam(defaultValue = "normal", required = false) String type,
Expand Down Expand Up @@ -193,7 +193,7 @@ public ResponseEntity<MeetingsPageDTO> findMeetings(
content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE,
schema = @Schema(implementation = ApiErrorDTO.class)))
})
@PreAuthorize("hasAuthority('default-roles-vk-bund')")
@PreAuthorize("@rolesAuthorization.hasBasicAccessRole")
public ResponseEntity<MeetingDTO> findById(
@Parameter(description = "Id of the meeting.", required = true)
@PathVariable UUID mId)
Expand Down Expand Up @@ -346,7 +346,7 @@ public ResponseEntity<MeetingPermissionsDTO> getPermissions(
content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE,
schema = @Schema(implementation = ApiErrorDTO.class)))
})
@PreAuthorize("hasAuthority('default-roles-vk-bund')")
@PreAuthorize("@rolesAuthorization.hasBasicAccessRole")
public ResponseEntity<MeetingDTO> createMeeting(
@io.swagger.v3.oas.annotations.parameters.RequestBody(description = "The meeting to be created")
@RequestBody MeetingCreateDTO meeting)
Expand Down Expand Up @@ -389,7 +389,7 @@ public ResponseEntity<MeetingDTO> createMeeting(
content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE,
schema = @Schema(implementation = ApiErrorDTO.class)))
})
@PreAuthorize("hasAuthority('default-roles-vk-bund')")
@PreAuthorize("@rolesAuthorization.hasBasicAccessRole")
public ResponseEntity<MeetingDTO> updateMeeting(
@Parameter(description = "Id of the meeting to be updated.", required = true)
@PathVariable UUID mId,
Expand Down Expand Up @@ -550,7 +550,7 @@ public String generateLink(
content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE,
schema = @Schema(implementation = ApiErrorDTO.class)))
})
@PreAuthorize("hasAuthority('default-roles-vk-bund')")
@PreAuthorize("@rolesAuthorization.hasBasicAccessRole")
public ResponseEntity<List<MeetingParticipantDTO>> listParticipants(
@Parameter(description = "Id of the meeting to get the participants list.", required = true)
@PathVariable UUID mId)
Expand Down Expand Up @@ -591,7 +591,7 @@ public ResponseEntity<List<MeetingParticipantDTO>> listParticipants(
content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE,
schema = @Schema(implementation = ApiErrorDTO.class)))
})
@PreAuthorize("hasAuthority('default-roles-vk-bund')")
@PreAuthorize("@rolesAuthorization.hasBasicAccessRole")
public ResponseEntity<MeetingParticipantDTO> createParticipant(
@Parameter(description = "Id of the meeting.", required = true)
@PathVariable UUID mId,
Expand Down Expand Up @@ -634,7 +634,7 @@ public ResponseEntity<MeetingParticipantDTO> createParticipant(
content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE,
schema = @Schema(implementation = ApiErrorDTO.class)))
})
@PreAuthorize("hasAuthority('default-roles-vk-bund')")
@PreAuthorize("@rolesAuthorization.hasBasicAccessRole")
public ResponseEntity<MeetingParticipantDTO> updateParticipant(
@Parameter(description = "Id of the meeting.", required = true)
@PathVariable UUID mId,
Expand Down Expand Up @@ -677,7 +677,7 @@ public ResponseEntity<MeetingParticipantDTO> updateParticipant(
content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE,
schema = @Schema(implementation = ApiErrorDTO.class)))
})
@PreAuthorize("hasAuthority('default-roles-vk-bund')")
@PreAuthorize("@rolesAuthorization.hasBasicAccessRole")
public ResponseEntity<Void> deleteParticipant(
@Parameter(description = "Id of the meeting.", required = true)
@PathVariable UUID mId,
Expand Down Expand Up @@ -716,7 +716,7 @@ public ResponseEntity<Void> deleteParticipant(
content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE,
schema = @Schema(implementation = ApiErrorDTO.class)))
})
@PreAuthorize("hasAuthority('default-roles-vk-bund')")
@PreAuthorize("@rolesAuthorization.hasBasicAccessRole")
public boolean isRegisteredUser(
@Parameter(description = "Id (email) of the user to be checked.", required = true)
@PathVariable String userId)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ public class NotificationController
content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE,
schema = @Schema(implementation = ApiErrorDTO.class)))
})
@PreAuthorize("hasAuthority('default-roles-vk-bund')")
@PreAuthorize("@rolesAuthorization.hasBasicAccessRole")
public ResponseEntity<NotificationsPageDTO> findForUser(
@Parameter(description = "The amount of items to return. Default value is 20.")
@RequestParam(required = false, defaultValue = "20") Integer pageSize,
Expand Down Expand Up @@ -138,7 +138,7 @@ public ResponseEntity<NotificationsPageDTO> findForUser(
content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE,
schema = @Schema(implementation = ApiErrorDTO.class)))
})
@PreAuthorize("hasAuthority('default-roles-vk-bund')")
@PreAuthorize("@rolesAuthorization.hasBasicAccessRole")
public ResponseEntity<Void> delete(
@Parameter(description = "Id of the to be deleted.", required = true)
@PathVariable UUID id)
Expand Down Expand Up @@ -167,7 +167,7 @@ public ResponseEntity<Void> delete(
content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE,
schema = @Schema(implementation = ApiErrorDTO.class)))
})
@PreAuthorize("hasAuthority('default-roles-vk-bund')")
@PreAuthorize("@rolesAuthorization.hasBasicAccessRole")
public ResponseEntity<Void> deleteAll()
{
Void delete = service.deleteAllForUser();
Expand Down Expand Up @@ -206,7 +206,7 @@ public ResponseEntity<Void> deleteAll()
content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE,
schema = @Schema(implementation = ApiErrorDTO.class))),
})
@PreAuthorize("hasAuthority('default-roles-vk-bund')")
@PreAuthorize("@rolesAuthorization.hasBasicAccessRole")
public ResponseEntity<Void> updateView(
@Parameter(description = "Id of the notification to be updated.", required = true)
@PathVariable UUID id)
Expand Down Expand Up @@ -237,7 +237,7 @@ public ResponseEntity<Void> updateView(
content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE,
schema = @Schema(implementation = ApiErrorDTO.class))),
})
@PreAuthorize("hasAuthority('default-roles-vk-bund')")
@PreAuthorize("@rolesAuthorization.hasBasicAccessRole")
public ResponseEntity<Void> updateViewAll()
{
logger.logRequest("Endpoint 'updateViewAll' called.");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package net.nordeck.ovc.backend.controller;

import lombok.Getter;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;

import java.util.Collection;


@Component("rolesAuthorization")
public class RolesAuthorization
{

@Value("${api.basic-access-role}")
@Getter
protected String basicAccessRole;

public boolean hasBasicAccessRole()
{
if (!SecurityContextHolder.getContext().getAuthentication().isAuthenticated())
{
return false;
}
Collection<? extends GrantedAuthority> authorities = SecurityContextHolder.getContext().getAuthentication().getAuthorities();
if (StringUtils.isEmpty(basicAccessRole))
{
return true;
}
return authorities.stream().anyMatch(a -> a.getAuthority().equalsIgnoreCase(basicAccessRole));
}

}

1 change: 1 addition & 0 deletions src/main/java/net/nordeck/ovc/backend/dto/DTOUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ protected static void setBasicDataFromEntity(MeetingAbstractDTO dto, MeetingEnti
dto.setLobbyEnabled(entity.isLobbyEnabled());
dto.setPassword(entity.getPassword());
dto.setType(getTypeFromEntity(entity));
dto.setStartedAt(entity.getStartedAt());
}

protected static RecurrenceDTO buildRecurrenceFromEntity(MeetingEntity entity)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,4 +80,12 @@ public class MeetingAbstractDTO
@JsonProperty("lobby_enabled")
private boolean lobbyEnabled;

@Schema(description = "The time UTC datetime in ISO-8601 format the meeting has been started. " +
"Needs to be converted by the client with its own zone offset. " +
"Relevant for INSTANT meeting.")
@JsonProperty("started_at")
@JsonSerialize(using = ZonedDateTimeSerializer.class)
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = Constants.DATE_TIME_ISO_8601_FORMAT)
private ZonedDateTime startedAt;

}
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,9 @@ public class MeetingEntity {
@Column(name = "excluded")
private boolean excluded;

@Column(name = "started_at")
private ZonedDateTime startedAt;

@OneToMany(mappedBy = "meetingId", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private List<MeetingParticipantEntity> participants;

Expand All @@ -170,6 +173,7 @@ public static MeetingEntity buildFromMeetingAbstractDTO(MeetingAbstractDTO dto)
.frequency(frequency)
.password(dto.getPassword())
.lobbyEnabled(dto.isLobbyEnabled())
.startedAt(dto.getStartedAt())
.build();

setRecurrence(dto, entity);
Expand Down
7 changes: 5 additions & 2 deletions src/main/resources/liquibase/changelog-init.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext" xmlns:pro="http://www.liquibase.org/xml/ns/pro" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd http://www.liquibase.org/xml/ns/pro http://www.liquibase.org/xml/ns/pro/liquibase-pro-latest.xsd http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd">
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd">
<property name="NOW" value="now() " dbms="mysql,h2"/>
<property name="NOW" value="CURRENT_TIMESTAMP" dbms="postgresql"/>
<property name="NOW" value="sysdate" dbms="oracle"/>
Expand Down Expand Up @@ -48,6 +50,7 @@
<column defaultValueBoolean="false" name="excluded" type="BOOLEAN"/>
<column name="sip_jibri_link" type="VARCHAR(255)"/>
<column name="series_end_time" type="TIMESTAMP WITH TIME ZONE"/>
<column name="started_at" type="TIMESTAMP WITHOUT TIME ZONE"/>
</createTable>
</changeSet>
<changeSet author="wagner.wutzke" id="1740266386086-2">
Expand Down Expand Up @@ -271,4 +274,4 @@
<changeSet author="wagner.wutzke" id="1740266386086-27">
<addForeignKeyConstraint baseColumnNames="step_execution_id" baseTableName="batch_step_execution_context" constraintName="step_exec_ctx_fk" deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="step_execution_id" referencedTableName="batch_step_execution" validate="true"/>
</changeSet>
</databaseChangeLog>
</databaseChangeLog>
24 changes: 17 additions & 7 deletions src/test/java/net/nordeck/ovc/backend/TestUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,18 @@
import net.nordeck.ovc.backend.entity.MeetingParticipantEntity;
import net.nordeck.ovc.backend.entity.NotificationEntity;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;

import java.time.Instant;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.*;

import static net.nordeck.ovc.backend.service.NotificationService.DELETE_CANDIDATE;
import static org.mockito.Mockito.when;


public class TestUtils
Expand Down Expand Up @@ -187,7 +186,7 @@ public static NotificationDTO getNotificationDTO()
return NotificationDTO.buildFromEntity(getNotificationEntity());
}

public static void initSecurityContext(Authentication auth, String email)
public static Authentication initSecurityContext(String email, List<String> roles)
{
Map<String, Object> claims = new HashMap<>();
if (email == null)
Expand All @@ -203,8 +202,19 @@ public static void initSecurityContext(Authentication auth, String email)
HashMap<String, Object> headers = new HashMap<>();
headers.put("auth", "Bearer");
Jwt token = new Jwt("123456", Instant.now(), expiresAt, headers, claims);
when(auth.getPrincipal()).thenReturn(token);

List<GrantedAuthority> authorities = new ArrayList<>();
if (roles != null)
{
for(String role : roles)
{
authorities.add(new SimpleGrantedAuthority(role));
}
}
JwtAuthenticationToken auth = new JwtAuthenticationToken(token, authorities, "auth-token");
SecurityContextHolder.getContext().setAuthentication(auth);
auth.setAuthenticated(true);
return auth;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
Expand Down Expand Up @@ -59,9 +58,7 @@ public class MeetingControllerTest
private MeetingParticipantRequestDTO participantRequestDTO;
private String json, jsonResponse;


@Mock
private Authentication auth;
private Authentication auth = TestUtils.initSecurityContext(null, null);;

@BeforeEach
void initData() throws IOException
Expand All @@ -72,8 +69,6 @@ void initData() throws IOException

json = objectMapper.writeValueAsString(participantRequestDTO);
jsonResponse = objectMapper.writeValueAsString(participantDTO);

TestUtils.initSecurityContext(auth, null);
}

@AfterEach
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
package net.nordeck.ovc.backend.controller;

import com.fasterxml.jackson.databind.ObjectMapper;
import net.nordeck.ovc.backend.TestUtils;
import net.nordeck.ovc.backend.dto.NotificationDTO;
import net.nordeck.ovc.backend.dto.NotificationsPageDTO;
import net.nordeck.ovc.backend.TestUtils;
import net.nordeck.ovc.backend.service.NotificationService;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
Expand Down Expand Up @@ -42,14 +40,7 @@ public class NotificationControllerTest
@MockBean
NotificationService service;

@Mock
private Authentication auth;

@BeforeEach
void initBeforeEach()
{
TestUtils.initSecurityContext(auth, null);
}
Authentication auth = TestUtils.initSecurityContext(null, null);

@AfterEach
void finishAfterEach()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
import io.jsonwebtoken.security.InvalidKeyException;
import jakarta.persistence.EntityNotFoundException;
import jakarta.validation.ConstraintViolationException;
import net.nordeck.ovc.backend.dto.ApiErrorDTO;
import net.nordeck.ovc.backend.Constants;
import net.nordeck.ovc.backend.dto.ApiErrorDTO;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
Expand Down
Loading

0 comments on commit 6cdc316

Please sign in to comment.