Skip to content
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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import com.nexblocks.authguard.dal.hibernate.common.AbstractHibernateRepository;
import com.nexblocks.authguard.dal.hibernate.common.ReactiveQueryExecutor;
import com.nexblocks.authguard.dal.model.AccountDO;
import com.nexblocks.authguard.dal.model.PasswordDO;
import com.nexblocks.authguard.dal.model.PermissionDO;
import com.nexblocks.authguard.dal.model.UserIdentifierDO;
import com.nexblocks.authguard.dal.persistence.AccountsRepository;
import com.nexblocks.authguard.service.exceptions.ServiceConflictException;
Expand Down Expand Up @@ -33,14 +35,12 @@ public class HibernateAccountsRepository extends AbstractHibernateRepository<Acc
private static final String DOMAIN_FIELD = "domain";

private final HibernateUserIdentifiersRepository userIdentifiersRepository;
private final HibernatePermissionsRepository permissionsRepository;

@Inject
public HibernateAccountsRepository(final ReactiveQueryExecutor queryExecutor) {
super(AccountDO.class, queryExecutor);

this.userIdentifiersRepository = new HibernateUserIdentifiersRepository(queryExecutor);
this.permissionsRepository = new HibernatePermissionsRepository(queryExecutor);
}

@Override
Expand Down Expand Up @@ -102,6 +102,97 @@ public Uni<Optional<AccountDO>> findByIdentifier(final String identifier, final
DOMAIN_FIELD, domain);
}

@Override
public Uni<AccountDO> addAccountPermissions(final AccountDO account, final List<PermissionDO> permissions) {
String sql = "INSERT INTO account_permissions (AccountDO_id, permissions_id) " +
"VALUES (:accountId, :permissionId)";

return queryExecutor.getSessionFactory().withTransaction(session -> {
List<Uni<Void>> insertUnis = permissions.stream()
.map(permission -> session.createNativeQuery(sql)
.setParameter("accountId", account.getId())
.setParameter("permissionId", permission.getId())
.executeUpdate()
.replaceWithVoid()
)
.toList();

return Uni.combine().all().unis(insertUnis)
.with(list -> account);
});
}

@Override
public Uni<AccountDO> removeAccountPermissions(final AccountDO account, final List<PermissionDO> permissions) {
String sql = "DELETE FROM account_permissions " +
"WHERE AccountDO_id = :accountId and permissions_id in :permissionIds";

return queryExecutor.getSessionFactory().withTransaction(session -> session.createNativeQuery(sql)
.setParameter("accountId", account.getId())
.setParameter("permissionIds", permissions.stream().map(PermissionDO::getId).toList())
.executeUpdate()
.map(ignored -> account));
}

@Override
public Uni<AccountDO> addUserIdentifier(final AccountDO account, final UserIdentifierDO identifier) {
return queryExecutor.getSessionFactory().withTransaction(session -> {
return session.find(AccountDO.class, account.getId())
.flatMap(retrieved -> {
retrieved.getIdentifiers().add(identifier);

return session.merge(retrieved);
});
});
}

@Override
public Uni<AccountDO> removeUserIdentifier(final AccountDO account, final UserIdentifierDO identifier) {
return queryExecutor.getSessionFactory().withTransaction(session -> {
return session.find(AccountDO.class, account.getId())
.flatMap(retrieved -> {
retrieved.setIdentifiers(retrieved.getIdentifiers()
.stream()
.filter(existing -> !existing.getIdentifier().equals(identifier.getIdentifier()))
.collect(Collectors.toSet()));

return session.merge(retrieved);
});
});
}

@Override
public Uni<AccountDO> replaceIdentifierInPlace(final AccountDO accountDO, final String oldIdentifier,
final UserIdentifierDO newIdentifier) {
return queryExecutor.getSessionFactory().withTransaction(session -> {
return session.find(AccountDO.class, accountDO.getId())
.flatMap(retrieved -> {
// remove the old one
retrieved.setIdentifiers(retrieved.getIdentifiers()
.stream()
.filter(existing -> !existing.getIdentifier().equals(oldIdentifier))
.collect(Collectors.toSet()));

// add the new one
retrieved.getIdentifiers().add(newIdentifier);

return session.merge(retrieved);
});
});
}

@Override
public Uni<AccountDO> updateUserPassword(final AccountDO account, final PasswordDO hashedPassword) {
return queryExecutor.getSessionFactory().withTransaction(session -> {
return session.find(AccountDO.class, account.getId())
.flatMap(retrieved -> {
retrieved.setHashedPassword(hashedPassword);

return session.merge(retrieved);
});
});
}

@Override
public Uni<List<AccountDO>> getByRole(final String role, final String domain) {
return queryExecutor.getAList(GET_BY_ROLE, AccountDO.class,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,15 @@
import com.google.inject.Inject;
import com.nexblocks.authguard.dal.hibernate.common.AbstractHibernateRepository;
import com.nexblocks.authguard.dal.hibernate.common.CommonFields;
import com.nexblocks.authguard.dal.hibernate.common.QueryExecutor;
import com.nexblocks.authguard.dal.hibernate.common.ReactiveQueryExecutor;
import com.nexblocks.authguard.dal.model.AppDO;
import com.nexblocks.authguard.dal.model.PermissionDO;
import com.nexblocks.authguard.dal.persistence.ApplicationsRepository;
import com.nexblocks.authguard.dal.persistence.Page;
import io.smallrye.mutiny.Uni;

import java.util.List;
import java.util.Optional;
import io.smallrye.mutiny.Uni;
import java.util.function.Function;

public class HibernateAppsRepository extends AbstractHibernateRepository<AppDO>
implements ApplicationsRepository {
Expand Down Expand Up @@ -49,4 +47,37 @@ public Uni<List<AppDO>> getAllForAccount(final long accountId, final Page<Long>
.setParameter(ACCOUNT_ID_FIELD, accountId)
.setParameter(CURSOR_FIELD, page.getCursor()), page.getCount());
}

@Override
public Uni<AppDO> addAppPermissions(final AppDO app, final List<PermissionDO> permissions) {
String sql = "INSERT INTO apps_permissions (AppDO_id, permissions_id) " +
"VALUES (:appId, :permissionId)";

return queryExecutor.getSessionFactory().withTransaction(session -> {
List<Uni<Void>> insertUnis = permissions.stream()
.map(permission -> session.createNativeQuery(sql)
.setParameter("appId", app.getId())
.setParameter("permissionId", permission.getId())
.executeUpdate()
.replaceWithVoid()
)
.toList();

return Uni.combine().all().unis(insertUnis)
.with(list -> app);
});

}

@Override
public Uni<AppDO> removeAppPermissions(final AppDO app, final List<PermissionDO> permissions) {
String sql = "DELETE FROM apps_permissions " +
"WHERE AppDO_id = :appId and permissions_id in :permissionIds";

return queryExecutor.getSessionFactory().withTransaction(session -> session.createNativeQuery(sql)
.setParameter("appId", app.getId())
.setParameter("permissionIds", permissions.stream().map(PermissionDO::getId).toList())
.executeUpdate()
.map(ignored -> app));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,12 @@
import com.nexblocks.authguard.dal.hibernate.common.ReactiveQueryExecutor;
import com.nexblocks.authguard.dal.hibernate.common.SessionProvider;
import com.nexblocks.authguard.dal.model.*;
import com.nexblocks.authguard.service.exceptions.ServiceConflictException;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;

import java.time.Instant;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
import java.util.*;
import java.util.stream.Collectors;

import static org.assertj.core.api.Assertions.assertThat;
Expand All @@ -21,6 +17,7 @@
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class HibernateAccountsRepositoryTest {
private HibernateAccountsRepository repository;
private HibernatePermissionsRepository permissionsRepository;
protected HibernateUserIdentifiersRepository userIdentifiersRepository;

@BeforeAll
Expand All @@ -36,6 +33,7 @@ protected void initialize(final SessionProvider sessionProvider) {

repository = new HibernateAccountsRepository(queryExecutor);
userIdentifiersRepository = new HibernateUserIdentifiersRepository(queryExecutor);
permissionsRepository = new HibernatePermissionsRepository(queryExecutor);
}

@Test
Expand All @@ -56,6 +54,7 @@ public void saveAndGetById() {
UserIdentifierDO.builder()
.identifier(email.getEmail())
.type(UserIdentifierDO.Type.EMAIL)
.active(true)
.build()
))
.build();
Expand Down Expand Up @@ -86,6 +85,7 @@ public void getByExternalId() {
UserIdentifierDO.builder()
.identifier(email.getEmail())
.type(UserIdentifierDO.Type.EMAIL)
.active(true)
.build()
))
.build();
Expand Down Expand Up @@ -116,6 +116,7 @@ public void getByEmail() {
UserIdentifierDO.builder()
.identifier(email.getEmail())
.type(UserIdentifierDO.Type.EMAIL)
.active(true)
.build()
))
.build();
Expand All @@ -141,6 +142,7 @@ public void findByIdentifier() {
.identifier(identifier)
.type(UserIdentifierDO.Type.USERNAME)
.domain("main")
.active(true)
.build()))
.hashedPassword(PasswordDO.builder()
.password("password")
Expand Down Expand Up @@ -231,6 +233,7 @@ public void updatePassword() {
.identifiers(Collections.singleton(UserIdentifierDO.builder()
.identifier(identifier)
.type(UserIdentifierDO.Type.USERNAME)
.active(true)
.build()))
.hashedPassword(PasswordDO.builder()
.password("password")
Expand Down Expand Up @@ -275,10 +278,13 @@ public void removeIdentifier() {
.roles(Collections.emptySet())
.permissions(Collections.emptySet())
.metadata(Collections.emptyMap())
.identifiers(Collections.singleton(UserIdentifierDO.builder()
.identifier(identifier)
.type(UserIdentifierDO.Type.USERNAME)
.build()))
.identifiers(new HashSet<>(Arrays.asList(
UserIdentifierDO.builder()
.identifier(identifier)
.type(UserIdentifierDO.Type.USERNAME)
.active(true)
.build()
)))
.hashedPassword(PasswordDO.builder()
.password("password")
.salt("salt")
Expand Down Expand Up @@ -332,6 +338,7 @@ public void updateIdentifier() {
.identifiers(Collections.singleton(UserIdentifierDO.builder()
.identifier(identifier)
.type(UserIdentifierDO.Type.USERNAME)
.active(true)
.build()))
.hashedPassword(PasswordDO.builder()
.password("password")
Expand Down Expand Up @@ -589,4 +596,76 @@ public void saveDuplicateNullPhoneNumbers() {
repository.save(first).subscribeAsCompletionStage().join();
repository.save(second).subscribeAsCompletionStage().join();
}

@Test
public void addAndRemoveAccountPermission() {
long id = Math.abs(UUID.randomUUID().getMostSignificantBits());
String identifier = "addAccountPermission";

AccountDO account = AccountDO.builder()
.id(id)
.roles(Collections.emptySet())
.permissions(Collections.emptySet())
.metadata(Collections.emptyMap())
.domain("main")
.identifiers(Collections.singleton(UserIdentifierDO.builder()
.identifier(identifier)
.type(UserIdentifierDO.Type.USERNAME)
.domain("main")
.active(true)
.build()))
.hashedPassword(PasswordDO.builder()
.password("password")
.salt("salt")
.build())
.build();

AccountDO persisted = repository.save(account).subscribeAsCompletionStage().join();

PermissionDO firstPermission = permissionsRepository.save(
PermissionDO.builder()
.id(Math.abs(UUID.randomUUID().getMostSignificantBits()))
.domain("main")
.forAccounts(true)
.permissionGroup("account_tests")
.name("read")
.build()
)
.subscribeAsCompletionStage()
.join();

PermissionDO secondPermission = permissionsRepository.save(
PermissionDO.builder()
.id(Math.abs(UUID.randomUUID().getMostSignificantBits()))
.domain("main")
.forAccounts(true)
.permissionGroup("account_tests")
.name("write")
.build()
)
.subscribeAsCompletionStage()
.join();

// add
repository.addAccountPermissions(persisted, Arrays.asList(firstPermission, secondPermission))
.subscribeAsCompletionStage()
.join();

Optional<AccountDO> afterAdd = repository.getById(persisted.getId()).subscribeAsCompletionStage().join();

assertThat(afterAdd).isNotEmpty();
assertThat(afterAdd.get().getPermissions())
.containsExactlyInAnyOrder(firstPermission, secondPermission);

// remove one
repository.removeAccountPermissions(persisted, Collections.singletonList(firstPermission))
.subscribeAsCompletionStage()
.join();

Optional<AccountDO> afterRemove = repository.getById(persisted.getId()).subscribeAsCompletionStage().join();

assertThat(afterRemove).isNotEmpty();
assertThat(afterRemove.get().getPermissions())
.containsExactlyInAnyOrder(secondPermission);
}
}
Loading
Loading