/*
* Copyright 2006-2014 University of Dundee. All rights reserved.
* Use is subject to license terms supplied in LICENSE.txt
*/
package ome.api;
import java.util.List;
import java.util.Map;
import ome.annotations.Hidden;
import ome.annotations.NotNull;
import ome.conditions.AuthenticationException;
import ome.model.IObject;
import ome.model.core.OriginalFile;
import ome.model.internal.Details;
import ome.model.internal.Permissions;
import ome.model.meta.Experimenter;
import ome.model.meta.ExperimenterGroup;
import ome.model.meta.GroupExperimenterMap;
import ome.system.EventContext;
import ome.system.Roles;
/**
* Administration interface providing access to admin-only functionality as well
* as JMX-based server access and selected user functions. Most methods require
* membership in privileged {@link ExperimenterGroup groups}.
*
* Methods which return {@link ome.model.meta.Experimenter} or
* {@link ome.model.meta.ExperimenterGroup} instances fetch and load all related
* instances of {@link ome.model.meta.ExperimenterGroup} or
* {@link ome.model.meta.Experimenter}, respectively.
*
* @author <br>
* Josh Moore <a
* href="mailto:josh.moore@gmx.de"> josh.moore@gmx.de</a>
* @since OME3.0
*/
public interface IAdmin extends ServiceInterface {
/**
* Returns true if the currently logged in user can modify the given
* {@link IObject}. This uses the same logic that would be applied during
* a Hibernate flush to the database.
*/
boolean canUpdate(IObject obj);
// ~ Getting users and groups
// =========================================================================
/**
* fetch an {@link Experimenter} and all related
* {@link ExperimenterGroup groups}.
*
* @param id
* id of the Experimenter
* @return an Experimenter. Never null.
* @throws ome.conditions.ApiUsageException
* if id does not exist.
*/
Experimenter getExperimenter(long id);
/**
* look up an {@link Experimenter} and all related
* {@link ExperimenterGroup groups} by name.
*
* @param omeName
* Name of the Experimenter
* @return an Experimenter. Never null.
* @throws ome.conditions.ApiUsageException
* if omeName does not exist.
*/
Experimenter lookupExperimenter(@NotNull
String omeName);
/**
* Looks up all {@link Experimenter experimenters} present and all related
* {@link ExperimenterGroup groups}.
*
* @return all Experimenters. Never null.
*/
List<Experimenter> lookupExperimenters();
/**
* Looks up all id of {@link Experimenter experimenters} who uses LDAP
* authentication (has set dn on password table).
*
* @return list of Experimenters. Never null.
*/
List<Map<String, Object>> lookupLdapAuthExperimenters();
/**
* Looks up {@link Experimenter experimenters} who uses LDAP authentication
* (has set dn on password table).
*
* @return Experimenter. Never null.
*/
String lookupLdapAuthExperimenter(long id);
/**
* fetch an {@link ExperimenterGroup} and all contained
* {@link Experimenter users}.
*
* @param id
* id of the ExperimenterGroup
* @return an ExperimenterGroup. Never null.
* @throws ome.conditions.ApiUsageException
* if id does not exist.
*/
ExperimenterGroup getGroup(long id);
/**
* look up an {@link ExperimenterGroup} and all contained
* {@link Experimenter users} by name.
*
* @param groupName
* Name of the ExperimenterGroup
* @return an ExperimenterGroup. Never null.
* @throws ome.conditions.ApiUsageException
* if groupName does not exist.
*/
ExperimenterGroup lookupGroup(@NotNull
String groupName);
/**
* Looks up all {@link ExperimenterGroup groups} present and all related
* {@link Experimenter experimenters}. The experimenters' groups are also
* loaded.
*
* @return all Groups. Never null.
*/
List<ExperimenterGroup> lookupGroups();
/**
* fetch all {@link Experimenter users} contained in this group. The
* returned users will have all fields filled in and all collections
* unloaded.
*
* @param groupId
* id of the ExperimenterGroup
* @return non-null array of all {@link Experimenter users} in this group.
*/
Experimenter[] containedExperimenters(long groupId);
/**
* fetch all {@link ExperimenterGroup groups} of which the given user is a
* member. The returned groups will have all fields filled in and all
* collections unloaded.
*
* @param experimenterId
* id of the Experimenter. Not null.
* @return non-null array of all {@link ExperimenterGroup groups} for this
* user.
*/
ExperimenterGroup[] containedGroups(long experimenterId);
/**
* retrieve the default {@link ExperimenterGroup group} for the given user
* id.
*
* @param experimenterId
* of the Experimenter. Not null.
* @return non-null {@link ExperimenterGroup}. If no default group is
* found, an exception will be thrown.
*/
ExperimenterGroup getDefaultGroup(long experimenterId);
/**
* Finds the ids for all groups for which the given {@link Experimenter} is
* owner/leader.
*
* @param e
* Non-null, managed (i.e. with id) {@link Experimenter}
* @see ExperimenterGroup#getDetails()
* @see Details#getOwner()
*/
List<Long> getLeaderOfGroupIds(Experimenter e);
/**
* Finds the ids for all groups for which the given {@link Experimenter} is
* a member.
*
* @param e
* Non-null, managed (i.e. with id) {@link Experimenter}
* @see ExperimenterGroup#getDetails()
* @see Details#getOwner()
*/
List<Long> getMemberOfGroupIds(Experimenter e);
// ~ Updating users and groups
// =========================================================================
/**
* Allows a user to update his/her own information. This is limited to the
* fields on Experimenter, all other fields (groups, etc.) are ignored. The
* experimenter argument need not have the proper id nor the proper omeName
* (which is immutable). To change the users default group (which is the
* only other customizable option), use
* {@link #setDefaultGroup(Experimenter, ExperimenterGroup)}
*
* @see #setDefaultGroup(Experimenter, ExperimenterGroup)
* @param experimenter
* A data transfer object. Only the fields: firstName,
* middleName, lastName, email, and institution are checked. Not
* null.
*/
void updateSelf(@NotNull
Experimenter experimenter);
/**
* Uploads a photo for the user which will be displayed on his/her profile.
* This photo will be saved as an {@link ome.model.core.OriginalFile} object
* with the given format, and attached to the user's {@link Experimenter}
* object via an {@link ome.model.annotations.FileAnnotation} with
* the namespace: "openmicroscopy.org/omero/experimenter/photo" (NSEXPERIMENTERPHOTO).
* If such an {@link ome.model.core.OriginalFile} instance already exists,
* it will be overwritten. If more than one photo is present, the oldest
* version will be modified (i.e. the highest updateEvent id).
*
* Note: as outlined in ticket:1794, this photo will be placed in the "user"
* group and therefore will be visible to everyone on the system.
*
* @param filename Not null. String name which will be used.
* @param format Not null. Format.value string. 'image/jpeg' and 'image/png' are common values.
* @param data Not null. Data from the image. This will be written to disk.
* @return the id of the overwritten or newly created user photo OriginalFile object.
*/
long uploadMyUserPhoto(String filename, String format, byte[] data);
/**
* Retrieve the {@link ome.model.core.OriginalFile} object attached to this
* user as specified by {@link #uploadMyUserPhoto(String, String, byte[])}.
* The return value is order by the most recently modified file first.
*
* @return file objects. Possibly empty.
*/
List<OriginalFile> getMyUserPhotos();
/**
* Updates an experimenter if admin or owner of group. Only string fields on
* the object are taken into account.
* The root and guest experimenters may not be renamed.
*
* Before a SecurityViolation would be thrown, however, this method will
* pass to {@link #updateSelf(Experimenter)} <em>if</em> the current user
* matches the given experimenter.
*
* @param experimenter
* the Experimenter to update.
*/
void updateExperimenter(@NotNull
Experimenter experimenter);
/**
* Updates an experimenter if admin or owner of group.
* Only string fields on the object are taken into account.
* The root and guest experimenters may not be renamed.
*
* @param experimenter
* the Experimenter to update.
* @param password
* Not-null. Must pass validation in the security sub-system.
*/
void updateExperimenterWithPassword(@NotNull
Experimenter experimenter, @Hidden
String password);
/**
* Updates an experimenter group if admin or owner of group.
* Only string fields on the object are taken into account.
* The root, system and guest groups may not be renamed,
* nor may the user's current group.
*
* @param group
* the ExperimenterGroup to update.
*/
void updateGroup(@NotNull
ExperimenterGroup group);
// ~ Creating users in groups
// =========================================================================
/**
* create and return a new user. This user will be created with the default
* group specified.
*
* @param newUser
* a new {@link Experimenter} instance
* @param group group name of the default group for this user
* @return id of the newly created {@link Experimenter}
*/
long createUser(@NotNull
Experimenter newUser, @NotNull
String group);
/**
* create and return a new system user. This user will be created with the
* "System" (administration) group as default and will also be in the "user"
* group.
*
* @param newSystemUser a new {@link Experimenter} instance
* @return id of the newly created {@link Experimenter}
*/
long createSystemUser(@NotNull
Experimenter newSystemUser);
/**
* create and return a new user in the given groups.
*
* @param experimenter
* A new {@link Experimenter} instance. Not null.
* @param defaultGroup
* Instance of {@link ExperimenterGroup}. Not null.
* @param otherGroups
* Array of {@link ExperimenterGroup} instances. Can be null.
* @return id of the newly created {@link Experimenter} Not null.
*/
long createExperimenter(@NotNull
Experimenter experimenter, @NotNull
ExperimenterGroup defaultGroup, ExperimenterGroup... otherGroups);
/**
* create and return a new user in the given groups with password.
*
* @param experimenter
* A new {@link Experimenter} instance. Not null.
* @param password
* Not-null. Must pass validation in the security sub-system.
* @param defaultGroup
* Instance of {@link ExperimenterGroup}. Not null.
* @param otherGroups
* Array of {@link ExperimenterGroup} instances. Can be null.
* @return id of the newly created {@link Experimenter} Not null.
* @throws ome.conditions.SecurityViolation
* if the new password is too weak.
*/
long createExperimenterWithPassword(@NotNull
Experimenter experimenter, @Hidden
String password, @NotNull
ExperimenterGroup defaultGroup, ExperimenterGroup... otherGroups);
/**
* create and return a new group. The {@link Details#setPermissions(Permissions)}
* method should be called on the instance which is passed. The given
* {@link Permissions} will become the default for all objects created while
* logged into this group, possibly modified by the user's umask settings.
* If no permissions is set, the default will be {@link Permissions#USER_PRIVATE},
* i.e. a group in which no user can see the other group member's data.
*
* @param group a new {@link ExperimenterGroup} instance. Not null.
* @return id of the newly created {@link ExperimenterGroup}
* @see <a href="http://trac.openmicroscopy.org.uk/ome/ticket/1434">ticket:1434"</a>
*/
long createGroup(ExperimenterGroup group);
/**
* adds a user to the given groups.
*
* @param user
* A currently managed entity. Not null.
* @param groups
* Groups to which the user will be added. Not null.
*/
void addGroups(@NotNull
Experimenter user, @NotNull
ExperimenterGroup... groups);
/**
* Removes an experimenter from the given groups.
* <ul>
* <li>The root experimenter is required to be in both the user and system groups.</li>
* <li>An experimenter may not remove themself from the user or system group.</li>
* <li>An experimenter may not be a member of only the user group,
* some other group is also required as the default group.</li>
* <li>An experimenter must remain a member of some group.</li>
* </ul>
*
* @param user
* A currently managed entity. Not null.
* @param groups
* Groups from which the user will be removed. Not null.
*/
void removeGroups(@NotNull
Experimenter user, @NotNull
ExperimenterGroup... groups);
/**
* sets the default group for a given user.
*
* @param user
* A currently managed {@link Experimenter}. Not null.
* @param group
* The group which should be set as default group for this user.
* Not null.
*/
void setDefaultGroup(@NotNull
Experimenter user, @NotNull
ExperimenterGroup group);
/**
* adds the user to the owner list for this group.
*
* Since Beta4.2 (ticket:1434) multiple users can be the "owner" of a group.
*
* @param group
* A currently managed {@link ExperimenterGroup}. Not null.
* @param owner
* A currently managed {@link Experimenter}. Not null.
*/
void setGroupOwner(@NotNull
ExperimenterGroup group, @NotNull
Experimenter owner);
/**
* removes the user from the owner list for this group.
*
* Since Beta4.2 (ticket:1434) multiple users can be the "owner" of a group.
*
* @param group
* A currently managed {@link ExperimenterGroup}. Not null.
* @param owner
* A currently managed {@link Experimenter}. Not null.
*/
void unsetGroupOwner(@NotNull
ExperimenterGroup group, @NotNull
Experimenter owner);
/**
* adds the given users to the owner list for this group.
*
* @param group
* A currently managed {@link ExperimenterGroup}. Not null.
* @param owner
* A set of currently managed {@link Experimenter}s. Not null.
*/
void addGroupOwners(@NotNull
ExperimenterGroup group, @NotNull
Experimenter... owner);
/**
* removes the given users from the owner list for this group.
*
* @param group
* A currently managed {@link ExperimenterGroup}. Not null.
* @param owner
* A set of currently managed {@link Experimenter}s. Not null.
*/
void removeGroupOwners(@NotNull
ExperimenterGroup group, @NotNull
Experimenter... owner);
/**
* removes a user by removing the password information for that user as well
* as all {@link GroupExperimenterMap} instances.
*
* @param user
* Experimenter to be deleted. Not null.
*/
void deleteExperimenter(@NotNull
Experimenter user);
/**
* removes a group by first removing all users in the group, and then
* deleting the actual {@link ExperimenterGroup} instance.
*
* @param group
* {@link ExperimenterGroup} to be deleted. Not null.
*/
void deleteGroup(@NotNull
ExperimenterGroup group);
// ~ Permissions and Ownership
// =========================================================================
/**
* call
* {@link ome.model.internal.Details#setOwner(Experimenter) details.setOwner()}
* on this instance. It is valid for the instance to be
* {@link IObject#unload() unloaded} (or constructed with an
* unloading-constructor.)
*
* @param iObject
* An entity or an unloaded reference to an entity. Not null.
* @param omeName
* The user name who should gain ownership of this entity. Not
* null.
*/
void changeOwner(@NotNull
IObject iObject, @NotNull
String omeName);
/**
* call
* {@link ome.model.internal.Details#setGroup(ExperimenterGroup) details.setGroup()}
* on this instance. It is valid for the instance to be
* {@link IObject#unload() unloaded} (or constructed with an
* unloading-constructor.)
*
* @param iObject
* An entity or an unloaded reference to an entity. Not null.
* @param groupName
* The group name who should gain ownership of this entity. Not
* null.
*/
void changeGroup(@NotNull
IObject iObject, @NotNull
String groupName);
/**
* call
* {@link ome.model.internal.Details#setPermissions(Permissions) defaults.setPermissions()}
* on this instance. It is valid for the instance to be
* {@link IObject#unload() unloaded} (or constructed with an
* unloading-constructor.)
*
* @param iObject
* An entity or an unloaded reference to an entity. Not null.
* @param perms
* The permissions value for this entity. Not null.
*/
void changePermissions(@NotNull
IObject iObject, @NotNull
Permissions perms);
/**
* Moves the given objects into the "user" group to make them visible
* and linkable from all security contexts.
*
* @param iObjects
* @see <a href="https://trac.openmicroscopy.org/ome/ticket/1794">ticket 1794</a>
*/
void moveToCommonSpace(IObject... iObjects);
// ~ Authentication and Authorization
// =========================================================================
/**
* Can be used after repeated {@link AuthenticationException} instances are
* thrown, to request that an email with a temporary password be sent. The
* given email must match the email for the user listed under the name
* argument.
*
* Does not require a session to be active.
*
* @param name
* @param email
* @throws AuthenticationException
* when name and email do not match
* @deprecated
*/
@Deprecated
void reportForgottenPassword(String name, String email)
throws AuthenticationException;
/**
* Used after an {@link ome.conditions.ExpiredCredentialException} instance is thrown.
*
* Does not require
*/
void changeExpiredCredentials(String name, String oldCred, String newCred)
throws AuthenticationException;
/**
* change the password for the current user.
* <p>
* <em>Warning:</em>This method requires the user to be authenticated
* with a password and not with a one-time session id. To avoid this
* problem, use {@link #changePasswordWithOldPassword(String, String)}.
* </p>
*
* @param newPassword
* Possibly null to allow logging in with no password.
* @throws ome.conditions.SecurityViolation
* if the user is not authenticated with a password.
* @see <a href="http://trac.openmicroscopy.org.uk/ome/ticket/911">ticket:911</a>
* @see <a href="http://trac.openmicroscopy.org.uk/ome/ticket/3201">ticket:3201</a>
*/
void changePassword(@Hidden
String newPassword);
/**
* change the password for the current user by passing the old password.
*
* @param oldPassword
* Not-null. Must pass validation in the security sub-system.
* @param newPassword
* Possibly null to allow logging in with no password.
* @throws ome.conditions.SecurityViolation
* if the oldPassword is incorrect.
*/
void changePasswordWithOldPassword(
@Hidden @NotNull String oldPassword,
@Hidden String newPassword);
/**
* change the password for the a given user.
*
* @param newPassword
* Not-null. Might must pass validation in the security
* sub-system.
* @throws ome.conditions.SecurityViolation
* if the new password is too weak.
*/
void changeUserPassword(@NotNull
String omeName, @Hidden
String newPassword);
/**
* uses JMX to refresh the login cache <em>if supported</em>. Some
* backends may not provide refreshing. This may be called internally during
* some other administrative tasks. The exact implementation of this depends
* on the application server and the authentication/authorization backend.
*/
void synchronizeLoginCache();
// ~ Security context
// =========================================================================
/**
* returns the active {@link Roles} in use by the server.
*
* @return Non-null, immutable {@link Roles} instance.
*/
Roles getSecurityRoles();
/**
* returns an implementation of {@link EventContext} loaded with the
* security for the current user and thread. If called remotely, not all
* values of {@link EventContext} will be sensible.
*
* @return Non-null, immutable {@link EventContext} instance
*/
EventContext getEventContext();
}