001package systems.dmx.core.service.accesscontrol;
002
003import systems.dmx.core.Association;
004import systems.dmx.core.DMXObject;
005import systems.dmx.core.RelatedTopic;
006import systems.dmx.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    /**
115     * Returns the username that is associated with a session.
116     *
117     * @return  the username, or <code>null</code> if no user is associated with the session.
118     */
119    String username(HttpSession session);
120
121
122
123    // === Workspaces / Memberships ===
124
125    /**
126     * Returns a workspace by URI.
127     * <p>
128     * This is a privileged method: it works also if the current user has no READ permission for the workspace.
129     *
130     * @return  The workspace (a topic of type "Workspace").
131     *
132     * @throws  RuntimeException    If no workspace exists for the given URI.
133     */
134    Topic getWorkspace(String uri);
135
136    // ---
137
138    /**
139     * Returns the ID of the "DMX" workspace.
140     */
141    long getDMXWorkspaceId();
142
143    /**
144     * Returns the ID of the "Administration" workspace.
145     */
146    long getAdministrationWorkspaceId();
147
148    /**
149     * Returns the ID of the "System" workspace.
150     */
151    long getSystemWorkspaceId();
152
153    // ---
154
155    /**
156     * Returns the ID of the workspace a topic or association is assigned to.
157     *
158     * @param   objectId    a topic ID, or an association ID
159     *
160     * @return  The workspace ID, or <code>-1</code> if no workspace is assigned.
161     */
162    long getAssignedWorkspaceId(long objectId);
163
164    /**
165     * Performs the initial workspace assignment for an object.
166     * <p>
167     * Use this method only for objects which have no workspace assignment already, that is e.g. objects
168     * created in a migration or objects created while workspace assignment is deliberately suppressed.
169     */
170    void assignToWorkspace(DMXObject object, long workspaceId);
171
172    /**
173     * Checks if an association represents a workspace assignment.
174     * <p>
175     * This is a privileged method: it works also if the current user has no READ permission for the potential
176     * workspace.
177     */
178    boolean isWorkspaceAssignment(Association assoc);
179
180    // ---
181
182    /**
183     * Runs a code block while suppressing the standard workspace assignment for all topics/associations
184     * created within that code block.
185     */
186    <V> V runWithoutWorkspaceAssignment(Callable<V> callable) throws Exception;
187
188    /**
189     * Returns true if standard workspace assignment is currently suppressed for the current thread.
190     */
191    boolean workspaceAssignmentIsSuppressed();
192
193
194
195    // === Topicmaps ===
196
197    void deleteAssociationMapcontext(Association assoc);
198
199
200
201    // === Config Service ===
202
203    /**
204     * Returns the configuration topic of the given type for the given topic.
205     * <p>
206     * This is a privileged method, it bypasses the access control system.
207     *
208     * @throws  RuntimeException    if no such configuration topic exists.
209     */
210    RelatedTopic getConfigTopic(String configTypeUri, long topicId);
211
212
213
214    // === Email Addresses ===
215
216    /**
217     * Returns the username for the given email address.
218     * <p>
219     * The username is determined by traversing from the Email Address topic along a
220     * <code>org.deepamehta.signup.user_mailbox</code> association.
221     * <p>
222     * This is a privileged method, it bypasses the access control system.
223     *
224     * @throws  RuntimeException    if no such Email Address topic exists in the DB, or
225     *                              if more than one such Email Address topics exist in the DB, or
226     *                              if the Email Address topic is not associated to a Username topic.
227     */
228    String getUsername(String emailAddress);
229
230    /**
231     * Returns the email address for the given username.
232     * <p>
233     * The email address is determined by traversing from the Username topic along a
234     * <code>org.deepamehta.signup.user_mailbox</code> association.
235     * <p>
236     * This is a privileged method, it bypasses the access control system.
237     *
238     * @throws  RuntimeException    if no such Username topic exists in the DB, or
239     *                              if the Username topic is not associated to an Email Address topic.
240     */
241    String getEmailAddress(String username);
242
243    // ---
244
245    /**
246     * Returns true if an "Email Address" (dmx.contacts.email_address) topic with the given value exists,
247     * false otherwise.
248     * <p>
249     * This is a privileged method, it bypasses the access control system.
250     */
251    boolean emailAddressExists(String emailAddress);
252}