]> git.aero2k.de Git - tmp/jakarta-migration.git/blob
68b9545f72f5d6206a2390ade6dffccd8f154ec1
[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             StringBuilder accDelStr = new StringBuilder("DELETE FROM ");
202             accDelStr.append(getEntityName(ctx));
203             accDelStr.append(" WHERE csid = :csid");
204             //TODO: add tenant id
205             Query accDel = em.createQuery(accDelStr.toString());
206             accDel.setParameter("csid", id);
207             //TODO: add tenant id
208
209             //if userid gives any indication about the id provider, it should
210             //be used to avoid the following approach
211             Query usrDel = null;
212             User userLocal = getUser(em, accountFound);
213             if (userLocal != null) {
214                 StringBuilder usrDelStr = new StringBuilder("DELETE FROM ");
215                 usrDelStr.append(User.class.getCanonicalName());
216                 usrDelStr.append(" WHERE username = :username");
217                 //TODO: add tenant id
218                 usrDel = em.createQuery(usrDelStr.toString());
219                 usrDel.setParameter("username", accountFound.getUserId());
220             }
221             em.getTransaction().begin();
222 //            int accDelCount = accDel.executeUpdate();
223 //            if (accDelCount != 1) {
224 //                if (em != null && em.getTransaction().isActive()) {
225 //                    em.getTransaction().rollback();
226 //                }
227 //            }
228             if (userLocal != null) {
229                 int usrDelCount = usrDel.executeUpdate();
230                 if (usrDelCount != 1) {
231                     if (em != null && em.getTransaction().isActive()) {
232                         em.getTransaction().rollback();
233                     }
234                 }
235                 if (usrDelCount != 1) {
236                     String msg = "could not find user with username=" + accountFound.getUserId();
237                     logger.error(msg);
238                     throw new DocumentNotFoundException(msg);
239                 }
240             }
241             em.remove(accountFound);
242             em.getTransaction().commit();
243
244         } catch (DocumentException de) {
245             if (em != null && em.getTransaction().isActive()) {
246                 em.getTransaction().rollback();
247             }
248             throw de;
249         } catch (Exception e) {
250             if (logger.isDebugEnabled()) {
251                 logger.debug("Caught exception ", e);
252             }
253             if (em != null && em.getTransaction().isActive()) {
254                 em.getTransaction().rollback();
255             }
256             throw new DocumentException(e);
257         } finally {
258             if (emf != null) {
259                 releaseEntityManagerFactory(emf);
260             }
261         }
262     }
263
264     private AccountsCommon getAccount(EntityManager em, String id) throws DocumentNotFoundException {
265         AccountsCommon accountFound = em.find(AccountsCommon.class, id);
266         if (accountFound == null) {
267             if (em != null && em.getTransaction().isActive()) {
268                 em.getTransaction().rollback();
269             }
270             String msg = "could not find account with id=" + id;
271             logger.error(msg);
272             throw new DocumentNotFoundException(msg);
273         }
274         return accountFound;
275     }
276
277     private boolean checkAllowedUpdates(AccountsCommon toAccount, AccountsCommon fromAccount) throws BadRequestException {
278         if (!fromAccount.getUserId().equals(toAccount.getUserId())) {
279             String msg = "User id " + toAccount.getUserId() + " not found!";
280             logger.error(msg);
281             logger.debug(msg + " found userid=" + fromAccount.getUserId());
282             throw new BadRequestException(msg);
283         }
284         return true;
285     }
286
287     private User createUser(AccountsCommon account) {
288         User user = new User();
289         user.setUsername(account.getUserId());
290         if (hasPassword(account.getPassword())) {
291             user.setPasswd(getEncPassword(account));
292         }
293         user.setCreatedAtItem(new Date());
294         return user;
295     }
296
297     private User getUser(EntityManager em, AccountsCommon account) throws DocumentNotFoundException {
298         User userFound = em.find(User.class, account.getUserId());
299         if (userFound == null) {
300             if (em != null && em.getTransaction().isActive()) {
301                 em.getTransaction().rollback();
302             }
303             String msg = "could not find user with id=" + account.getUserId();
304             logger.error(msg);
305             throw new DocumentNotFoundException(msg);
306         }
307         return userFound;
308     }
309
310     private void updateUser(EntityManager em, AccountsCommon account) throws Exception {
311         User userFound = getUser(em, account);
312         if (userFound != null) {
313             userFound.setPasswd(getEncPassword(account));
314             userFound.setUpdatedAtItem(new Date());
315             if (logger.isDebugEnabled()) {
316                 logger.debug("updated user=" + userFound.toString());
317             }
318             em.persist(userFound);
319         }
320     }
321
322     private String getEncPassword(AccountsCommon account) {
323         byte[] bpass = Base64.decodeBase64(account.getPassword());
324         SecurityUtils.validatePassword(new String(bpass));
325         String secEncPasswd = SecurityUtils.createPasswordHash(
326                 account.getUserId(), new String(bpass));
327         return secEncPasswd;
328     }
329
330     private boolean hasPassword(byte[] bpass) {
331         return bpass != null && bpass.length > 0;
332     }
333 //    private UserTenant createTenantAssoc(AccountsCommon account) {
334 //        UserTenant userTenant = new UserTenant();
335 //        userTenant.setUserId(account.getUserId());
336 //        List<AccountsCommon.Tenant> atl = account.getTenant();
337 //        List<UserTenant.Tenant> utl =
338 //                new ArrayList<UserTenant.Tenant>();
339 //        for (AccountsCommon.Tenant at : atl) {
340 //            UserTenant.Tenant ut = new UserTenant.Tenant();
341 //            ut.setId(at.getId());
342 //            ut.setName(at.getName());
343 //            utl.add(ut);
344 //        }
345 //        userTenant.setTenant(utl);
346 //        return userTenant;
347 //    }
348 }