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.core.workflow.java;
20  
21  import org.apache.commons.lang3.tuple.Pair;
22  import org.apache.syncope.common.keymaster.client.api.ConfParamOps;
23  import org.apache.syncope.common.lib.request.PasswordPatch;
24  import org.apache.syncope.common.lib.request.UserCR;
25  import org.apache.syncope.common.lib.request.UserUR;
26  import org.apache.syncope.common.lib.types.ResourceOperation;
27  import org.apache.syncope.core.persistence.api.dao.GroupDAO;
28  import org.apache.syncope.core.persistence.api.dao.RealmDAO;
29  import org.apache.syncope.core.persistence.api.dao.UserDAO;
30  import org.apache.syncope.core.persistence.api.entity.EntityFactory;
31  import org.apache.syncope.core.persistence.api.entity.user.User;
32  import org.apache.syncope.core.provisioning.api.PropagationByResource;
33  import org.apache.syncope.core.provisioning.api.UserWorkflowResult;
34  import org.apache.syncope.core.provisioning.api.data.UserDataBinder;
35  import org.apache.syncope.core.provisioning.api.event.EntityLifecycleEvent;
36  import org.apache.syncope.core.provisioning.api.rules.RuleEnforcer;
37  import org.apache.syncope.core.spring.security.AuthContextUtils;
38  import org.apache.syncope.core.spring.security.SecurityProperties;
39  import org.apache.syncope.core.workflow.api.WorkflowException;
40  import org.identityconnectors.framework.common.objects.SyncDeltaType;
41  import org.springframework.context.ApplicationEventPublisher;
42  
43  /**
44   * Simple implementation basically not involving any workflow engine.
45   */
46  public class DefaultUserWorkflowAdapter extends AbstractUserWorkflowAdapter {
47  
48      protected final ConfParamOps confParamOps;
49  
50      public DefaultUserWorkflowAdapter(
51              final UserDataBinder dataBinder,
52              final UserDAO userDAO,
53              final RealmDAO realmDAO,
54              final GroupDAO groupDAO,
55              final EntityFactory entityFactory,
56              final SecurityProperties securityProperties,
57              final RuleEnforcer ruleEnforcer,
58              final ConfParamOps confParamOps,
59              final ApplicationEventPublisher publisher) {
60  
61          super(dataBinder, userDAO, realmDAO, groupDAO, entityFactory, securityProperties, ruleEnforcer, publisher);
62          this.confParamOps = confParamOps;
63      }
64  
65      @Override
66      protected UserWorkflowResult<Pair<String, Boolean>> doCreate(
67              final UserCR userCR,
68              final boolean disablePwdPolicyCheck,
69              final Boolean enabled,
70              final String creator,
71              final String context) {
72  
73          User user = entityFactory.newEntity(User.class);
74          dataBinder.create(user, userCR);
75  
76          String status;
77          boolean propagateEnable;
78          if (enabled == null) {
79              status = "created";
80              propagateEnable = true;
81          } else {
82              status = enabled
83                      ? "active"
84                      : "suspended";
85              propagateEnable = enabled;
86              user.setSuspended(!enabled);
87          }
88  
89          metadata(user, creator, context);
90          user.setStatus(status);
91          user = userDAO.save(user);
92  
93          publisher.publishEvent(
94                  new EntityLifecycleEvent<>(this, SyncDeltaType.CREATE, user, AuthContextUtils.getDomain()));
95  
96          PropagationByResource<String> propByRes = new PropagationByResource<>();
97          propByRes.set(ResourceOperation.CREATE, userDAO.findAllResourceKeys(user.getKey()));
98  
99          PropagationByResource<Pair<String, String>> propByLinkedAccount = new PropagationByResource<>();
100         user.getLinkedAccounts().forEach(account -> propByLinkedAccount.add(
101                 ResourceOperation.CREATE,
102                 Pair.of(account.getResource().getKey(), account.getConnObjectKeyValue())));
103 
104         return new UserWorkflowResult<>(
105                 Pair.of(user.getKey(), propagateEnable),
106                 propByRes,
107                 propByLinkedAccount,
108                 "create");
109     }
110 
111     @Override
112     protected UserWorkflowResult<String> doActivate(
113             final User user, final String token, final String updater, final String context) {
114 
115         if (!user.checkToken(token)) {
116             throw new WorkflowException(new IllegalArgumentException("Wrong token: " + token + " for " + user));
117         }
118 
119         metadata(user, updater, context);
120         user.removeToken();
121         user.setStatus("active");
122         User updated = userDAO.save(user);
123 
124         publisher.publishEvent(
125                 new EntityLifecycleEvent<>(this, SyncDeltaType.UPDATE, updated, AuthContextUtils.getDomain()));
126 
127         return new UserWorkflowResult<>(updated.getKey(), null, null, "activate");
128     }
129 
130     @Override
131     protected UserWorkflowResult<Pair<UserUR, Boolean>> doUpdate(
132             final User user, final UserUR userUR, final String updater, final String context) {
133 
134         Pair<PropagationByResource<String>, PropagationByResource<Pair<String, String>>> propInfo =
135                 dataBinder.update(user, userUR);
136 
137         metadata(user, updater, context);
138         User updated = userDAO.save(user);
139 
140         publisher.publishEvent(
141                 new EntityLifecycleEvent<>(this, SyncDeltaType.UPDATE, updated, AuthContextUtils.getDomain()));
142 
143         return new UserWorkflowResult<>(
144                 Pair.of(userUR, !user.isSuspended()),
145                 propInfo.getLeft(),
146                 propInfo.getRight(),
147                 "update");
148     }
149 
150     @Override
151     protected UserWorkflowResult<String> doSuspend(final User user, final String updater, final String context) {
152         metadata(user, updater, context);
153         user.setStatus("suspended");
154         User updated = userDAO.save(user);
155 
156         publisher.publishEvent(
157                 new EntityLifecycleEvent<>(this, SyncDeltaType.UPDATE, updated, AuthContextUtils.getDomain()));
158 
159         return new UserWorkflowResult<>(updated.getKey(), null, null, "suspend");
160     }
161 
162     @Override
163     protected UserWorkflowResult<String> doReactivate(final User user, final String updater, final String context) {
164         metadata(user, updater, context);
165         user.setStatus("active");
166         User updated = userDAO.save(user);
167 
168         publisher.publishEvent(
169                 new EntityLifecycleEvent<>(this, SyncDeltaType.UPDATE, updated, AuthContextUtils.getDomain()));
170 
171         return new UserWorkflowResult<>(updated.getKey(), null, null, "reactivate");
172     }
173 
174     @Override
175     protected void doRequestPasswordReset(final User user, final String updater, final String context) {
176         user.generateToken(
177                 confParamOps.get(AuthContextUtils.getDomain(), "token.length", 256, Integer.class),
178                 confParamOps.get(AuthContextUtils.getDomain(), "token.expireTime", 60, Integer.class));
179         metadata(user, updater, context);
180         User updated = userDAO.save(user);
181 
182         publisher.publishEvent(
183                 new EntityLifecycleEvent<>(this, SyncDeltaType.UPDATE, updated, AuthContextUtils.getDomain()));
184     }
185 
186     @Override
187     protected UserWorkflowResult<Pair<UserUR, Boolean>> doConfirmPasswordReset(
188             final User user, final String token, final String password, final String updater, final String context) {
189 
190         if (!user.checkToken(token)) {
191             throw new WorkflowException(new IllegalArgumentException("Wrong token: " + token + " for " + user));
192         }
193 
194         user.removeToken();
195 
196         UserUR userUR = new UserUR();
197         userUR.setKey(user.getKey());
198         userUR.setPassword(new PasswordPatch.Builder().
199                 onSyncope(true).
200                 resources(userDAO.findAllResourceKeys(user.getKey())).
201                 value(password).build());
202 
203         return doUpdate(user, userUR, updater, context);
204     }
205 
206     @Override
207     protected void doDelete(final User user, final String eraser, final String context) {
208         userDAO.delete(user);
209 
210         publisher.publishEvent(
211                 new EntityLifecycleEvent<>(this, SyncDeltaType.DELETE, user, AuthContextUtils.getDomain()));
212     }
213 }