Project

General

Profile

1
/**
2
 *  '$RCSfile$'
3
 *  Copyright: 2000-2011 Regents of the University of California and the
4
 *              National Center for Ecological Analysis and Synthesis
5
 *
6
 *   '$Author: leinfelder $'
7
 *     '$Date: 2011-06-27 10:15:59 -0700 (Mon, 27 Jun 2011) $'
8
 *
9
 * This program is free software; you can redistribute it and/or modify
10
 * it under the terms of the GNU General Public License as published by
11
 * the Free Software Foundation; either version 2 of the License, or
12
 * (at your option) any later version.
13
 *
14
 * This program is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 * GNU General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU General Public License
20
 * along with this program; if not, write to the Free Software
21
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22
 */
23

    
24
package edu.ucsb.nceas.metacat.dataone;
25

    
26
import java.io.InputStream;
27
import java.util.Calendar;
28
import java.util.Date;
29
import java.util.List;
30
import java.util.Vector;
31

    
32
import org.apache.log4j.Logger;
33
import org.dataone.service.exceptions.InvalidRequest;
34
import org.dataone.service.exceptions.InvalidToken;
35
import org.dataone.service.exceptions.NotAuthorized;
36
import org.dataone.service.exceptions.NotFound;
37
import org.dataone.service.exceptions.NotImplemented;
38
import org.dataone.service.exceptions.ServiceFailure;
39
import org.dataone.service.types.AccessPolicy;
40
import org.dataone.service.types.AccessRule;
41
import org.dataone.service.types.Event;
42
import org.dataone.service.types.Identifier;
43
import org.dataone.service.types.Log;
44
import org.dataone.service.types.LogEntry;
45
import org.dataone.service.types.NodeReference;
46
import org.dataone.service.types.Permission;
47
import org.dataone.service.types.Session;
48
import org.dataone.service.types.Subject;
49
import org.dataone.service.types.SystemMetadata;
50

    
51
import edu.ucsb.nceas.metacat.EventLog;
52
import edu.ucsb.nceas.metacat.IdentifierManager;
53
import edu.ucsb.nceas.metacat.McdbDocNotFoundException;
54

    
55
public abstract class D1NodeService {
56
	
57
    private static Logger logMetacat = Logger.getLogger(D1NodeService.class);
58

    
59
  
60
	/* Methods common to CNCore and MNCore APIs */
61

    
62
	/**
63
	 * Return the log records associated with a given event between the start and 
64
	 * end dates listed given a particular Subject listed in the Session
65
	 * 
66
	 * @param session - the Session object containing the credentials for the Subject
67
	 * @param fromDate - the start date of the desired log records
68
	 * @param toDate - the end date of the desired log records
69
	 * @param event - restrict log records of a specific event type
70
	 * @param start - zero based offset from the first record in the 
71
	 *                set of matching log records. Used to assist with 
72
	 *                paging the response.
73
	 * @param count - maximum number of log records to return in the response. 
74
	 *                Used to assist with paging the response.
75
	 * 
76
	 * @return the desired log records
77
	 * 
78
	 * @throws InvalidToken
79
	 * @throws ServiceFailure
80
	 * @throws NotAuthorized
81
	 * @throws InvalidRequest
82
	 * @throws NotImplemented
83
	 */
84
	public Log getLogRecords(Session session, Date fromDate, Date toDate, 
85
      Event event, Integer start, Integer count) throws InvalidToken, ServiceFailure,
86
	    NotAuthorized, InvalidRequest, NotImplemented {
87

    
88

    
89
		Log log = new Log();
90
		Vector<LogEntry> logs = new Vector<LogEntry>();
91
		IdentifierManager im = IdentifierManager.getInstance();
92
		EventLog el = EventLog.getInstance();
93
		if (fromDate == null) {
94
			logMetacat.debug("setting fromdate from null");
95
			fromDate = new Date(1);
96
		}
97
		if (toDate == null) {
98
			logMetacat.debug("setting todate from null");
99
			toDate = new Date();
100
		}
101

    
102
		logMetacat.debug("fromDate: " + fromDate);
103
		logMetacat.debug("toDate: " + toDate);
104

    
105
		String report = el.getReport(null, null, null, null,
106
				new java.sql.Timestamp(fromDate.getTime()),
107
				new java.sql.Timestamp(toDate.getTime()), false);
108

    
109
		logMetacat.debug("report: " + report);
110

    
111
		String logEntry = "<logEntry>";
112
		String endLogEntry = "</logEntry>";
113
		int startIndex = 0;
114
		int foundIndex = report.indexOf(logEntry, startIndex);
115
		while (foundIndex != -1) {
116
			// parse out each entry
117
			int endEntryIndex = report.indexOf(endLogEntry, foundIndex);
118
			String entry = report.substring(foundIndex, endEntryIndex);
119
			logMetacat.debug("entry: " + entry);
120
			startIndex = endEntryIndex + endLogEntry.length();
121
			foundIndex = report.indexOf(logEntry, startIndex);
122

    
123
			String entryId = getLogEntryField("entryid", entry);
124
			String ipAddress = getLogEntryField("ipAddress", entry);
125
			String principal = getLogEntryField("principal", entry);
126
			String docid = getLogEntryField("docid", entry);
127
			String eventS = getLogEntryField("event", entry);
128
			String dateLogged = getLogEntryField("dateLogged", entry);
129

    
130
			LogEntry le = new LogEntry();
131

    
132
			Event e = Event.convert(eventS);
133
			if (e == null) { // skip any events that are not Dataone Crud events
134
				continue;
135
			}
136
			le.setEvent(e);
137
			Identifier entryid = new Identifier();
138
			entryid.setValue(entryId);
139
			le.setEntryId(entryid);
140
			Identifier identifier = new Identifier();
141
			try {
142
				logMetacat.debug("converting docid '" + docid + "' to a guid.");
143
				if (docid == null || docid.trim().equals("") || docid.trim().equals("null")) {
144
					continue;
145
				}
146
				docid = docid.substring(0, docid.lastIndexOf("."));
147
				identifier.setValue(im.getGUID(docid, im.getLatestRevForLocalId(docid)));
148
			} catch (Exception ex) { 
149
				// try to get the guid, if that doesn't
150
				// work, just use the local id
151
				// throw new ServiceFailure("1030",
152
				// "Error getting guid for localId " +
153
				// docid + ": " + ex.getMessage());\
154

    
155
				// skip it if the guid can't be found
156
				continue;
157
			}
158

    
159
			le.setIdentifier(identifier);
160
			le.setIpAddress(ipAddress);
161
			Calendar c = Calendar.getInstance();
162
			String year = dateLogged.substring(0, 4);
163
			String month = dateLogged.substring(5, 7);
164
			String date = dateLogged.substring(8, 10);
165
			logMetacat.debug("year: " + year + " month: " + month + " day: " + date);
166
			c.set(new Integer(year).intValue(), new Integer(month).intValue(),
167
					new Integer(date).intValue());
168
			Date logDate = c.getTime();
169
			le.setDateLogged(logDate);
170
			NodeReference memberNode = new NodeReference();
171
			memberNode.setValue(ipAddress);
172
			le.setMemberNode(memberNode);
173
			Subject princ = new Subject();
174
			princ.setValue(principal);
175
			le.setSubject(princ);
176
			le.setUserAgent("metacat/RESTService");
177

    
178
			if (event == null) {
179
				logs.add(le);
180
			}
181

    
182
			if (event != null
183
					&& e.toString().toLowerCase().trim().equals(
184
							event.toString().toLowerCase().trim())) {
185
				logs.add(le);
186
			}
187
		}
188

    
189
		log.setLogEntryList(logs);
190
		logMetacat.info("getLogRecords");
191
		return log;
192
	}
193
	
194
	/* End methods common to CNCore and MNCore APIs */
195

    
196
	/* Methods common to CNRead and MNRead APIs */
197
	
198
	/**
199
	 * Return the object identified by the given object identifier
200
	 * 
201
	 * @param session - the Session object containing the credentials for the Subject
202
	 * @param pid - the object identifier for the given object
203
	 * 
204
	 * @return inputStream - the input stream of the given object
205
	 * 
206
	 * @throws InvalidToken
207
	 * @throws ServiceFailure
208
	 * @throws NotAuthorized
209
	 * @throws InvalidRequest
210
	 * @throws NotImplemented
211
	 */
212
	public InputStream get(Session session, Identifier pid) 
213
	  throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, 
214
	  NotImplemented, InvalidRequest {
215

    
216
		return null;
217
	}
218

    
219
	/**
220
	 * Return the system metadata for a given object
221
	 * 
222
	 * @param session - the Session object containing the credentials for the Subject
223
	 * @param pid - the object identifier for the given object
224
	 * 
225
	 * @return inputStream - the input stream of the given system metadata object
226
	 * 
227
	 * @throws InvalidToken
228
	 * @throws ServiceFailure
229
	 * @throws NotAuthorized
230
	 * @throws NotFound
231
	 * @throws InvalidRequest
232
	 * @throws NotImplemented
233
	 */
234
	public SystemMetadata getSystemMetadata(Session session, Identifier pid)
235
    throws InvalidToken, ServiceFailure, NotAuthorized, NotFound,
236
    InvalidRequest, NotImplemented {
237

    
238
		return null;
239
  }
240
	
241
	/* End methods common to CNRead and MNRead APIs */
242

    
243
	/* Methods common to CNAuthorization and MNAuthorization APIs */
244
  
245
	/**
246
	 * Set access for a given object using the object identifier and a Subject
247
	 * under a given Session.
248
	 * 
249
	 * @param session - the Session object containing the credentials for the Subject
250
	 * @param pid - the object identifier for the given object to apply the policy
251
	 * @param policy - the access policy to be applied
252
	 * 
253
	 * @return true if the application of the policy succeeds
254
	 * @throws InvalidToken
255
	 * @throws ServiceFailure
256
	 * @throws NotFound
257
	 * @throws NotAuthorized
258
	 * @throws NotImplemented
259
	 * @throws InvalidRequest
260
	 */
261
	public boolean setAccessPolicy(Session session, Identifier pid, 
262
    AccessPolicy accessPolicy) 
263
	  throws InvalidToken, ServiceFailure, NotFound, NotAuthorized, 
264
	  NotImplemented, InvalidRequest {
265

    
266
		boolean success = false;
267
		
268
		// get the subject
269
		Subject subject = session.getSubject();
270
		// get the system metadata
271
		String guid = pid.getValue();
272
		
273
		// are we allowed to do this?
274
		if (!hasPermission(session, pid, Permission.CHANGE_PERMISSION)) {
275
			throw new NotAuthorized("4420", "not allowed by " + subject.getValue() + " on " + guid);	
276
		}
277
		
278
		SystemMetadata systemMetadata = null;
279
		try {
280
			systemMetadata = IdentifierManager.getInstance().getSystemMetadata(guid);
281
		} catch (McdbDocNotFoundException e) {
282
			throw new NotFound("4400", "No record found for: " + guid);
283
		}
284
				
285
		// set the access policy
286
		systemMetadata.setAccessPolicy(accessPolicy);
287
		
288
		// update the metadata
289
		try {
290
			IdentifierManager.getInstance().updateSystemMetadata(systemMetadata);
291
			success = true;
292
		} catch (McdbDocNotFoundException e) {
293
			throw new ServiceFailure("4430", e.getMessage());
294
		}
295

    
296
		return success;
297
	}
298
	
299
	/**
300
	 * Test if the user identified by the provided token has authorization 
301
	 * for operation on the specified object.
302
	 * 
303
	 * @param session - the Session object containing the credentials for the Subject
304
	 * @param pid - The identifer of the resource for which access is being checked
305
	 * @param operation - The type of operation which is being requested for the given pid
306
	 *
307
	 * @return true if the operation is allowed
308
	 * 
309
	 * @throws ServiceFailure
310
	 * @throws InvalidToken
311
	 * @throws NotFound
312
	 * @throws NotAuthorized
313
	 * @throws NotImplemented
314
	 * @throws InvalidRequest
315
	 */
316
	public boolean isAuthorized(Session session, Identifier pid, Permission permission)
317
	  throws ServiceFailure, InvalidToken, NotFound, NotAuthorized,
318
	  NotImplemented, InvalidRequest {
319

    
320
		boolean allowed = false;
321
		
322
		// get the subject
323
		Subject subject = session.getSubject();
324
		
325
		// get the system metadata
326
		String guid = pid.getValue();
327
		SystemMetadata systemMetadata = null;
328
		try {
329
			systemMetadata = IdentifierManager.getInstance().getSystemMetadata(guid);
330
		} catch (McdbDocNotFoundException e) {
331
			throw new NotFound("1800", "No record found for: " + guid);
332
		}
333
		List<AccessRule> allows = systemMetadata.getAccessPolicy().getAllowList();
334
		for (AccessRule accessRule: allows) {
335
			if (accessRule.getSubjectList().contains(subject)) {
336
				allowed = accessRule.getPermissionList().contains(permission);
337
				if (allowed) {
338
					break;
339
				}
340
			}
341
		}
342
		
343
		// TODO: throw or return?
344
		if (!allowed) {
345
			throw new NotAuthorized("1820", permission + "not allowed by " + subject.getValue() + " on " + guid);
346
		}
347
		return allowed;
348
	}
349
	
350
	protected boolean hasPermission(Session session, Identifier pid, Permission permission)
351
	  throws ServiceFailure, InvalidToken, NotFound, NotAuthorized,
352
	  NotImplemented, InvalidRequest {
353

    
354
		boolean allowed = false;
355
		
356
		// get the subject
357
		Subject subject = session.getSubject();
358
		
359
		// get the system metadata
360
		String guid = pid.getValue();
361
		SystemMetadata systemMetadata = null;
362
		try {
363
			systemMetadata = IdentifierManager.getInstance().getSystemMetadata(guid);
364
		} catch (McdbDocNotFoundException e) {
365
			throw new NotFound("1800", "No record found for: " + guid);
366
		}
367
		List<AccessRule> allows = systemMetadata.getAccessPolicy().getAllowList();
368
		for (AccessRule accessRule: allows) {
369
			if (accessRule.getSubjectList().contains(subject)) {
370
				allowed = accessRule.getPermissionList().contains(permission);
371
				if (allowed) {
372
					break;
373
				}
374
			}
375
		}
376

    
377
		return allowed;
378
	}
379

    
380
	/* End methods common to CNAuthorization and MNAuthorization APIs */
381
	
382
	/**
383
	 * parse a logEntry and get the relevant field from it
384
	 * 
385
	 * @param fieldname
386
	 * @param entry
387
	 * @return
388
	 */
389
	private String getLogEntryField(String fieldname, String entry) {
390
		String begin = "<" + fieldname + ">";
391
		String end = "</" + fieldname + ">";
392
		// logMetacat.debug("looking for " + begin + " and " + end +
393
		// " in entry " + entry);
394
		String s = entry.substring(entry.indexOf(begin) + begin.length(), entry
395
				.indexOf(end));
396
		logMetacat.debug("entry " + fieldname + " : " + s);
397
		return s;
398
	}
399

    
400
}
(3-3/8)