SharingService.java

package se.jobtechdev.personaldatagateway.api.service;

import jakarta.annotation.Nullable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import se.jobtechdev.personaldatagateway.api.exception.MutualExclusivityException;
import se.jobtechdev.personaldatagateway.api.generated.entities.*;
import se.jobtechdev.personaldatagateway.api.repository.PersonRepository;
import se.jobtechdev.personaldatagateway.api.repository.SharingAccessRepository;
import se.jobtechdev.personaldatagateway.api.repository.SharingRepository;
import se.jobtechdev.personaldatagateway.api.util.TimeProvider;
import se.jobtechdev.personaldatagateway.api.util.UuidProvider;

import java.time.ZonedDateTime;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;

@Component
public class SharingService {
  private final SharingRepository sharingRepository;

  private final SharingAccessRepository sharingAccessRepository;

  private final PersonRepository personRepository;

  @SuppressWarnings("unused")
  @Autowired
  public SharingService(
      SharingRepository sharingRepository,
      SharingAccessRepository sharingAccessRepository,
      PersonRepository personRepository) {
    this.sharingRepository = sharingRepository;
    this.sharingAccessRepository = sharingAccessRepository;
    this.personRepository = personRepository;
  }

  @Transactional
  public SharingEntity createSharing(
      PersonEntity person,
      DatasourceEntity datasource,
      boolean publicSharing,
      ZonedDateTime expires,
      ClientEntity client) {
    // Assert mutually exclusive parameters
    if (publicSharing == (client != null)) {
      throw new MutualExclusivityException();
    }

    final var sharingId = UuidProvider.uuid();
    final var created = TimeProvider.now();
    final var sharing =
        new SharingEntity(
            sharingId, client, datasource, person, created, null, expires, created, Set.of());
    return sharingRepository.save(sharing);
  }

  public Optional<SharingEntity> getSharingById(UUID sharingId) {
    return sharingRepository.findById(sharingId);
  }

  @Transactional
  public SharingEntity revoke(SharingEntity sharing) {
    final var now = TimeProvider.now();
    sharing.setRevoked(now);
    sharing.setUpdated(now);
    return sharingRepository.save(sharing);
  }

  @Transactional
  public SharingEntity update(SharingEntity sharing) {
    return sharingRepository.save(sharing);
  }

  public Page<SharingAccessEntity> getAllSharingAccessesBySharing(SharingEntity sharingEntity, Pageable pageable) {
    return sharingAccessRepository.findBySharingEntity(sharingEntity, pageable);
  }

  public Page<SharingEntity> getSharingsByUserId(String userId, Pageable pageable) {
    final var personEntity = personRepository.findById(userId);
    return sharingRepository.findByPersonEntity(personEntity.orElse(null), pageable);
  }

  public Optional<SharingAccessEntity> getSharingAccessById(UUID sharingAccessId) {
    return sharingAccessRepository.findById(sharingAccessId);
  }

  @Transactional
  public Optional<SharingAccessEntity> createSharingAccess(SharingEntity sharing) {
    final var sharingAccessId = UuidProvider.uuid();
    final var now = TimeProvider.now();
    final var sharingAccess = new SharingAccessEntity(sharingAccessId, sharing, now, now, now);
    final var saved = sharingAccessRepository.save(sharingAccess);
    return Optional.of(saved);
  }

  public List<SharingEntity> getActiveSharings(
      PersonEntity person, DatasourceEntity datasource, @Nullable ClientEntity client) {
    final var clientId = Optional.ofNullable(client).map(ClientEntity::getId).orElse(null);

    return sharingRepository.findAllActiveSharings(person.getId(), datasource.getId(), clientId);
  }
}