001: /*
002:
003: This software is OSI Certified Open Source Software.
004: OSI Certified is a certification mark of the Open Source Initiative.
005:
006: The license (Mozilla version 1.0) can be read at the MMBase site.
007: See http://www.MMBase.org/license
008:
009: */
010: package org.mmbase.security;
011:
012: import java.util.Set;
013: import java.util.HashSet;
014:
015: import org.mmbase.util.functions.Parameters;
016: import org.mmbase.bridge.Query;
017: import org.mmbase.storage.search.Constraint;
018:
019: /**
020: * The abstract implementation of the Authorization. To make your own implementation of
021: * authorization, you have to extend this class, and implement the abstract methods.
022: *
023: * @author Eduard Witteveen
024: * @author Michiel Meeuwissen
025: * @version $Id: Authorization.java,v 1.29 2008/01/21 17:28:15 michiel Exp $
026: */
027: public abstract class Authorization extends Configurable {
028:
029: /**
030: * This method should be overrided by an extending class.
031: * It has to be called, when a new Node has been created.
032: * This way, the authentication can create default rights
033: * for this object, depending on the UserContext and generate
034: * logging information.
035: * @param user The UserContext, containing the information
036: * about the user.
037: * @param nodeid The id of the MMObjectNode, which has just been added to
038: * the MMBase cloud.
039: */
040: public abstract void create(UserContext user, int nodeid);
041:
042: /**
043: * This method should be overrided by an extending class.
044: * It has to be called, when a Node has been changed.
045: * This way, the authentication can generate log information
046: * for this object, which can be used for accountability
047: * @param user The UserContext, containing the information about the user.
048: * @param nodeid The id of the MMObjectNode, which has just been changed
049: * in the cloud.
050: */
051: public abstract void update(UserContext user, int nodeid);
052:
053: /**
054: * This method should be overrided by an extending class.
055: * It has to be called, when a Node has been removed from
056: * the cloud.
057: * This way, the authentication can generate log information
058: * for this node, and remove the authorization object which
059: * belongs to this node.
060: * @param user The UserContext, containing the information
061: * about the user.
062: * @param nodeid The id of the MMObjectNode, which has just been removed
063: * in the cloud.
064: */
065: public abstract void remove(UserContext user, int nodeid);
066:
067: /**
068: * This method should be overrided by an extending class.
069: * This method checks if an operation is permitted on a certain node done
070: * by a certain user.
071: * @param user The UserContext, containing the information the user.
072: * @param nodeid The id of the MMObjectNode, which has to be checked.
073: * It the action is CREATE then this will be interpreted as a typedef node.
074: * @param operation The operation which will be performed.
075: * @return <code>true</code> if the operation is permitted,
076: * <code>false</code> if the operation is not permitted,
077: */
078: public abstract boolean check(UserContext user, int nodeid,
079: Operation operation);
080:
081: /**
082: * This method wraps the check-method with the same arguments. The only difference being that it
083: * throws on exception if the specified operation is not permitted.
084: *
085: * It is wise to override check, and not verify (And I wonder why this method is not simply final).
086: *
087: * @exception SecurityException If the assertion fails
088: * @see #check(UserContext, int, Operation)
089: */
090: public void verify(UserContext user, int nodeid, Operation operation)
091: throws SecurityException {
092: if (!check(user, nodeid, operation)) {
093: throw new SecurityException("Operation '" + operation
094: + "' on " + nodeid + " was NOT permitted to "
095: + user.getIdentifier());
096: }
097: }
098:
099: /**
100: * This method should be overrided by an extending class.
101: * This method checks if the creation of a certain relation or changing
102: * the source or destination of a certain relation done by a certain
103: * user is permitted.
104: *
105: * @param user The UserContext, containing the information about the user.
106: * @param nodeid The id of the relation which has to be checked. If the operation is CREATE
107: * then this will be interpreted as the typedef node (extending insrel) for the relation to be
108: * created.
109: * @param srcnodeid The id of the (new) source node of the relation.
110: * @param dstnodeid The id of the (new) destination node of the relation.
111: * @param operation The operation which will be performed (CREATE (create
112: * relation) or CHANGE_RELATION (source and/or destination
113: * are changed).
114: * @return <code>true</code> if the operation is permitted,
115: * <code>false</code> if the operation is not permitted,
116: */
117: public abstract boolean check(UserContext user, int nodeid,
118: int srcnodeid, int dstnodeid, Operation operation);
119:
120: /**
121: * This method wraps the check-method with the same arguments. The only difference being that it
122: * throws on exception if the specified operation is not permitted.
123: *
124: * It is wise to override check, and not verify (And I wonder why this method is not simply final).
125: *
126: * @exception SecurityException If the assertion fails
127: * @see #check(UserContext, int, int, int, Operation)
128: */
129: public void verify(UserContext user, int nodeid, int srcnodeid,
130: int dstnodeid, Operation operation)
131: throws SecurityException {
132: if (!check(user, nodeid, srcnodeid, dstnodeid, operation)) {
133: throw new SecurityException("Operation '" + operation
134: + "' on " + nodeid + " was NOT permitted to "
135: + user.getIdentifier());
136: }
137: }
138:
139: /**
140: * Checks whether user may do a certain action.
141: * Default implemetation simply uses default ActionChecker of the Action itself. Extensions may
142: * provide configuration, e.g. make links between groups and/or user object with Action objects,
143: * to provide more fine grained control over which users may execute what 'actions'.
144: *
145: * in the MMBase cloud.
146: * @since MMBase-1.9
147: */
148: public boolean check(UserContext user, Action ac,
149: Parameters parameters) {
150: return ac.getDefault().check(user, ac, parameters);
151: }
152:
153: /**
154: * @since MMBase-1.9
155: */
156: public final void verify(UserContext user, Action ac,
157: Parameters parameters) {
158: if (!check(user, ac, parameters)) {
159: throw new SecurityException("Action '" + ac
160: + " was NOT permitted to " + user.getIdentifier());
161: }
162: }
163:
164: /**
165: * This method could be overrided by an extending class.
166: * This method returns the context of a specific node.
167: * @param user The UserContext, containing the information about the user.
168: * @param nodeid The id of the MMObjectNode, which has to be asserted.
169: * @return the context setting of the node.
170: * @exception SecurityException If operation is not allowed(needs read rights)
171: */
172: public abstract String getContext(UserContext user, int nodeid)
173: throws SecurityException;
174:
175: /**
176: * This method could be overrided by an extending class.
177: * This method changes the rights on a node, by telling
178: * the authorization that it should use the context which
179: * is defined.
180: * @param user The UserContext, containing the information about the user.
181: * @param nodeid The id of the MMObjectNode, which has to be asserted.
182: * @param context The context which rights the node will get
183: * @exception SecurityException If operation is not allowed
184: * @exception SecurityException If context is not known
185: */
186: public abstract void setContext(UserContext user, int nodeid,
187: String context) throws SecurityException;
188:
189: /**
190: * This method could be overrided by an extending class.
191: * This method returns a list of contexts which can be
192: * used to change the node.
193: * @param user The UserContext, containing the information
194: * about the user.
195: * @param nodeid The id of the MMObjectNode, which has to be asserted.
196: * @return a <code>Set</code> of <code>String</code>s which
197: * represent a context in readable form..
198: * @exception SecurityException
199: */
200: public abstract Set<String> getPossibleContexts(UserContext user,
201: int nodeid) throws SecurityException;
202:
203: /**
204: * This method could be overrided by an extending class.
205: * This method returns a list of contexts availabel to a user when creating or searching for an object.
206: * The default implementation returns only the user's own default context.
207: * @param user The UserContext, containing the information
208: * about the user.
209: * @return a <code>Set</code> of <code>String</code>s which
210: * represent a context in readable form..
211: * @exception SecurityException
212: * @since MMBase-1.8.2
213: */
214: public Set<String> getPossibleContexts(UserContext user)
215: throws SecurityException {
216: Set<String> contexts = new HashSet<String>();
217: contexts.add(user.getOwnerField());
218: return contexts;
219: }
220:
221: /**
222: * Checks rights on a query. This means that the query is explored and (if possible) a
223: * constraint for it is constructed, which, if appied to the query, makes it return only
224: * checked results for the given user.
225: *
226: * Of course, this will normally only be implemented for the 'READ' operation.
227: *
228: * The constraint is <em>not</em> applied automaticly. This has to be done by using BasicQuery.setSecurityConstraint().
229: *
230: * @param user The UserContext, for which the query must be considered
231: * @param query The query to be explored
232: * @return A {@link QueryCheck} structure (containing whether the constriant is sufficient, and the
233: * new constraint or null).
234: *
235: * @since MMBase-1.7
236: */
237:
238: public QueryCheck check(UserContext user, Query query,
239: Operation operation) {
240: return NO_CHECK;
241: }
242:
243: /**
244: * Constant which can be used as a result for the check query function. It means: 'No extra
245: * contraints to be added, and the query's result will have to be postprocessed for security.
246: *
247: * @since MMBase-1.7
248: */
249: public static final QueryCheck NO_CHECK = new QueryCheck(false,
250: null);
251:
252: /**
253: * Constant which can be used as a result for the check query function. It means: 'No extra
254: * contraints to be added, but the query's result will <em>not</em> have to be postprocessed for
255: * security. This means that there are no restrictions on the given operation at all (normally:
256: * 'read' is permit to everybody).
257: *
258: * @since MMBase-1.7
259: */
260: public static final QueryCheck COMPLETE_CHECK = new QueryCheck(
261: true, null);
262:
263: /**
264: * Defines the result of a security check on a query. Such a result has two members: A
265: * 'Constraint' which has to be added to the query and a boolean which sais if the query (with
266: * the given Constraint) has now been fully checked and that it's result does not need further
267: * postprocessing.
268: *
269: * @since MMBase-1.7
270: */
271:
272: public static class QueryCheck {
273: final Constraint constraint;
274: final boolean check;
275:
276: public QueryCheck(boolean ch, Constraint co) {
277: check = ch;
278: constraint = co;
279: }
280:
281: /**
282: * Whether the contained result completely checks for security.
283: */
284: public boolean isChecked() {
285: return check;
286: }
287:
288: /**
289: * The stored constraint. This can be null if no constraint was needed (if checked), or no helpfull
290: * constraint could be constructed (if not checked).
291: */
292: public Constraint getConstraint() {
293: return constraint;
294: }
295:
296: /**
297: * {@inheritDoc}
298: * Used for debugging.
299: * @since MMBase-1.8
300: */
301: public String toString() {
302: return (check ? "CHECKED: " : "NOT CHECKED: ") + constraint;
303: }
304:
305: }
306: }
|