1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.syncope.fit.core;
20
21 import static org.awaitility.Awaitility.await;
22 import static org.junit.jupiter.api.Assertions.assertEquals;
23 import static org.junit.jupiter.api.Assertions.assertFalse;
24 import static org.junit.jupiter.api.Assertions.assertNotNull;
25 import static org.junit.jupiter.api.Assertions.assertTrue;
26 import static org.junit.jupiter.api.Assertions.fail;
27
28 import java.nio.charset.StandardCharsets;
29 import java.util.concurrent.TimeUnit;
30 import javax.ws.rs.core.Response;
31 import org.apache.commons.io.IOUtils;
32 import org.apache.syncope.common.lib.SyncopeClientException;
33 import org.apache.syncope.common.lib.command.CommandTO;
34 import org.apache.syncope.common.lib.form.FormProperty;
35 import org.apache.syncope.common.lib.form.FormPropertyType;
36 import org.apache.syncope.common.lib.form.SyncopeForm;
37 import org.apache.syncope.common.lib.request.UserCR;
38 import org.apache.syncope.common.lib.to.AnyObjectTO;
39 import org.apache.syncope.common.lib.to.ExecTO;
40 import org.apache.syncope.common.lib.to.FormPropertyDefTO;
41 import org.apache.syncope.common.lib.to.ImplementationTO;
42 import org.apache.syncope.common.lib.to.MacroTaskTO;
43 import org.apache.syncope.common.lib.to.RoleTO;
44 import org.apache.syncope.common.lib.to.UserTO;
45 import org.apache.syncope.common.lib.types.ClientExceptionType;
46 import org.apache.syncope.common.lib.types.ExecStatus;
47 import org.apache.syncope.common.lib.types.IdRepoEntitlement;
48 import org.apache.syncope.common.lib.types.IdRepoImplementationType;
49 import org.apache.syncope.common.lib.types.ImplementationEngine;
50 import org.apache.syncope.common.lib.types.TaskType;
51 import org.apache.syncope.common.rest.api.RESTHeaders;
52 import org.apache.syncope.common.rest.api.beans.ExecSpecs;
53 import org.apache.syncope.common.rest.api.beans.RealmQuery;
54 import org.apache.syncope.common.rest.api.beans.TaskQuery;
55 import org.apache.syncope.common.rest.api.service.TaskService;
56 import org.apache.syncope.fit.AbstractITCase;
57 import org.apache.syncope.fit.core.reference.TestCommand;
58 import org.apache.syncope.fit.core.reference.TestCommandArgs;
59 import org.apache.syncope.fit.core.reference.TestMacroActions;
60 import org.junit.jupiter.api.AfterAll;
61 import org.junit.jupiter.api.BeforeAll;
62 import org.junit.jupiter.api.Test;
63
64 public class MacroTaskITCase extends AbstractITCase {
65
66 private static String MACRO_TASK_KEY;
67
68 private static final TestCommandArgs TCA = new TestCommandArgs();
69
70 static {
71 TCA.setParentRealm("${parent}");
72 TCA.setRealmName("${realm}");
73 TCA.setPrinterName("aprinter112");
74 }
75
76 @BeforeAll
77 public static void testCommandsSetup() throws Exception {
78 CommandITCase.testCommandSetup();
79
80 ImplementationTO transformer = null;
81 try {
82 transformer = IMPLEMENTATION_SERVICE.read(
83 IdRepoImplementationType.COMMAND, "GroovyCommand");
84 } catch (SyncopeClientException e) {
85 if (e.getType().getResponseStatus() == Response.Status.NOT_FOUND) {
86 transformer = new ImplementationTO();
87 transformer.setKey("GroovyCommand");
88 transformer.setEngine(ImplementationEngine.GROOVY);
89 transformer.setType(IdRepoImplementationType.COMMAND);
90 transformer.setBody(IOUtils.toString(MacroTaskITCase.class.getResourceAsStream("/GroovyCommand.groovy"),
91 StandardCharsets.UTF_8));
92 Response response = IMPLEMENTATION_SERVICE.create(transformer);
93 transformer = IMPLEMENTATION_SERVICE.read(
94 transformer.getType(), response.getHeaderString(RESTHeaders.RESOURCE_KEY));
95 assertNotNull(transformer.getKey());
96 }
97 }
98 assertNotNull(transformer);
99
100 ImplementationTO macroActions = null;
101 try {
102 macroActions = IMPLEMENTATION_SERVICE.read(IdRepoImplementationType.MACRO_ACTIONS,
103 TestMacroActions.class.getSimpleName());
104 } catch (SyncopeClientException e) {
105 if (e.getType().getResponseStatus() == Response.Status.NOT_FOUND) {
106 macroActions = new ImplementationTO();
107 macroActions.setKey(TestMacroActions.class.getSimpleName());
108 macroActions.setEngine(ImplementationEngine.JAVA);
109 macroActions.setType(IdRepoImplementationType.MACRO_ACTIONS);
110 macroActions.setBody(TestMacroActions.class.getName());
111 Response response = IMPLEMENTATION_SERVICE.create(macroActions);
112 macroActions = IMPLEMENTATION_SERVICE.read(
113 macroActions.getType(), response.getHeaderString(RESTHeaders.RESOURCE_KEY));
114 assertNotNull(macroActions.getKey());
115 }
116 }
117 assertNotNull(macroActions);
118
119 if (MACRO_TASK_KEY == null) {
120 MACRO_TASK_KEY = TASK_SERVICE.<MacroTaskTO>search(
121 new TaskQuery.Builder(TaskType.MACRO).build()).getResult().
122 stream().filter(t -> "Test Macro".equals(t.getName())).findFirst().map(MacroTaskTO::getKey).
123 orElseGet(() -> {
124 MacroTaskTO task = new MacroTaskTO();
125 task.setName("Test Macro");
126 task.setActive(true);
127 task.setRealm("/odd");
128 task.getCommands().add(new CommandTO.Builder("GroovyCommand").build());
129 task.getCommands().add(
130 new CommandTO.Builder(TestCommand.class.getSimpleName()).args(TCA).build());
131
132 FormPropertyDefTO realm = new FormPropertyDefTO();
133 realm.setKey("realm");
134 realm.setName("Realm");
135 realm.setWritable(true);
136 realm.setRequired(true);
137 realm.setType(FormPropertyType.String);
138 task.getFormPropertyDefs().add(realm);
139
140 FormPropertyDefTO parent = new FormPropertyDefTO();
141 parent.setKey("parent");
142 parent.setName("Parent Realm");
143 parent.setWritable(true);
144 parent.setRequired(true);
145 parent.setType(FormPropertyType.Dropdown);
146 task.getFormPropertyDefs().add(parent);
147
148 task.setMacroActions(TestMacroActions.class.getSimpleName());
149
150 Response response = TASK_SERVICE.create(TaskType.MACRO, task);
151 return response.getHeaderString(RESTHeaders.RESOURCE_KEY);
152 });
153 }
154 }
155
156 @AfterAll
157 public static void cleanup() {
158 TestCommandArgs args = new TestCommandArgs();
159 try {
160 ANY_OBJECT_SERVICE.delete(args.getPrinterName());
161 REALM_SERVICE.delete(args.getParentRealm() + "/" + args.getRealmName());
162 } catch (Exception e) {
163
164 }
165 }
166
167 @Test
168 public void execute() {
169 SyncopeForm form = TASK_SERVICE.getMacroTaskForm(MACRO_TASK_KEY);
170 form.getProperty("realm").orElseThrow().setValue("macro");
171 FormProperty parent = form.getProperty("parent").orElseThrow();
172 assertTrue(parent.getDropdownValues().stream().anyMatch(v -> "/odd".equals(v.getKey())));
173 parent.setValue("/odd");
174
175 int preExecs = TASK_SERVICE.read(TaskType.MACRO, MACRO_TASK_KEY, true).getExecutions().size();
176 ExecTO execution = TASK_SERVICE.execute(new ExecSpecs.Builder().key(MACRO_TASK_KEY).build(), form);
177 assertNotNull(execution.getExecutor());
178
179 await().atMost(MAX_WAIT_SECONDS, TimeUnit.SECONDS).pollInterval(1, TimeUnit.SECONDS).until(() -> {
180 try {
181 return preExecs < TASK_SERVICE.read(TaskType.MACRO, MACRO_TASK_KEY, true).getExecutions().size();
182 } catch (Exception e) {
183 return false;
184 }
185 });
186
187 ExecTO exec = TASK_SERVICE.read(TaskType.MACRO, MACRO_TASK_KEY, true).getExecutions().get(preExecs);
188 assertEquals(ExecStatus.SUCCESS.name(), exec.getStatus());
189
190 AnyObjectTO printer = ANY_OBJECT_SERVICE.read(PRINTER, TCA.getPrinterName());
191 assertNotNull(printer);
192 assertEquals("/odd/macro", printer.getRealm());
193 assertFalse(REALM_SERVICE.search(
194 new RealmQuery.Builder().base(printer.getRealm()).build()).getResult().isEmpty());
195 }
196
197 @Test
198 public void saveSameCommandMultipleOccurrencies() {
199 TestCommandArgs tca1 = new TestCommandArgs();
200 tca1.setParentRealm("parent1");
201 tca1.setRealmName("realm1");
202 tca1.setPrinterName("printer1");
203
204 MacroTaskTO task = new MacroTaskTO();
205 task.setName("saveSameCommandMultipleOccurrencies");
206 task.setActive(true);
207 task.setRealm("/");
208 task.getCommands().add(new CommandTO.Builder("GroovyCommand").build());
209 task.getCommands().add(new CommandTO.Builder(TestCommand.class.getSimpleName()).args(tca1).build());
210 task.getCommands().add(new CommandTO.Builder("GroovyCommand").build());
211
212 Response response = TASK_SERVICE.create(TaskType.MACRO, task);
213 String newTaskKey = response.getHeaderString(RESTHeaders.RESOURCE_KEY);
214
215 task = TASK_SERVICE.<MacroTaskTO>read(TaskType.MACRO, newTaskKey, false);
216 assertEquals(3, task.getCommands().size());
217 assertEquals("GroovyCommand", task.getCommands().get(0).getKey());
218 assertEquals(TestCommand.class.getSimpleName(), task.getCommands().get(1).getKey());
219 assertEquals(tca1, task.getCommands().get(1).getArgs());
220 assertEquals("GroovyCommand", task.getCommands().get(2).getKey());
221
222 TestCommandArgs tca2 = new TestCommandArgs();
223 tca2.setParentRealm("parent2");
224 tca2.setRealmName("realm2");
225 tca2.setPrinterName("printer2");
226 task.getCommands().add(new CommandTO.Builder(TestCommand.class.getSimpleName()).args(tca2).build());
227
228 TASK_SERVICE.update(TaskType.MACRO, task);
229
230 task = TASK_SERVICE.<MacroTaskTO>read(TaskType.MACRO, newTaskKey, false);
231 assertEquals(4, task.getCommands().size());
232 assertEquals("GroovyCommand", task.getCommands().get(0).getKey());
233 assertEquals(TestCommand.class.getSimpleName(), task.getCommands().get(1).getKey());
234 assertEquals(tca1, task.getCommands().get(1).getArgs());
235 assertEquals("GroovyCommand", task.getCommands().get(2).getKey());
236 assertEquals(TestCommand.class.getSimpleName(), task.getCommands().get(3).getKey());
237 assertEquals(tca2, task.getCommands().get(3).getArgs());
238 }
239
240 @Test
241 public void cantExecute() {
242
243 RoleTO role = new RoleTO();
244 role.setKey("new" + getUUIDString());
245 role.getRealms().add("/even");
246 role.getEntitlements().add(IdRepoEntitlement.TASK_EXECUTE);
247 role = createRole(role);
248 assertNotNull(role);
249
250
251 UserCR userCR = UserITCase.getUniqueSample("cantrunncommand@test.org");
252 userCR.getRoles().add(role.getKey());
253 UserTO userTO = createUser(userCR).getEntity();
254 assertNotNull(userTO);
255
256
257 TaskService taskService = CLIENT_FACTORY.create(
258 userTO.getUsername(), "password123").getService(TaskService.class);
259 try {
260 taskService.execute(new ExecSpecs.Builder().key(MACRO_TASK_KEY).build());
261 fail();
262 } catch (SyncopeClientException e) {
263 assertEquals(ClientExceptionType.DelegatedAdministration, e.getType());
264 }
265 }
266 }