Skip to content

Commit 7bd0397

Browse files
committed
Grandular account and app updates
1 parent 068e926 commit 7bd0397

11 files changed

Lines changed: 632 additions & 39 deletions

File tree

dal/hibernate-dal/hibernate-persistence/src/main/java/com/nexblocks/authguard/dal/hibernate/persistence/HibernateAccountsRepository.java

Lines changed: 93 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
import com.nexblocks.authguard.dal.hibernate.common.AbstractHibernateRepository;
55
import com.nexblocks.authguard.dal.hibernate.common.ReactiveQueryExecutor;
66
import com.nexblocks.authguard.dal.model.AccountDO;
7+
import com.nexblocks.authguard.dal.model.PasswordDO;
8+
import com.nexblocks.authguard.dal.model.PermissionDO;
79
import com.nexblocks.authguard.dal.model.UserIdentifierDO;
810
import com.nexblocks.authguard.dal.persistence.AccountsRepository;
911
import com.nexblocks.authguard.service.exceptions.ServiceConflictException;
@@ -33,14 +35,12 @@ public class HibernateAccountsRepository extends AbstractHibernateRepository<Acc
3335
private static final String DOMAIN_FIELD = "domain";
3436

3537
private final HibernateUserIdentifiersRepository userIdentifiersRepository;
36-
private final HibernatePermissionsRepository permissionsRepository;
3738

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

4243
this.userIdentifiersRepository = new HibernateUserIdentifiersRepository(queryExecutor);
43-
this.permissionsRepository = new HibernatePermissionsRepository(queryExecutor);
4444
}
4545

4646
@Override
@@ -102,6 +102,97 @@ public Uni<Optional<AccountDO>> findByIdentifier(final String identifier, final
102102
DOMAIN_FIELD, domain);
103103
}
104104

105+
@Override
106+
public Uni<AccountDO> addAccountPermissions(final AccountDO account, final List<PermissionDO> permissions) {
107+
String sql = "INSERT INTO account_permissions (AccountDO_id, permissions_id) " +
108+
"VALUES (:accountId, :permissionId)";
109+
110+
return queryExecutor.getSessionFactory().withTransaction(session -> {
111+
List<Uni<Void>> insertUnis = permissions.stream()
112+
.map(permission -> session.createNativeQuery(sql)
113+
.setParameter("accountId", account.getId())
114+
.setParameter("permissionId", permission.getId())
115+
.executeUpdate()
116+
.replaceWithVoid()
117+
)
118+
.toList();
119+
120+
return Uni.combine().all().unis(insertUnis)
121+
.with(list -> account);
122+
});
123+
}
124+
125+
@Override
126+
public Uni<AccountDO> removeAccountPermissions(final AccountDO account, final List<PermissionDO> permissions) {
127+
String sql = "DELETE FROM account_permissions " +
128+
"WHERE AccountDO_id = :accountId and permissions_id in :permissionIds";
129+
130+
return queryExecutor.getSessionFactory().withTransaction(session -> session.createNativeQuery(sql)
131+
.setParameter("accountId", account.getId())
132+
.setParameter("permissionIds", permissions.stream().map(PermissionDO::getId).toList())
133+
.executeUpdate()
134+
.map(ignored -> account));
135+
}
136+
137+
@Override
138+
public Uni<AccountDO> addUserIdentifier(final AccountDO account, final UserIdentifierDO identifier) {
139+
return queryExecutor.getSessionFactory().withTransaction(session -> {
140+
return session.find(AccountDO.class, account.getId())
141+
.flatMap(retrieved -> {
142+
retrieved.getIdentifiers().add(identifier);
143+
144+
return session.merge(retrieved);
145+
});
146+
});
147+
}
148+
149+
@Override
150+
public Uni<AccountDO> removeUserIdentifier(final AccountDO account, final UserIdentifierDO identifier) {
151+
return queryExecutor.getSessionFactory().withTransaction(session -> {
152+
return session.find(AccountDO.class, account.getId())
153+
.flatMap(retrieved -> {
154+
retrieved.setIdentifiers(retrieved.getIdentifiers()
155+
.stream()
156+
.filter(existing -> !existing.getIdentifier().equals(identifier.getIdentifier()))
157+
.collect(Collectors.toSet()));
158+
159+
return session.merge(retrieved);
160+
});
161+
});
162+
}
163+
164+
@Override
165+
public Uni<AccountDO> replaceIdentifierInPlace(final AccountDO accountDO, final String oldIdentifier,
166+
final UserIdentifierDO newIdentifier) {
167+
return queryExecutor.getSessionFactory().withTransaction(session -> {
168+
return session.find(AccountDO.class, accountDO.getId())
169+
.flatMap(retrieved -> {
170+
// remove the old one
171+
retrieved.setIdentifiers(retrieved.getIdentifiers()
172+
.stream()
173+
.filter(existing -> !existing.getIdentifier().equals(oldIdentifier))
174+
.collect(Collectors.toSet()));
175+
176+
// add the new one
177+
retrieved.getIdentifiers().add(newIdentifier);
178+
179+
return session.merge(retrieved);
180+
});
181+
});
182+
}
183+
184+
@Override
185+
public Uni<AccountDO> updateUserPassword(final AccountDO account, final PasswordDO hashedPassword) {
186+
return queryExecutor.getSessionFactory().withTransaction(session -> {
187+
return session.find(AccountDO.class, account.getId())
188+
.flatMap(retrieved -> {
189+
retrieved.setHashedPassword(hashedPassword);
190+
191+
return session.merge(retrieved);
192+
});
193+
});
194+
}
195+
105196
@Override
106197
public Uni<List<AccountDO>> getByRole(final String role, final String domain) {
107198
return queryExecutor.getAList(GET_BY_ROLE, AccountDO.class,

dal/hibernate-dal/hibernate-persistence/src/main/java/com/nexblocks/authguard/dal/hibernate/persistence/HibernateAppsRepository.java

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,15 @@
33
import com.google.inject.Inject;
44
import com.nexblocks.authguard.dal.hibernate.common.AbstractHibernateRepository;
55
import com.nexblocks.authguard.dal.hibernate.common.CommonFields;
6-
import com.nexblocks.authguard.dal.hibernate.common.QueryExecutor;
76
import com.nexblocks.authguard.dal.hibernate.common.ReactiveQueryExecutor;
87
import com.nexblocks.authguard.dal.model.AppDO;
8+
import com.nexblocks.authguard.dal.model.PermissionDO;
99
import com.nexblocks.authguard.dal.persistence.ApplicationsRepository;
1010
import com.nexblocks.authguard.dal.persistence.Page;
1111
import io.smallrye.mutiny.Uni;
1212

1313
import java.util.List;
1414
import java.util.Optional;
15-
import io.smallrye.mutiny.Uni;
16-
import java.util.function.Function;
1715

1816
public class HibernateAppsRepository extends AbstractHibernateRepository<AppDO>
1917
implements ApplicationsRepository {
@@ -49,4 +47,37 @@ public Uni<List<AppDO>> getAllForAccount(final long accountId, final Page<Long>
4947
.setParameter(ACCOUNT_ID_FIELD, accountId)
5048
.setParameter(CURSOR_FIELD, page.getCursor()), page.getCount());
5149
}
50+
51+
@Override
52+
public Uni<AppDO> addAppPermissions(final AppDO app, final List<PermissionDO> permissions) {
53+
String sql = "INSERT INTO apps_permissions (AppDO_id, permissions_id) " +
54+
"VALUES (:appId, :permissionId)";
55+
56+
return queryExecutor.getSessionFactory().withTransaction(session -> {
57+
List<Uni<Void>> insertUnis = permissions.stream()
58+
.map(permission -> session.createNativeQuery(sql)
59+
.setParameter("appId", app.getId())
60+
.setParameter("permissionId", permission.getId())
61+
.executeUpdate()
62+
.replaceWithVoid()
63+
)
64+
.toList();
65+
66+
return Uni.combine().all().unis(insertUnis)
67+
.with(list -> app);
68+
});
69+
70+
}
71+
72+
@Override
73+
public Uni<AppDO> removeAppPermissions(final AppDO app, final List<PermissionDO> permissions) {
74+
String sql = "DELETE FROM apps_permissions " +
75+
"WHERE AppDO_id = :appId and permissions_id in :permissionIds";
76+
77+
return queryExecutor.getSessionFactory().withTransaction(session -> session.createNativeQuery(sql)
78+
.setParameter("appId", app.getId())
79+
.setParameter("permissionIds", permissions.stream().map(PermissionDO::getId).toList())
80+
.executeUpdate()
81+
.map(ignored -> app));
82+
}
5283
}

dal/hibernate-dal/hibernate-persistence/src/test/java/com/nexblocks/authguard/dal/hibernate/persistence/HibernateAccountsRepositoryTest.java

Lines changed: 88 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,12 @@
33
import com.nexblocks.authguard.dal.hibernate.common.ReactiveQueryExecutor;
44
import com.nexblocks.authguard.dal.hibernate.common.SessionProvider;
55
import com.nexblocks.authguard.dal.model.*;
6-
import com.nexblocks.authguard.service.exceptions.ServiceConflictException;
76
import org.junit.jupiter.api.BeforeAll;
87
import org.junit.jupiter.api.Test;
98
import org.junit.jupiter.api.TestInstance;
109

1110
import java.time.Instant;
12-
import java.util.Collections;
13-
import java.util.List;
14-
import java.util.Optional;
15-
import java.util.UUID;
11+
import java.util.*;
1612
import java.util.stream.Collectors;
1713

1814
import static org.assertj.core.api.Assertions.assertThat;
@@ -21,6 +17,7 @@
2117
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
2218
public class HibernateAccountsRepositoryTest {
2319
private HibernateAccountsRepository repository;
20+
private HibernatePermissionsRepository permissionsRepository;
2421
protected HibernateUserIdentifiersRepository userIdentifiersRepository;
2522

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

3734
repository = new HibernateAccountsRepository(queryExecutor);
3835
userIdentifiersRepository = new HibernateUserIdentifiersRepository(queryExecutor);
36+
permissionsRepository = new HibernatePermissionsRepository(queryExecutor);
3937
}
4038

4139
@Test
@@ -56,6 +54,7 @@ public void saveAndGetById() {
5654
UserIdentifierDO.builder()
5755
.identifier(email.getEmail())
5856
.type(UserIdentifierDO.Type.EMAIL)
57+
.active(true)
5958
.build()
6059
))
6160
.build();
@@ -86,6 +85,7 @@ public void getByExternalId() {
8685
UserIdentifierDO.builder()
8786
.identifier(email.getEmail())
8887
.type(UserIdentifierDO.Type.EMAIL)
88+
.active(true)
8989
.build()
9090
))
9191
.build();
@@ -116,6 +116,7 @@ public void getByEmail() {
116116
UserIdentifierDO.builder()
117117
.identifier(email.getEmail())
118118
.type(UserIdentifierDO.Type.EMAIL)
119+
.active(true)
119120
.build()
120121
))
121122
.build();
@@ -141,6 +142,7 @@ public void findByIdentifier() {
141142
.identifier(identifier)
142143
.type(UserIdentifierDO.Type.USERNAME)
143144
.domain("main")
145+
.active(true)
144146
.build()))
145147
.hashedPassword(PasswordDO.builder()
146148
.password("password")
@@ -231,6 +233,7 @@ public void updatePassword() {
231233
.identifiers(Collections.singleton(UserIdentifierDO.builder()
232234
.identifier(identifier)
233235
.type(UserIdentifierDO.Type.USERNAME)
236+
.active(true)
234237
.build()))
235238
.hashedPassword(PasswordDO.builder()
236239
.password("password")
@@ -275,10 +278,13 @@ public void removeIdentifier() {
275278
.roles(Collections.emptySet())
276279
.permissions(Collections.emptySet())
277280
.metadata(Collections.emptyMap())
278-
.identifiers(Collections.singleton(UserIdentifierDO.builder()
279-
.identifier(identifier)
280-
.type(UserIdentifierDO.Type.USERNAME)
281-
.build()))
281+
.identifiers(new HashSet<>(Arrays.asList(
282+
UserIdentifierDO.builder()
283+
.identifier(identifier)
284+
.type(UserIdentifierDO.Type.USERNAME)
285+
.active(true)
286+
.build()
287+
)))
282288
.hashedPassword(PasswordDO.builder()
283289
.password("password")
284290
.salt("salt")
@@ -332,6 +338,7 @@ public void updateIdentifier() {
332338
.identifiers(Collections.singleton(UserIdentifierDO.builder()
333339
.identifier(identifier)
334340
.type(UserIdentifierDO.Type.USERNAME)
341+
.active(true)
335342
.build()))
336343
.hashedPassword(PasswordDO.builder()
337344
.password("password")
@@ -589,4 +596,76 @@ public void saveDuplicateNullPhoneNumbers() {
589596
repository.save(first).subscribeAsCompletionStage().join();
590597
repository.save(second).subscribeAsCompletionStage().join();
591598
}
599+
600+
@Test
601+
public void addAndRemoveAccountPermission() {
602+
long id = Math.abs(UUID.randomUUID().getMostSignificantBits());
603+
String identifier = "addAccountPermission";
604+
605+
AccountDO account = AccountDO.builder()
606+
.id(id)
607+
.roles(Collections.emptySet())
608+
.permissions(Collections.emptySet())
609+
.metadata(Collections.emptyMap())
610+
.domain("main")
611+
.identifiers(Collections.singleton(UserIdentifierDO.builder()
612+
.identifier(identifier)
613+
.type(UserIdentifierDO.Type.USERNAME)
614+
.domain("main")
615+
.active(true)
616+
.build()))
617+
.hashedPassword(PasswordDO.builder()
618+
.password("password")
619+
.salt("salt")
620+
.build())
621+
.build();
622+
623+
AccountDO persisted = repository.save(account).subscribeAsCompletionStage().join();
624+
625+
PermissionDO firstPermission = permissionsRepository.save(
626+
PermissionDO.builder()
627+
.id(Math.abs(UUID.randomUUID().getMostSignificantBits()))
628+
.domain("main")
629+
.forAccounts(true)
630+
.permissionGroup("account_tests")
631+
.name("read")
632+
.build()
633+
)
634+
.subscribeAsCompletionStage()
635+
.join();
636+
637+
PermissionDO secondPermission = permissionsRepository.save(
638+
PermissionDO.builder()
639+
.id(Math.abs(UUID.randomUUID().getMostSignificantBits()))
640+
.domain("main")
641+
.forAccounts(true)
642+
.permissionGroup("account_tests")
643+
.name("write")
644+
.build()
645+
)
646+
.subscribeAsCompletionStage()
647+
.join();
648+
649+
// add
650+
repository.addAccountPermissions(persisted, Arrays.asList(firstPermission, secondPermission))
651+
.subscribeAsCompletionStage()
652+
.join();
653+
654+
Optional<AccountDO> afterAdd = repository.getById(persisted.getId()).subscribeAsCompletionStage().join();
655+
656+
assertThat(afterAdd).isNotEmpty();
657+
assertThat(afterAdd.get().getPermissions())
658+
.containsExactlyInAnyOrder(firstPermission, secondPermission);
659+
660+
// remove one
661+
repository.removeAccountPermissions(persisted, Collections.singletonList(firstPermission))
662+
.subscribeAsCompletionStage()
663+
.join();
664+
665+
Optional<AccountDO> afterRemove = repository.getById(persisted.getId()).subscribeAsCompletionStage().join();
666+
667+
assertThat(afterRemove).isNotEmpty();
668+
assertThat(afterRemove.get().getPermissions())
669+
.containsExactlyInAnyOrder(secondPermission);
670+
}
592671
}

0 commit comments

Comments
 (0)