]> git.aero2k.de Git - tmp/jakarta-migration.git/blob
f0d479ca574dbdddb994102b05305791ec584961
[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.Query;
29 import org.apache.commons.codec.binary.Base64;
30 import org.collectionspace.services.account.AccountsCommon;
31 import org.collectionspace.services.authentication.User;
32 import org.collectionspace.services.common.context.ServiceContext;
33 import org.collectionspace.services.common.document.BadRequestException;
34 import org.collectionspace.services.common.document.DocumentException;
35 import org.collectionspace.services.common.document.DocumentHandler;
36 import org.collectionspace.services.common.document.DocumentHandler.Action;
37 import org.collectionspace.services.common.document.DocumentNotFoundException;
38 import org.collectionspace.services.common.document.DocumentWrapper;
39 import org.collectionspace.services.common.document.DocumentWrapperImpl;
40 import org.collectionspace.services.common.security.SecurityUtils;
41 import org.collectionspace.services.common.storage.jpa.JpaStorageClient;
42
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
45
46 /**
47  * AccountStorageClient deals with both Account and Default Identity Provider's
48  * state in persistent storage
49  * @author 
50  */
51 public class AccountStorageClient extends JpaStorageClient {
52
53     private final Logger logger = LoggerFactory.getLogger(AccountStorageClient.class);
54
55     public AccountStorageClient() {
56     }
57
58     @Override
59     public String create(ServiceContext ctx,
60             DocumentHandler handler) throws BadRequestException,
61             DocumentException {
62
63         String docType = ctx.getDocumentType();
64         if (docType == null) {
65             throw new DocumentNotFoundException(
66                     "Unable to find DocumentType for service " + ctx.getServiceName());
67         }
68         if (handler == null) {
69             throw new IllegalArgumentException(
70                     "AccountStorageClient.create: handler is missing");
71         }
72         EntityManagerFactory emf = null;
73         EntityManager em = null;
74         try {
75             handler.prepare(Action.CREATE);
76             AccountsCommon account = (AccountsCommon) handler.getCommonPart();
77             DocumentWrapper<AccountsCommon> wrapDoc =
78                     new DocumentWrapperImpl<AccountsCommon>(account);
79             handler.handle(Action.CREATE, wrapDoc);
80             emf = getEntityManagerFactory();
81             em = emf.createEntityManager();
82             em.getTransaction().begin();
83             //if userid and password are given, add to default id provider
84             if (account.getUserId() != null && account.getPassword() != null) {
85                 User user = createUser(account);
86                 em.persist(user);
87             }
88 //            if (account.getTenant() != null) {
89 //                UserTenant ut = createTenantAssoc(account);
90 //                em.persist(ut);
91 //            }
92             em.persist(account);
93             em.getTransaction().commit();
94             handler.complete(Action.CREATE, wrapDoc);
95             return (String) getValue(account, "getCsid");
96         } catch (BadRequestException bre) {
97             if (em != null && em.getTransaction().isActive()) {
98                 em.getTransaction().rollback();
99             }
100             throw bre;
101         } catch (Exception e) {
102             if (em != null && em.getTransaction().isActive()) {
103                 em.getTransaction().rollback();
104             }
105             if (logger.isDebugEnabled()) {
106                 logger.debug("Caught exception ", e);
107             }
108             throw new DocumentException(e);
109         } finally {
110             if (em != null) {
111                 releaseEntityManagerFactory(emf);
112             }
113         }
114     }
115
116     @Override
117     public void update(ServiceContext ctx, String id, DocumentHandler handler)
118             throws BadRequestException, DocumentNotFoundException,
119             DocumentException {
120         String docType = ctx.getDocumentType();
121         if (docType == null) {
122             throw new DocumentNotFoundException(
123                     "Unable to find DocumentType for service " + ctx.getServiceName());
124         }
125         if (handler == null) {
126             throw new IllegalArgumentException(
127                     "AccountStorageClient.update: handler is missing");
128         }
129         EntityManagerFactory emf = null;
130         EntityManager em = null;
131         try {
132             handler.prepare(Action.UPDATE);
133             AccountsCommon account = (AccountsCommon) handler.getCommonPart();
134             DocumentWrapper<AccountsCommon> wrapDoc =
135                     new DocumentWrapperImpl<AccountsCommon>(account);
136             setCsid(account, id); //set id just in case it was not populated by consumer
137             handler.handle(Action.UPDATE, wrapDoc);
138             emf = getEntityManagerFactory();
139             em = emf.createEntityManager();
140             em.getTransaction().begin();
141             AccountsCommon accountFound = getAccount(em, id);
142
143             checkAllowedUpdates(account, accountFound);
144             //if userid and password are given, add to default id provider
145             if (account.getUserId() != null && account.getPassword() != null) {
146
147                 User userFound = getUser(em, account);
148                 User user = createUser(account);
149                 em.merge(user);
150             }
151             em.merge(account);
152             em.getTransaction().commit();
153             handler.complete(Action.UPDATE, wrapDoc);
154         } catch (BadRequestException bre) {
155             if (em != null && em.getTransaction().isActive()) {
156                 em.getTransaction().rollback();
157             }
158             throw bre;
159         } catch (DocumentException de) {
160             if (em != null && em.getTransaction().isActive()) {
161                 em.getTransaction().rollback();
162             }
163             throw de;
164         } catch (Exception e) {
165             if (logger.isDebugEnabled()) {
166                 logger.debug("Caught exception ", e);
167             }
168             throw new DocumentException(e);
169         } finally {
170             if (emf != null) {
171                 releaseEntityManagerFactory(emf);
172             }
173         }
174     }
175
176     @Override
177     public void delete(ServiceContext ctx, String id)
178             throws DocumentNotFoundException,
179             DocumentException {
180
181         if (logger.isDebugEnabled()) {
182             logger.debug("deleting entity with id=" + id);
183         }
184         String docType = ctx.getDocumentType();
185         if (docType == null) {
186             throw new DocumentNotFoundException(
187                     "Unable to find DocumentType for service " + ctx.getServiceName());
188         }
189         EntityManagerFactory emf = null;
190         EntityManager em = null;
191         try {
192             emf = getEntityManagerFactory();
193             em = emf.createEntityManager();
194             //TODO investigate if deep delete is possible
195             //query an delete is inefficient
196             AccountsCommon accountFound = getAccount(em, id);
197
198             StringBuilder accDelStr = new StringBuilder("DELETE FROM ");
199             accDelStr.append(getEntityName(ctx));
200             accDelStr.append(" WHERE csid = :csid");
201             //TODO: add tenant id
202             Query accDel = em.createQuery(accDelStr.toString());
203             accDel.setParameter("csid", id);
204             //TODO: add tenant id
205
206             //if userid gives any indication about the id provider, it should
207             //be used to avoid the following approach
208             Query usrDel = null;
209             User userLocal = getUser(em, accountFound);
210             if (userLocal != null) {
211                 StringBuilder usrDelStr = new StringBuilder("DELETE FROM ");
212                 usrDelStr.append(User.class.getCanonicalName());
213                 usrDelStr.append(" WHERE username = :username");
214                 //TODO: add tenant id
215                 usrDel = em.createQuery(usrDelStr.toString());
216                 usrDel.setParameter("username", accountFound.getUserId());
217             }
218             em.getTransaction().begin();
219 //            int accDelCount = accDel.executeUpdate();
220 //            if (accDelCount != 1) {
221 //                if (em != null && em.getTransaction().isActive()) {
222 //                    em.getTransaction().rollback();
223 //                }
224 //            }
225             if (userLocal != null) {
226                 int usrDelCount = usrDel.executeUpdate();
227                 if (usrDelCount != 1) {
228                     if (em != null && em.getTransaction().isActive()) {
229                         em.getTransaction().rollback();
230                     }
231                 }
232                 if (usrDelCount != 1) {
233                     String msg = "could not find user with username=" + accountFound.getUserId();
234                     logger.error(msg);
235                     throw new DocumentNotFoundException(msg);
236                 }
237             }
238             em.remove(accountFound);
239             em.getTransaction().commit();
240
241         } catch (DocumentException de) {
242             if (em != null && em.getTransaction().isActive()) {
243                 em.getTransaction().rollback();
244             }
245             throw de;
246         } catch (Exception e) {
247             if (logger.isDebugEnabled()) {
248                 logger.debug("Caught exception ", e);
249             }
250             if (em != null && em.getTransaction().isActive()) {
251                 em.getTransaction().rollback();
252             }
253             throw new DocumentException(e);
254         } finally {
255             if (emf != null) {
256                 releaseEntityManagerFactory(emf);
257             }
258         }
259     }
260
261     private AccountsCommon getAccount(EntityManager em, String id) throws DocumentNotFoundException {
262         AccountsCommon accountFound = em.find(AccountsCommon.class, id);
263         if (accountFound == null) {
264             if (em != null && em.getTransaction().isActive()) {
265                 em.getTransaction().rollback();
266             }
267             String msg = "could not find account with id=" + id;
268             logger.error(msg);
269             throw new DocumentNotFoundException(msg);
270         }
271         return accountFound;
272     }
273
274     private boolean checkAllowedUpdates(AccountsCommon toAccount, AccountsCommon fromAccount) throws BadRequestException {
275         if (!fromAccount.getUserId().equals(toAccount.getUserId())) {
276             String msg = "User id " + toAccount.getUserId() + " not found!";
277             logger.error(msg);
278             logger.debug(msg + " found userid=" + fromAccount.getUserId());
279             throw new BadRequestException(msg);
280         }
281         return true;
282     }
283
284     private User createUser(AccountsCommon account) {
285         User user = new User();
286         user.setUsername(account.getUserId());
287         byte[] bpass = Base64.decodeBase64(account.getPassword());
288         SecurityUtils.validatePassword(new String(bpass));
289         String secEncPasswd = SecurityUtils.createPasswordHash(
290                 account.getUserId(), new String(bpass));
291         user.setPasswd(secEncPasswd);
292         return user;
293     }
294
295     private User getUser(EntityManager em, AccountsCommon account) throws DocumentNotFoundException {
296         User userFound = em.find(User.class, account.getUserId());
297         if (userFound == null) {
298             if (em != null && em.getTransaction().isActive()) {
299                 em.getTransaction().rollback();
300             }
301             String msg = "could not find user with id=" + account.getUserId();
302             logger.error(msg);
303             throw new DocumentNotFoundException(msg);
304         }
305         return userFound;
306     }
307
308 //    private UserTenant createTenantAssoc(AccountsCommon account) {
309 //        UserTenant userTenant = new UserTenant();
310 //        userTenant.setUserId(account.getUserId());
311 //        List<AccountsCommon.Tenant> atl = account.getTenant();
312 //        List<UserTenant.Tenant> utl =
313 //                new ArrayList<UserTenant.Tenant>();
314 //        for (AccountsCommon.Tenant at : atl) {
315 //            UserTenant.Tenant ut = new UserTenant.Tenant();
316 //            ut.setId(at.getId());
317 //            ut.setName(at.getName());
318 //            utl.add(ut);
319 //        }
320 //        userTenant.setTenant(utl);
321 //        return userTenant;
322 //    }
323 }