more tests

This commit is contained in:
anhefti 2019-04-02 12:03:56 +02:00
parent 462546a30a
commit f403fa5eb1
16 changed files with 587 additions and 53 deletions

View file

@ -12,8 +12,8 @@ package ch.ethz.seb.sebserver.gbl.authorization;
public enum PrivilegeType {
/** No privilege type at all (placeholder) */
NONE,
/** The read-only privilege type for read access */
READ_ONLY,
/** The read privilege type for read access */
READ,
/** The modify privilege type includes read-only type privilege plus privilege for editing right but without create
* and delete
* rights */
@ -24,8 +24,8 @@ public enum PrivilegeType {
/** Use this to check implicit privilege.
*
* Implicit in this case means: if the privilegeType is of type PrivilegeType.WRITE,
* PrivilegeType.MODIFY and PrivilegeType.READ_ONLY are implicitly included.
* If the privilegeType is of type PrivilegeType.MODIFY, the PrivilegeType.READ_ONLY are implicitly included
* PrivilegeType.MODIFY and PrivilegeType.READ are implicitly included.
* If the privilegeType is of type PrivilegeType.MODIFY, the PrivilegeType.READ are implicitly included
* and so on.
*
* @param type the PrivilegeType
@ -38,12 +38,12 @@ public enum PrivilegeType {
switch (this) {
case NONE:
return false;
case READ_ONLY:
return type == READ_ONLY;
case READ:
return type == READ;
case MODIFY:
return type == READ_ONLY || type == MODIFY;
return type == READ || type == MODIFY;
case WRITE:
return type == READ_ONLY || type == MODIFY || type == WRITE;
return type == READ || type == MODIFY || type == WRITE;
default:
return false;
}

View file

@ -108,7 +108,7 @@ public class ActivitiesPane implements TemplateComposer {
// User Account
// if current user has base or institutional read privilege for User Account, show list
if (this.currentUser.hasInstitutionalPrivilege(PrivilegeType.READ_ONLY, EntityType.USER)) {
if (this.currentUser.hasInstitutionalPrivilege(PrivilegeType.READ, EntityType.USER)) {
final TreeItem userAccounts = this.widgetFactory.treeItemLocalized(
navigation,
ActivityDefinition.USER_ACCOUNT.displayName);
@ -131,7 +131,7 @@ public class ActivitiesPane implements TemplateComposer {
}
// LMS Setup
if (this.currentUser.hasInstitutionalPrivilege(PrivilegeType.READ_ONLY, EntityType.LMS_SETUP)) {
if (this.currentUser.hasInstitutionalPrivilege(PrivilegeType.READ, EntityType.LMS_SETUP)) {
final TreeItem lmsSetup = this.widgetFactory.treeItemLocalized(
navigation,
ActivityDefinition.LMS_SETUP.displayName);
@ -143,7 +143,7 @@ public class ActivitiesPane implements TemplateComposer {
}
// Exam (Quiz Discovery)
if (this.currentUser.hasInstitutionalPrivilege(PrivilegeType.READ_ONLY, EntityType.EXAM)) {
if (this.currentUser.hasInstitutionalPrivilege(PrivilegeType.READ, EntityType.EXAM)) {
// Quiz Discovery
// TODO discussion if this should be visible on Activity Pane or just over the Exam activity and Import action

View file

@ -226,7 +226,7 @@ public class CurrentUser {
*
* @return true on read-only privilege grant on wrapped EntityType */
public boolean r() {
return hasBasePrivilege(PrivilegeType.READ_ONLY, this.entityType);
return hasBasePrivilege(PrivilegeType.READ, this.entityType);
}
/** Checks the base modify privilege grant
@ -247,7 +247,7 @@ public class CurrentUser {
*
* @return true institutional read-only privilege grant on wrapped EntityType */
public boolean ir() {
return hasInstitutionalPrivilege(PrivilegeType.READ_ONLY, this.entityType);
return hasInstitutionalPrivilege(PrivilegeType.READ, this.entityType);
}
/** Checks the institutional modify privilege grant
@ -277,7 +277,7 @@ public class CurrentUser {
*
* @return true on read-only privilege grant for wrapped grantEntity */
public boolean r() {
return hasPrivilege(PrivilegeType.READ_ONLY, this.grantEntity);
return hasPrivilege(PrivilegeType.READ, this.grantEntity);
}
/** Checks the modify privilege grant for wrapped grantEntity

View file

@ -23,7 +23,7 @@ import ch.ethz.seb.sebserver.gbl.util.Result;
*
* 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. */
* has write, modify or even read rights on an entity instance or on an entity type. */
public interface AuthorizationService {
/** Gets the UserService that is bundled within the AuthorizationGrantService
@ -138,7 +138,7 @@ public interface AuthorizationService {
* @param grantEntity Entity instance
* @return true if the current user has read-only grant on given Entity instance or false on deny */
default boolean hasReadonlyGrant(final GrantEntity grantEntity) {
return hasGrant(PrivilegeType.READ_ONLY, grantEntity);
return hasGrant(PrivilegeType.READ, grantEntity);
}
/** Check modify grant for a given Entity instance and current user.
@ -199,14 +199,14 @@ public interface AuthorizationService {
return Result.of(grantEntity);
}
/** Check read-only grant by using corresponding hasGrant(XY) method and throws PermissionDeniedException
/** Check read grant by using corresponding hasGrant(XY) method and throws PermissionDeniedException
* on deny or returns the given grantEntity within a Result on successful grant.
* This is useful to use with a Result based functional chain.
*
* @param entityType the type of the entity to check the given privilege type on
* @param institutionId the institution identifier for institutional privilege grant check */
default <E extends GrantEntity> Result<E> checkReadonly(final E grantEntity) {
return check(PrivilegeType.READ_ONLY, grantEntity);
default <E extends GrantEntity> Result<E> checkRead(final E grantEntity) {
return check(PrivilegeType.READ, grantEntity);
}
/** Check modify grant by using corresponding hasGrant(XY) method and throws PermissionDeniedException

View file

@ -60,9 +60,9 @@ public class AuthorizationServiceImpl implements AuthorizationService {
.andForRole(UserRole.INSTITUTIONAL_ADMIN)
.withInstitutionalPrivilege(PrivilegeType.MODIFY)
.andForRole(UserRole.EXAM_ADMIN)
.withInstitutionalPrivilege(PrivilegeType.READ_ONLY)
.withInstitutionalPrivilege(PrivilegeType.READ)
.andForRole(UserRole.EXAM_SUPPORTER)
.withInstitutionalPrivilege(PrivilegeType.READ_ONLY)
.withInstitutionalPrivilege(PrivilegeType.READ)
.create();
// grants for user account
@ -88,39 +88,39 @@ public class AuthorizationServiceImpl implements AuthorizationService {
// grants for lms setup
addPrivilege(EntityType.LMS_SETUP)
.forRole(UserRole.SEB_SERVER_ADMIN)
.withBasePrivilege(PrivilegeType.READ_ONLY)
.withBasePrivilege(PrivilegeType.READ)
.andForRole(UserRole.INSTITUTIONAL_ADMIN)
.withInstitutionalPrivilege(PrivilegeType.WRITE)
.andForRole(UserRole.EXAM_ADMIN)
.withInstitutionalPrivilege(PrivilegeType.MODIFY)
.andForRole(UserRole.EXAM_SUPPORTER)
.withInstitutionalPrivilege(PrivilegeType.READ_ONLY)
.withInstitutionalPrivilege(PrivilegeType.READ)
.create();
// grants for exam
addPrivilege(EntityType.EXAM)
.forRole(UserRole.SEB_SERVER_ADMIN)
.withBasePrivilege(PrivilegeType.READ_ONLY)
.withBasePrivilege(PrivilegeType.READ)
.andForRole(UserRole.INSTITUTIONAL_ADMIN)
.withInstitutionalPrivilege(PrivilegeType.READ_ONLY)
.withInstitutionalPrivilege(PrivilegeType.READ)
.andForRole(UserRole.EXAM_ADMIN)
.withInstitutionalPrivilege(PrivilegeType.MODIFY)
.withOwnerPrivilege(PrivilegeType.WRITE)
.andForRole(UserRole.EXAM_SUPPORTER)
.withInstitutionalPrivilege(PrivilegeType.READ_ONLY)
.withInstitutionalPrivilege(PrivilegeType.READ)
.create();
// grants for indicators
addPrivilege(EntityType.INDICATOR)
.forRole(UserRole.SEB_SERVER_ADMIN)
.withBasePrivilege(PrivilegeType.READ_ONLY)
.withBasePrivilege(PrivilegeType.READ)
.andForRole(UserRole.INSTITUTIONAL_ADMIN)
.withInstitutionalPrivilege(PrivilegeType.READ_ONLY)
.withInstitutionalPrivilege(PrivilegeType.READ)
.andForRole(UserRole.EXAM_ADMIN)
.withInstitutionalPrivilege(PrivilegeType.MODIFY)
.withOwnerPrivilege(PrivilegeType.WRITE)
.andForRole(UserRole.EXAM_SUPPORTER)
.withInstitutionalPrivilege(PrivilegeType.READ_ONLY)
.withInstitutionalPrivilege(PrivilegeType.READ)
.create();
// TODO other entities
@ -128,9 +128,9 @@ public class AuthorizationServiceImpl implements AuthorizationService {
// grants for user activity logs
addPrivilege(EntityType.USER_ACTIVITY_LOG)
.forRole(UserRole.SEB_SERVER_ADMIN)
.withBasePrivilege(PrivilegeType.READ_ONLY)
.withBasePrivilege(PrivilegeType.READ)
.andForRole(UserRole.INSTITUTIONAL_ADMIN)
.withInstitutionalPrivilege(PrivilegeType.READ_ONLY)
.withInstitutionalPrivilege(PrivilegeType.READ)
.create();
}

View file

@ -135,7 +135,7 @@ public abstract class EntityController<T extends GrantEntity, M extends GrantEnt
// if current user has no read access for specified entity type within other institution
// then the current users institutionId is put as a SQL filter criteria attribute to extends query performance
if (!this.authorization.hasGrant(PrivilegeType.READ_ONLY, this.entityDAO.entityType())) {
if (!this.authorization.hasGrant(PrivilegeType.READ, this.entityDAO.entityType())) {
filterMap.putIfAbsent(API.PARAM_INSTITUTION_ID, String.valueOf(institutionId));
}
@ -170,7 +170,7 @@ public abstract class EntityController<T extends GrantEntity, M extends GrantEnt
// if current user has no read access for specified entity type within other institution then its own institution,
// then the current users institutionId is put as a SQL filter criteria attribute to extends query performance
if (!this.authorization.hasGrant(PrivilegeType.READ_ONLY, this.entityDAO.entityType())) {
if (!this.authorization.hasGrant(PrivilegeType.READ, this.entityDAO.entityType())) {
filterMap.putIfAbsent(API.PARAM_INSTITUTION_ID, String.valueOf(institutionId));
}
@ -196,7 +196,7 @@ public abstract class EntityController<T extends GrantEntity, M extends GrantEnt
this.entityDAO
.byModelId(modelId)
.flatMap(this.authorization::checkReadonly);
.flatMap(this.authorization::checkRead);
final BulkAction bulkAction = new BulkAction(
bulkActionType,
@ -220,7 +220,7 @@ public abstract class EntityController<T extends GrantEntity, M extends GrantEnt
return this.entityDAO
.byModelId(modelId)
.flatMap(this.authorization::checkReadonly)
.flatMap(this.authorization::checkRead)
.getOrThrow();
}
@ -354,7 +354,7 @@ public abstract class EntityController<T extends GrantEntity, M extends GrantEnt
protected void checkReadPrivilege(final Long institutionId) {
this.authorization.check(
PrivilegeType.READ_ONLY,
PrivilegeType.READ,
this.entityDAO.entityType(),
institutionId);
}

View file

@ -11,25 +11,33 @@ package ch.ethz.seb.sebserver.webservice.weblayer.api;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;
import org.mybatis.dynamic.sql.SqlTable;
import org.springframework.http.MediaType;
import org.springframework.util.MultiValueMap;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import ch.ethz.seb.sebserver.gbl.api.API;
import ch.ethz.seb.sebserver.gbl.api.APIMessage;
import ch.ethz.seb.sebserver.gbl.api.APIMessage.APIMessageException;
import ch.ethz.seb.sebserver.gbl.api.EntityType;
import ch.ethz.seb.sebserver.gbl.api.POSTMapper;
import ch.ethz.seb.sebserver.gbl.authorization.PrivilegeType;
import ch.ethz.seb.sebserver.gbl.model.Domain;
import ch.ethz.seb.sebserver.gbl.model.Domain.EXAM;
import ch.ethz.seb.sebserver.gbl.model.Page;
import ch.ethz.seb.sebserver.gbl.model.exam.Exam;
import ch.ethz.seb.sebserver.gbl.model.exam.QuizData;
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;
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;
@ -40,6 +48,7 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkActionServic
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ExamDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.FilterMap;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserActivityLogDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPIService;
import ch.ethz.seb.sebserver.webservice.servicelayer.validation.BeanValidationService;
@ -49,6 +58,7 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.validation.BeanValidationSe
public class ExamAdministrationController extends ActivatableEntityController<Exam, Exam> {
private final ExamDAO examDAO;
private final UserDAO userDAO;
private final LmsAPIService lmsAPIService;
public ExamAdministrationController(
@ -58,7 +68,8 @@ public class ExamAdministrationController extends ActivatableEntityController<Ex
final PaginationService paginationService,
final BulkActionService bulkActionService,
final BeanValidationService beanValidationService,
final LmsAPIService lmsAPIService) {
final LmsAPIService lmsAPIService,
final UserDAO userDAO) {
super(authorization,
bulkActionService,
@ -68,6 +79,7 @@ public class ExamAdministrationController extends ActivatableEntityController<Ex
beanValidationService);
this.examDAO = examDAO;
this.userDAO = userDAO;
this.lmsAPIService = lmsAPIService;
}
@ -104,7 +116,7 @@ public class ExamAdministrationController extends ActivatableEntityController<Ex
} else {
this.authorization.check(
PrivilegeType.READ_ONLY,
PrivilegeType.READ,
EntityType.EXAM,
institutionId);
@ -146,9 +158,41 @@ public class ExamAdministrationController extends ActivatableEntityController<Ex
return this.lmsAPIService
.getLmsAPITemplate(lmsSetupId)
.map(template -> {
this.authorization.checkRead(template.lmsSetup());
return template;
})
.flatMap(template -> template.getQuiz(quizId))
.map(quiz -> new Exam(null, quiz, postParams))
.getOrThrow();
}
@Override
protected Result<Exam> validForSave(final Exam entity) {
return super.validForSave(entity)
.map(this::checkExamSupporterRole);
}
private Exam checkExamSupporterRole(final Exam exam) {
final Set<String> examSupporter = this.userDAO.all(
this.authorization.getUserService().getCurrentUser().getUserInfo().institutionId,
true)
.map(users -> users.stream()
.filter(user -> user.getRoles().contains(UserRole.EXAM_SUPPORTER.name()))
.map(user -> user.uuid)
.collect(Collectors.toSet()))
.getOrThrow();
for (final String supporterUUID : exam.getSupporter()) {
if (!examSupporter.contains(supporterUUID)) {
throw new APIMessageException(APIMessage.fieldValidationError(
new FieldError(
Domain.EXAM.TYPE_NAME,
Domain.EXAM.ATTR_SUPPORTER,
"exam:supporter:grantDenied:" + supporterUUID)));
}
}
return exam;
}
}

View file

@ -81,7 +81,7 @@ public class QuizController {
@RequestParam final MultiValueMap<String, String> allRequestParams) {
this.authorization.check(
PrivilegeType.READ_ONLY,
PrivilegeType.READ,
EntityType.EXAM,
institutionId);
@ -115,7 +115,7 @@ public class QuizController {
.getLmsAPITemplate(lmsSetupId)
.getOrThrow()
.getQuiz(modelId)
.flatMap(this.authorization::checkReadonly)
.flatMap(this.authorization::checkRead)
.getOrThrow();
}

View file

@ -134,7 +134,7 @@ public class UserActivityLogController {
private void checkBaseReadPrivilege(final Long institutionId) {
this.authorization.check(
PrivilegeType.READ_ONLY,
PrivilegeType.READ,
EntityType.USER_ACTIVITY_LOG,
institutionId);
}

View file

@ -89,7 +89,7 @@ sebserver.institution.action.export.sebconfig=SEB Client Config
sebserver.institution.info.pleaseSelect=Please Select an Institution first.
sebserver.institution.form.title.new=New Institution
sebserver.institution.form.title=Institution : {0}
sebserver.institution.form.title=Institution
sebserver.institution.form.name=Name
sebserver.institution.form.urlSuffix=URL Suffix

View file

@ -0,0 +1,295 @@
################################
# Overall
################################
sebserver.overall.version=SEB Server Version : {0}
sebserver.overall.imprint=Imprint
sebserver.overall.about=About
sebserver.overall.message.leave.without.save=You have unsaved changes!\nAre you sure you want to leave the page?\The changes will be lost.
sebserver.overall.upload=Please Select
sebserver.overall.action.modify.cancel=Cancel
sebserver.overall.action.modify.cancel.confirm=Are you sure you want to cancel? Modifications will be lost.
sebserver.overall.action.filter=Apply filter
sebserver.overall.action.filter.clear=Clear filter criteria
sebserver.overall.action.ok=OK
sebserver.overall.action.cancel=Cancel
sebserver.overall.action.close=Close
sebserver.overall.action.goAwayFromEditPageConfirm=Are you sure you want to leave this page? Unsaved data will be lost.
sebserver.overall.action.category.varia=Varia
################################
# Form validation and messages
################################
sebserver.form.validation.error.title=Form data validation failed
sebserver.form.validation.error.message=There is missing or incorrect form data.
sebserver.form.validation.fieldError.size=The size must be between {3} and {4}
sebserver.form.validation.fieldError.name=The Name is mandatory and must have a size between {3} and {4} character
sebserver.form.validation.fieldError.urlSuffix=The URL Suffix must have a size between {3} and {4} character
sebserver.form.validation.fieldError.notNull=This field is mandatory
sebserver.form.validation.fieldError.username.notunique=This Username is already in use. Please choose another one.
sebserver.form.validation.fieldError.password.wrong=The old password is wrong
sebserver.form.validation.fieldError.password.mismatch=The re-typed password doesn't match the new password
sebserver.form.validation.fieldError.invalidURL=The input does not match the URL pattern.
sebserver.form.validation.fieldError.exists=This name already exists. Please choose another one.
sebserver.error.unexpected=Unexpected Error
sebserver.page.message=Information
sebserver.dialog.confirm.title=Confirmation
sebserver.dialog.confirm.deactivation=Note that there are {0} other entities that belong to this entity.<br/>These will also be deactivated by deactivating this entity.<br/><br/>Are You sure you want to deactivate this entity?
sebserver.dialog.confirm.deactivation.noDependencies=Are You sure you want to deactivate?
################################
# Login Page
################################
sebserver.login.username=User Name
sebserver.login.pwd=Password
sebserver.login.login=Sign In
sebserver.login.failed.title=Login failed
sebserver.login.failed.message=Access denied: wrong username or password
sebserver.logout=Sign out
sebserver.logout.success.message=You have been successfully signed out.
sebserver.login.password.change=Information
sebserver.login.password.change.success=The password was successfully changed. Please sign in with your new password
################################
# Main Page
################################
sebserver.logout=Logout
sebserver.mainpage.maximize.tooltip=Maximize
sebserver.mainpage.minimize.tooltip=Minimize
sebserver.activitiespane.title=Administration
sebserver.actionpane.title=Actions
################################
# Institution
################################
sebserver.institution.list.actions=Selected Institution
sebserver.institution.list.empty=No institution has been found. Please adapt the filter or create a new institution
sebserver.institution.list.title=Institutions
sebserver.institution.list.column.name=Name
sebserver.institution.list.column.urlSuffix=URL Suffix
sebserver.institution.list.column.active=Active
sebserver.institution.action.list=Institution
sebserver.institution.action.form=Institution
sebserver.institution.action.new=Add Institution
sebserver.institution.action.list.view=View Institution
sebserver.institution.action.list.modify=Edit Institution
sebserver.institution.action.modify=Edit
sebserver.institution.action.save=Save Institution
sebserver.institution.action.activate=Activate
sebserver.institution.action.deactivate=Deactivate
sebserver.institution.action.delete=Delete Institution
sebserver.institution.action.export.sebconfig=SEB Client Config
sebserver.institution.info.pleaseSelect=Please select an institution first.
sebserver.institution.form.title.new=Add Institution
sebserver.institution.form.title=Institution
sebserver.institution.form.name=Name
sebserver.institution.form.urlSuffix=URL Suffix
sebserver.institution.form.logoImage=Logo Image
################################
# User Account
################################
sebserver.useraccount.list.actions=Selected User Account
sebserver.useraccount.role.SEB_SERVER_ADMIN=SEB Server Administrator
sebserver.useraccount.role.INSTITUTIONAL_ADMIN=Institutional Administrator
sebserver.useraccount.role.EXAM_ADMIN=Exam Administrator
sebserver.useraccount.role.EXAM_SUPPORTER=Exam Supporter
sebserver.useraccount.list.empty=No user account has been found. Please adapt the filter or create a new user account
sebserver.useraccount.list.title=User Accounts
sebserver.useraccount.list.column.institution=Institution
sebserver.useraccount.list.column.name=Name
sebserver.useraccount.list.column.username=User Name
sebserver.useraccount.list.column.email=Mail
sebserver.useraccount.list.column.language=Language
sebserver.useraccount.list.column.active=Active
sebserver.useraccount.action.list=User Account
sebserver.useraccount.action.form=User Account of {0}
sebserver.useraccount.action.new=Add User Account
sebserver.useraccount.action.view=View User Account
sebserver.useraccount.action.list.modify=Edit User Account
sebserver.useraccount.action.modify=Edit
sebserver.useraccount.action.save=Save User Account
sebserver.useraccount.action.activate=Activate
sebserver.useraccount.action.deactivate=Deactivate
sebserver.useraccount.action.delete=Delete User Account
sebserver.useraccount.action.change.password=Change Password
sebserver.useraccount.action.change.password.save=Save New Password
sebserver.useraccount.info.pleaseSelect=Please select a user account first.
sebserver.useraccount.form.title=User Account
sebserver.useraccount.form.title.new=Add User Account
sebserver.useraccount.form.institution=Institution
sebserver.useraccount.form.name=Name
sebserver.useraccount.form.username=Username
sebserver.useraccount.form.mail=E-Mail
sebserver.useraccount.form.language=Language
sebserver.useraccount.form.timezone=Time Zone
sebserver.useraccount.form.roles=User Roles
sebserver.useraccount.form.password=Password
sebserver.useraccount.form.password.confirm=Confirm Password
sebserver.useraccount.form.pwchange.title=Change Password : {0}
sebserver.useraccount.form.password=Password
sebserver.useraccount.form.password.new=New Password
sebserver.useraccount.form.password.new.confirm=Confirm New Password
################################
# LMS Setup
################################
sebserver.lmssetup.type.MOCKUP=Mock-up
sebserver.lmssetup.type.MOODLE=Moodle
sebserver.lmssetup.type.OPEN_EDX=Open edX
sebserver.lmssetup.list.actions=Selected LMS Setup
sebserver.lmssetup.list.empty=No LMS Setup has been found. Please adapt the filter or create a new LMS Setup
sebserver.lmssetup.list.title=Learning Management System Setups
sebserver.lmssetup.list.column.institution=Institution
sebserver.lmssetup.list.column.name=Name
sebserver.lmssetup.list.column.type=LMS Type
sebserver.lmssetup.list.column.active=Active
sebserver.lmssetup.action.list=LMS Setup
sebserver.lmssetup.action.form=LMS Setup
sebserver.lmssetup.action.new=Add LMS Setup
sebserver.lmssetup.action.list.view=View LMS Setup
sebserver.lmssetup.action.list.modify=Edit LMS Setup
sebserver.lmssetup.action.modify=Edit
sebserver.lmssetup.action.test=Test Setup
sebserver.lmssetup.action.test.ok=Successfully connected to the course API
sebserver.lmssetup.action.test.tokenRequestError=The API access was denied: {0}
sebserver.lmssetup.action.test.quizRequestError=Unable to request courses or quizzes from the course API of the LMS. {0}
sebserver.lmssetup.action.test.missingParameter=There is one or more missing connection parameter.<br/>Please check the connection parameter for this LMS Setup
sebserver.lmssetup.action.test.unknownError=An unexpected error happened while trying to connect to the LMS course API. {0}
sebserver.lmssetup.action.save=Save LMS Setup
sebserver.lmssetup.action.activate=Activate
sebserver.lmssetup.action.deactivate=Deactivate
sebserver.lmssetup.action.delete=Delete LMS Setup
sebserver.lmssetup.info.pleaseSelect=Please Select a LMS Setup first
sebserver.lmssetup.form.title=Learning Management System Setup
sebserver.lmssetup.form.title.new=Add Learning Management System Setup
sebserver.lmssetup.form.institution=Institution
sebserver.lmssetup.form.name=Name
sebserver.lmssetup.form.type=Type
sebserver.lmssetup.form.clientname.seb=SEB Auth. Name
sebserver.lmssetup.form.secret.seb=SEB Auth. Password
sebserver.lmssetup.form.url=LMS Server Address
sebserver.lmssetup.form.clientname.lms=LMS Server Username
sebserver.lmssetup.form.secret.lms=LMS Server Password
################################
# Quiz Discovery
################################
sebserver.quizdiscovery.list.actions=Selected Quiz
sebserver.quizdiscovery.list.title=Quizzes
sebserver.quizdiscovery.list.empty=No Quiz has been found. Please adapt the filter or create a new LMS Setup
sebserver.quizdiscovery.list.column.institution=Institution
sebserver.quizdiscovery.list.column.lmssetup=LMS
sebserver.quizdiscovery.list.column.name=Name
sebserver.quizdiscovery.list.column.starttime=Start Time {0}
sebserver.quizdiscovery.list.column.endtime=End Time {0}
sebserver.quizdiscovery.info.pleaseSelect=Please Select a Quiz first
sebserver.quizdiscovery.action.list=Quiz Discovery
sebserver.quizdiscovery.action.import=Import as Exam
sebserver.quizdiscovery.action.details=Show Details
sebserver.quizdiscovery.quiz.details.title=Quiz Details
sebserver.quizdiscovery.quiz.details.lms=LMS
sebserver.quizdiscovery.quiz.details.name=Name
sebserver.quizdiscovery.quiz.details.description=Description
sebserver.quizdiscovery.quiz.details.starttime=Start Time
sebserver.quizdiscovery.quiz.details.endtime=End Time
sebserver.quizdiscovery.quiz.details.url=Start URL
################################
# Exam
################################
sebserver.exam.list.actions=Selected Exam
sebserver.exam.list.title=Exams
sebserver.exam.list.column.institution=Institution
sebserver.exam.list.column.lmssetup=LMS
sebserver.exam.list.column.name=Name
sebserver.exam.list.column.starttime=Start Time {0}
sebserver.exam.list.column.type=Type
sebserver.exam.list.empty=No Exam has been found. Please adapt the filter or import one from Quiz
sebserver.exam.action.list=Exam
sebserver.exam.action.list.view=View Exam
sebserver.exam.action.list.modify=Edit Exam
sebserver.exam.action.modify=Edit Exam
sebserver.exam.action.import=Import From Quizzes
sebserver.exam.action.save=Save Exam
sebserver.exam.action.activate=Activate Exam
sebserver.exam.action.deactivate=Deactivate Exam
sebserver.exam.info.pleaseSelect=Please Select an Exam first
sebserver.exam.form.title.import=New Exam
sebserver.exam.form.title=Exam
sebserver.exam.form.lmssetup=LMS Setup
sebserver.exam.form.quizid=Quiz Identifier
sebserver.exam.form.name=Name
sebserver.exam.form.description=Description
sebserver.exam.form.starttime=Start Time
sebserver.exam.form.endtime=End Time
sebserver.exam.form.status=Status
sebserver.exam.form.type=Exam Type
sebserver.exam.form.supporter=Exam Supporter
sebserver.exam.type.UNDEFINED=Not Defined
sebserver.exam.type.MANAGED=Managed Devices
sebserver.exam.type.BYOD=Bring Your Own Device
sebserver.exam.type.VDI=VDI (Virtual Desktop Infrastructure)
sebserver.exam.indicator.list.actions=Selected Indicator
sebserver.exam.indicator.list.title=Indicators
sebserver.exam.indicator.list.column.type=Type
sebserver.exam.indicator.list.column.name=Name
sebserver.exam.indicator.list.column.thresholds=Thresholds
sebserver.exam.indicator.list.empty=There is currently no indicator defined for this exam. Please create a new one
sebserver.exam.indicator.list.pleaseSelect=Please select an indicator first
sebserver.exam.indicator.type.LAST_PING=Last Ping
sebserver.exam.indicator.type.ERROR_COUNT=Error Count
sebserver.exam.indicator.info.pleaseSelect=Please select an indicator first
sebserver.exam.indicator.action.list.new=New Indicator
sebserver.exam.indicator.action.list.modify=Edit
sebserver.exam.indicator.action.list.delete=Delete
sebserver.exam.indicator.action.save=Save
sebserver.exam.indicator.form.title=Indicator
sebserver.exam.indicator.form.title.new=Add Indicator
sebserver.exam.indicator.form.exam=Exam
sebserver.exam.indicator.form.name=Name
sebserver.exam.indicator.form.type=Type
sebserver.exam.indicator.form.color=Default Color
sebserver.exam.indicator.form.thresholds=Thresholds
sebserver.exam.indicator.thresholds.list.title=Thresholds
sebserver.exam.indicator.thresholds.list.value=Value
sebserver.exam.indicator.thresholds.list.color=Color
sebserver.exam.indicator.thresholds.list.add=Add Threshold
sebserver.exam.indicator.thresholds.list.remove=Delete Threshold

View file

@ -47,7 +47,7 @@ public class CurrentUserTest extends GuiIntegrationTest {
// login as SEB Administrator
authorizationContextHolder.getAuthorizationContext().login("admin", "admin");
assertTrue(currentUser.hasBasePrivilege(PrivilegeType.READ_ONLY, EntityType.INSTITUTION));
assertTrue(currentUser.hasBasePrivilege(PrivilegeType.READ, EntityType.INSTITUTION));
assertTrue(currentUser.hasPrivilege(PrivilegeType.WRITE, currentUser.get()));
assertTrue(currentUser.hasBasePrivilege(PrivilegeType.WRITE, EntityType.INSTITUTION));
assertTrue(currentUser.hasInstitutionalPrivilege(PrivilegeType.MODIFY, EntityType.INSTITUTION));

View file

@ -0,0 +1,105 @@
/*
* Copyright (c) 2019 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.integration.api.admin;
import static org.junit.Assert.*;
import java.util.Arrays;
import java.util.List;
import org.junit.Test;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.test.context.jdbc.Sql;
import com.fasterxml.jackson.core.type.TypeReference;
import ch.ethz.seb.sebserver.gbl.api.API;
import ch.ethz.seb.sebserver.gbl.api.APIMessage;
import ch.ethz.seb.sebserver.gbl.model.exam.Exam;
import ch.ethz.seb.sebserver.gbl.model.exam.Exam.ExamType;
@Sql(scripts = { "classpath:schema-test.sql", "classpath:data-test.sql" })
public class ExamAPITest extends AdministrationAPIIntegrationTester {
@Test
public void testModify() throws Exception {
final String sebAdminAccess = getSebAdminAccess();
final Exam exam = ExamImportTest.createImportedExamFromLmsSetupMock(
this,
sebAdminAccess,
sebAdminAccess,
"LmsSetupMock",
"quiz2",
ExamType.MANAGED);
assertNotNull(exam);
assertEquals("quiz2", exam.getExternalId());
assertEquals(ExamType.MANAGED, exam.getType());
assertTrue(exam.getSupporter().isEmpty());
// add ExamSupporter
final Exam newExam = new RestAPITestHelper()
.withAccessToken(sebAdminAccess)
.withPath(API.EXAM_ADMINISTRATION_ENDPOINT)
.withMethod(HttpMethod.PUT)
.withBodyJson(new Exam(
exam.id,
exam.institutionId,
exam.lmsSetupId,
exam.externalId,
exam.name,
exam.description,
exam.startTime,
exam.endTime,
exam.startURL,
exam.type,
exam.quitPassword,
exam.owner,
Arrays.asList("user5"),
false))
.withExpectedStatus(HttpStatus.OK)
.getAsObject(new TypeReference<Exam>() {
});
assertFalse(newExam.getSupporter().isEmpty());
assertTrue(newExam.getSupporter().size() == 1);
assertEquals("user5", newExam.getSupporter().iterator().next());
// try to add a user as exam supporter with no exam support role should not be possible
final List<APIMessage> error = new RestAPITestHelper()
.withAccessToken(sebAdminAccess)
.withPath(API.EXAM_ADMINISTRATION_ENDPOINT)
.withMethod(HttpMethod.PUT)
.withBodyJson(new Exam(
exam.id,
exam.institutionId,
exam.lmsSetupId,
exam.externalId,
exam.name,
exam.description,
exam.startTime,
exam.endTime,
exam.startURL,
exam.type,
exam.quitPassword,
exam.owner,
Arrays.asList("user2"),
false))
.withExpectedStatus(HttpStatus.BAD_REQUEST)
.getAsObject(new TypeReference<List<APIMessage>>() {
});
assertNotNull(error);
assertTrue(error.size() == 1);
final APIMessage error1 = error.iterator().next();
assertEquals("[exam, supporter, grantDenied, user2]", String.valueOf(error1.attributes));
}
}

View file

@ -8,8 +8,7 @@
package ch.ethz.seb.sebserver.webservice.integration.api.admin;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.*;
import org.junit.Test;
import org.springframework.http.HttpMethod;
@ -19,7 +18,9 @@ import org.springframework.test.context.jdbc.Sql;
import com.fasterxml.jackson.core.type.TypeReference;
import ch.ethz.seb.sebserver.gbl.api.API;
import ch.ethz.seb.sebserver.gbl.model.Domain;
import ch.ethz.seb.sebserver.gbl.model.exam.Exam;
import ch.ethz.seb.sebserver.gbl.model.exam.Exam.ExamType;
import ch.ethz.seb.sebserver.gbl.model.exam.QuizData;
import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup;
@ -27,9 +28,9 @@ import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup;
public class ExamImportTest extends AdministrationAPIIntegrationTester {
@Test
public void testImportFromQuizz() throws Exception {
public void testImportFromQuiz() throws Exception {
// create new active LmsSetup Mock with seb-admin
final LmsSetup lmsSetup1 = QuizDataTest.createLmsSetupMockWith(
final LmsSetup lmsSetup1 = QuizDataTest.createLmsSetupMock(
this,
getSebAdminAccess(),
"new LmsSetup 1",
@ -49,6 +50,95 @@ public class ExamImportTest extends AdministrationAPIIntegrationTester {
assertNotNull(exam);
assertEquals("quiz1", exam.getExternalId());
assertEquals(lmsSetup1.id, exam.getLmsSetupId());
assertEquals(ExamType.UNDEFINED, exam.getType());
final Exam exam2 = createImportedExamFromLmsSetupMock(
this,
getSebAdminAccess(),
getSebAdminAccess(),
"LmsSetupMock",
"quiz2",
ExamType.MANAGED);
assertNotNull(exam2);
assertEquals("quiz2", exam2.getExternalId());
assertEquals(ExamType.MANAGED, exam2.getType());
}
@Test
public void testImportFromQuizWithInstitutionalAdmin2() throws Exception {
// Institutional administrators are able to create LMS Setups but not to import quizzes
// as Exams. Only Exam administrators should be allowed to import Exams from quizzes
try {
createImportedExamFromLmsSetupMock(
this,
getAdminInstitution2Access(),
getAdminInstitution2Access(),
"LmsSetupMock",
"quiz2",
ExamType.MANAGED);
fail("AssertionError expected here");
} catch (final AssertionError ae) {
assertEquals("Response status expected:<200> but was:<403>", ae.getMessage());
}
// Only Exam administrators should be allowed to import Exams from quizzes
final Exam exam2 = createImportedExamFromLmsSetupMock(
this,
getAdminInstitution2Access(),
getExamAdmin1(), // this exam administrator is on Institution 2
"LmsSetupMock",
"quiz2",
ExamType.MANAGED);
assertNotNull(exam2);
assertEquals("quiz2", exam2.getExternalId());
assertEquals(ExamType.MANAGED, exam2.getType());
}
@Test
public void testImportFromQuizWithInstitutional() throws Exception {
// and creation between different institutions should also not be possible
try {
createImportedExamFromLmsSetupMock(
this,
getAdminInstitution1Access(),
getExamAdmin1(), // this exam administrator is on Institution 2
"LmsSetupMock",
"quiz2",
ExamType.MANAGED);
fail("AssertionError expected here");
} catch (final AssertionError ae) {
assertEquals("Response status expected:<200> but was:<403>", ae.getMessage());
}
}
public static final Exam createImportedExamFromLmsSetupMock(
final AdministrationAPIIntegrationTester tester,
final String tokenForLmsSetupCreation,
final String tokenForExamImport,
final String lmsSetupName,
final String importQuizName,
final ExamType examType) throws Exception {
// create new active LmsSetup Mock with seb-admin
final LmsSetup lmsSetup1 = QuizDataTest.createLmsSetupMock(
tester,
tokenForLmsSetupCreation,
lmsSetupName,
true);
// import Exam from quiz1
return tester.restAPITestHelper()
.withAccessToken(tokenForExamImport)
.withPath(API.EXAM_ADMINISTRATION_ENDPOINT)
.withMethod(HttpMethod.POST)
.withAttribute(QuizData.QUIZ_ATTR_LMS_SETUP_ID, lmsSetup1.getModelId())
.withAttribute(QuizData.QUIZ_ATTR_ID, importQuizName)
.withAttribute(Domain.EXAM.ATTR_TYPE, examType.name())
.withExpectedStatus(HttpStatus.OK)
.getAsObject(new TypeReference<Exam>() {
});
}
}

View file

@ -31,7 +31,7 @@ public class QuizDataTest extends AdministrationAPIIntegrationTester {
@Test
public void testGetInstitutionalQuizPage() throws Exception {
// create new active LmsSetup Mock with seb-admin
final LmsSetup lmsSetup1 = createLmsSetupMockWith(
final LmsSetup lmsSetup1 = createLmsSetupMock(
this,
getSebAdminAccess(),
"new LmsSetup 1",
@ -41,7 +41,7 @@ public class QuizDataTest extends AdministrationAPIIntegrationTester {
assertTrue(lmsSetup1.isActive());
// create new inactive LmsSetup Mock with institution 2 admin
final LmsSetup lmsSetup2 = createLmsSetupMockWith(
final LmsSetup lmsSetup2 = createLmsSetupMock(
this,
getAdminInstitution2Access(),
"new LmsSetup 2",
@ -116,7 +116,7 @@ public class QuizDataTest extends AdministrationAPIIntegrationTester {
@Test
public void testGetQuiz() throws Exception {
// create new active LmsSetup Mock with seb-admin
final LmsSetup lmsSetup = createLmsSetupMockWith(
final LmsSetup lmsSetup = createLmsSetupMock(
this,
getSebAdminAccess(),
"new LmsSetup 1",
@ -135,7 +135,7 @@ public class QuizDataTest extends AdministrationAPIIntegrationTester {
assertNotNull(quizData);
}
public static final LmsSetup createLmsSetupMockWith(
public static final LmsSetup createLmsSetupMock(
final AdministrationAPIIntegrationTester tester,
final String token,
final String name,

View file

@ -32,7 +32,7 @@ public class AuthorizationServiceTest {
public void testInstitutionGrantForSEB_SERVER_ADMIN() {
final AuthorizationServiceImpl service = getTestServiceWithUserWithRoles(UserRole.SEB_SERVER_ADMIN);
assertTrue(service.hasGrant(PrivilegeType.READ_ONLY, EntityType.INSTITUTION));
assertTrue(service.hasGrant(PrivilegeType.READ, EntityType.INSTITUTION));
assertTrue(service.hasGrant(PrivilegeType.MODIFY, EntityType.INSTITUTION));
assertTrue(service.hasGrant(PrivilegeType.WRITE, EntityType.INSTITUTION));
@ -47,7 +47,7 @@ public class AuthorizationServiceTest {
public void testInstitutionGrantsForINSTITUTIONAL_ADMIN() {
final AuthorizationServiceImpl service = getTestServiceWithUserWithRoles(UserRole.INSTITUTIONAL_ADMIN);
assertFalse(service.hasGrant(PrivilegeType.READ_ONLY, EntityType.INSTITUTION));
assertFalse(service.hasGrant(PrivilegeType.READ, EntityType.INSTITUTION));
assertFalse(service.hasGrant(PrivilegeType.MODIFY, EntityType.INSTITUTION));
assertFalse(service.hasGrant(PrivilegeType.WRITE, EntityType.INSTITUTION));