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;
20
21 import com.nimbusds.oauth2.sdk.ParseException;
22 import java.io.IOException;
23 import java.lang.reflect.Method;
24 import java.util.List;
25 import java.util.Optional;
26 import java.util.stream.Collectors;
27 import org.apache.commons.lang3.ArrayUtils;
28 import org.apache.syncope.common.lib.SyncopeClientException;
29 import org.apache.syncope.common.lib.to.Item;
30 import org.apache.syncope.common.lib.to.OIDCC4UIProviderTO;
31 import org.apache.syncope.common.lib.types.ClientExceptionType;
32 import org.apache.syncope.common.lib.types.OIDCC4UIEntitlement;
33 import org.apache.syncope.core.logic.oidc.OIDCClientCache;
34 import org.apache.syncope.core.persistence.api.dao.NotFoundException;
35 import org.apache.syncope.core.persistence.api.dao.OIDCC4UIProviderDAO;
36 import org.apache.syncope.core.persistence.api.entity.OIDCC4UIProvider;
37 import org.apache.syncope.core.provisioning.api.data.OIDCC4UIProviderDataBinder;
38 import org.springframework.security.access.prepost.PreAuthorize;
39 import org.springframework.transaction.annotation.Transactional;
40
41 public class OIDCC4UIProviderLogic extends AbstractTransactionalLogic<OIDCC4UIProviderTO> {
42
43 protected final OIDCClientCache oidcClientCacheLogin;
44
45 protected final OIDCClientCache oidcClientCacheLogout;
46
47 protected final OIDCC4UIProviderDAO opDAO;
48
49 protected final OIDCC4UIProviderDataBinder binder;
50
51 public OIDCC4UIProviderLogic(
52 final OIDCClientCache oidcClientCacheLogin,
53 final OIDCClientCache oidcClientCacheLogout,
54 final OIDCC4UIProviderDAO opDAO,
55 final OIDCC4UIProviderDataBinder binder) {
56
57 this.oidcClientCacheLogin = oidcClientCacheLogin;
58 this.oidcClientCacheLogout = oidcClientCacheLogout;
59 this.opDAO = opDAO;
60 this.binder = binder;
61 }
62
63 @PreAuthorize("hasRole('" + OIDCC4UIEntitlement.OP_CREATE + "')")
64 public String createFromDiscovery(final OIDCC4UIProviderTO opTO) {
65 try {
66 OIDCClientCache.importMetadata(opTO);
67
68 return create(opTO);
69 } catch (IOException | InterruptedException | ParseException e) {
70 LOG.error("While getting the Discovery Document for {}", opTO.getIssuer(), e);
71 SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.Unknown);
72 sce.getElements().add(e.getMessage());
73 throw sce;
74 }
75 }
76
77 @PreAuthorize("hasRole('" + OIDCC4UIEntitlement.OP_CREATE + "')")
78 public String create(final OIDCC4UIProviderTO opTO) {
79 if (opTO.getConnObjectKeyItem() == null) {
80 Item connObjectKeyItem = new Item();
81 connObjectKeyItem.setIntAttrName("username");
82 connObjectKeyItem.setExtAttrName("email");
83 opTO.setConnObjectKeyItem(connObjectKeyItem);
84 }
85
86 OIDCC4UIProvider provider = binder.create(opTO);
87
88 return provider.getKey();
89 }
90
91 @PreAuthorize("isAuthenticated()")
92 @Transactional(readOnly = true)
93 public List<OIDCC4UIProviderTO> list() {
94 return opDAO.findAll().stream().map(binder::getOIDCProviderTO).collect(Collectors.toList());
95 }
96
97 @PreAuthorize("hasRole('" + OIDCC4UIEntitlement.OP_READ + "')")
98 @Transactional(readOnly = true)
99 public OIDCC4UIProviderTO read(final String key) {
100 OIDCC4UIProvider op = Optional.ofNullable(opDAO.find(key)).
101 orElseThrow(() -> new NotFoundException("OIDC Provider '" + key + '\''));
102
103 return binder.getOIDCProviderTO(op);
104 }
105
106 @PreAuthorize("hasRole('" + OIDCC4UIEntitlement.OP_UPDATE + "')")
107 public void update(final OIDCC4UIProviderTO opTO) {
108 OIDCC4UIProvider op = Optional.ofNullable(opDAO.find(opTO.getKey())).
109 orElseThrow(() -> new NotFoundException("OIDC Provider '" + opTO.getKey() + '\''));
110
111 if (!op.getIssuer().equals(opTO.getIssuer())) {
112 LOG.error("Issuers do not match: expected {}, found {}",
113 op.getIssuer(), opTO.getIssuer());
114 SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.InvalidEntity);
115 sce.getElements().add("Issuers do not match");
116 throw sce;
117 }
118
119 binder.update(op, opTO);
120 oidcClientCacheLogin.removeAll(op.getName());
121 oidcClientCacheLogout.removeAll(op.getName());
122 }
123
124 @PreAuthorize("hasRole('" + OIDCC4UIEntitlement.OP_DELETE + "')")
125 public void delete(final String key) {
126 OIDCC4UIProvider op = Optional.ofNullable(opDAO.find(key)).
127 orElseThrow(() -> new NotFoundException("OIDC Provider '" + key + '\''));
128
129 opDAO.delete(key);
130 oidcClientCacheLogin.removeAll(op.getName());
131 oidcClientCacheLogout.removeAll(op.getName());
132 }
133
134 @Override
135 protected OIDCC4UIProviderTO resolveReference(
136 final Method method, final Object... args) throws UnresolvedReferenceException {
137
138 String key = null;
139
140 if (ArrayUtils.isNotEmpty(args)) {
141 for (int i = 0; key == null && i < args.length; i++) {
142 if (args[i] instanceof String) {
143 key = (String) args[i];
144 } else if (args[i] instanceof OIDCC4UIProviderTO) {
145 key = ((OIDCC4UIProviderTO) args[i]).getKey();
146 }
147 }
148 }
149
150 if (key != null) {
151 try {
152 return binder.getOIDCProviderTO(opDAO.find(key));
153 } catch (final Throwable ignore) {
154 LOG.debug("Unresolved reference", ignore);
155 throw new UnresolvedReferenceException(ignore);
156 }
157 }
158
159 throw new UnresolvedReferenceException();
160 }
161 }