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:
6 * http://www.collectionspace.org
7 * http://wiki.collectionspace.org
9 * Copyright 2009 University of California at Berkeley
11 * Licensed under the Educational Community License (ECL), Version 2.0.
12 * You may not use this file except in compliance with this License.
14 * You may obtain a copy of the ECL 2.0 License at
16 * https://source.collectionspace.org/collection-space/LICENSE.txt
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.
24 package org.collectionspace.services.account;
26 import java.util.List;
27 import java.util.ArrayList;
29 import javax.persistence.PersistenceException;
31 import org.collectionspace.authentication.AuthN;
32 import org.collectionspace.services.account.storage.AccountRoleDocumentHandler;
33 import org.collectionspace.services.authorization.AccountRole;
34 import org.collectionspace.services.authorization.AccountRoleRel;
35 import org.collectionspace.services.authorization.Role;
36 import org.collectionspace.services.authorization.RoleValue;
37 import org.collectionspace.services.authorization.SubjectType;
39 import org.collectionspace.services.common.AbstractCollectionSpaceResourceImpl;
40 import org.collectionspace.services.common.context.RemoteServiceContextFactory;
41 import org.collectionspace.services.common.context.ServiceContext;
42 import org.collectionspace.services.common.context.ServiceContextFactory;
43 import org.collectionspace.services.common.document.DocumentHandler;
44 import org.collectionspace.services.common.storage.StorageClient;
45 import org.collectionspace.services.common.storage.jpa.JPATransactionContext;
46 import org.collectionspace.services.common.storage.jpa.JpaRelationshipStorageClient;
47 import org.collectionspace.services.common.storage.jpa.JpaStorageUtils;
48 import org.collectionspace.services.common.context.ServiceContextProperties;
50 import org.slf4j.Logger;
51 import org.slf4j.LoggerFactory;
54 * AccountRoleSubResource is used to manage account-role relationship
57 @SuppressWarnings("rawtypes")
58 public class AccountRoleSubResource
59 // extends AbstractCollectionSpaceResourceImpl<AccountRole, AccountRolesList> {
60 extends AbstractCollectionSpaceResourceImpl<AccountRole, AccountRole> {
62 final public static String ACCOUNT_ACCOUNTROLE_SERVICE = "accounts/accountroles";
63 final public static String ROLE_ACCOUNTROLE_SERVICE = "authorization/roles/accountroles";
64 //this service is never exposed as standalone RESTful service...just use unique
65 //service name to identify binding
66 /** The service name. */
67 private String serviceName = ACCOUNT_ACCOUNTROLE_SERVICE;
69 final Logger logger = LoggerFactory.getLogger(AccountRoleSubResource.class);
70 /** The storage client. */
71 final StorageClient storageClient = new JpaRelationshipStorageClient<AccountRole>();
75 * @param serviceName qualified service path
77 public AccountRoleSubResource(String serviceName) {
78 this.serviceName = serviceName;
82 * @see org.collectionspace.services.common.AbstractCollectionSpaceResourceImpl#getVersionString()
85 protected String getVersionString() {
86 /** The last change revision. */
87 final String lastChangeRevision = "$LastChangedRevision: 1165 $";
88 return lastChangeRevision;
92 * @see org.collectionspace.services.common.AbstractCollectionSpaceResourceImpl#getServiceName()
95 public String getServiceName() {
100 * @see org.collectionspace.services.common.CollectionSpaceResource#getCommonPartClass()
103 public Class<AccountRole> getCommonPartClass() {
104 return AccountRole.class;
108 * @see org.collectionspace.services.common.CollectionSpaceResource#getServiceContextFactory()
110 @SuppressWarnings("unchecked")
112 public ServiceContextFactory<AccountRole, AccountRole> getServiceContextFactory() {
113 return RemoteServiceContextFactory.get();
117 * Creates the service context.
119 * @param input the input
120 * @param subject the subject
122 * @return the service context< account role, account role>
124 * @throws Exception the exception
126 private ServiceContext<AccountRole, AccountRole> createServiceContext(
127 ServiceContext parentCtx,
129 SubjectType subject) throws Exception {
130 ServiceContext<AccountRole, AccountRole> ctx = createServiceContext(input);
131 JPATransactionContext parentTransactionContext = parentCtx != null ? (JPATransactionContext)parentCtx.getCurrentTransactionContext() : null;
133 // If the parent context has an active JPA connection then we'll use it.
135 if (parentTransactionContext != null) {
136 ctx.setTransactionContext(parentTransactionContext);
139 // Set other context values
141 ctx.setDocumentType(AccountRole.class.getPackage().getName()); //persistence unit
142 ctx.setProperty(ServiceContextProperties.ENTITY_NAME, AccountRoleRel.class.getName());
143 ctx.setProperty(ServiceContextProperties.ENTITY_CLASS, AccountRoleRel.class);
144 //subject name is necessary to indicate if role or account is a subject
145 ctx.setProperty(ServiceContextProperties.SUBJECT, subject);
147 //set context for the relationship query
148 if (subject == SubjectType.ROLE) {
149 ctx.setProperty(ServiceContextProperties.OBJECT_CLASS, AccountsCommon.class);
150 ctx.setProperty(ServiceContextProperties.OBJECT_ID, "account_id");
151 } else if (subject == SubjectType.ACCOUNT) {
152 ctx.setProperty(ServiceContextProperties.OBJECT_CLASS, Role.class);
153 ctx.setProperty(ServiceContextProperties.OBJECT_ID, "role_id");
160 * @see org.collectionspace.services.common.AbstractCollectionSpaceResourceImpl#getStorageClient(org.collectionspace.services.common.context.ServiceContext)
163 public StorageClient getStorageClient(ServiceContext<AccountRole, AccountRole> ctx) {
164 //FIXME use ctx to identify storage client
165 return storageClient;
169 * createAccountRole creates one or more account-role relationships
170 * between object (account/role) and subject (role/account)
176 public String createAccountRole(ServiceContext parentCtx, AccountRole input, SubjectType subject)
180 // We need to associate every new account with the Spring Security Admin role so we can make
181 // changes to the Spring Security ACL tables. The Spring Security Admin role has NO CollectionSpace
182 // specific permissions. It is an internal/private role that service consumers and end-users NEVER see.
185 //Preserve the original incoming list of roles
186 List<RoleValue> inputRoleValues = input.getRole();
188 //Change the role list to be just the Spring role
189 List<RoleValue> springRoles = new ArrayList<RoleValue>();
190 input.setRole(springRoles);
191 RoleValue springAdminRole = new RoleValue();
192 springRoles.add(springAdminRole);
193 springAdminRole.setRoleId(AuthN.ROLE_SPRING_ADMIN_ID);
194 springAdminRole.setRoleName(AuthN.ROLE_SPRING_ADMIN_NAME);
196 // The Spring role relationship may already exist, if it does then we'll get a PersistenceException that
197 // we'll just ignore.
199 ServiceContext<AccountRole, AccountRole> ctx = createServiceContext(parentCtx, input, subject);
200 DocumentHandler handler = createDocumentHandler(ctx);
201 getStorageClient(ctx).create(ctx, handler);
202 } catch (PersistenceException e) {
203 //If we get this exception, it means that the role relationship already exists, so
204 //we can just ignore this exception.
205 if (logger.isTraceEnabled() == true) {
206 logger.trace(AuthN.ROLE_SPRING_ADMIN_NAME +
207 " relationship already exists for account: " +
208 input.getAccount().get(0).getAccountId(), e);
213 // Now we'll add the account relationships for the original incoming roles.
215 input.setRole(inputRoleValues);
216 ServiceContext<AccountRole, AccountRole> ctx = createServiceContext(parentCtx, input, subject);
217 DocumentHandler handler = createDocumentHandler(ctx);
218 String bogusCsid = getStorageClient(ctx).create(ctx, handler);
224 * getAccountRole retrieves account-role relationships using given
225 * csid of object (account/role) and subject (role/account)
231 public AccountRole getAccountRole(ServiceContext parentCtx,
232 String csid, SubjectType subject) throws Exception {
234 if (logger.isDebugEnabled()) {
235 logger.debug("getAccountRole with csid=" + csid);
237 AccountRole result = null;
238 ServiceContext<AccountRole, AccountRole> ctx = createServiceContext(parentCtx, (AccountRole) null, subject);
239 DocumentHandler handler = createDocumentHandler(ctx);
240 getStorageClient(ctx).get(ctx, csid, handler);
241 result = (AccountRole) ctx.getOutput();
247 * Gets the account role.
249 * @param csid the csid
250 * @param subject the subject
251 * @param accountRoleCsid the account role csid
252 * @return the account role
253 * @throws Exception the exception
255 public AccountRoleRel getAccountRoleRel(
256 ServiceContext parentCtx,
259 String accountRoleCsid) throws Exception {
261 if (logger.isDebugEnabled()) {
262 logger.debug("getAccountRole with csid=" + csid);
264 ServiceContext<AccountRole, AccountRole> ctx = createServiceContext(parentCtx, (AccountRole)null, subject);
265 AccountRoleDocumentHandler handler = (AccountRoleDocumentHandler)createDocumentHandler(ctx);
266 handler.setAccountRoleCsid(accountRoleCsid);
267 AccountRoleRel accountRoleRel = (AccountRoleRel)JpaStorageUtils.getEntity(new Long(accountRoleCsid).longValue(), AccountRoleRel.class);
269 return accountRoleRel;
273 * X_delete account role.
275 * @param csid the csid
276 * @param subject the subject
277 * @throws Exception the exception
279 public void x_deleteAccountRole(
280 ServiceContext parentCtx,
282 SubjectType subject) throws Exception {
284 if (logger.isDebugEnabled()) {
285 logger.debug("deleteAccountRole with csid=" + csid);
287 AccountRole toDelete = getAccountRole(parentCtx, csid, subject);
288 deleteAccountRole(parentCtx, csid, subject, toDelete);
292 * deleteAccountRole deletes all account-role relationships using given
293 * csid of object (account/role) and subject (role/account)
294 * @param csid of the object
299 public void deleteAccountRole(
300 ServiceContext parentCtx,
302 SubjectType subject) throws Exception {
304 if (logger.isDebugEnabled()) {
305 logger.debug("deleteAccountRole with csid=" + csid);
307 ServiceContext<AccountRole, AccountRole> ctx = createServiceContext(parentCtx, (AccountRole) null, subject);
308 getStorageClient(ctx).delete(ctx, csid);
312 * deleteAccountRole deletes given account-role relationships using given
313 * csid of object (account/role) and subject (role/account)
314 * @param csid of the object
316 * @param input with account role relationships to delete
320 public void deleteAccountRole(
321 ServiceContext parentCtx,
322 String csid, SubjectType subject, AccountRole input)
325 ServiceContext<AccountRole, AccountRole> ctx = createServiceContext(parentCtx, input, subject);
326 DocumentHandler handler = createDocumentHandler(ctx);
327 getStorageClient(ctx).delete(ctx, csid, handler);