]> git.aero2k.de Git - tmp/jakarta-migration.git/blob
be4c7482da8cfa53247506a605a9887d82de4f51
[tmp/jakarta-migration.git] /
1 /**
2  *  This document is a part of the source code and related artifacts
3  *  for CollectionSpace, an open source collections management system
4  *  for museums and related institutions:
5
6  *  http://www.collectionspace.org
7  *  http://wiki.collectionspace.org
8
9  *  Copyright 2009 University of California at Berkeley
10
11  *  Licensed under the Educational Community License (ECL), Version 2.0.
12  *  You may not use this file except in compliance with this License.
13
14  *  You may obtain a copy of the ECL 2.0 License at
15
16  *  https://source.collectionspace.org/collection-space/LICENSE.txt
17
18  *  Unless required by applicable law or agreed to in writing, software
19  *  distributed under the License is distributed on an "AS IS" BASIS,
20  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21  *  See the License for the specific language governing permissions and
22  *  limitations under the License.
23  */
24 package org.collectionspace.services.account.storage;
25
26 import java.util.Date;
27 import javax.persistence.EntityManager;
28 import javax.persistence.EntityManagerFactory;
29 import javax.persistence.Query;
30 import org.apache.commons.codec.binary.Base64;
31 import org.collectionspace.services.account.AccountsCommon;
32 import org.collectionspace.services.authentication.User;
33 import org.collectionspace.services.common.context.ServiceContext;
34 import org.collectionspace.services.common.document.BadRequestException;
35 import org.collectionspace.services.common.document.DocumentException;
36 import org.collectionspace.services.common.document.DocumentHandler;
37 import org.collectionspace.services.common.document.DocumentHandler.Action;
38 import org.collectionspace.services.common.document.DocumentNotFoundException;
39 import org.collectionspace.services.common.document.DocumentWrapper;
40 import org.collectionspace.services.common.document.DocumentWrapperImpl;
41 import org.collectionspace.services.common.security.SecurityUtils;
42 import org.collectionspace.services.common.storage.jpa.JpaStorageClientImpl;
43
44 import org.slf4j.Logger;
45 import org.slf4j.LoggerFactory;
46
47 /**
48  * AccountStorageClient deals with both Account and Default Identity Provider's
49  * state in persistent storage
50  * @author 
51  */
52 public class AccountStorageClient extends JpaStorageClientImpl {
53
54     private final Logger logger = LoggerFactory.getLogger(AccountStorageClient.class);
55
56     public AccountStorageClient() {
57     }
58
59     @Override
60     public String create(ServiceContext ctx,
61             DocumentHandler handler) throws BadRequestException,
62             DocumentException {
63
64         String docType = ctx.getDocumentType();
65         if (docType == null) {
66             throw new DocumentNotFoundException(
67                     "Unable to find DocumentType for service " + ctx.getServiceName());
68         }
69         if (handler == null) {
70             throw new IllegalArgumentException(
71                     "AccountStorageClient.create: handler is missing");
72         }
73         EntityManagerFactory emf = null;
74         EntityManager em = null;
75         try {
76             handler.prepare(Action.CREATE);
77             AccountsCommon account = (AccountsCommon) handler.getCommonPart();
78             DocumentWrapper<AccountsCommon> wrapDoc =
79                     new DocumentWrapperImpl<AccountsCommon>(account);
80             handler.handle(Action.CREATE, wrapDoc);
81             emf = getEntityManagerFactory();
82             em = emf.createEntityManager();
83             em.getTransaction().begin();
84             //if userid and password are given, add to default id provider
85             if (account.getUserId() != null && account.getPassword() != null) {
86                 User user = createUser(account);
87                 em.persist(user);
88             }
89 //            if (account.getTenant() != null) {
90 //                UserTenant ut = createTenantAssoc(account);
91 //                em.persist(ut);
92 //            }
93             account.setCreatedAtItem(new Date());
94             em.persist(account);
95             em.getTransaction().commit();
96             handler.complete(Action.CREATE, wrapDoc);
97             return (String) getValue(account, "getCsid");
98         } catch (BadRequestException bre) {
99             if (em != null && em.getTransaction().isActive()) {
100                 em.getTransaction().rollback();
101             }
102             throw bre;
103         } catch (Exception e) {
104             if (em != null && em.getTransaction().isActive()) {
105                 em.getTransaction().rollback();
106             }
107             if (logger.isDebugEnabled()) {
108                 logger.debug("Caught exception ", e);
109             }
110             throw new DocumentException(e);
111         } finally {
112             if (em != null) {
113                 releaseEntityManagerFactory(emf);
114             }
115         }
116     }
117
118     @Override
119     public void update(ServiceContext ctx, String id, DocumentHandler handler)
120             throws BadRequestException, DocumentNotFoundException,
121             DocumentException {
122         String docType = ctx.getDocumentType();
123         if (docType == null) {
124             throw new DocumentNotFoundException(
125                     "Unable to find DocumentType for service " + ctx.getServiceName());
126         }
127         if (handler == null) {
128             throw new IllegalArgumentException(
129                     "AccountStorageClient.update: handler is missing");
130         }
131         EntityManagerFactory emf = null;
132         EntityManager em = null;
133         try {
134             handler.prepare(Action.UPDATE);
135             AccountsCommon account = (AccountsCommon) handler.getCommonPart();
136             DocumentWrapper<AccountsCommon> wrapDoc =
137                     new DocumentWrapperImpl<AccountsCommon>(account);
138             setCsid(account, id); //set id just in case it was not populated by consumer
139             handler.handle(Action.UPDATE, wrapDoc);
140             emf = getEntityManagerFactory();
141             em = emf.createEntityManager();
142             em.getTransaction().begin();
143             AccountsCommon accountFound = getAccount(em, id);
144             Date now = new Date();
145             checkAllowedUpdates(account, accountFound);
146             //if userid and password are given, add to default id provider
147             if (account.getUserId() != null && hasPassword(account.getPassword())) {
148                 updateUser(em, account);
149             }
150             account = em.merge(account);
151             account.setUpdatedAtItem(now);
152             if (logger.isDebugEnabled()) {
153                 logger.debug("merged account=" + account.toString());
154             }
155             em.getTransaction().commit();
156             handler.complete(Action.UPDATE, wrapDoc);
157         } catch (BadRequestException bre) {
158             if (em != null && em.getTransaction().isActive()) {
159                 em.getTransaction().rollback();
160             }
161             throw bre;
162         } catch (DocumentException de) {
163             if (em != null && em.getTransaction().isActive()) {
164                 em.getTransaction().rollback();
165             }
166             throw de;
167         } catch (Exception e) {
168             if (logger.isDebugEnabled()) {
169                 logger.debug("Caught exception ", e);
170             }
171             throw new DocumentException(e);
172         } finally {
173             if (emf != null) {
174                 releaseEntityManagerFactory(emf);
175             }
176         }
177     }
178
179     @Override
180     public void delete(ServiceContext ctx, String id)
181             throws DocumentNotFoundException,
182             DocumentException {
183
184         if (logger.isDebugEnabled()) {
185             logger.debug("deleting entity with id=" + id);
186         }
187         String docType = ctx.getDocumentType();
188         if (docType == null) {
189             throw new DocumentNotFoundException(
190                     "Unable to find DocumentType for service " + ctx.getServiceName());
191         }
192         EntityManagerFactory emf = null;
193         EntityManager em = null;
194         try {
195             emf = getEntityManagerFactory();
196             em = emf.createEntityManager();
197             //TODO investigate if deep delete is possible
198             //query an delete is inefficient
199             AccountsCommon accountFound = getAccount(em, id);
200
201             //TODO: add tenant id
202
203             //if userid gives any indication about the id provider, it should
204             //be used to avoid the following approach
205             Query usrDel = null;
206             User userLocal = getUser(em, accountFound);
207             if (userLocal != null) {
208                 StringBuilder usrDelStr = new StringBuilder("DELETE FROM ");
209                 usrDelStr.append(User.class.getCanonicalName());
210                 usrDelStr.append(" WHERE username = :username");
211                 //TODO: add tenant id
212                 usrDel = em.createQuery(usrDelStr.toString());
213                 usrDel.setParameter("username", accountFound.getUserId());
214             }
215             em.getTransaction().begin();
216
217             if (userLocal != null) {
218                 int usrDelCount = usrDel.executeUpdate();
219                 if (usrDelCount != 1) {
220                     if (em != null && em.getTransaction().isActive()) {
221                         em.getTransaction().rollback();
222                     }
223                 }
224                 if (usrDelCount != 1) {
225                     String msg = "could not find user with username=" + accountFound.getUserId();
226                     logger.error(msg);
227                     throw new DocumentNotFoundException(msg);
228                 }
229             }
230             em.remove(accountFound);
231             em.getTransaction().commit();
232
233         } catch (DocumentException de) {
234             if (em != null && em.getTransaction().isActive()) {
235                 em.getTransaction().rollback();
236             }
237             throw de;
238         } catch (Exception e) {
239             if (logger.isDebugEnabled()) {
240                 logger.debug("Caught exception ", e);
241             }
242             if (em != null && em.getTransaction().isActive()) {
243                 em.getTransaction().rollback();
244             }
245             throw new DocumentException(e);
246         } finally {
247             if (emf != null) {
248                 releaseEntityManagerFactory(emf);
249             }
250         }
251     }
252
253     private AccountsCommon getAccount(EntityManager em, String id) throws DocumentNotFoundException {
254         AccountsCommon accountFound = em.find(AccountsCommon.class, id);
255         if (accountFound == null) {
256             if (em != null && em.getTransaction().isActive()) {
257                 em.getTransaction().rollback();
258             }
259             String msg = "could not find account with id=" + id;
260             logger.error(msg);
261             throw new DocumentNotFoundException(msg);
262         }
263         return accountFound;
264     }
265
266     private boolean checkAllowedUpdates(AccountsCommon toAccount, AccountsCommon fromAccount) throws BadRequestException {
267         if (!fromAccount.getUserId().equals(toAccount.getUserId())) {
268             String msg = "User id " + toAccount.getUserId() + " not found!";
269             logger.error(msg);
270             logger.debug(msg + " found userid=" + fromAccount.getUserId());
271             throw new BadRequestException(msg);
272         }
273         return true;
274     }
275
276     private User createUser(AccountsCommon account) {
277         User user = new User();
278         user.setUsername(account.getUserId());
279         if (hasPassword(account.getPassword())) {
280             user.setPasswd(getEncPassword(account));
281         }
282         user.setCreatedAtItem(new Date());
283         return user;
284     }
285
286     private User getUser(EntityManager em, AccountsCommon account) throws DocumentNotFoundException {
287         User userFound = em.find(User.class, account.getUserId());
288         if (userFound == null) {
289             if (em != null && em.getTransaction().isActive()) {
290                 em.getTransaction().rollback();
291             }
292             String msg = "could not find user with id=" + account.getUserId();
293             logger.error(msg);
294             throw new DocumentNotFoundException(msg);
295         }
296         return userFound;
297     }
298
299     private void updateUser(EntityManager em, AccountsCommon account) throws Exception {
300         User userFound = getUser(em, account);
301         if (userFound != null) {
302             userFound.setPasswd(getEncPassword(account));
303             userFound.setUpdatedAtItem(new Date());
304             if (logger.isDebugEnabled()) {
305                 logger.debug("updated user=" + userFound.toString());
306             }
307             em.persist(userFound);
308         }
309     }
310
311     private String getEncPassword(AccountsCommon account) {
312         //jaxb unmarshaller already unmarshal xs:base64Binary, no need to b64 decode
313         //byte[] bpass = Base64.decodeBase64(account.getPassword());
314         SecurityUtils.validatePassword(new String(account.getPassword()));
315         String secEncPasswd = SecurityUtils.createPasswordHash(
316                 account.getUserId(), new String(account.getPassword()));
317         return secEncPasswd;
318     }
319
320     private boolean hasPassword(byte[] bpass) {
321         return bpass != null && bpass.length > 0;
322     }
323 //    private UserTenant createTenantAssoc(AccountsCommon account) {
324 //        UserTenant userTenant = new UserTenant();
325 //        userTenant.setUserId(account.getUserId());
326 //        List<AccountsCommon.Tenant> atl = account.getTenant();
327 //        List<UserTenant.Tenant> utl =
328 //                new ArrayList<UserTenant.Tenant>();
329 //        for (AccountsCommon.Tenant at : atl) {
330 //            UserTenant.Tenant ut = new UserTenant.Tenant();
331 //            ut.setId(at.getId());
332 //            ut.setName(at.getName());
333 //            utl.add(ut);
334 //        }
335 //        userTenant.setTenant(utl);
336 //        return userTenant;
337 //    }
338 }