public class BasicSecuritySystem extends java.lang.Object implements SecuritySystem, org.springframework.context.ApplicationContextAware, org.springframework.context.ApplicationListener<EventLogMessage>
SecuritySystem
. Uses an ctor-injected
EventContext
and the ThreadLocal-
based
CurrentDetails
to provide the security infrastructure.Token
,
SecuritySystem
,
Details
,
Permissions
Modifier and Type | Field and Description |
---|---|
protected ACLVoter |
aclVoter |
protected CurrentDetails |
cd |
protected ome.system.OmeroContext |
ctx |
protected EventProvider |
eventProvider |
protected java.util.List<SecurityFilter> |
filters |
protected OmeroInterceptor |
interceptor |
protected PolicyService |
policyService |
protected ome.system.Roles |
roles |
protected SessionManager |
sessionManager |
protected SessionProvider |
sessionProvider |
protected ome.system.ServiceFactory |
sf |
protected ShareStore |
store |
protected SystemTypes |
sysTypes |
protected TokenHolder |
tokenHolder |
Constructor and Description |
---|
BasicSecuritySystem(OmeroInterceptor interceptor,
SystemTypes sysTypes,
CurrentDetails cd,
SessionManager sessionManager,
SessionProvider sessionProvider,
EventProvider eventProvider,
ome.system.Roles roles,
ome.system.ServiceFactory sf,
TokenHolder tokenHolder,
java.util.List<SecurityFilter> filters,
PolicyService policyService,
ACLVoter aclVoter)
Main public constructor for this
SecuritySystem implementation. |
Modifier and Type | Method and Description |
---|---|
void |
addLog(java.lang.String action,
java.lang.Class klass,
java.lang.Long id) |
ome.model.internal.Details |
checkManagedDetails(ome.model.IObject object,
ome.model.internal.Details trustedDetails)
checks that a non-privileged user has not attempted to edit the entity's
security details . |
protected void |
checkReady(java.lang.String method)
calls
isReady() and if not throws an ApiUsageException . |
void |
checkRestriction(java.lang.String name,
ome.model.IObject obj)
Checks whether or not a
Policy instance of matching
name has been registered, considers itself active, and
considers the passed context object to be restricted. |
void |
clearLogs() |
void |
copyToken(ome.model.IObject source,
ome.model.IObject copy) |
void |
disable(java.lang.String... ids)
disables components of the backend for the current Thread.
|
void |
disableReadFilter(java.lang.Object session)
disable this filer.
|
<T extends ome.model.IObject> |
doAction(SecureAction action,
T... objs)
It would be better to catch the
SecureAction.updateObject(IObject...) method in a try/finally block,
but since flush can be so poorly controlled that's not possible. |
void |
enable(java.lang.String... ids)
enables components of the backend for the current Thread.
|
void |
enableReadFilter(java.lang.Object session)
enables the read filter such that graph queries will have non-visible
entities silently removed from the return value.
|
java.lang.Long |
getEffectiveUID()
Returns the Id of the currently logged in user.
|
ome.system.EventContext |
getEventContext()
Calls
SecuritySystem.getEventContext(boolean) with a false as "refresh". |
ome.system.EventContext |
getEventContext(boolean refresh)
If refresh is false, returns the current
EventContext stored
in the session. |
java.util.List<ome.model.meta.EventLog> |
getLogs() |
ome.system.Roles |
getSecurityRoles() |
boolean |
hasPrivilegedToken(ome.model.IObject obj)
|
void |
invalidateEventContext()
Clears the content of the
EventContext so that the
SecuritySystem will no longer return true for SecuritySystem.isReady() . |
boolean |
isDisabled(java.lang.String id)
checks if the listed id is disabled for the current Thread.
|
boolean |
isGraphCritical(ome.model.internal.Details details)
Determines if the current security context has the possibility of
corrupting consistent graphs.
|
protected boolean |
isGroupContextPermitted(long sessionId,
long groupId)
Check the given group context.
|
protected boolean |
isGroupContextPermitted(long groupId,
java.lang.String permittedGroupIds) |
boolean |
isOwnerOrSupervisor(ome.model.IObject iObject)
tests whether or not the current user is either the owner of this entity,
or the supervisor of this entity, for example as root or as group owner.
|
boolean |
isReady()
implements
SecuritySystem.isReady() . |
boolean |
isSystemType(java.lang.Class<? extends ome.model.IObject> klass)
classes which cannot be created by regular users.
|
void |
loadEventContext(boolean isReadOnly)
Prepares the current
EventContext instance with the current
Principal . |
void |
loadEventContext(boolean isReadOnly,
boolean isClose) |
void |
login(ome.system.Principal principal)
stores this
Principal instance in the current thread context for
authenticating and authorizing all actions. |
int |
logout()
clears the top
Principal instance from the current thread
context. |
ome.model.internal.Details |
newTransientDetails(ome.model.IObject object)
creates a new secure
details for transient
entities. |
void |
onApplicationEvent(EventLogMessage elm) |
void |
runAsAdmin(AdminAction action)
Calls
runAsAdmin(AdminAction) with a null-group id. |
void |
runAsAdmin(ome.model.meta.ExperimenterGroup group,
AdminAction action)
merge event is disabled for
runAsAdmin(AdminAction) because
passing detached (client-side) entities to this method is particularly
dangerous. |
static BasicSecuritySystem |
selfConfigure(SessionManager sm,
ome.system.ServiceFactory sf,
SessionCache cache)
Simplified factory method which generates all the security primitives
internally.
|
void |
setApplicationContext(org.springframework.context.ApplicationContext arg0) |
void |
updateReadFilter(org.hibernate.Session session) |
protected final OmeroInterceptor interceptor
protected final SystemTypes sysTypes
protected final CurrentDetails cd
protected final TokenHolder tokenHolder
protected final ome.system.Roles roles
protected final SessionManager sessionManager
protected final SessionProvider sessionProvider
protected final EventProvider eventProvider
protected final ome.system.ServiceFactory sf
protected final java.util.List<SecurityFilter> filters
protected final PolicyService policyService
protected ome.system.OmeroContext ctx
protected ShareStore store
protected final ACLVoter aclVoter
public BasicSecuritySystem(OmeroInterceptor interceptor, SystemTypes sysTypes, CurrentDetails cd, SessionManager sessionManager, SessionProvider sessionProvider, EventProvider eventProvider, ome.system.Roles roles, ome.system.ServiceFactory sf, TokenHolder tokenHolder, java.util.List<SecurityFilter> filters, PolicyService policyService, ACLVoter aclVoter)
SecuritySystem
implementation.interceptor
- the OMERO interceptor for HibernatesysTypes
- the system typescd
- the current detailssessionManager
- the session managersessionProvider
- a session providereventProvider
- an event providerroles
- the OMERO rolessf
- the session factorytokenHolder
- the token holderfilters
- the security filterspolicyService
- the policy serviceaclVoter
- the ACL voter, may be null
public static BasicSecuritySystem selfConfigure(SessionManager sm, ome.system.ServiceFactory sf, SessionCache cache)
sm
- the session managersf
- the session factorycache
- the session cachepublic void setApplicationContext(org.springframework.context.ApplicationContext arg0) throws org.springframework.beans.BeansException
setApplicationContext
in interface org.springframework.context.ApplicationContextAware
org.springframework.beans.BeansException
public void login(ome.system.Principal principal)
SecuritySystem
Principal
instance in the current thread context for
authenticating and authorizing all actions. This method does not
make any queries and is only a conduit for login information from the
outermost levels. Session bean implementations and other in-JVM clients
can fill the Principal
. Note, however, a call must first be made
to SecuritySystem.loadEventContext(boolean)
for some calls to be made to the
SecuritySystem
. In general, this means that execution must pass
through the EventHandler
login
in interface SecuritySystem
principal
- the new current principalpublic int logout()
SecuritySystem
Principal
instance from the current thread
context.logout
in interface SecuritySystem
public boolean isReady()
SecuritySystem.isReady()
. Simply checks for null
values in all the relevant fields of CurrentDetails
isReady
in interface SecuritySystem
public boolean isSystemType(java.lang.Class<? extends ome.model.IObject> klass)
isSystemType
in interface SecuritySystem
klass
- A class which extends from IObject
public boolean isOwnerOrSupervisor(ome.model.IObject iObject)
iObject
- Non-null managed entity.public void enableReadFilter(java.lang.Object session)
ACLVoter.allowLoad(Session, Class, Details, long)
for more.
Note: this filter must be disabled on logout, otherwise the necessary
parameters (current user, current group, etc.) for building the filters
will not be available. Similarly, while enabling this filter, no calls
should be made on the given session object.session
- a generic session object which can be used to enable this
filter. Each SecuritySystem
implementation will
require a specific session type.EventHandler.invoke(org.aopalliance.intercept.MethodInvocation)
public void updateReadFilter(org.hibernate.Session session)
public void disableReadFilter(java.lang.Object session)
session
- a generic session object which can be used to disable this
filter. Each SecuritySystem
implementation will
require a specifc session type.EventHandler.invoke(org.aopalliance.intercept.MethodInvocation)
public void disable(java.lang.String... ids)
SecuritySystem
SecuritySystem.isDisabled(String)
will return false. It is the
responsibility of various security system components to then throw
exceptions.disable
in interface SecuritySystem
ids
- Non-null, non-empty array of String ids to disable.public void enable(java.lang.String... ids)
SecuritySystem
SecuritySystem.isDisabled(String)
will return true.enable
in interface SecuritySystem
ids
- possibly null array of String ids. A null array specifies that
all subsystems are to be enabled. Otherwise, only those
subsystems specified by the ids.public boolean isDisabled(java.lang.String id)
SecuritySystem
isDisabled
in interface SecuritySystem
id
- non-null String representing a backend subsystem.SecuritySystem.disable(String[])
public ome.model.internal.Details newTransientDetails(ome.model.IObject object) throws ome.conditions.ApiUsageException, ome.conditions.SecurityViolation
SecuritySystem
details
for transient
entities. Non-privileged users can only edit the
Permissions
field. Privileged users can
use the Details
object as a single-step chmod
and
chgrp
.
newTransientDetails
always returns
a non-null Details that is not equivalent (==) to the Details argument.
This method can be used from anywhere in the codebase to obtain a valid
Details
, but passing in an IObject
instance with a null
Details
. However, if the Details
is non-null, there is
the possibility that this method will throw an exception.newTransientDetails
in interface SecuritySystem
ome.conditions.ApiUsageException
- if SecuritySystem
is not ready
ome.conditions.SecurityViolation
- if Details
instance contains illegal values.public ome.model.internal.Details checkManagedDetails(ome.model.IObject object, ome.model.internal.Details trustedDetails) throws ome.conditions.ApiUsageException, ome.conditions.SecurityViolation
SecuritySystem
security details
. Privileged users can set
fields on Details
as a single-step chmod
and
chgrp
.
managedDetails
may create
a new Details instance and return that if needed. If the returned Details
is not equivalent (==) to the argument Details, then values have been
changed.checkManagedDetails
in interface SecuritySystem
object
- non-null IObject
instance. Details
for that
instance can be null.trustedDetails
- possibly null Details
instance. These Details
are trusted in the sense that they have already once passed
through the SecuritySystem
.ome.conditions.ApiUsageException
- if SecuritySystem
is not ready
ome.conditions.SecurityViolation
- if Details
instance contains illegal values.public boolean isGraphCritical(ome.model.internal.Details details)
SecuritySystem
The current group is non-negative, then use the previous logic; else the current group is negative, and the object is in a non-"user" group: USE THAT GROUP; else the object is in the "user" group: UNCLEAR (for the moment we're throwing an exception)If no
Details
instance is passed or a Details
without
a ExperimenterGroup
value, then throw as well.isGraphCritical
in interface SecuritySystem
details
- the detailsprotected boolean isGroupContextPermitted(long sessionId, long groupId)
sessionId
- a session IDgroupId
- a group IDprotected boolean isGroupContextPermitted(long groupId, java.lang.String permittedGroupIds)
groupId
- a group IDpermittedGroupIds
- a comma-separated string of group IDspublic void loadEventContext(boolean isReadOnly)
SecuritySystem
EventContext
instance with the current
Principal
. An exception is thrown if there is none.loadEventContext
in interface SecuritySystem
public void loadEventContext(boolean isReadOnly, boolean isClose)
public void addLog(java.lang.String action, java.lang.Class klass, java.lang.Long id)
public java.util.List<ome.model.meta.EventLog> getLogs()
public void clearLogs()
public void invalidateEventContext()
SecuritySystem
EventContext
so that the
SecuritySystem
will no longer return true for SecuritySystem.isReady()
.
The Principal
set during SecuritySystem.login(Principal)
is retained.invalidateEventContext
in interface SecuritySystem
public <T extends ome.model.IObject> T doAction(SecureAction action, T... objs)
SecureAction.updateObject(IObject...)
method in a try/finally block,
but since flush can be so poorly controlled that's not possible. instead,
we use the one time token which is removed this Object is checked for
privileges
.doAction
in interface SecuritySystem
objs
- A managed (non-detached) entity. Not null.action
- A code-block that will be given the entity argument with a
hasPrivilegedToken(IObject)
privileged token}.public void runAsAdmin(AdminAction action)
runAsAdmin(AdminAction)
with a null-group id.runAsAdmin
in interface SecuritySystem
action
- the action to runpublic void runAsAdmin(ome.model.meta.ExperimenterGroup group, AdminAction action)
runAsAdmin(AdminAction)
because
passing detached (client-side) entities to this method is particularly
dangerous.runAsAdmin
in interface SecuritySystem
group
- the group to run the action asaction
- the action to runpublic void copyToken(ome.model.IObject source, ome.model.IObject copy)
TokenHolder.copyToken(IObject, IObject)
public boolean hasPrivilegedToken(ome.model.IObject obj)
SecuritySystem
hasPrivilegedToken
in interface SecuritySystem
TokenHolder.hasPrivilegedToken(IObject)
public void checkRestriction(java.lang.String name, ome.model.IObject obj)
SecuritySystem
Policy
instance of matching
name has been registered, considers itself active, and
considers the passed context object to be restricted.checkRestriction
in interface SecuritySystem
name
- A non-null unique name for a class of policies.obj
- An instance which is to be checked against matching policies.public ome.system.Roles getSecurityRoles()
getSecurityRoles
in interface SecuritySystem
public ome.system.EventContext getEventContext(boolean refresh)
SecuritySystem
EventContext
stored
in the session. Otherwise, reloads the context to have the most
up-to-date information.getEventContext
in interface SecuritySystem
refresh
- if the event context should first be reloadedpublic ome.system.EventContext getEventContext()
SecuritySystem
SecuritySystem.getEventContext(boolean)
with a false as "refresh".
This is the previous, safer logic of the method since consumers
are not expecting a long method run.getEventContext
in interface SecuritySystem
public java.lang.Long getEffectiveUID()
getEffectiveUID
in interface SecuritySystem
protected void checkReady(java.lang.String method)
isReady()
and if not throws an ApiUsageException
.
The SecuritySystem
must be in a valid state to perform several
functions.public void onApplicationEvent(EventLogMessage elm)
onApplicationEvent
in interface org.springframework.context.ApplicationListener<EventLogMessage>