1 package org.kuali.student.common.ui.server.gwt;
2
3 import java.util.HashMap;
4 import java.util.List;
5 import java.util.Map;
6 import java.util.UUID;
7
8 import org.apache.commons.lang.StringUtils;
9 import org.apache.log4j.Logger;
10 import org.kuali.rice.kew.dto.DocumentDetailDTO;
11 import org.kuali.rice.kew.service.WorkflowUtility;
12 import org.kuali.rice.kim.bo.types.dto.AttributeSet;
13 import org.kuali.rice.kim.service.IdentityManagementService;
14 import org.kuali.student.common.assembly.data.Data;
15 import org.kuali.student.common.assembly.data.Metadata;
16 import org.kuali.student.common.assembly.transform.AuthorizationFilter;
17 import org.kuali.student.common.assembly.transform.MetadataFilter;
18 import org.kuali.student.common.assembly.transform.TransformFilter;
19 import org.kuali.student.common.assembly.transform.TransformationManager;
20 import org.kuali.student.common.assembly.transform.TransformFilter.TransformFilterAction;
21 import org.kuali.student.common.dto.DtoConstants;
22 import org.kuali.student.common.exceptions.DataValidationErrorException;
23 import org.kuali.student.common.exceptions.DoesNotExistException;
24 import org.kuali.student.common.exceptions.OperationFailedException;
25 import org.kuali.student.common.exceptions.VersionMismatchException;
26 import org.kuali.student.common.rice.StudentIdentityConstants;
27 import org.kuali.student.common.rice.authorization.PermissionType;
28 import org.kuali.student.common.ui.client.service.DataSaveResult;
29 import org.kuali.student.common.ui.shared.IdAttributes;
30 import org.kuali.student.common.util.security.SecurityUtils;
31 import org.kuali.student.common.validation.dto.ValidationResultInfo;
32 import org.kuali.student.core.assembly.transform.ProposalWorkflowFilter;
33 import org.kuali.student.core.proposal.dto.ProposalInfo;
34 import org.kuali.student.core.proposal.service.ProposalService;
35 import org.springframework.transaction.annotation.Transactional;
36
37 @Transactional(readOnly=true,noRollbackFor={DoesNotExistException.class},rollbackFor={Throwable.class})
38 public abstract class AbstractDataService implements DataService{
39
40 private static final long serialVersionUID = 1L;
41
42 final Logger LOG = Logger.getLogger(AbstractDataService.class);
43
44 private TransformationManager transformationManager;
45
46 private IdentityManagementService permissionService;
47
48 private WorkflowUtility workflowUtilityService;
49
50
51 private ProposalService proposalService;
52
53 @Override
54 public Data getData(String id) throws OperationFailedException {
55 Map<String, Object> filterProperties = getDefaultFilterProperties();
56 filterProperties.put(TransformFilter.FILTER_ACTION, TransformFilterAction.GET);
57 filterProperties.put(MetadataFilter.METADATA_ID_VALUE, id);
58
59 String dtoId = id;
60
61
62 try{
63 if (proposalService != null){
64 ProposalInfo proposalInfo = proposalService.getProposal(dtoId);
65 filterProperties.put(ProposalWorkflowFilter.PROPOSAL_INFO, proposalInfo);
66 dtoId = proposalInfo.getProposalReference().get(0);
67 }
68
69 Object dto = get(dtoId);
70 if (dto != null){
71 return transformationManager.transform(dto, getDtoClass().getName(), filterProperties);
72 }
73 } catch(DoesNotExistException e){
74 return null;
75 } catch (Exception e) {
76 LOG.error("Error getting data",e);
77 throw new OperationFailedException("Error getting data",e);
78 }
79 return null;
80 }
81
82 @Override
83 public Metadata getMetadata(String id, Map<String, String> attributes) {
84 Map<String, Object> filterProperties = getDefaultFilterProperties();
85 filterProperties.put(MetadataFilter.METADATA_ID_VALUE, id);
86
87
88 String idType = (attributes != null? attributes.get(IdAttributes.ID_TYPE):null);
89 String docType = (attributes != null ? attributes.get(StudentIdentityConstants.DOCUMENT_TYPE_NAME):null);
90 String dtoState = (attributes != null ? attributes.get(DtoConstants.DTO_STATE):null);
91 String dtoNextState = (attributes != null ? attributes.get(DtoConstants.DTO_NEXT_STATE):null);
92 String workflowNode = (attributes != null ? attributes.get(DtoConstants.DTO_WORKFLOW_NODE):null);
93
94 if (idType == null){
95 filterProperties.remove(MetadataFilter.METADATA_ID_TYPE);
96 } else {
97 filterProperties.put(MetadataFilter.METADATA_ID_TYPE, idType);
98 }
99
100 if (docType == null){
101 filterProperties.put(ProposalWorkflowFilter.WORKFLOW_DOC_TYPE, getDefaultWorkflowDocumentType());
102 } else {
103 filterProperties.put(ProposalWorkflowFilter.WORKFLOW_DOC_TYPE, docType);
104 }
105
106 if (dtoState != null){
107 filterProperties.put(DtoConstants.DTO_STATE, dtoState);
108 }
109
110 if (dtoNextState != null){
111 filterProperties.put(DtoConstants.DTO_NEXT_STATE, dtoNextState);
112 }
113
114 if (workflowNode != null){
115 filterProperties.put(DtoConstants.DTO_WORKFLOW_NODE, workflowNode);
116 }
117
118 if (checkDocumentLevelPermissions()){
119 filterProperties.put(AuthorizationFilter.DOC_LEVEL_PERM_CHECK, Boolean.TRUE.toString());
120 }
121
122 Metadata metadata = transformationManager.getMetadata(getDtoClass().getName(), filterProperties);
123 return metadata;
124 }
125
126 @Override
127 @Transactional(readOnly=false,noRollbackFor={DoesNotExistException.class},rollbackFor={Throwable.class})
128 public DataSaveResult saveData(Data data) throws OperationFailedException, DataValidationErrorException, VersionMismatchException{
129 Map<String, Object> filterProperties = getDefaultFilterProperties();
130 filterProperties.put(TransformFilter.FILTER_ACTION, TransformFilterAction.SAVE);
131
132 DataSaveResult saveResult = new DataSaveResult();
133 try {
134
135 Object dto = transformationManager.transform(data, getDtoClass(), filterProperties);
136
137
138
139
140 dto = save(dto, filterProperties);
141
142
143 List<ValidationResultInfo> validationResults = validate(dto);
144
145
146 Data persistedData = transformationManager.transform(dto, getDtoClass().getName(), filterProperties);
147
148 saveResult.setValue(persistedData);
149 saveResult.setValidationResults(validationResults);
150 }catch (DataValidationErrorException dvee){
151
152 throw dvee;
153 }catch (OperationFailedException ofe){
154 throw ofe;
155 }catch (VersionMismatchException vme){
156 throw vme;
157 }catch (Exception e) {
158 LOG.error("Failed to save data",e);
159 throw new OperationFailedException("Failed to save data",e);
160 }
161
162 return saveResult;
163 }
164
165
166
167 @Override
168 public List<ValidationResultInfo> validateData(Data data) throws OperationFailedException {
169 List<ValidationResultInfo> validationResults;
170
171 try {
172 Metadata metadata = transformationManager.getUnfilteredMetadata(getDtoClass().getName());
173 Object dto = transformationManager.getMapper().convertFromData(data, getDtoClass(), metadata);
174 validationResults = validate(dto);
175 } catch (Exception e) {
176 throw new OperationFailedException("Unable to validate data", e);
177 }
178
179 return validationResults;
180 }
181
182 @Override
183 public Boolean isAuthorized(PermissionType type, Map<String,String> attributes) {
184 String user = SecurityUtils.getCurrentPrincipalId();
185 boolean result = false;
186 if (checkDocumentLevelPermissions()) {
187 if (type == null) {
188 return null;
189 }
190 String namespaceCode = type.getPermissionNamespace();
191 String permissionTemplateName = type.getPermissionTemplateName();
192
193 AttributeSet roleQuals = new AttributeSet();
194 AttributeSet permissionDetails = new AttributeSet();
195
196 if (attributes != null) {
197
198
199
200 if (proposalService != null){
201 ProposalInfo proposalInfo = null;
202 try {
203
204 if (attributes.containsKey(IdAttributes.IdType.KS_KEW_OBJECT_ID.toString())){
205 proposalInfo = proposalService.getProposal(attributes.get(IdAttributes.IdType.KS_KEW_OBJECT_ID.toString()));
206 } else if (attributes.containsKey(IdAttributes.IdType.DOCUMENT_ID.toString())){
207 proposalInfo = proposalService.getProposalByWorkflowId(attributes.get(IdAttributes.IdType.DOCUMENT_ID.toString()));
208 }
209
210
211 DocumentDetailDTO docDetail = getWorkflowUtilityService().getDocumentDetail(Long.parseLong(proposalInfo.getWorkflowId()));
212 String routeStatusCode = docDetail.getDocRouteStatus();
213
214
215 if (proposalInfo != null){
216 attributes.put(IdAttributes.IdType.KS_KEW_OBJECT_ID.toString(), proposalInfo.getId());
217 attributes.put(StudentIdentityConstants.QUALIFICATION_DATA_ID, proposalInfo.getId());
218 attributes.put(IdAttributes.IdType.DOCUMENT_ID.toString(), proposalInfo.getWorkflowId());
219 attributes.put(StudentIdentityConstants.DOCUMENT_TYPE_NAME, proposalInfo.getType());
220 attributes.put(StudentIdentityConstants.ROUTE_STATUS_CODE, routeStatusCode);
221 }
222 } catch (Exception e){
223 LOG.error("Could not retrieve proposal to determine permission qualifiers:" + e.toString());
224 }
225 }
226
227 permissionDetails.putAll(attributes);
228
229
230
231 attributes.put("RAND_NO_CACHE", UUID.randomUUID().toString());
232 roleQuals.putAll(attributes);
233 }
234 if (StringUtils.isNotBlank(namespaceCode) && StringUtils.isNotBlank(permissionTemplateName)) {
235 LOG.info("Checking Permission '" + namespaceCode + "/" + permissionTemplateName + "' for user '" + user + "'");
236 result = getPermissionService().isAuthorizedByTemplateName(user, namespaceCode, permissionTemplateName, permissionDetails, roleQuals);
237 }
238 else {
239 LOG.info("Can not check Permission with namespace '" + namespaceCode + "' and template name '" + permissionTemplateName + "' for user '" + user + "'");
240 return Boolean.TRUE;
241 }
242 }
243 else {
244 LOG.info("Will not check for document level permissions. Defaulting authorization to true.");
245 result = true;
246 }
247 LOG.info("Result of authorization check for user '" + user + "': " + result);
248 return Boolean.valueOf(result);
249 }
250
251 public Map<String, Object> getDefaultFilterProperties(){
252 Map<String, Object> filterProperties = new HashMap<String,Object>();
253 filterProperties.put(MetadataFilter.METADATA_ID_TYPE, StudentIdentityConstants.QUALIFICATION_KEW_OBJECT_ID);
254 filterProperties.put(ProposalWorkflowFilter.WORKFLOW_USER, SecurityUtils.getCurrentPrincipalId());
255
256 return filterProperties;
257 }
258
259 protected DataSaveResult _saveData(Data data, Map<String, Object> filterProperties) throws OperationFailedException{
260 try {
261 filterProperties.put(MetadataFilter.METADATA_ID_VALUE, (String)data.query("id"));
262
263 Object dto = transformationManager.transform(data, getDtoClass(),filterProperties);
264 dto = save(dto, filterProperties);
265
266 Data persistedData = transformationManager.transform(dto,getDtoClass().getName(), filterProperties);
267 return new DataSaveResult(null, persistedData);
268 } catch (DataValidationErrorException dvee){
269 return new DataSaveResult(dvee.getValidationResults(), null);
270 } catch (Exception e) {
271 LOG.error("Unable to save", e);
272 throw new OperationFailedException("Unable to save");
273 }
274 }
275
276 protected boolean checkDocumentLevelPermissions() {
277 return false;
278 }
279
280
281
282 public TransformationManager getTransformationManager() {
283 return transformationManager;
284 }
285
286 public void setTransformationManager(TransformationManager transformationManager) {
287 this.transformationManager = transformationManager;
288 }
289
290 public IdentityManagementService getPermissionService() {
291 return permissionService;
292 }
293
294 public void setPermissionService(IdentityManagementService permissionService) {
295 this.permissionService = permissionService;
296 }
297
298 public ProposalService getProposalService() {
299 return proposalService;
300 }
301
302 public void setProposalService(ProposalService proposalService) {
303 this.proposalService = proposalService;
304 }
305
306 public WorkflowUtility getWorkflowUtilityService() {
307 return workflowUtilityService;
308 }
309
310 public void setWorkflowUtilityService(WorkflowUtility workflowUtilityService) {
311 this.workflowUtilityService = workflowUtilityService;
312 }
313
314 protected abstract String getDefaultWorkflowDocumentType();
315
316 protected abstract String getDefaultMetaDataState();
317
318
319
320
321
322
323
324
325
326 protected abstract Object get(String id) throws Exception;
327
328
329
330
331
332
333
334
335
336
337 protected abstract Object save(Object dto, Map<String, Object> properties) throws Exception;
338
339
340
341
342
343
344
345
346
347 protected abstract List<ValidationResultInfo> validate(Object dto) throws Exception;
348
349
350
351
352
353
354 protected abstract Class<?> getDtoClass();
355 }