1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.syncope.client.enduser;
20
21 import static org.mockito.ArgumentMatchers.any;
22 import static org.mockito.ArgumentMatchers.anyBoolean;
23 import static org.mockito.ArgumentMatchers.anyString;
24 import static org.mockito.ArgumentMatchers.eq;
25 import static org.mockito.ArgumentMatchers.isNull;
26 import static org.mockito.Mockito.mock;
27 import static org.mockito.Mockito.when;
28
29 import com.giffing.wicket.spring.boot.context.extensions.WicketApplicationInitConfiguration;
30 import com.giffing.wicket.spring.boot.context.extensions.boot.actuator.WicketEndpointRepository;
31 import com.giffing.wicket.spring.boot.starter.app.classscanner.candidates.WicketClassCandidatesHolder;
32 import com.giffing.wicket.spring.boot.starter.configuration.extensions.core.settings.general.GeneralSettingsProperties;
33 import com.giffing.wicket.spring.boot.starter.configuration.extensions.external.spring.boot.actuator.WicketEndpointRepositoryDefault;
34 import java.io.IOException;
35 import java.time.OffsetDateTime;
36 import java.util.ArrayList;
37 import java.util.HashMap;
38 import java.util.HashSet;
39 import java.util.List;
40 import java.util.Map;
41 import java.util.Optional;
42 import org.apache.cxf.jaxrs.client.Client;
43 import org.apache.syncope.client.enduser.init.ClassPathScanImplementationLookup;
44 import org.apache.syncope.client.lib.AuthenticationHandler;
45 import org.apache.syncope.client.lib.SyncopeAnonymousClient;
46 import org.apache.syncope.client.lib.SyncopeClient;
47 import org.apache.syncope.client.lib.SyncopeClientFactoryBean;
48 import org.apache.syncope.client.ui.commons.DynamicMenuStringResourceLoader;
49 import org.apache.syncope.client.ui.commons.rest.AnonymousRestClient;
50 import org.apache.syncope.common.keymaster.client.api.ConfParamOps;
51 import org.apache.syncope.common.keymaster.client.api.DomainOps;
52 import org.apache.syncope.common.keymaster.client.api.ServiceOps;
53 import org.apache.syncope.common.keymaster.client.api.model.JPADomain;
54 import org.apache.syncope.common.lib.SyncopeConstants;
55 import org.apache.syncope.common.lib.collections.CircularFifoQueue;
56 import org.apache.syncope.common.lib.info.NumbersInfo;
57 import org.apache.syncope.common.lib.info.PlatformInfo;
58 import org.apache.syncope.common.lib.info.SystemInfo;
59 import org.apache.syncope.common.lib.to.AnyTypeTO;
60 import org.apache.syncope.common.lib.to.PlainSchemaTO;
61 import org.apache.syncope.common.lib.to.UserTO;
62 import org.apache.syncope.common.lib.types.AnyTypeKind;
63 import org.apache.syncope.common.lib.types.AttrSchemaType;
64 import org.apache.syncope.common.rest.api.beans.SchemaQuery;
65 import org.apache.syncope.common.rest.api.service.AnyTypeService;
66 import org.apache.syncope.common.rest.api.service.SchemaService;
67 import org.apache.syncope.common.rest.api.service.SyncopeService;
68 import org.apache.wicket.request.resource.IResource;
69 import org.apache.wicket.util.tester.WicketTester;
70 import org.junit.jupiter.api.BeforeAll;
71 import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
72 import org.springframework.context.annotation.AnnotationConfigApplicationContext;
73 import org.springframework.context.annotation.Bean;
74 import org.springframework.context.annotation.Configuration;
75 import org.springframework.core.io.ResourceLoader;
76
77 public abstract class AbstractTest {
78
79 @ImportAutoConfiguration
80 @Configuration(proxyBeanMethods = false)
81 public static class SyncopeEnduserWebApplicationTestConfig {
82
83 @Bean
84 public EnduserProperties enduserProperties() {
85 EnduserProperties enduserProperties = new EnduserProperties();
86
87 enduserProperties.getSecurityHeaders().put("X-XSS-Protection", "1; mode=block");
88 enduserProperties.getSecurityHeaders().
89 put("Strict-Transport-Security", "max-age=31536000; includeSubDomains; preload");
90 enduserProperties.getSecurityHeaders().put("X-Content-Type-Options", "nosniff");
91 enduserProperties.getSecurityHeaders().put("X-Frame-Options", "sameorigin");
92
93 enduserProperties.setAdminUser("admin");
94
95 enduserProperties.setAnonymousUser("anonymousUser");
96
97 return enduserProperties;
98 }
99
100 @Bean
101 public ServiceOps selfServiceOps() {
102 return mock(ServiceOps.class);
103 }
104
105 @Bean
106 public DomainOps domainOps() {
107 DomainOps domainOps = mock(DomainOps.class);
108 when(domainOps.list()).thenReturn(List.of(new JPADomain.Builder(SyncopeConstants.MASTER_DOMAIN).build()));
109 return domainOps;
110 }
111
112 @Bean
113 public ConfParamOps confParamOps() {
114 ConfParamOps confParamOps = mock(ConfParamOps.class);
115 when(confParamOps.get(anyString(), anyString(), anyBoolean(), eq(boolean.class))).thenReturn(false);
116 return confParamOps;
117 }
118
119 @Bean
120 public AnonymousRestClient anonymousRestClient() {
121 return mock(AnonymousRestClient.class);
122 }
123
124 @Bean
125 public GeneralSettingsProperties generalSettingsProperties() {
126 return new GeneralSettingsProperties();
127 }
128
129 @Bean
130 public List<WicketApplicationInitConfiguration> configurations() {
131 return List.of();
132 }
133
134 @Bean
135 public WicketClassCandidatesHolder wicketClassCandidatesHolder() {
136 return new WicketClassCandidatesHolder();
137 }
138
139 @Bean
140 public WicketEndpointRepository wicketEndpointRepository() {
141 return new WicketEndpointRepositoryDefault();
142 }
143
144 @Bean
145 public ClassPathScanImplementationLookup classPathScanImplementationLookup() {
146 ClassPathScanImplementationLookup lookup = new ClassPathScanImplementationLookup();
147 lookup.load();
148 return lookup;
149 }
150
151 @Bean
152 public DynamicMenuStringResourceLoader dynamicMenuStringResourceLoader() {
153 return new DynamicMenuStringResourceLoader();
154 }
155 }
156
157 public static class TestSyncopeWebApplication extends SyncopeWebApplication {
158
159 public TestSyncopeWebApplication(
160 final ResourceLoader resourceLoader,
161 final EnduserProperties props,
162 final ClassPathScanImplementationLookup lookup,
163 final ServiceOps serviceOps,
164 final List<IResource> resources,
165 final DynamicMenuStringResourceLoader dynamicMenuStringResourceLoader) {
166
167 super(resourceLoader, props, lookup, serviceOps, resources, dynamicMenuStringResourceLoader);
168 }
169
170 public interface SyncopeServiceClient extends SyncopeService, Client {
171 }
172
173 public interface AnyTypeServiceClient extends AnyTypeService, Client {
174 }
175
176 public interface SchemaServiceClient extends SchemaService, Client {
177 }
178
179 private SyncopeService getSyncopeService() {
180 SyncopeServiceClient service = mock(SyncopeServiceClient.class);
181 when(service.type(anyString())).thenReturn(service);
182 when(service.accept(anyString())).thenReturn(service);
183
184 return service;
185 }
186
187 private SchemaService getSchemaService() {
188 SchemaServiceClient service = mock(SchemaServiceClient.class);
189
190 when(service.type(anyString())).thenReturn(service);
191 when(service.accept(anyString())).thenReturn(service);
192
193 PlainSchemaTO firstname = new PlainSchemaTO();
194 firstname.setKey("firstname");
195 firstname.setType(AttrSchemaType.String);
196 firstname.setAnyTypeClass("minimal user");
197 firstname.setMandatoryCondition("false");
198 when(service.search(any(SchemaQuery.class))).thenReturn(List.of(firstname));
199 return service;
200 }
201
202 private AnyTypeService getAnyTypeService() {
203 AnyTypeServiceClient service = mock(AnyTypeServiceClient.class);
204
205 when(service.type(anyString())).thenReturn(service);
206 when(service.accept(anyString())).thenReturn(service);
207
208 AnyTypeTO anyTypeTO = new AnyTypeTO();
209 anyTypeTO.setKey("123456");
210 anyTypeTO.setKind(AnyTypeKind.USER);
211
212 when(service.read(anyString())).thenReturn(anyTypeTO);
213 return service;
214 }
215
216 private UserTO getUserTO() {
217 UserTO userTO = new UserTO();
218 userTO.setUsername("username");
219 return userTO;
220 }
221
222 @Override
223 public SyncopeClientFactoryBean newClientFactory() {
224 SyncopeClient client = mock(SyncopeClient.class);
225 SyncopeAnonymousClient anonymousClient = mock(SyncopeAnonymousClient.class);
226
227 when(client.jwtInfo()).thenReturn(Optional.of(new SyncopeClient.JwtInfo("<anyJWT>", OffsetDateTime.now())));
228
229 when(client.self()).thenReturn(new SyncopeClient.Self(getUserTO(), Map.of(), List.of()));
230
231 when(anonymousClient.platform()).thenReturn(new PlatformInfo(
232 new HashSet<>(),
233 new ArrayList<>(),
234 new ArrayList<>(),
235 new ArrayList<>(),
236 new ArrayList<>(),
237 new HashSet<>(),
238 new HashSet<>(),
239 new HashSet<>()));
240 when(anonymousClient.numbers()).thenAnswer(ic -> {
241 NumbersInfo numbersInfo = new NumbersInfo(
242 0,
243 Map.of(),
244 Map.of(),
245 0,
246 Map.of(),
247 null,
248 0,
249 Map.of(),
250 null,
251 0,
252 Map.of(),
253 0,
254 0,
255 new HashMap<>());
256
257 numbersInfo.confCompleteness().put(NumbersInfo.ConfItem.RESOURCE.name(), false);
258 numbersInfo.confCompleteness().put(NumbersInfo.ConfItem.ACCOUNT_POLICY.name(), false);
259 numbersInfo.confCompleteness().put(NumbersInfo.ConfItem.PASSWORD_POLICY.name(), false);
260 numbersInfo.confCompleteness().put(NumbersInfo.ConfItem.NOTIFICATION.name(), false);
261 numbersInfo.confCompleteness().put(NumbersInfo.ConfItem.PULL_TASK.name(), false);
262 numbersInfo.confCompleteness().put(NumbersInfo.ConfItem.ANY_TYPE.name(), false);
263 numbersInfo.confCompleteness().put(NumbersInfo.ConfItem.SECURITY_QUESTION.name(), false);
264 numbersInfo.confCompleteness().put(NumbersInfo.ConfItem.ROLE.name(), false);
265
266 return numbersInfo;
267 });
268 when(anonymousClient.system()).thenReturn(new SystemInfo(
269 null,
270 null,
271 null,
272 0,
273 0,
274 new CircularFifoQueue<>()));
275
276 SyncopeService syncopeService = getSyncopeService();
277 when(client.getService(SyncopeService.class)).thenReturn(syncopeService);
278
279 SchemaService schemaService = getSchemaService();
280 when(client.getService(SchemaService.class)).thenReturn(schemaService);
281
282 AnyTypeService anyTypeService = getAnyTypeService();
283 when(client.getService(AnyTypeService.class)).thenReturn(anyTypeService);
284
285 SyncopeClientFactoryBean clientFactory = mock(SyncopeClientFactoryBean.class);
286 when(clientFactory.setDomain(any())).thenReturn(clientFactory);
287 when(clientFactory.create(any(AuthenticationHandler.class))).thenReturn(client);
288 when(clientFactory.create(anyString(), anyString())).thenReturn(client);
289 when(clientFactory.createAnonymous(anyString(), isNull())).thenReturn(anonymousClient);
290
291 return clientFactory;
292 }
293 }
294
295 protected static EnduserProperties PROPS;
296
297 protected static WicketTester TESTER;
298
299 @BeforeAll
300 public static void setupTester() throws IOException {
301 AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
302 ctx.register(SyncopeEnduserWebApplicationTestConfig.class);
303 ctx.register(TestSyncopeWebApplication.class);
304 ctx.refresh();
305
306 PROPS = ctx.getBean(EnduserProperties.class);
307 TESTER = new WicketTester(ctx.getBean(SyncopeWebApplication.class));
308 }
309 }