1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.syncope.core.logic.wa;
20
21 import java.time.OffsetDateTime;
22 import java.time.ZonedDateTime;
23 import java.util.Comparator;
24 import java.util.List;
25 import java.util.Objects;
26 import java.util.stream.Collectors;
27 import java.util.stream.Stream;
28 import org.apache.commons.lang3.builder.CompareToBuilder;
29 import org.apache.commons.lang3.builder.EqualsBuilder;
30 import org.apache.commons.lang3.tuple.Pair;
31 import org.apache.syncope.common.lib.types.IdRepoEntitlement;
32 import org.apache.syncope.common.lib.wa.MfaTrustedDevice;
33 import org.apache.syncope.core.logic.AbstractAuthProfileLogic;
34 import org.apache.syncope.core.persistence.api.dao.AuthProfileDAO;
35 import org.apache.syncope.core.persistence.api.dao.search.OrderByClause;
36 import org.apache.syncope.core.persistence.api.entity.EntityFactory;
37 import org.apache.syncope.core.persistence.api.entity.am.AuthProfile;
38 import org.apache.syncope.core.provisioning.api.data.AuthProfileDataBinder;
39 import org.springframework.security.access.prepost.PreAuthorize;
40
41 public class MfaTrusStorageLogic extends AbstractAuthProfileLogic {
42
43 protected final EntityFactory entityFactory;
44
45 public MfaTrusStorageLogic(
46 final EntityFactory entityFactory,
47 final AuthProfileDAO authProfileDAO,
48 final AuthProfileDataBinder binder) {
49
50 super(authProfileDAO, binder);
51 this.entityFactory = entityFactory;
52 }
53
54 @PreAuthorize("hasRole('" + IdRepoEntitlement.ANONYMOUS + "')")
55 public Pair<Integer, List<MfaTrustedDevice>> search(
56 final Integer page,
57 final Integer itemsPerPage,
58 final String principal,
59 final Long id,
60 final OffsetDateTime recordDate,
61 final List<OrderByClause> orderByClauses) {
62
63 List<Comparator<MfaTrustedDevice>> comparatorList = orderByClauses.
64 stream().
65 map(orderByClause -> {
66 Comparator<MfaTrustedDevice> comparator = null;
67 if (orderByClause.getField().equals("id")) {
68 comparator = (o1, o2) -> new CompareToBuilder().
69 append(o1.getId(), o2.getId()).toComparison();
70 }
71 if (orderByClause.getField().equals("expirationDate")) {
72 comparator = (o1, o2) -> new CompareToBuilder().
73 append(o1.getExpirationDate(), o2.getExpirationDate()).toComparison();
74 }
75 if (orderByClause.getField().equals("recordDate")) {
76 comparator = (o1, o2) -> new CompareToBuilder().
77 append(o1.getRecordDate(), o2.getRecordDate()).toComparison();
78 }
79 if (comparator != null) {
80 if (orderByClause.getDirection() == OrderByClause.Direction.DESC) {
81 return comparator.reversed();
82 }
83 return comparator;
84 }
85 return null;
86 }).
87 filter(Objects::nonNull).
88 collect(Collectors.toList());
89
90 List<MfaTrustedDevice> devices = (principal == null
91 ? authProfileDAO.findAll(-1, -1).stream().
92 map(AuthProfile::getMfaTrustedDevices).filter(Objects::nonNull).flatMap(List::stream)
93 : authProfileDAO.findByOwner(principal).
94 map(AuthProfile::getMfaTrustedDevices).filter(Objects::nonNull).map(List::stream).
95 orElse(Stream.empty())).
96 filter(device -> {
97 EqualsBuilder builder = new EqualsBuilder();
98 builder.appendSuper(device.getExpirationDate().isAfter(ZonedDateTime.now()));
99 if (id != null) {
100 builder.append(id, (Long) device.getId());
101 }
102 if (recordDate != null) {
103 builder.appendSuper(device.getRecordDate().isAfter(recordDate.toZonedDateTime()));
104 }
105 return builder.build();
106 }).
107 filter(Objects::nonNull).
108 collect(Collectors.toList());
109
110 List<MfaTrustedDevice> result = devices.stream().
111 limit(itemsPerPage).
112 skip(itemsPerPage * (page <= 0 ? 0L : page.longValue() - 1L)).
113 sorted((o1, o2) -> {
114 int compare;
115 for (Comparator<MfaTrustedDevice> comparator : comparatorList) {
116 compare = comparator.compare(o1, o2);
117 if (compare != 0) {
118 return compare;
119 }
120 }
121 return 0;
122 })
123 .collect(Collectors.toList());
124 return Pair.of(devices.size(), result);
125 }
126
127 @PreAuthorize("hasRole('" + IdRepoEntitlement.ANONYMOUS + "')")
128 public void create(final String owner, final MfaTrustedDevice device) {
129 AuthProfile profile = authProfileDAO.findByOwner(owner).orElseGet(() -> {
130 AuthProfile authProfile = entityFactory.newEntity(AuthProfile.class);
131 authProfile.setOwner(owner);
132 return authProfile;
133 });
134
135 List<MfaTrustedDevice> devices = profile.getMfaTrustedDevices();
136 devices.add(device);
137 profile.setMfaTrustedDevices(devices);
138 authProfileDAO.save(profile);
139 }
140
141 @PreAuthorize("hasRole('" + IdRepoEntitlement.ANONYMOUS + "')")
142 public void delete(final OffsetDateTime expirationDate, final String recordKey) {
143 List<AuthProfile> profiles = authProfileDAO.findAll(-1, -1);
144 profiles.forEach(profile -> {
145 List<MfaTrustedDevice> devices = profile.getMfaTrustedDevices();
146 if (devices != null) {
147 if (recordKey != null) {
148 devices.removeIf(device -> recordKey.equals(device.getRecordKey()));
149 } else if (expirationDate != null) {
150 devices.removeIf(device -> device.getExpirationDate().isBefore(expirationDate.toZonedDateTime()));
151 } else {
152 devices = List.of();
153 }
154 profile.setMfaTrustedDevices(devices);
155 authProfileDAO.save(profile);
156 }
157 });
158 }
159 }