]> git.aero2k.de Git - tmp/jakarta-migration.git/blob
f069b0f9e6befd4c03ce5bf412a07d724215561b
[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 javax.persistence.EntityManager;
27 import javax.persistence.EntityManagerFactory;
28 import javax.persistence.NoResultException;
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.DocumentFilter;
37 import org.collectionspace.services.common.document.DocumentHandler;
38 import org.collectionspace.services.common.document.DocumentHandler.Action;
39 import org.collectionspace.services.common.document.DocumentNotFoundException;
40 import org.collectionspace.services.common.document.DocumentWrapper;
41 import org.collectionspace.services.common.document.DocumentWrapperImpl;
42 import org.collectionspace.services.common.security.SecurityUtils;
43 import org.collectionspace.services.common.storage.jpa.JpaStorageClient;
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 JpaStorageClient {
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, ctx.getTenantId());
87                 em.persist(user);
88             }
89             account.setTenantid(ctx.getTenantId());
90             em.persist(account);
91             em.getTransaction().commit();
92             handler.complete(Action.CREATE, wrapDoc);
93             return (String) getValue(account, "getCsid");
94         } catch (Exception e) {
95             if (em != null && em.getTransaction().isActive()) {
96                 em.getTransaction().rollback();
97             }
98             if (logger.isDebugEnabled()) {
99                 logger.debug("Caught exception ", e);
100             }
101             throw new DocumentException(e);
102         } finally {
103             if (em != null) {
104                 releaseEntityManagerFactory(emf);
105             }
106         }
107     }
108
109     @Override
110     public void update(ServiceContext ctx, String id, DocumentHandler handler)
111             throws BadRequestException, DocumentNotFoundException,
112             DocumentException {
113         String docType = ctx.getDocumentType();
114         if (docType == null) {
115             throw new DocumentNotFoundException(
116                     "Unable to find DocumentType for service " + ctx.getServiceName());
117         }
118         if (handler == null) {
119             throw new IllegalArgumentException(
120                     "AccountStorageClient.update: handler is missing");
121         }
122         EntityManagerFactory emf = null;
123         EntityManager em = null;
124         try {
125             handler.prepare(Action.UPDATE);
126             AccountsCommon account = (AccountsCommon) handler.getCommonPart();
127             DocumentWrapper<AccountsCommon> wrapDoc =
128                     new DocumentWrapperImpl<AccountsCommon>(account);
129             setCsid(account, id); //set id just in case it was not populated by consumer
130             handler.handle(Action.UPDATE, wrapDoc);
131             emf = getEntityManagerFactory();
132             em = emf.createEntityManager();
133             em.getTransaction().begin();
134             AccountsCommon accountFound = getAccount(em, id);
135
136             checkAllowedUpdates(account, accountFound);
137             //if userid and password are given, add to default id provider
138             if (account.getUserId() != null && account.getPassword() != null) {
139
140                 User userFound = getUser(em, account);
141                 User user = createUser(account, ctx.getTenantId());
142                 em.merge(user);
143             }
144             em.merge(account);
145             em.getTransaction().commit();
146             handler.complete(Action.UPDATE, wrapDoc);
147         } catch (BadRequestException bre) {
148             throw bre;
149         } catch (DocumentException de) {
150             throw de;
151         } catch (Exception e) {
152             if (logger.isDebugEnabled()) {
153                 logger.debug("Caught exception ", e);
154             }
155             throw new DocumentException(e);
156         } finally {
157             if (emf != null) {
158                 releaseEntityManagerFactory(emf);
159             }
160         }
161     }
162
163     @Override
164     public void delete(ServiceContext ctx, String id)
165             throws DocumentNotFoundException,
166             DocumentException {
167
168         if (logger.isDebugEnabled()) {
169             logger.debug("deleting entity with id=" + id);
170         }
171         String docType = ctx.getDocumentType();
172         if (docType == null) {
173             throw new DocumentNotFoundException(
174                     "Unable to find DocumentType for service " + ctx.getServiceName());
175         }
176         EntityManagerFactory emf = null;
177         EntityManager em = null;
178         try {
179             emf = getEntityManagerFactory();
180             em = emf.createEntityManager();
181             //TODO investigate if deep delete is possible
182             //query an delete is inefficient
183             AccountsCommon accountFound = getAccount(em, id);
184
185             StringBuilder accDelStr = new StringBuilder("DELETE FROM ");
186             accDelStr.append(getEntityName(ctx));
187             accDelStr.append(" WHERE csid = :csid");
188             //TODO: add tenant id
189             Query accDel = em.createQuery(accDelStr.toString());
190             accDel.setParameter("csid", id);
191             //TODO: add tenant id
192
193             //if userid gives any indication about the id provider, it should
194             //be used to avoid the following approach
195             User userLocal = em.find(User.class, accountFound.getUserId());
196             Query usrDel = null;
197             if (userLocal != null) {
198                 StringBuilder usrDelStr = new StringBuilder("DELETE FROM ");
199                 usrDelStr.append(User.class.getCanonicalName());
200                 usrDelStr.append(" WHERE username = :username");
201                 //TODO: add tenant id
202                 usrDel = em.createQuery(usrDelStr.toString());
203                 usrDel.setParameter("username", accountFound.getUserId());
204             }
205             em.getTransaction().begin();
206             int accDelCount = accDel.executeUpdate();
207             if (accDelCount != 1) {
208                 if (em != null && em.getTransaction().isActive()) {
209                     em.getTransaction().rollback();
210                 }
211             }
212             if (userLocal != null) {
213                 int usrDelCount = usrDel.executeUpdate();
214                 if (usrDelCount != 1) {
215                     if (em != null && em.getTransaction().isActive()) {
216                         em.getTransaction().rollback();
217                     }
218                 }
219                 if (usrDelCount != 1) {
220                     String msg = "could not find user with username=" + accountFound.getUserId();
221                     logger.error(msg);
222                     throw new DocumentNotFoundException(msg);
223                 }
224             }
225             em.getTransaction().commit();
226
227         } catch (DocumentException de) {
228             throw de;
229         } catch (Exception e) {
230             if (logger.isDebugEnabled()) {
231                 logger.debug("Caught exception ", e);
232             }
233             if (em != null && em.getTransaction().isActive()) {
234                 em.getTransaction().rollback();
235             }
236             throw new DocumentException(e);
237         } finally {
238             if (emf != null) {
239                 releaseEntityManagerFactory(emf);
240             }
241         }
242     }
243
244     private AccountsCommon getAccount(EntityManager em, String id) throws DocumentNotFoundException {
245         AccountsCommon accountFound = em.find(AccountsCommon.class, id);
246         if (accountFound == null) {
247             if (em != null && em.getTransaction().isActive()) {
248                 em.getTransaction().rollback();
249             }
250             String msg = "could not find account with id=" + id;
251             logger.error(msg);
252             throw new DocumentNotFoundException(msg);
253         }
254         return accountFound;
255     }
256
257     private boolean checkAllowedUpdates(AccountsCommon toAccount, AccountsCommon fromAccount) throws BadRequestException {
258         if (!fromAccount.getUserId().equals(toAccount.getUserId())) {
259             String msg = "User id " + toAccount.getUserId() + " not found!";
260             logger.error(msg);
261             logger.debug(msg + " found userid=" + fromAccount.getUserId());
262             throw new BadRequestException(msg);
263         }
264         return true;
265     }
266
267     private User createUser(AccountsCommon account, String tenantId) {
268         User user = new User();
269         user.setTenantid(tenantId);
270         user.setUsername(account.getUserId());
271         byte[] bpass = Base64.decodeBase64(account.getPassword());
272         SecurityUtils.validatePassword(new String(bpass));
273         String secEncPasswd = SecurityUtils.createPasswordHash(
274                 account.getUserId(), new String(bpass));
275         user.setPasswd(secEncPasswd);
276         return user;
277     }
278
279     private User getUser(EntityManager em, AccountsCommon account) throws DocumentNotFoundException {
280         User userFound = em.find(User.class, account.getUserId());
281         if (userFound == null) {
282             if (em != null && em.getTransaction().isActive()) {
283                 em.getTransaction().rollback();
284             }
285             String msg = "could not find user with id=" + account.getUserId();
286             logger.error(msg);
287             throw new DocumentNotFoundException(msg);
288         }
289         return userFound;
290     }
291 }