View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.syncope.client.console;
20  
21  import static org.mockito.ArgumentMatchers.any;
22  import static org.mockito.ArgumentMatchers.anyString;
23  import static org.mockito.ArgumentMatchers.isNull;
24  import static org.mockito.Mockito.mock;
25  import static org.mockito.Mockito.when;
26  
27  import com.giffing.wicket.spring.boot.context.extensions.WicketApplicationInitConfiguration;
28  import com.giffing.wicket.spring.boot.context.extensions.boot.actuator.WicketEndpointRepository;
29  import com.giffing.wicket.spring.boot.starter.app.classscanner.candidates.WicketClassCandidatesHolder;
30  import com.giffing.wicket.spring.boot.starter.configuration.extensions.core.settings.general.GeneralSettingsProperties;
31  import com.giffing.wicket.spring.boot.starter.configuration.extensions.external.spring.boot.actuator.WicketEndpointRepositoryDefault;
32  import java.io.IOException;
33  import java.util.HashMap;
34  import java.util.List;
35  import java.util.Set;
36  import org.apache.commons.lang3.tuple.Pair;
37  import org.apache.commons.lang3.tuple.Triple;
38  import org.apache.cxf.jaxrs.client.Client;
39  import org.apache.syncope.client.console.commons.AccessPolicyConfProvider;
40  import org.apache.syncope.client.console.commons.AnyDirectoryPanelAdditionalActionLinksProvider;
41  import org.apache.syncope.client.console.commons.AnyDirectoryPanelAdditionalActionsProvider;
42  import org.apache.syncope.client.console.commons.AnyWizardBuilderAdditionalSteps;
43  import org.apache.syncope.client.console.commons.ExternalResourceProvider;
44  import org.apache.syncope.client.console.commons.ImplementationInfoProvider;
45  import org.apache.syncope.client.console.commons.PolicyTabProvider;
46  import org.apache.syncope.client.console.commons.StatusProvider;
47  import org.apache.syncope.client.console.commons.VirSchemaDetailsPanelProvider;
48  import org.apache.syncope.client.console.init.ClassPathScanImplementationLookup;
49  import org.apache.syncope.client.console.wizards.any.UserFormFinalizer;
50  import org.apache.syncope.client.lib.AuthenticationHandler;
51  import org.apache.syncope.client.lib.SyncopeAnonymousClient;
52  import org.apache.syncope.client.lib.SyncopeClient;
53  import org.apache.syncope.client.lib.SyncopeClientFactoryBean;
54  import org.apache.syncope.common.keymaster.client.api.DomainOps;
55  import org.apache.syncope.common.keymaster.client.api.ServiceOps;
56  import org.apache.syncope.common.keymaster.client.api.model.Domain;
57  import org.apache.syncope.common.lib.SyncopeConstants;
58  import org.apache.syncope.common.lib.info.NumbersInfo;
59  import org.apache.syncope.common.lib.info.PlatformInfo;
60  import org.apache.syncope.common.lib.info.SystemInfo;
61  import org.apache.syncope.common.lib.to.AnyTypeTO;
62  import org.apache.syncope.common.lib.to.PlainSchemaTO;
63  import org.apache.syncope.common.lib.to.UserTO;
64  import org.apache.syncope.common.lib.types.AnyTypeKind;
65  import org.apache.syncope.common.lib.types.AttrSchemaType;
66  import org.apache.syncope.common.rest.api.beans.SchemaQuery;
67  import org.apache.syncope.common.rest.api.service.AnyTypeService;
68  import org.apache.syncope.common.rest.api.service.FIQLQueryService;
69  import org.apache.syncope.common.rest.api.service.SchemaService;
70  import org.apache.syncope.common.rest.api.service.SyncopeService;
71  import org.apache.wicket.request.resource.IResource;
72  import org.apache.wicket.util.tester.WicketTester;
73  import org.junit.jupiter.api.BeforeAll;
74  import org.springframework.context.annotation.AnnotationConfigApplicationContext;
75  import org.springframework.context.annotation.Bean;
76  import org.springframework.context.annotation.Configuration;
77  import org.springframework.context.annotation.Import;
78  
79  public abstract class AbstractTest {
80  
81      @Import(IdRepoConsoleContext.class)
82      @Configuration(proxyBeanMethods = false)
83      public static class SyncopeConsoleWebApplicationTestConfig {
84  
85          @Bean
86          public ConsoleProperties consoleProperties() {
87              ConsoleProperties consoleProperties = new ConsoleProperties();
88  
89              consoleProperties.getSecurityHeaders().put("X-XSS-Protection", "1; mode=block");
90              consoleProperties.getSecurityHeaders().
91                      put("Strict-Transport-Security", "max-age=31536000; includeSubDomains; preload");
92              consoleProperties.getSecurityHeaders().put("X-Content-Type-Options", "nosniff");
93              consoleProperties.getSecurityHeaders().put("X-Frame-Options", "sameorigin");
94  
95              consoleProperties.setAnonymousUser("anonymousUser");
96  
97              return consoleProperties;
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 Domain.Builder(SyncopeConstants.MASTER_DOMAIN).build()));
109             return domainOps;
110         }
111 
112         @Bean
113         public GeneralSettingsProperties generalSettingsProperties() {
114             return new GeneralSettingsProperties();
115         }
116 
117         @Bean
118         public List<WicketApplicationInitConfiguration> configurations() {
119             return List.of();
120         }
121 
122         @Bean
123         public WicketClassCandidatesHolder wicketClassCandidatesHolder() {
124             return new WicketClassCandidatesHolder();
125         }
126 
127         @Bean
128         public WicketEndpointRepository wicketEndpointRepository() {
129             return new WicketEndpointRepositoryDefault();
130         }
131 
132         @Bean
133         public ClassPathScanImplementationLookup classPathScanImplementationLookup() {
134             ClassPathScanImplementationLookup lookup = new ClassPathScanImplementationLookup(
135                     Set.of(), consoleProperties());
136             lookup.load();
137             return lookup;
138         }
139     }
140 
141     public static class TestSyncopeWebApplication extends SyncopeWebApplication {
142 
143         public TestSyncopeWebApplication(
144                 final ConsoleProperties props,
145                 final ClassPathScanImplementationLookup lookup,
146                 final ServiceOps serviceOps,
147                 final ExternalResourceProvider resourceProvider,
148                 final AnyDirectoryPanelAdditionalActionsProvider anyDirectoryPanelAdditionalActionsProvider,
149                 final AnyDirectoryPanelAdditionalActionLinksProvider anyDirectoryPanelAdditionalActionLinksProvider,
150                 final AnyWizardBuilderAdditionalSteps anyWizardBuilderAdditionalSteps,
151                 final StatusProvider statusProvider,
152                 final VirSchemaDetailsPanelProvider virSchemaDetailsPanelProvider,
153                 final ImplementationInfoProvider implementationInfoProvider,
154                 final AccessPolicyConfProvider accessPolicyConfProvider,
155                 final List<PolicyTabProvider> policyTabProviders,
156                 final List<UserFormFinalizer> userFormFinalizers,
157                 final List<IResource> resources) {
158 
159             super(props, lookup, serviceOps, resourceProvider, anyDirectoryPanelAdditionalActionsProvider,
160                     anyDirectoryPanelAdditionalActionLinksProvider, anyWizardBuilderAdditionalSteps, statusProvider,
161                     virSchemaDetailsPanelProvider, implementationInfoProvider, accessPolicyConfProvider,
162                     policyTabProviders, userFormFinalizers, resources);
163         }
164 
165         public interface SyncopeServiceClient extends SyncopeService, Client {
166         }
167 
168         public interface AnyTypeServiceClient extends AnyTypeService, Client {
169         }
170 
171         public interface SchemaServiceClient extends SchemaService, Client {
172         }
173 
174         public interface FIQLQueryServiceClient extends FIQLQueryService, Client {
175         }
176 
177         private SyncopeService getSyncopeService() {
178             SyncopeServiceClient service = mock(SyncopeServiceClient.class);
179             when(service.type(anyString())).thenReturn(service);
180             when(service.accept(anyString())).thenReturn(service);
181 
182             return service;
183         }
184 
185         private SchemaService getSchemaService() {
186             SchemaServiceClient service = mock(SchemaServiceClient.class);
187 
188             when(service.type(anyString())).thenReturn(service);
189             when(service.accept(anyString())).thenReturn(service);
190 
191             PlainSchemaTO firstname = new PlainSchemaTO();
192             firstname.setKey("firstname");
193             firstname.setType(AttrSchemaType.String);
194             firstname.setAnyTypeClass("minimal user");
195             firstname.setMandatoryCondition("false");
196             when(service.search(any(SchemaQuery.class))).thenReturn(List.of(firstname));
197             return service;
198         }
199 
200         private AnyTypeService getAnyTypeService() {
201             AnyTypeServiceClient service = mock(AnyTypeServiceClient.class);
202 
203             when(service.type(anyString())).thenReturn(service);
204             when(service.accept(anyString())).thenReturn(service);
205 
206             AnyTypeTO anyTypeTO = new AnyTypeTO();
207             anyTypeTO.setKey("123456");
208             anyTypeTO.setKind(AnyTypeKind.USER);
209 
210             when(service.read(anyString())).thenReturn(anyTypeTO);
211             return service;
212         }
213 
214         private FIQLQueryService getFIQLQueryService() {
215             FIQLQueryServiceClient service = mock(FIQLQueryServiceClient.class);
216 
217             when(service.type(anyString())).thenReturn(service);
218             when(service.accept(anyString())).thenReturn(service);
219 
220             return service;
221         }
222 
223         private UserTO getUserTO() {
224             UserTO userTO = new UserTO();
225             userTO.setUsername("username");
226             return userTO;
227         }
228 
229         @SuppressWarnings("unchecked")
230         @Override
231         public SyncopeClientFactoryBean newClientFactory() {
232             SyncopeClient client = mock(SyncopeClient.class);
233             SyncopeAnonymousClient anonymousClient = mock(SyncopeAnonymousClient.class);
234 
235             when(client.self()).thenReturn(Triple.of(new HashMap<>(), List.of(), getUserTO()));
236 
237             when(anonymousClient.gitAndBuildInfo()).thenReturn(Pair.of("", ""));
238             when(anonymousClient.platform()).thenReturn(new PlatformInfo());
239             when(anonymousClient.numbers()).thenAnswer(ic -> {
240                 NumbersInfo numbersInfo = new NumbersInfo();
241 
242                 numbersInfo.getConfCompleteness().put(
243                         NumbersInfo.ConfItem.RESOURCE.name(), numbersInfo.getTotalResources() > 0);
244                 numbersInfo.getConfCompleteness().put(
245                         NumbersInfo.ConfItem.ACCOUNT_POLICY.name(), false);
246                 numbersInfo.getConfCompleteness().put(
247                         NumbersInfo.ConfItem.PASSWORD_POLICY.name(), false);
248                 numbersInfo.getConfCompleteness().put(
249                         NumbersInfo.ConfItem.NOTIFICATION.name(), false);
250                 numbersInfo.getConfCompleteness().put(
251                         NumbersInfo.ConfItem.PULL_TASK.name(), false);
252                 numbersInfo.getConfCompleteness().put(
253                         NumbersInfo.ConfItem.VIR_SCHEMA.name(), false);
254                 numbersInfo.getConfCompleteness().put(
255                         NumbersInfo.ConfItem.ANY_TYPE.name(), false);
256                 numbersInfo.getConfCompleteness().put(
257                         NumbersInfo.ConfItem.SECURITY_QUESTION.name(), false);
258                 numbersInfo.getConfCompleteness().put(
259                         NumbersInfo.ConfItem.ROLE.name(), numbersInfo.getTotalRoles() > 0);
260 
261                 return numbersInfo;
262             });
263             when(anonymousClient.system()).thenReturn(new SystemInfo());
264 
265             SyncopeService syncopeService = getSyncopeService();
266             when(client.getService(SyncopeService.class)).thenReturn(syncopeService);
267 
268             SchemaService schemaService = getSchemaService();
269             when(client.getService(SchemaService.class)).thenReturn(schemaService);
270 
271             AnyTypeService anyTypeService = getAnyTypeService();
272             when(client.getService(AnyTypeService.class)).thenReturn(anyTypeService);
273 
274             FIQLQueryService fiqlQueryService = getFIQLQueryService();
275             when(client.getService(FIQLQueryService.class)).thenReturn(fiqlQueryService);
276 
277             SyncopeClientFactoryBean clientFactory = mock(SyncopeClientFactoryBean.class);
278             when(clientFactory.setDomain(any())).thenReturn(clientFactory);
279             when(clientFactory.create(any(AuthenticationHandler.class))).thenReturn(client);
280             when(clientFactory.create(anyString(), anyString())).thenReturn(client);
281             when(clientFactory.createAnonymous(anyString(), isNull())).thenReturn(anonymousClient);
282 
283             return clientFactory;
284         }
285     }
286 
287     protected static ConsoleProperties PROPS;
288 
289     protected static WicketTester TESTER;
290 
291     @BeforeAll
292     public static void setupTester() throws IOException {
293         AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
294         ctx.register(SyncopeConsoleWebApplicationTestConfig.class);
295         ctx.register(TestSyncopeWebApplication.class);
296         ctx.refresh();
297 
298         PROPS = ctx.getBean(ConsoleProperties.class);
299         TESTER = new WicketTester(ctx.getBean(SyncopeWebApplication.class));
300     }
301 }