refactoring of AuthorisationService

This commit is contained in:
anhefti 2019-02-14 22:46:17 +01:00
parent 64f10c6455
commit 285290d93d
20 changed files with 539 additions and 812 deletions

View file

@ -75,6 +75,22 @@ public final class Privilege {
return this.ownershipPrivilege.hasImplicit(privilegeType);
}
public final boolean hasGrant(
final String userId,
final Long userInstitutionId,
final PrivilegeType privilegeType,
final Long institutionId,
final String ownerId) {
return this.hasBasePrivilege(privilegeType)
|| ((institutionId != null) &&
(this.hasInstitutionalPrivilege(privilegeType)
&& userInstitutionId.longValue() == institutionId
.longValue())
|| (this.hasOwnershipPrivilege(privilegeType)
&& userId.equals(ownerId)));
}
@Override
public String toString() {
return "Privilege [privilegeType=" + this.basePrivilege + ", institutionalPrivilege="

View file

@ -207,13 +207,8 @@ public class FormBuilder {
this.formParent,
value,
new LocTextKey("sebserver.overall.upload"),
span, 1);
if (this.readonly) {
imageUpload.setReadonly();
this.form.putField(name, lab, imageUpload);
} else {
this.form.putField(name, lab, imageUpload);
}
span, 1, this.readonly);
this.form.putField(name, lab, imageUpload);
return this;
}

View file

@ -12,7 +12,6 @@ import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
import java.util.function.Predicate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -78,12 +77,17 @@ public class CurrentUser {
public boolean hasPrivilege(final PrivilegeType privilegeType, final EntityType entityType) {
if (loadPrivileges()) {
try {
return get().getRoles()
final UserInfo userInfo = get();
return userInfo.getRoles()
.stream()
.map(roleName -> UserRole.valueOf(roleName))
.map(role -> new RoleTypeKey(entityType, role))
.map(key -> this.privileges.get(key))
.filter(checkPrivilege(get(), privilegeType, null))
.filter(priv -> (priv != null) && priv.hasGrant(
userInfo.uuid,
userInfo.institutionId,
privilegeType,
null, null))
.findFirst()
.isPresent();
} catch (final Exception e) {
@ -102,12 +106,18 @@ public class CurrentUser {
if (loadPrivileges()) {
final EntityType entityType = grantEntity.entityType();
try {
return get().getRoles()
final UserInfo userInfo = get();
return userInfo.getRoles()
.stream()
.map(roleName -> UserRole.valueOf(roleName))
.map(role -> new RoleTypeKey(entityType, role))
.map(key -> this.privileges.get(key))
.filter(checkPrivilege(get(), privilegeType, grantEntity))
.filter(priv -> (priv != null) && priv.hasGrant(
userInfo.uuid,
userInfo.institutionId,
privilegeType,
grantEntity.getInstitutionId(),
grantEntity.getOwnerId()))
.findFirst()
.isPresent();
} catch (final Exception e) {
@ -119,20 +129,6 @@ public class CurrentUser {
return false;
}
private Predicate<Privilege> checkPrivilege(
final UserInfo userInfo,
final PrivilegeType privilegeType,
final GrantEntity grantEntity) {
return priv -> priv.hasBasePrivilege(privilegeType)
|| ((grantEntity != null) &&
(priv.hasInstitutionalPrivilege(privilegeType)
&& get().institutionId.longValue() == grantEntity.getInstitutionId()
.longValue())
|| (priv.hasOwnershipPrivilege(privilegeType)
&& get().uuid.equals(grantEntity.getOwnerId())));
}
public boolean isAvailable() {
updateContext();
return this.authContext != null && this.authContext.isLoggedIn();

View file

@ -41,88 +41,71 @@ public class ImageUpload extends Composite {
private final ServerPushService serverPushService;
final Composite imageCanvas;
final FileUpload fileUpload;
private final Composite imageCanvas;
private final FileUpload fileUpload;
private String imageBase64 = null;
private boolean loadNewImage = false;
private boolean imageLoaded = false;
ImageUpload(final Composite parent, final ServerPushService serverPushService) {
ImageUpload(final Composite parent, final ServerPushService serverPushService, final boolean readonly) {
super(parent, SWT.NONE);
super.setLayout(new GridLayout(2, false));
this.serverPushService = serverPushService;
this.fileUpload = new FileUpload(this, SWT.NONE);
this.fileUpload.setText("Select File");
this.fileUpload.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false));
if (!readonly) {
this.fileUpload = new FileUpload(this, SWT.NONE);
this.fileUpload.setText("Select File");
this.fileUpload.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false));
final FileUploadHandler uploadHandler = new FileUploadHandler(new FileUploadReceiver() {
@Override
public void receive(final InputStream stream, final FileDetails details) throws IOException {
try {
final String contentType = details.getContentType();
if (contentType != null && contentType.startsWith("image")) {
ImageUpload.this.imageBase64 = Base64.getEncoder().encodeToString(stream.readAllBytes());
}
} catch (final Exception e) {
log.error("Error while trying to upload image", e);
} finally {
ImageUpload.this.imageLoaded = true;
stream.close();
}
}
});
this.fileUpload.addSelectionListener(new SelectionAdapter() {
private static final long serialVersionUID = -6776734104137568801L;
@Override
public void widgetSelected(final SelectionEvent event) {
ImageUpload.this.loadNewImage = true;
ImageUpload.this.imageLoaded = false;
ImageUpload.this.fileUpload.submit(uploadHandler.getUploadUrl());
ImageUpload.this.serverPushService.runServerPush(
new ServerPushContext(ImageUpload.this, ImageUpload::uploadInProgress),
ImageUpload::wait,
ImageUpload::update);
}
});
} else {
this.fileUpload = null;
}
this.imageCanvas = new Composite(this, SWT.NONE);
final GridData canvas = new GridData(SWT.FILL, SWT.FILL, true, true);
this.imageCanvas.setLayoutData(canvas);
final FileUploadHandler uploadHandler = new FileUploadHandler(new FileUploadReceiver() {
@Override
public void receive(final InputStream stream, final FileDetails details) throws IOException {
try {
final String contentType = details.getContentType();
if (contentType != null && contentType.startsWith("image")) {
ImageUpload.this.imageBase64 = Base64.getEncoder().encodeToString(stream.readAllBytes());
}
} catch (final Exception e) {
log.error("Error while trying to upload image", e);
} finally {
ImageUpload.this.imageLoaded = true;
stream.close();
}
}
});
this.fileUpload.addSelectionListener(new SelectionAdapter() {
private static final long serialVersionUID = -6776734104137568801L;
@Override
public void widgetSelected(final SelectionEvent event) {
ImageUpload.this.loadNewImage = true;
ImageUpload.this.imageLoaded = false;
ImageUpload.this.fileUpload.submit(uploadHandler.getUploadUrl());
ImageUpload.this.serverPushService.runServerPush(
new ServerPushContext(
ImageUpload.this,
runAgainContext -> {
final ImageUpload imageUpload = (ImageUpload) runAgainContext.getAnchor();
return imageUpload.loadNewImage && !imageUpload.imageLoaded;
}),
context -> {
try {
Thread.sleep(200);
} catch (final Exception e) {
e.printStackTrace();
}
},
context -> {
final ImageUpload imageUpload = (ImageUpload) context.getAnchor();
if (imageUpload.imageBase64 != null
&& imageUpload.loadNewImage
&& imageUpload.imageLoaded) {
final Base64InputStream input = new Base64InputStream(
new ByteArrayInputStream(
imageUpload.imageBase64.getBytes(StandardCharsets.UTF_8)),
false);
imageUpload.imageCanvas.setData(RWT.CUSTOM_VARIANT, "bgLogoNoImage");
imageUpload.imageCanvas.setBackgroundImage(new Image(context.getDisplay(), input));
context.layout();
imageUpload.layout();
imageUpload.loadNewImage = false;
}
});
}
});
}
public void setSelectionText(final String text) {
if (this.fileUpload != null) {
this.fileUpload.setText(text);
}
}
public String getImageBase64() {
@ -141,9 +124,34 @@ public class ImageUpload extends Composite {
this.imageCanvas.setBackgroundImage(new Image(super.getDisplay(), input));
}
public void setReadonly() {
this.fileUpload.setVisible(false);
this.fileUpload.setEnabled(false);
private static final boolean uploadInProgress(final ServerPushContext context) {
final ImageUpload imageUpload = (ImageUpload) context.getAnchor();
return imageUpload.loadNewImage && !imageUpload.imageLoaded;
}
private static final void wait(final ServerPushContext context) {
try {
Thread.sleep(200);
} catch (final Exception e) {
}
}
private static final void update(final ServerPushContext context) {
final ImageUpload imageUpload = (ImageUpload) context.getAnchor();
if (imageUpload.imageBase64 != null
&& imageUpload.loadNewImage
&& imageUpload.imageLoaded) {
final Base64InputStream input = new Base64InputStream(
new ByteArrayInputStream(
imageUpload.imageBase64.getBytes(StandardCharsets.UTF_8)),
false);
imageUpload.imageCanvas.setData(RWT.CUSTOM_VARIANT, "bgLogoNoImage");
imageUpload.imageCanvas.setBackgroundImage(new Image(context.getDisplay(), input));
context.layout();
imageUpload.layout();
imageUpload.loadNewImage = false;
}
}
}

View file

@ -343,17 +343,23 @@ public class WidgetFactory {
final Composite parent,
final String value,
final LocTextKey locTextKey,
final int hspan, final int vspan) {
final int hspan,
final int vspan,
final boolean readonly) {
final ImageUpload imageUpload = imageUploadLocalized(parent, locTextKey);
final ImageUpload imageUpload = imageUploadLocalized(parent, locTextKey, readonly);
final GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, false, hspan, vspan);
imageUpload.setLayoutData(gridData);
imageUpload.setImageBase64(value);
return imageUpload;
}
public ImageUpload imageUploadLocalized(final Composite parent, final LocTextKey locTextKey) {
final ImageUpload imageUpload = new ImageUpload(parent, this.serverPushService);
public ImageUpload imageUploadLocalized(
final Composite parent,
final LocTextKey locTextKey,
final boolean readonly) {
final ImageUpload imageUpload = new ImageUpload(parent, this.serverPushService, readonly);
injectI18n(imageUpload, locTextKey);
return imageUpload;
}
@ -454,7 +460,7 @@ public class WidgetFactory {
return imageUpload -> {
if (locTextKey != null) {
imageUpload.fileUpload.setText(i18nSupport.getText(locTextKey));
imageUpload.setSelectionText(i18nSupport.getText(locTextKey));
}
};
}

View file

@ -1,36 +0,0 @@
/*
* Copyright (c) 2018 ETH Zürich, Educational Development and Technology (LET)
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package ch.ethz.seb.sebserver.webservice.servicelayer.authorization;
import ch.ethz.seb.sebserver.gbl.authorization.PrivilegeType;
import ch.ethz.seb.sebserver.gbl.model.EntityType;
/** Defines a authorization grant rule for a specified EntityType.
*
* If there is the need for a specialized authorization grant rule for a specified EntityType, just
* create an implementation of this interface for a specified EntityType as a normal Spring Component
* and the AuthorizationGrantService will automatically collect it on initialization and use it for
* the specified EntityType instead of the default implementation. */
public interface AuthorizationGrantRule {
/** The EntityType of the authorization grant rule implementation.
* This is used by the AuthorizationGrantService on initialization.
*
* @return the authorization grant rule implementation */
EntityType entityType();
/** Implements a authorization grant rule check for a given entity, user and grant type.
*
* @param entity the GrantEntity instance to check the grant rule on
* @param user the SEBServerUser instance to check the grant rule on
* @param grantType the GrantType to check
* @return true if a given user has a given grant-type on a given entity, false otherwise */
boolean hasGrant(GrantEntity entity, SEBServerUser user, PrivilegeType grantType);
}

View file

@ -1,126 +0,0 @@
/*
* Copyright (c) 2018 ETH Zürich, Educational Development and Technology (LET)
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package ch.ethz.seb.sebserver.webservice.servicelayer.authorization;
import java.security.Principal;
import java.util.Collection;
import java.util.function.Predicate;
import ch.ethz.seb.sebserver.gbl.authorization.Privilege;
import ch.ethz.seb.sebserver.gbl.authorization.PrivilegeType;
import ch.ethz.seb.sebserver.gbl.model.EntityType;
import ch.ethz.seb.sebserver.gbl.util.Result;
/** A service to check authorization grants for a given user for entity-types and -instances
*
* If there is one or more GrantEntity objects within an authenticated user-request, this service
* can be used check the authenticated user access grant within the object. Check if a given user
* has write, modify or even read-only rights on an entity instance or on an entity type. */
public interface AuthorizationGrantService {
/** Gets the UserService that is bundled within the AuthorizationGrantService
*
* @return the UserService that is bundled within the AuthorizationGrantService */
UserService getUserService();
/** All Privileges in a collection.
*
* @return all registered Privileges */
Collection<Privilege> getAllPrivileges();
/** Checks if the current user has any privilege (base or institutional or owner) for the given EntityType and
* PrivilegeType.
*
* @param entityType the EntityType
* @param privilegeType the PrivilegeType to check on EntityType */
void checkHasAnyPrivilege(EntityType entityType, PrivilegeType privilegeType);
void checkPrivilege(EntityType entityType, PrivilegeType privilegeType, Long institutionId);
void checkPrivilege(EntityType entityType, PrivilegeType privilegeType, Long institutionId, Long ownerId);
/** Check if current user has grant on a given GrantEntity instance for specified PrivilegeType
*
* @param entity The GrantEntity to check specified PrivilegeType for
* @param privilegeType The PrivilegeType
* @return a with a Result of the granted entity instance or with a Result of a PermissionDeniedException */
<E extends GrantEntity> Result<E> checkGrantOnEntity(E entity, PrivilegeType privilegeType);
/** Checks if the current user has a implicit base privilege for a given entity-type
*
* @param entityType the entity type
* @param privilegeType the privilege type to check
* @return true if the current user has a implicit base privilege on specified PrivilegeType for a given
* EntityType */
boolean hasBasePrivilege(EntityType entityType, PrivilegeType privilegeType);
/** Checks if a given user has a implicit base privilege for a given entity-type
*
* @param entityType the entity type
* @param privilegeType the privilege type to check
* @return true if a given user has a implicit base privilege on specified PrivilegeType for a given EntityType */
boolean hasBasePrivilege(EntityType entityType, PrivilegeType privilegeType, Principal principal);
/** Checks if the current user has an implicit institutional privilege on a given EntityType
*
* @param entityType the entity type
* @param privilegeType the privilege type to check
* @return true if the current user has an implicit institutional privilege on the given EntityType */
boolean hasInstitutionalPrivilege(EntityType entityType, PrivilegeType privilegeType);
/** Checks if a given user has an implicit institutional privilege on a given EntityType
*
* @param entityType the entity type
* @param privilegeType the privilege type to check
* @return true if a given user has an implicit institutional privilege on the given EntityType */
boolean hasInstitutionalPrivilege(EntityType entityType, PrivilegeType privilegeType, Principal principal);
/** Checks if the current user has grant on a given entity for a specified PrivilegeType
*
* @param entity the entity-instance
* @param privilegeType the privilege type to check
* @return true if the current user has a specified grant for a given entity-instance */
boolean hasGrant(GrantEntity entity, PrivilegeType privilegeType);
/** Checks if a given user has grant on a given entity for a specified PrivilegeType
*
* @param entity the entity-instance
* @param privilegeType the grant type to check
* @param principal an authorization Principal instance to extract the user from
* @return true if the given user has grant on a given entity for a specified PrivilegeType */
boolean hasGrant(GrantEntity entity, PrivilegeType privilegeType, Principal principal);
/** Checks if a given user has specified grant for a given entity-instance
*
* @param entity the entity-instance
* @param privilegeType the grant type to check
* @param user a SEBServerUser instance to check grant for
* @return true if a given user has a specified grant for a given entity-instance. False otherwise */
boolean hasGrant(GrantEntity entity, PrivilegeType privilegeType, SEBServerUser user);
/** Closure to get a grant check predicate for the current user
* to filter a several entity-instances within the same grant
*
* @param entityType the EntityType for the grant check filter
* @param privilegeType the PrivilegeType for the grant check filter
* @return A filter predicate working on the given attributes to check user grants */
<T extends GrantEntity> Predicate<T> getGrantFilter(EntityType entityType, PrivilegeType privilegeType);
/** Closure to get a grant check predicate to filter a several entity-instances within the same grant
*
* @param entityType the EntityType for the grant check filter
* @param privilegeType the PrivilegeType for the grant check filter
* @param principal an authorization Principal instance to extract the user from
* @return A filter predicate working on the given attributes to check user grants */
<T extends GrantEntity> Predicate<T> getGrantFilter(
EntityType entityType,
PrivilegeType privilegeType,
Principal principal);
}

View file

@ -1,450 +0,0 @@
/*
* Copyright (c) 2018 ETH Zürich, Educational Development and Technology (LET)
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package ch.ethz.seb.sebserver.webservice.servicelayer.authorization;
import java.security.Principal;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Predicate;
import javax.annotation.PostConstruct;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import ch.ethz.seb.sebserver.gbl.authorization.Privilege;
import ch.ethz.seb.sebserver.gbl.authorization.Privilege.RoleTypeKey;
import ch.ethz.seb.sebserver.gbl.authorization.PrivilegeType;
import ch.ethz.seb.sebserver.gbl.model.EntityType;
import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
import ch.ethz.seb.sebserver.gbl.util.Result;
@Lazy
@Service
@WebServiceProfile
public class AuthorizationGrantServiceImpl implements AuthorizationGrantService {
/** Map of role based grants for specified entity types. */
private final Map<Privilege.RoleTypeKey, Privilege> privileges = new HashMap<>();
/** Map of collected AuthorizationGrantRule exceptions */
private final Map<EntityType, AuthorizationGrantRule> exceptionalRules =
new EnumMap<>(EntityType.class);
private final UserService userService;
public AuthorizationGrantServiceImpl(
final Collection<AuthorizationGrantRule> exceptionalGrantRules,
final UserService userService) {
this.userService = userService;
if (exceptionalGrantRules != null) {
exceptionalGrantRules.stream()
.forEach(r -> this.exceptionalRules.put(r.entityType(), r));
}
}
@Override
public UserService getUserService() {
return this.userService;
}
@Override
public Collection<Privilege> getAllPrivileges() {
return Collections.unmodifiableCollection(this.privileges.values());
}
/** Initialize the (hard-coded) grants */
@PostConstruct
public void init() {
// grants for institution
addPrivilege(EntityType.INSTITUTION)
.forRole(UserRole.SEB_SERVER_ADMIN)
.withBasePrivilege(PrivilegeType.WRITE)
.andForRole(UserRole.INSTITUTIONAL_ADMIN)
.withInstitutionalPrivilege(PrivilegeType.MODIFY)
.andForRole(UserRole.EXAM_ADMIN)
.withInstitutionalPrivilege(PrivilegeType.READ_ONLY)
.andForRole(UserRole.EXAM_SUPPORTER)
.withInstitutionalPrivilege(PrivilegeType.READ_ONLY)
.create();
// grants for lms setup
addPrivilege(EntityType.LMS_SETUP)
.forRole(UserRole.SEB_SERVER_ADMIN)
.withBasePrivilege(PrivilegeType.WRITE)
.andForRole(UserRole.INSTITUTIONAL_ADMIN)
.withInstitutionalPrivilege(PrivilegeType.WRITE)
.andForRole(UserRole.EXAM_ADMIN)
.withInstitutionalPrivilege(PrivilegeType.MODIFY)
.andForRole(UserRole.EXAM_SUPPORTER)
.withInstitutionalPrivilege(PrivilegeType.READ_ONLY)
.create();
// grants for user account
addPrivilege(EntityType.USER)
.forRole(UserRole.SEB_SERVER_ADMIN)
.withBasePrivilege(PrivilegeType.WRITE)
.andForRole(UserRole.INSTITUTIONAL_ADMIN)
.withInstitutionalPrivilege(PrivilegeType.WRITE)
.andForRole(UserRole.EXAM_ADMIN)
.withOwnerPrivilege(PrivilegeType.MODIFY)
.andForRole(UserRole.EXAM_SUPPORTER)
.withOwnerPrivilege(PrivilegeType.MODIFY)
.create();
// grants for user activity logs
addPrivilege(EntityType.USER_ACTIVITY_LOG)
.forRole(UserRole.SEB_SERVER_ADMIN)
.withBasePrivilege(PrivilegeType.READ_ONLY)
.andForRole(UserRole.INSTITUTIONAL_ADMIN)
.withInstitutionalPrivilege(PrivilegeType.READ_ONLY)
.create();
// grants for exam
addPrivilege(EntityType.EXAM)
.forRole(UserRole.SEB_SERVER_ADMIN)
.withBasePrivilege(PrivilegeType.READ_ONLY)
.andForRole(UserRole.INSTITUTIONAL_ADMIN)
.withInstitutionalPrivilege(PrivilegeType.READ_ONLY)
.andForRole(UserRole.EXAM_ADMIN)
.withInstitutionalPrivilege(PrivilegeType.READ_ONLY)
.withOwnerPrivilege(PrivilegeType.WRITE)
.andForRole(UserRole.EXAM_SUPPORTER)
.withOwnerPrivilege(PrivilegeType.MODIFY)
.create();
// TODO other entities
}
@Override
public void checkHasAnyPrivilege(final EntityType entityType, final PrivilegeType privilegeType) {
final SEBServerUser currentUser = this.userService.getCurrentUser();
if (hasBasePrivilege(entityType, privilegeType, currentUser) ||
hasInstitutionalPrivilege(entityType, privilegeType, currentUser)) {
return;
}
throw new PermissionDeniedException(entityType, privilegeType, currentUser.getUserInfo().uuid);
}
@Override
public void checkPrivilege(
final EntityType entityType,
final PrivilegeType privilegeType,
final Long institutionId) {
final SEBServerUser currentUser = this.userService.getCurrentUser();
if (hasBasePrivilege(entityType, privilegeType, currentUser)) {
return;
}
if (institutionId == null) {
throw new PermissionDeniedException(entityType, privilegeType, currentUser.getUserInfo().uuid);
}
if (hasInstitutionalPrivilege(entityType, privilegeType, currentUser) &&
currentUser.institutionId().longValue() == institutionId.longValue()) {
return;
}
throw new PermissionDeniedException(entityType, privilegeType, currentUser.getUserInfo().uuid);
}
@Override
public void checkPrivilege(
final EntityType entityType,
final PrivilegeType privilegeType,
final Long institutionId,
final Long ownerId) {
final SEBServerUser currentUser = this.userService.getCurrentUser();
// TODO Auto-generated method stub
throw new PermissionDeniedException(entityType, privilegeType, currentUser.getUserInfo().uuid);
}
@Override
public <E extends GrantEntity> Result<E> checkGrantOnEntity(final E entity, final PrivilegeType privilegeType) {
final SEBServerUser currentUser = this.userService.getCurrentUser();
if (hasGrant(entity, privilegeType, currentUser)) {
return Result.of(entity);
} else {
return Result.ofError(new PermissionDeniedException(entity, privilegeType, currentUser.getUserInfo().uuid));
}
}
@Override
public boolean hasBasePrivilege(final EntityType entityType, final PrivilegeType privilegeType) {
return hasBasePrivilege(entityType, privilegeType, this.userService.getCurrentUser());
}
@Override
public boolean hasBasePrivilege(
final EntityType entityType,
final PrivilegeType privilegeType,
final Principal principal) {
return hasBasePrivilege(entityType, privilegeType, this.userService.extractFromPrincipal(principal));
}
private boolean hasBasePrivilege(
final EntityType entityType,
final PrivilegeType privilegeType,
final SEBServerUser user) {
for (final UserRole role : user.getUserRoles()) {
final Privilege roleTypeGrant = this.privileges.get(new RoleTypeKey(entityType, role));
if (roleTypeGrant != null && roleTypeGrant.hasBasePrivilege(privilegeType)) {
return true;
}
}
return false;
}
@Override
public boolean hasInstitutionalPrivilege(
final EntityType entityType,
final PrivilegeType privilegeType) {
return hasInstitutionalPrivilege(
entityType,
privilegeType,
this.userService.getCurrentUser());
}
@Override
public boolean hasInstitutionalPrivilege(
final EntityType entityType,
final PrivilegeType privilegeType,
final Principal principal) {
return hasInstitutionalPrivilege(
entityType,
privilegeType,
this.userService.extractFromPrincipal(principal));
}
private boolean hasInstitutionalPrivilege(
final EntityType entityType,
final PrivilegeType privilegeType,
final SEBServerUser user) {
for (final UserRole role : user.getUserRoles()) {
final Privilege roleTypeGrant = this.privileges.get(new RoleTypeKey(entityType, role));
if (roleTypeGrant != null && roleTypeGrant.hasInstitutionalPrivilege(privilegeType)) {
return true;
}
}
return false;
}
@Override
public boolean hasGrant(final GrantEntity entity, final PrivilegeType grantType) {
return hasGrant(entity, grantType, this.userService.getCurrentUser());
}
@Override
public boolean hasGrant(final GrantEntity entity, final PrivilegeType grantType, final Principal principal) {
return hasGrant(entity, grantType, this.userService.extractFromPrincipal(principal));
}
@Override
public boolean hasGrant(final GrantEntity entity, final PrivilegeType grantType, final SEBServerUser user) {
final AuthorizationGrantRule authorizationGrantRule = getGrantRule(entity.entityType());
if (authorizationGrantRule == null) {
return false;
}
return authorizationGrantRule.hasGrant(entity, user, grantType);
}
@Override
public <T extends GrantEntity> Predicate<T> getGrantFilter(
final EntityType entityType,
final PrivilegeType grantType) {
return getGrantFilter(entityType, grantType, this.userService.getCurrentUser());
}
@Override
public <T extends GrantEntity> Predicate<T> getGrantFilter(
final EntityType entityType,
final PrivilegeType grantType,
final Principal principal) {
return getGrantFilter(entityType, grantType, this.userService.extractFromPrincipal(principal));
}
private <T extends GrantEntity> Predicate<T> getGrantFilter(
final EntityType entityType,
final PrivilegeType grantType,
final SEBServerUser user) {
final AuthorizationGrantRule authorizationGrantRule = getGrantRule(entityType);
if (authorizationGrantRule == null)
return entity -> false;
return entity -> authorizationGrantRule.hasGrant(entity, user, grantType);
}
private AuthorizationGrantRule getGrantRule(final EntityType type) {
return this.exceptionalRules.computeIfAbsent(
type,
entityType -> new BaseTypeGrantRule(entityType, this));
}
private PrivilegeBuilder addPrivilege(final EntityType entityType) {
return new PrivilegeBuilder(entityType);
}
/** This is the default (or base) implementation of a AuthorizationGrantRule.
*
* The rule is: go over all user-roles of the given user and for each user-role check
* if there is base-privilege on the given entity-type for the given grant type.
* if true return true
* if false; check if there is a given institutional-privilege on the given
* entity-instance for the given grant type.
* if true return true
* if false; check if there is a given ownership-privilege on the given
* entity-instance for the given grant type.
* if true return true
* if false return false */
private static class BaseTypeGrantRule implements AuthorizationGrantRule {
private final EntityType type;
private final Map<UserRole, Privilege> grants;
public BaseTypeGrantRule(final EntityType type, final AuthorizationGrantServiceImpl service) {
this.type = type;
this.grants = new EnumMap<>(UserRole.class);
for (final UserRole role : UserRole.values()) {
this.grants.put(role,
service.privileges.get(new RoleTypeKey(type, role)));
}
}
@Override
public EntityType entityType() {
return this.type;
}
@Override
public boolean hasGrant(final GrantEntity entity, final SEBServerUser user, final PrivilegeType grantType) {
for (final UserRole role : user.getUserRoles()) {
final Privilege roleTypeGrant = this.grants.get(role);
if (roleTypeGrant != null && hasGrant(roleTypeGrant, user, entity, grantType)) {
return true;
}
}
return false;
}
public boolean hasGrant(
final Privilege roleTypeGrant,
final SEBServerUser user,
final GrantEntity entity,
final PrivilegeType grantType) {
return roleTypeGrant.hasBasePrivilege(grantType) ||
hasInstitutionalGrant(roleTypeGrant, user, entity, grantType) ||
hasOwnershipGrant(roleTypeGrant, user, entity, grantType);
}
private boolean hasInstitutionalGrant(
final Privilege roleTypeGrant,
final SEBServerUser user,
final GrantEntity entity,
final PrivilegeType grantType) {
if (entity.getInstitutionId() == null) {
return false;
}
return roleTypeGrant.hasInstitutionalPrivilege(grantType) &&
user.institutionId().longValue() == entity.getInstitutionId().longValue();
}
private boolean hasOwnershipGrant(
final Privilege roleTypeGrant,
final SEBServerUser user,
final GrantEntity entity,
final PrivilegeType grantType) {
if (entity.getOwnerId() == null) {
return false;
}
return roleTypeGrant.hasOwnershipPrivilege(grantType) &&
user.uuid().equals(entity.getOwnerId());
}
}
/** Implements a GrantRuleBuilder for internal use and to make the code more readable.
* See init (PostConstruct) */
private final class PrivilegeBuilder {
private final EntityType entityType;
private UserRole userRole;
private PrivilegeType basePrivilege = PrivilegeType.NONE;
private PrivilegeType institutionalPrivilege = PrivilegeType.NONE;
private PrivilegeType ownerPrivilege = PrivilegeType.NONE;
public PrivilegeBuilder(final EntityType entityType) {
super();
this.entityType = entityType;
}
public PrivilegeBuilder forRole(final UserRole userRole) {
this.userRole = userRole;
return this;
}
public PrivilegeBuilder withBasePrivilege(final PrivilegeType basePrivilege) {
this.basePrivilege = basePrivilege;
return this;
}
public PrivilegeBuilder withInstitutionalPrivilege(final PrivilegeType institutionalPrivilege) {
this.institutionalPrivilege = institutionalPrivilege;
return this;
}
public PrivilegeBuilder withOwnerPrivilege(final PrivilegeType ownerPrivilege) {
this.ownerPrivilege = ownerPrivilege;
return this;
}
public PrivilegeBuilder andForRole(final UserRole userRole) {
create();
return new PrivilegeBuilder(this.entityType)
.forRole(userRole);
}
public void create() {
final RoleTypeKey roleTypeKey = new RoleTypeKey(this.entityType, this.userRole);
final Privilege roleTypeGrant = new Privilege(
roleTypeKey,
this.basePrivilege,
this.institutionalPrivilege,
this.ownerPrivilege);
AuthorizationGrantServiceImpl.this.privileges.put(roleTypeKey, roleTypeGrant);
}
}
}

View file

@ -0,0 +1,124 @@
/*
* Copyright (c) 2018 ETH Zürich, Educational Development and Technology (LET)
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package ch.ethz.seb.sebserver.webservice.servicelayer.authorization;
import java.util.Collection;
import java.util.Set;
import ch.ethz.seb.sebserver.gbl.authorization.Privilege;
import ch.ethz.seb.sebserver.gbl.authorization.PrivilegeType;
import ch.ethz.seb.sebserver.gbl.model.EntityType;
import ch.ethz.seb.sebserver.gbl.model.user.UserInfo;
import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
import ch.ethz.seb.sebserver.gbl.util.Result;
/** A service to check authorization grants for a given user for entity-types and -instances
*
* If there is one or more GrantEntity objects within an authenticated user-request, this service
* can be used check the authenticated user access grant within the object. Check if a given user
* has write, modify or even read-only rights on an entity instance or on an entity type. */
public interface AuthorizationService {
/** Gets the UserService that is bundled within the AuthorizationGrantService
*
* @return the UserService that is bundled within the AuthorizationGrantService */
UserService getUserService();
/** All Privileges in a collection.
*
* @return all registered Privileges */
Collection<Privilege> getAllPrivileges();
boolean hasPrivilege(
PrivilegeType privilegeType,
EntityType entityType,
Long institutionId,
String userId,
Long userInstitutionId,
Set<UserRole> userRoles);
boolean hasPrivilege(PrivilegeType privilegeType, GrantEntity grantEntity);
default boolean hasPrivilege(final PrivilegeType privilegeType, final EntityType entityType) {
final SEBServerUser currentUser = getUserService().getCurrentUser();
final UserInfo userInfo = currentUser.getUserInfo();
return hasPrivilege(
privilegeType,
entityType,
null,
userInfo.uuid,
userInfo.institutionId,
currentUser.getUserRoles());
}
default boolean hasPrivilege(
final PrivilegeType privilegeType,
final EntityType entityType,
final Long institutionId) {
final SEBServerUser currentUser = getUserService().getCurrentUser();
final UserInfo userInfo = currentUser.getUserInfo();
return hasPrivilege(
privilegeType,
entityType,
institutionId,
userInfo.uuid,
userInfo.institutionId,
currentUser.getUserRoles());
}
default boolean hasReadonlyPrivilege(final GrantEntity grantEntity) {
return hasPrivilege(PrivilegeType.READ_ONLY, grantEntity);
}
default boolean hasModifyPrivilege(final GrantEntity grantEntity) {
return hasPrivilege(PrivilegeType.MODIFY, grantEntity);
}
default boolean hasWritePrivilege(final GrantEntity grantEntity) {
return hasPrivilege(PrivilegeType.WRITE, grantEntity);
}
default void check(final PrivilegeType privilegeType, final EntityType entityType) {
check(privilegeType, entityType, null);
}
default void check(final PrivilegeType privilegeType, final EntityType entityType, final Long institutionId) {
if (!hasPrivilege(privilegeType, entityType, institutionId)) {
throw new PermissionDeniedException(
entityType,
privilegeType,
getUserService().getCurrentUser().getUserInfo().uuid);
}
}
default <E extends GrantEntity> Result<E> check(final PrivilegeType privilegeType, final E grantEntity) {
if (!hasPrivilege(privilegeType, grantEntity)) {
throw new PermissionDeniedException(
grantEntity,
privilegeType,
getUserService().getCurrentUser().getUserInfo().uuid);
}
return Result.of(grantEntity);
}
default <E extends GrantEntity> Result<E> checkReadonly(final E grantEntity) {
return check(PrivilegeType.READ_ONLY, grantEntity);
}
default <E extends GrantEntity> Result<E> checkModify(final E grantEntity) {
return check(PrivilegeType.MODIFY, grantEntity);
}
default <E extends GrantEntity> Result<E> checkWrite(final E grantEntity) {
return check(PrivilegeType.WRITE, grantEntity);
}
}

View file

@ -0,0 +1,214 @@
/*
* Copyright (c) 2018 ETH Zürich, Educational Development and Technology (LET)
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package ch.ethz.seb.sebserver.webservice.servicelayer.authorization;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import javax.annotation.PostConstruct;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import ch.ethz.seb.sebserver.gbl.authorization.Privilege;
import ch.ethz.seb.sebserver.gbl.authorization.Privilege.RoleTypeKey;
import ch.ethz.seb.sebserver.gbl.authorization.PrivilegeType;
import ch.ethz.seb.sebserver.gbl.model.EntityType;
import ch.ethz.seb.sebserver.gbl.model.user.UserInfo;
import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
@Lazy
@Service
@WebServiceProfile
public class AuthorizationServiceImpl implements AuthorizationService {
private final UserService userService;
/** Map of role based grants for specified entity types. */
private final Map<Privilege.RoleTypeKey, Privilege> privileges = new HashMap<>();
public AuthorizationServiceImpl(final UserService userService) {
this.userService = userService;
}
@Override
public UserService getUserService() {
return this.userService;
}
@Override
public Collection<Privilege> getAllPrivileges() {
return Collections.unmodifiableCollection(this.privileges.values());
}
/** Initialize the (hard-coded) grants */
@PostConstruct
public void init() {
// grants for institution
addPrivilege(EntityType.INSTITUTION)
.forRole(UserRole.SEB_SERVER_ADMIN)
.withBasePrivilege(PrivilegeType.WRITE)
.andForRole(UserRole.INSTITUTIONAL_ADMIN)
.withInstitutionalPrivilege(PrivilegeType.MODIFY)
.andForRole(UserRole.EXAM_ADMIN)
.withInstitutionalPrivilege(PrivilegeType.READ_ONLY)
.andForRole(UserRole.EXAM_SUPPORTER)
.withInstitutionalPrivilege(PrivilegeType.READ_ONLY)
.create();
// grants for lms setup
addPrivilege(EntityType.LMS_SETUP)
.forRole(UserRole.SEB_SERVER_ADMIN)
.withBasePrivilege(PrivilegeType.WRITE)
.andForRole(UserRole.INSTITUTIONAL_ADMIN)
.withInstitutionalPrivilege(PrivilegeType.WRITE)
.andForRole(UserRole.EXAM_ADMIN)
.withInstitutionalPrivilege(PrivilegeType.MODIFY)
.andForRole(UserRole.EXAM_SUPPORTER)
.withInstitutionalPrivilege(PrivilegeType.READ_ONLY)
.create();
// grants for user account
addPrivilege(EntityType.USER)
.forRole(UserRole.SEB_SERVER_ADMIN)
.withBasePrivilege(PrivilegeType.WRITE)
.andForRole(UserRole.INSTITUTIONAL_ADMIN)
.withInstitutionalPrivilege(PrivilegeType.WRITE)
.andForRole(UserRole.EXAM_ADMIN)
.withOwnerPrivilege(PrivilegeType.MODIFY)
.andForRole(UserRole.EXAM_SUPPORTER)
.withOwnerPrivilege(PrivilegeType.MODIFY)
.create();
// grants for user activity logs
addPrivilege(EntityType.USER_ACTIVITY_LOG)
.forRole(UserRole.SEB_SERVER_ADMIN)
.withBasePrivilege(PrivilegeType.READ_ONLY)
.andForRole(UserRole.INSTITUTIONAL_ADMIN)
.withInstitutionalPrivilege(PrivilegeType.READ_ONLY)
.create();
// grants for exam
addPrivilege(EntityType.EXAM)
.forRole(UserRole.SEB_SERVER_ADMIN)
.withBasePrivilege(PrivilegeType.READ_ONLY)
.andForRole(UserRole.INSTITUTIONAL_ADMIN)
.withInstitutionalPrivilege(PrivilegeType.READ_ONLY)
.andForRole(UserRole.EXAM_ADMIN)
.withInstitutionalPrivilege(PrivilegeType.READ_ONLY)
.withOwnerPrivilege(PrivilegeType.WRITE)
.andForRole(UserRole.EXAM_SUPPORTER)
.withOwnerPrivilege(PrivilegeType.MODIFY)
.create();
// TODO other entities
}
@Override
public boolean hasPrivilege(
final PrivilegeType privilegeType,
final EntityType entityType,
final Long institutionId,
final String userId,
final Long userInstitutionId,
final Set<UserRole> userRoles) {
return userRoles
.stream()
.map(role -> new RoleTypeKey(entityType, role))
.map(key -> this.privileges.get(key))
.filter(priv -> (priv != null) && priv.hasGrant(
userId,
userInstitutionId,
privilegeType,
institutionId,
null))
.findFirst()
.isPresent();
}
@Override
public boolean hasPrivilege(final PrivilegeType privilegeType, final GrantEntity grantEntity) {
final UserInfo userInfo = this.userService.getCurrentUser().getUserInfo();
return userInfo.getRoles()
.stream()
.map(roleName -> UserRole.valueOf(roleName))
.map(role -> new RoleTypeKey(grantEntity.entityType(), role))
.map(key -> this.privileges.get(key))
.filter(priv -> (priv != null) && priv.hasGrant(
userInfo.uuid,
userInfo.institutionId,
privilegeType,
grantEntity.getInstitutionId(),
grantEntity.getOwnerId()))
.findFirst()
.isPresent();
}
private PrivilegeBuilder addPrivilege(final EntityType entityType) {
return new PrivilegeBuilder(entityType);
}
/** Implements a GrantRuleBuilder for internal use and to make the code more readable.
* See init (PostConstruct) */
private final class PrivilegeBuilder {
private final EntityType entityType;
private UserRole userRole;
private PrivilegeType basePrivilege = PrivilegeType.NONE;
private PrivilegeType institutionalPrivilege = PrivilegeType.NONE;
private PrivilegeType ownerPrivilege = PrivilegeType.NONE;
public PrivilegeBuilder(final EntityType entityType) {
super();
this.entityType = entityType;
}
public PrivilegeBuilder forRole(final UserRole userRole) {
this.userRole = userRole;
return this;
}
public PrivilegeBuilder withBasePrivilege(final PrivilegeType basePrivilege) {
this.basePrivilege = basePrivilege;
return this;
}
public PrivilegeBuilder withInstitutionalPrivilege(final PrivilegeType institutionalPrivilege) {
this.institutionalPrivilege = institutionalPrivilege;
return this;
}
public PrivilegeBuilder withOwnerPrivilege(final PrivilegeType ownerPrivilege) {
this.ownerPrivilege = ownerPrivilege;
return this;
}
public PrivilegeBuilder andForRole(final UserRole userRole) {
create();
return new PrivilegeBuilder(this.entityType)
.forRole(userRole);
}
public void create() {
final RoleTypeKey roleTypeKey = new RoleTypeKey(this.entityType, this.userRole);
final Privilege roleTypeGrant = new Privilege(
roleTypeKey,
this.basePrivilege,
this.institutionalPrivilege,
this.ownerPrivilege);
AuthorizationServiceImpl.this.privileges.put(roleTypeKey, roleTypeGrant);
}
}
}

View file

@ -15,7 +15,6 @@ import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import ch.ethz.seb.sebserver.gbl.api.API;
import ch.ethz.seb.sebserver.gbl.authorization.PrivilegeType;
import ch.ethz.seb.sebserver.gbl.model.Entity;
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
import ch.ethz.seb.sebserver.gbl.model.EntityProcessingReport;
@ -24,7 +23,7 @@ import ch.ethz.seb.sebserver.gbl.model.Page;
import ch.ethz.seb.sebserver.gbl.util.Result;
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.UserRecordDynamicSqlSupport;
import ch.ethz.seb.sebserver.webservice.servicelayer.PaginationService;
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.AuthorizationGrantService;
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.AuthorizationService;
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.GrantEntity;
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.UserService;
import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkAction;
@ -40,7 +39,7 @@ public abstract class ActivatableEntityController<T extends GrantEntity, M exten
private final ActivatableEntityDAO<T, M> activatableEntityDAO;
public ActivatableEntityController(
final AuthorizationGrantService authorizationGrantService,
final AuthorizationService authorizationGrantService,
final BulkActionService bulkActionService,
final ActivatableEntityDAO<T, M> entityDAO,
final UserActivityLogDAO userActivityLogDAO,
@ -130,9 +129,7 @@ public abstract class ActivatableEntityController<T extends GrantEntity, M exten
new EntityKey(id, entityType));
return this.entityDAO.byModelId(id)
.flatMap(entity -> this.authorizationGrantService.checkGrantOnEntity(
entity,
PrivilegeType.WRITE))
.flatMap(this.authorization::checkWrite)
.flatMap(entity -> this.bulkActionService.createReport(bulkAction));
}

View file

@ -10,7 +10,6 @@ package ch.ethz.seb.sebserver.webservice.weblayer.api;
import java.util.Arrays;
import java.util.Collection;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import javax.validation.Valid;
@ -39,7 +38,7 @@ import ch.ethz.seb.sebserver.gbl.model.EntityType;
import ch.ethz.seb.sebserver.gbl.model.Page;
import ch.ethz.seb.sebserver.gbl.util.Result;
import ch.ethz.seb.sebserver.webservice.servicelayer.PaginationService;
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.AuthorizationGrantService;
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.AuthorizationService;
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.GrantEntity;
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.UserService;
import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkAction;
@ -53,7 +52,7 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.validation.BeanValidationSe
public abstract class EntityController<T extends GrantEntity, M extends GrantEntity> {
protected final AuthorizationGrantService authorizationGrantService;
protected final AuthorizationService authorization;
protected final BulkActionService bulkActionService;
protected final EntityDAO<T, M> entityDAO;
protected final UserActivityLogDAO userActivityLogDAO;
@ -61,14 +60,14 @@ public abstract class EntityController<T extends GrantEntity, M extends GrantEnt
protected final BeanValidationService beanValidationService;
protected EntityController(
final AuthorizationGrantService authorizationGrantService,
final AuthorizationService authorization,
final BulkActionService bulkActionService,
final EntityDAO<T, M> entityDAO,
final UserActivityLogDAO userActivityLogDAO,
final PaginationService paginationService,
final BeanValidationService beanValidationService) {
this.authorizationGrantService = authorizationGrantService;
this.authorization = authorization;
this.bulkActionService = bulkActionService;
this.entityDAO = entityDAO;
this.userActivityLogDAO = userActivityLogDAO;
@ -78,7 +77,7 @@ public abstract class EntityController<T extends GrantEntity, M extends GrantEnt
@InitBinder
public void initBinder(final WebDataBinder binder) throws Exception {
this.authorizationGrantService
this.authorization
.getUserService()
.addUsersInstitutionDefaultPropertySupport(binder);
}
@ -153,9 +152,7 @@ public abstract class EntityController<T extends GrantEntity, M extends GrantEnt
return this.entityDAO
.byModelId(modelId)
.flatMap(entity -> this.authorizationGrantService.checkGrantOnEntity(
entity,
PrivilegeType.READ_ONLY))
.flatMap(this.authorization::checkReadonly)
.getOrThrow();
}
@ -181,7 +178,7 @@ public abstract class EntityController<T extends GrantEntity, M extends GrantEnt
.flatMap(this.entityDAO::loadEntities)
.getOrThrow()
.stream()
.filter(entity -> this.authorizationGrantService.hasGrant(entity, PrivilegeType.READ_ONLY))
.filter(this.authorization::hasReadonlyPrivilege)
.collect(Collectors.toList());
}
@ -201,9 +198,9 @@ public abstract class EntityController<T extends GrantEntity, M extends GrantEnt
defaultValue = UserService.USERS_INSTITUTION_AS_DEFAULT) final Long institutionId) {
// check write privilege for requested institution and concrete entityType
this.authorizationGrantService.checkPrivilege(
this.entityDAO.entityType(),
this.authorization.check(
PrivilegeType.WRITE,
this.entityDAO.entityType(),
institutionId);
final POSTMapper postMap = new POSTMapper(allRequestParams)
@ -232,7 +229,7 @@ public abstract class EntityController<T extends GrantEntity, M extends GrantEnt
@Valid @RequestBody final M modifyData) {
return this.beanValidationService.validateBean(modifyData)
.flatMap(m -> this.authorizationGrantService.checkGrantOnEntity(m, PrivilegeType.MODIFY))
.flatMap(this.authorization::checkModify)
.flatMap(m -> this.entityDAO.save(modelId, m))
.flatMap(e -> this.userActivityLogDAO.log(ActivityType.MODIFY, e))
.flatMap(e -> notifySaved(modifyData, e))
@ -284,26 +281,22 @@ public abstract class EntityController<T extends GrantEntity, M extends GrantEnt
new EntityKey(modelId, entityType));
return this.entityDAO.byModelId(modelId)
.flatMap(entity -> this.authorizationGrantService.checkGrantOnEntity(
entity,
PrivilegeType.WRITE))
.flatMap(this.authorization::checkWrite)
.flatMap(entity -> this.bulkActionService.createReport(bulkAction))
.getOrThrow();
}
protected void checkReadPrivilege(final Long institutionId) {
this.authorizationGrantService.checkPrivilege(
this.entityDAO.entityType(),
this.authorization.check(
PrivilegeType.READ_ONLY,
this.entityDAO.entityType(),
institutionId);
}
protected Result<Collection<T>> getAll(final FilterMap filterMap) {
final Predicate<T> grantFilter = this.authorizationGrantService.getGrantFilter(
this.entityDAO.entityType(),
PrivilegeType.READ_ONLY);
return this.entityDAO.allMatching(filterMap, grantFilter);
return this.entityDAO.allMatching(
filterMap,
this.authorization::hasReadonlyPrivilege);
}
protected Result<T> notifySaved(final M modifyData, final T entity) {

View file

@ -45,7 +45,7 @@ import ch.ethz.seb.sebserver.gbl.util.Utils;
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ExamRecordDynamicSqlSupport;
import ch.ethz.seb.sebserver.webservice.servicelayer.PaginationService;
import ch.ethz.seb.sebserver.webservice.servicelayer.PaginationService.SortOrder;
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.AuthorizationGrantService;
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.AuthorizationService;
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.UserService;
import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkActionService;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ExamDAO;
@ -66,7 +66,7 @@ public class ExamAdministrationController extends ActivatableEntityController<Ex
private final LmsAPIService lmsAPIService;
public ExamAdministrationController(
final AuthorizationGrantService authorizationGrantService,
final AuthorizationService authorization,
final UserActivityLogDAO userActivityLogDAO,
final ExamDAO examDAO,
final PaginationService paginationService,
@ -75,7 +75,7 @@ public class ExamAdministrationController extends ActivatableEntityController<Ex
final IndicatorDAO indicatorDAO,
final LmsAPIService lmsAPIService) {
super(authorizationGrantService,
super(authorization,
bulkActionService,
examDAO,
userActivityLogDAO,
@ -124,9 +124,9 @@ public class ExamAdministrationController extends ActivatableEntityController<Ex
} else {
this.authorizationGrantService.checkPrivilege(
EntityType.EXAM,
this.authorization.check(
PrivilegeType.READ_ONLY,
EntityType.EXAM,
institutionId);
final int pageNum = this.paginationService.getPageNumber(pageNumber);
@ -161,7 +161,7 @@ public class ExamAdministrationController extends ActivatableEntityController<Ex
public Collection<Indicator> getIndicatorOfExam(@PathVariable final Long examId) {
// check read-only grant on Exam
this.examDAO.byPK(examId)
.map(exam -> this.authorizationGrantService.checkGrantOnEntity(exam, PrivilegeType.READ_ONLY))
.map(this.authorization::checkReadonly)
.getOrThrow();
return this.indicatorDAO.allForExam(examId)
@ -175,7 +175,7 @@ public class ExamAdministrationController extends ActivatableEntityController<Ex
// check write grant on Exam
this.examDAO.byPK(examId)
.map(exam -> this.authorizationGrantService.checkGrantOnEntity(exam, PrivilegeType.WRITE))
.map(this.authorization::checkWrite)
.getOrThrow();
final Set<EntityKey> toDelete = (indicatorId != null)
@ -199,7 +199,7 @@ public class ExamAdministrationController extends ActivatableEntityController<Ex
// check write grant on Exam
this.examDAO.byPK(examId)
.flatMap(exam -> this.authorizationGrantService.checkGrantOnEntity(exam, PrivilegeType.WRITE))
.flatMap(this.authorization::checkWrite)
.getOrThrow();
if (indicator.id != null) {
@ -219,7 +219,7 @@ public class ExamAdministrationController extends ActivatableEntityController<Ex
// check modify grant on Exam
this.examDAO.byPK(indicator.examId)
.flatMap(e -> this.authorizationGrantService.checkGrantOnEntity(e, PrivilegeType.MODIFY))
.flatMap(this.authorization::checkModify)
.getOrThrow();
return this.indicatorDAO

View file

@ -19,7 +19,7 @@ import org.springframework.web.bind.annotation.RestController;
import ch.ethz.seb.sebserver.gbl.api.API;
import ch.ethz.seb.sebserver.gbl.authorization.Privilege;
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.AuthorizationGrantService;
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.AuthorizationService;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.InstitutionDAO;
@WebServiceProfile
@ -28,11 +28,11 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.dao.InstitutionDAO;
public class InfoController {
private final InstitutionDAO institutionDAO;
private final AuthorizationGrantService authorizationGrantService;
private final AuthorizationService authorizationGrantService;
protected InfoController(
final InstitutionDAO institutionDAO,
final AuthorizationGrantService authorizationGrantService) {
final AuthorizationService authorizationGrantService) {
this.institutionDAO = institutionDAO;
this.authorizationGrantService = authorizationGrantService;

View file

@ -19,7 +19,7 @@ import ch.ethz.seb.sebserver.gbl.model.institution.Institution;
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.InstitutionRecordDynamicSqlSupport;
import ch.ethz.seb.sebserver.webservice.servicelayer.PaginationService;
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.AuthorizationGrantService;
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.AuthorizationService;
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.SEBServerUser;
import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkActionService;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.InstitutionDAO;
@ -35,13 +35,13 @@ public class InstitutionController extends ActivatableEntityController<Instituti
public InstitutionController(
final InstitutionDAO institutionDAO,
final AuthorizationGrantService authorizationGrantService,
final AuthorizationService authorization,
final UserActivityLogDAO userActivityLogDAO,
final BulkActionService bulkActionService,
final PaginationService paginationService,
final BeanValidationService beanValidationService) {
super(authorizationGrantService,
super(authorization,
bulkActionService,
institutionDAO,
userActivityLogDAO,
@ -63,7 +63,7 @@ public class InstitutionController extends ActivatableEntityController<Instituti
@RequestMapping(path = API.SELF_PATH_SEGMENT, method = RequestMethod.GET)
public Institution getOwn() {
final SEBServerUser currentUser = this.authorizationGrantService
final SEBServerUser currentUser = this.authorization
.getUserService()
.getCurrentUser();

View file

@ -30,7 +30,7 @@ import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetupTestResult;
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.LmsSetupRecordDynamicSqlSupport;
import ch.ethz.seb.sebserver.webservice.servicelayer.PaginationService;
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.AuthorizationGrantService;
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.AuthorizationService;
import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkActionService;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.LmsSetupDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserActivityLogDAO;
@ -46,14 +46,14 @@ public class LmsSetupController extends ActivatableEntityController<LmsSetup, Lm
public LmsSetupController(
final LmsSetupDAO lmsSetupDAO,
final AuthorizationGrantService authorizationGrantService,
final AuthorizationService authorization,
final UserActivityLogDAO userActivityLogDAO,
final BulkActionService bulkActionService,
final LmsAPIService lmsAPIService,
final PaginationService paginationService,
final BeanValidationService beanValidationService) {
super(authorizationGrantService,
super(authorization,
bulkActionService,
lmsSetupDAO,
userActivityLogDAO,
@ -81,9 +81,7 @@ public class LmsSetupController extends ActivatableEntityController<LmsSetup, Lm
@PathVariable final Long modelId,
final HttpServletResponse response) {
this.authorizationGrantService.checkHasAnyPrivilege(
EntityType.LMS_SETUP,
PrivilegeType.WRITE);
this.authorization.check(PrivilegeType.WRITE, EntityType.LMS_SETUP);
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
response.setStatus(HttpStatus.OK.value());
@ -107,9 +105,7 @@ public class LmsSetupController extends ActivatableEntityController<LmsSetup, Lm
produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public LmsSetupTestResult connectionReport(@PathVariable final Long modelId) {
this.authorizationGrantService.checkHasAnyPrivilege(
EntityType.LMS_SETUP,
PrivilegeType.MODIFY);
this.authorization.check(PrivilegeType.MODIFY, EntityType.LMS_SETUP);
return this.lmsAPIService.createLmsAPITemplate(modelId)
.map(template -> template.testLmsSetup())

View file

@ -23,7 +23,7 @@ import ch.ethz.seb.sebserver.gbl.model.Page;
import ch.ethz.seb.sebserver.gbl.model.exam.QuizData;
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
import ch.ethz.seb.sebserver.gbl.util.Utils;
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.AuthorizationGrantService;
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.AuthorizationService;
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.UserService;
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPIService;
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPITemplate;
@ -37,18 +37,18 @@ public class QuizImportController {
private final int maxPageSize;
private final LmsAPIService lmsAPIService;
private final AuthorizationGrantService authorizationGrantService;
private final AuthorizationService authorization;
public QuizImportController(
@Value("${sebserver.webservice.api.pagination.defaultPageSize:10}") final int defaultPageSize,
@Value("${sebserver.webservice.api.pagination.maxPageSize:500}") final int maxPageSize,
final LmsAPIService lmsAPIService,
final AuthorizationGrantService authorizationGrantService) {
final AuthorizationService authorization) {
this.defaultPageSize = defaultPageSize;
this.maxPageSize = maxPageSize;
this.lmsAPIService = lmsAPIService;
this.authorizationGrantService = authorizationGrantService;
this.authorization = authorization;
}
@RequestMapping(method = RequestMethod.GET)
@ -68,9 +68,9 @@ public class QuizImportController {
.createLmsAPITemplate(lmsSetupId)
.getOrThrow();
this.authorizationGrantService.checkPrivilege(
EntityType.EXAM,
this.authorization.check(
PrivilegeType.READ_ONLY,
EntityType.EXAM,
institutionId);
return lmsAPITemplate.getQuizzes(

View file

@ -14,15 +14,15 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import ch.ethz.seb.sebserver.gbl.api.POSTMapper;
import ch.ethz.seb.sebserver.gbl.api.API;
import ch.ethz.seb.sebserver.gbl.api.POSTMapper;
import ch.ethz.seb.sebserver.gbl.model.user.UserInfo;
import ch.ethz.seb.sebserver.gbl.model.user.UserMod;
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
import ch.ethz.seb.sebserver.gbl.util.Result;
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.UserRecordDynamicSqlSupport;
import ch.ethz.seb.sebserver.webservice.servicelayer.PaginationService;
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.AuthorizationGrantService;
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.AuthorizationService;
import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkActionService;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserActivityLogDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserDAO;
@ -38,14 +38,14 @@ public class UserAccountController extends ActivatableEntityController<UserInfo,
public UserAccountController(
final UserDAO userDao,
final AuthorizationGrantService authorizationGrantService,
final AuthorizationService authorization,
final UserActivityLogDAO userActivityLogDAO,
final PaginationService paginationService,
final BulkActionService bulkActionService,
final ApplicationEventPublisher applicationEventPublisher,
final BeanValidationService beanValidationService) {
super(authorizationGrantService,
super(authorization,
bulkActionService,
userDao,
userActivityLogDAO,
@ -56,7 +56,7 @@ public class UserAccountController extends ActivatableEntityController<UserInfo,
@RequestMapping(path = "/me", method = RequestMethod.GET)
public UserInfo loggedInUser() {
return this.authorizationGrantService
return this.authorization
.getUserService()
.getCurrentUser()
.getUserInfo();

View file

@ -27,7 +27,7 @@ import ch.ethz.seb.sebserver.gbl.util.Result;
import ch.ethz.seb.sebserver.gbl.util.Utils;
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.UserRecordDynamicSqlSupport;
import ch.ethz.seb.sebserver.webservice.servicelayer.PaginationService;
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.AuthorizationGrantService;
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.AuthorizationService;
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.UserService;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserActivityLogDAO;
@ -37,22 +37,22 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserActivityLogDAO;
public class UserActivityLogController {
private final UserActivityLogDAO userActivityLogDAO;
private final AuthorizationGrantService authorizationGrantService;
private final AuthorizationService authorization;
private final PaginationService paginationService;
public UserActivityLogController(
final UserActivityLogDAO userActivityLogDAO,
final AuthorizationGrantService authorizationGrantService,
final AuthorizationService authorization,
final PaginationService paginationService) {
this.userActivityLogDAO = userActivityLogDAO;
this.authorizationGrantService = authorizationGrantService;
this.authorization = authorization;
this.paginationService = paginationService;
}
@InitBinder
public void initBinder(final WebDataBinder binder) throws Exception {
this.authorizationGrantService
this.authorization
.getUserService()
.addUsersInstitutionDefaultPropertySupport(binder);
}
@ -133,9 +133,9 @@ public class UserActivityLogController {
}
private void checkBaseReadPrivilege(final Long institutionId) {
this.authorizationGrantService.checkPrivilege(
EntityType.USER_ACTIVITY_LOG,
this.authorization.check(
PrivilegeType.READ_ONLY,
EntityType.USER_ACTIVITY_LOG,
institutionId);
}

View file

@ -11,7 +11,6 @@ package ch.ethz.seb.sebserver.webservice.servicelayer.authorization;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.security.Principal;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
@ -20,7 +19,6 @@ import java.util.stream.Collectors;
import org.joda.time.DateTimeZone;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.Mockito;
import ch.ethz.seb.sebserver.gbl.authorization.PrivilegeType;
@ -28,45 +26,42 @@ import ch.ethz.seb.sebserver.gbl.model.EntityType;
import ch.ethz.seb.sebserver.gbl.model.user.UserInfo;
import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
public class AuthorizationGrantServiceTest {
@Mock
private Principal principal;
public class AuthorizationServiceTest {
@Test
public void testInstitutionGrantForSEB_SERVER_ADMIN() {
final AuthorizationGrantServiceImpl service = getTestServiceWithUserWithRoles(UserRole.SEB_SERVER_ADMIN);
final AuthorizationServiceImpl service = getTestServiceWithUserWithRoles(UserRole.SEB_SERVER_ADMIN);
assertTrue(service.hasBasePrivilege(EntityType.INSTITUTION, PrivilegeType.READ_ONLY, this.principal));
assertTrue(service.hasBasePrivilege(EntityType.INSTITUTION, PrivilegeType.MODIFY, this.principal));
assertTrue(service.hasBasePrivilege(EntityType.INSTITUTION, PrivilegeType.WRITE, this.principal));
assertTrue(service.hasPrivilege(PrivilegeType.READ_ONLY, EntityType.INSTITUTION));
assertTrue(service.hasPrivilege(PrivilegeType.MODIFY, EntityType.INSTITUTION));
assertTrue(service.hasPrivilege(PrivilegeType.WRITE, EntityType.INSTITUTION));
final GrantEntity institution = entityOf(EntityType.INSTITUTION, 2L, "");
assertTrue(service.hasGrant(institution, PrivilegeType.READ_ONLY, this.principal));
assertTrue(service.hasGrant(institution, PrivilegeType.MODIFY, this.principal));
assertTrue(service.hasGrant(institution, PrivilegeType.WRITE, this.principal));
assertTrue(service.hasReadonlyPrivilege(institution));
assertTrue(service.hasModifyPrivilege(institution));
assertTrue(service.hasWritePrivilege(institution));
}
@Test
public void testInstitutionGrantsForINSTITUTIONAL_ADMIN() {
final AuthorizationGrantServiceImpl service = getTestServiceWithUserWithRoles(UserRole.INSTITUTIONAL_ADMIN);
final AuthorizationServiceImpl service = getTestServiceWithUserWithRoles(UserRole.INSTITUTIONAL_ADMIN);
assertFalse(service.hasBasePrivilege(EntityType.INSTITUTION, PrivilegeType.READ_ONLY, this.principal));
assertFalse(service.hasBasePrivilege(EntityType.INSTITUTION, PrivilegeType.MODIFY, this.principal));
assertFalse(service.hasBasePrivilege(EntityType.INSTITUTION, PrivilegeType.WRITE, this.principal));
assertFalse(service.hasPrivilege(PrivilegeType.READ_ONLY, EntityType.INSTITUTION));
assertFalse(service.hasPrivilege(PrivilegeType.MODIFY, EntityType.INSTITUTION));
assertFalse(service.hasPrivilege(PrivilegeType.WRITE, EntityType.INSTITUTION));
final GrantEntity ownInstitution = entityOf(EntityType.INSTITUTION, 1L, "");
assertTrue(service.hasGrant(ownInstitution, PrivilegeType.READ_ONLY, this.principal));
assertTrue(service.hasGrant(ownInstitution, PrivilegeType.MODIFY, this.principal));
assertFalse(service.hasGrant(ownInstitution, PrivilegeType.WRITE, this.principal));
assertTrue(service.hasReadonlyPrivilege(ownInstitution));
assertTrue(service.hasModifyPrivilege(ownInstitution));
assertFalse(service.hasWritePrivilege(ownInstitution));
final GrantEntity otherInstitution = entityOf(EntityType.INSTITUTION, 2L, "");
assertFalse(service.hasGrant(otherInstitution, PrivilegeType.READ_ONLY, this.principal));
assertFalse(service.hasGrant(otherInstitution, PrivilegeType.MODIFY, this.principal));
assertFalse(service.hasGrant(otherInstitution, PrivilegeType.WRITE, this.principal));
assertFalse(service.hasReadonlyPrivilege(otherInstitution));
assertFalse(service.hasModifyPrivilege(otherInstitution));
assertFalse(service.hasWritePrivilege(otherInstitution));
}
private SEBServerUser getUser(final UserRole... roles) {
@ -109,13 +104,12 @@ public class AuthorizationGrantServiceTest {
};
}
private AuthorizationGrantServiceImpl getTestServiceWithUserWithRoles(final UserRole... roles) {
private AuthorizationServiceImpl getTestServiceWithUserWithRoles(final UserRole... roles) {
final SEBServerUser user = getUser(roles);
final UserServiceImpl currentUserServiceMock = Mockito.mock(UserServiceImpl.class);
Mockito.when(currentUserServiceMock.extractFromPrincipal(this.principal)).thenReturn(user);
Mockito.when(currentUserServiceMock.getCurrentUser()).thenReturn(user);
final AuthorizationGrantServiceImpl authorizationGrantService = new AuthorizationGrantServiceImpl(
Collections.emptyList(),
final AuthorizationServiceImpl authorizationGrantService = new AuthorizationServiceImpl(
currentUserServiceMock);
authorizationGrantService.init();
return authorizationGrantService;