001package de.deepamehta.core.service.accesscontrol;
002
003import de.deepamehta.core.Association;
004import de.deepamehta.core.DeepaMehtaObject;
005import de.deepamehta.core.RelatedTopic;
006import de.deepamehta.core.Topic;
007
008import javax.servlet.http.HttpServletRequest;
009import javax.servlet.http.HttpSession;
010
011import java.util.concurrent.Callable;
012
013
014
015public interface AccessControl {
016
017
018
019    // === Permissions ===
020
021    /**
022     * Checks if a user is permitted to perform an operation on an object (topic or association).
023     *
024     * @param   username    the logged in user, or <code>null</code> if no user is logged in.
025     * @param   objectId    a topic ID, or an association ID.
026     *
027     * @return  <code>true</code> if permission is granted, <code>false</code> otherwise.
028     */
029    boolean hasPermission(String username, Operation operation, long objectId);
030
031    // ---
032
033    boolean hasReadPermission(String username, long workspaceId);
034
035    boolean hasWritePermission(String username, long workspaceId);
036
037
038
039    // === User Accounts ===
040
041    /**
042     * Checks if the given credentials are valid.
043     *
044     * @return  the corresponding Username topic if the credentials are valid, or <code>null</code> otherwise.
045     */
046    Topic checkCredentials(Credentials cred);
047
048    /**
049     * Changes the password of an existing user account.
050     * <p>
051     * This is a privileged method: it works also if the respective user is not logged in.
052     *
053     * @param   cred    the username and new password.
054     *                  An user account with the given username must exist. (The username can't be changed.)
055     */
056    void changePassword(Credentials cred);
057
058    // ---
059
060    /**
061     * Returns the Username topic that corresponds to a username.
062     *
063     * @return  the Username topic, or <code>null</code> if no such Username topic exists.
064     */
065    Topic getUsernameTopic(String username);
066
067    /**
068     * Returns the private workspace of the given user.
069     * <p>
070     * Note: a user can have more than one private workspace.
071     * This method returns only the first one.
072     * <p>
073     * This is a privileged method, it bypasses the access control system.
074     *
075     * @throws  RuntimeException    if the user has no private workspace.
076     *
077     * @return  The user's private workspace (a topic of type "Workspace").
078     */
079    Topic getPrivateWorkspace(String username);
080
081    /**
082     * Checks if a user is a member of a given workspace.
083     *
084     * @param   username    the logged in user, or <code>null</code> if no user is logged in.
085     */
086    boolean isMember(String username, long workspaceId);
087
088    /**
089     * Returns the creator of a topic or an association.
090     *
091     * @return  The username of the creator, or <code>null</code> if no creator is set.
092     */
093    String getCreator(long objectId);
094
095
096
097    // === Session ===
098
099    /**
100     * Returns the username that is associated with a request.
101     *
102     * @return  the username, or <code>null</code> if no user is associated with the request.
103     */
104    String getUsername(HttpServletRequest request);
105
106    /**
107     * Convenience method that returns the Username topic that corresponds to a request.
108     * Basically it calls <code>getUsernameTopic(getUsername(request))</code>.
109     *
110     * @return  the Username topic, or <code>null</code> if no user is associated with the request.
111     */
112    Topic getUsernameTopic(HttpServletRequest request);
113
114    String username(HttpSession session);
115
116
117
118    // === Workspaces / Memberships ===
119
120    /**
121     * Returns a workspace by URI.
122     * <p>
123     * This is a privileged method: it works also if the current user has no READ permission for the workspace.
124     *
125     * @return  The workspace (a topic of type "Workspace").
126     *
127     * @throws  RuntimeException    If no workspace exists for the given URI.
128     */
129    Topic getWorkspace(String uri);
130
131    // ---
132
133    /**
134     * Returns the ID of the "DeepaMehta" workspace.
135     */
136    long getDeepaMehtaWorkspaceId();
137
138    /**
139     * Returns the ID of the "Administration" workspace.
140     */
141    long getAdministrationWorkspaceId();
142
143    /**
144     * Returns the ID of the "System" workspace.
145     */
146    long getSystemWorkspaceId();
147
148    // ---
149
150    /**
151     * Returns the ID of the workspace a topic or association is assigned to.
152     *
153     * @param   objectId    a topic ID, or an association ID
154     *
155     * @return  The workspace ID, or <code>-1</code> if no workspace is assigned.
156     */
157    long getAssignedWorkspaceId(long objectId);
158
159    /**
160     * Performs the initial workspace assignment for an object.
161     * <p>
162     * Use this method only for objects which have no workspace assignment already, that is e.g. objects
163     * created in a migration or objects created while workspace assignment is deliberately suppressed.
164     */
165    void assignToWorkspace(DeepaMehtaObject object, long workspaceId);
166
167    /**
168     * Checks if an association represents a workspace assignment.
169     * <p>
170     * This is a privileged method: it works also if the current user has no READ permission for the potential
171     * workspace.
172     */
173    boolean isWorkspaceAssignment(Association assoc);
174
175    // ---
176
177    /**
178     * Runs a code block while suppressing the standard workspace assignment for all topics/associations
179     * created within that code block.
180     */
181    <V> V runWithoutWorkspaceAssignment(Callable<V> callable) throws Exception;
182
183    /**
184     * Returns true if standard workspace assignment is currently suppressed for the current thread.
185     */
186    boolean workspaceAssignmentIsSuppressed();
187
188
189
190    // === Topicmaps ===
191
192    void deleteAssociationMapcontext(Association assoc);
193
194
195
196    // === Config Service ===
197
198    /**
199     * Returns the configuration topic of the given type for the given topic.
200     * <p>
201     * This is a privileged method, it bypasses the access control system.
202     *
203     * @throws  RuntimeException    if no such configuration topic exists.
204     */
205    RelatedTopic getConfigTopic(String configTypeUri, long topicId);
206
207
208
209    // === Email Addresses ===
210
211    /**
212     * Returns the username for the given email address.
213     * <p>
214     * The username is determined by traversing from the Email Address topic along a
215     * <code>org.deepamehta.signup.user_mailbox</code> association.
216     * <p>
217     * This is a privileged method, it bypasses the access control system.
218     *
219     * @throws  RuntimeException    if no such Email Address topic exists in the DB, or
220     *                              if more than one such Email Address topics exist in the DB, or
221     *                              if the Email Address topic is not associated to a Username topic.
222     */
223    String getUsername(String emailAddress);
224
225    /**
226     * Returns the email address for the given username.
227     * <p>
228     * The email address is determined by traversing from the Username topic along a
229     * <code>org.deepamehta.signup.user_mailbox</code> association.
230     * <p>
231     * This is a privileged method, it bypasses the access control system.
232     *
233     * @throws  RuntimeException    if no such Username topic exists in the DB, or
234     *                              if the Username topic is not associated to an Email Address topic.
235     */
236    String getEmailAddress(String username);
237
238    // ---
239
240    /**
241     * Returns true if an "Email Address" (dm4.contacts.email_address) topic with the given value exists,
242     * false otherwise.
243     * <p>
244     * This is a privileged method, it bypasses the access control system.
245     */
246    boolean emailAddressExists(String emailAddress);
247}