Merge remote-tracking branch 'origin/develop' into develop

This commit is contained in:
niklas3 2013-11-27 15:53:53 +01:00
commit ef76312d12
45 changed files with 1240 additions and 816 deletions
core/src
view/src

@ -20,6 +20,8 @@ public class User extends LazyDeletableDomainObject implements Comparable<User>
private static final long serialVersionUID = 8116476815877870372L;
public static final String USER_ID = "uid";
@Id
@GeneratedValue
private Long id;

@ -16,8 +16,6 @@
*/
package se.su.dsv.scipro.repository;
import se.su.dsv.scipro.data.dataobjects.FileDescription;
import se.su.dsv.scipro.data.dataobjects.Project;
import se.su.dsv.scipro.data.dataobjects.User;
import java.io.InputStream;
@ -41,35 +39,15 @@ public interface FileRepository {
InputStream retrieveFileByPath(String path);
/**
* Retrieve information of files
*
* @param searchPath .
* @return .
*/
List<FileDescription> searchFiles(String searchPath, boolean recursive);
boolean delete(String path);
boolean existsFileByPath(String path);
List<FolderDescription> searchFolders(String path, boolean recursive);
SciProFileStream getFileStream(FileDescription fileDescription);
String formatBytes(float size);
String getProjectRootPath(Long projectId);
void sortFolderDescriptions(List<FolderDescription> list, SortOrder sortOrder);
void sortFileDescriptions(List<FileDescription> list, SortOrder sortOrder);
FileDescription latestUpload(Project project);
String detectMimeTypeFromFileExtension(String fileName);
FileDescription retrieveFileDescriptionByIdentifier(String identifier);
String getIntervalSubFolder(Long id);
}

@ -26,7 +26,6 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Repository;
import se.su.dsv.scipro.data.dataobjects.FileDescription;
import se.su.dsv.scipro.data.dataobjects.Project;
import se.su.dsv.scipro.data.dataobjects.User;
import se.su.dsv.scipro.repository.util.FileStorageException;
import se.su.dsv.scipro.repository.util.RepositoryHelper;
@ -47,11 +46,6 @@ public class FileRepositoryImpl implements FileRepository {
private static final Logger logger = LoggerFactory.getLogger(FileRepositoryImpl.class);
protected static final int STANDARD_INTERVAL_LENGTH = 100;
protected static final String ROOT_PATH = "root/";
protected static final String PROJECTS_PATH = "projects/";
@Inject
private RepositoryManager repositoryManager;
@ -146,76 +140,6 @@ public class FileRepositoryImpl implements FileRepository {
return null;
}
@Override
public FileDescription retrieveFileDescriptionByIdentifier(String identifier) {
try {
Node fileContent = repositoryManager.getDefaultSession().getNodeByIdentifier(identifier);
Node file = fileContent.getParent();
// Node fileContent = repositoryManager.getDefaultSession().getNodeByIdentifier(identifier);
// return fileContent.getProperty("jcr:data").getBinary().getStream();
FileDescription desc = new FileDescription();
desc.setPath(file.getPath());
desc.setName(Text.unescapeIllegalJcrChars(file.getName()));
desc.setTargetLastModified(file.getNode("jcr:content").getProperty("jcr:lastModified").getDate().getTime());
desc.setMimeType(file.getNode("jcr:content").getProperty("jcr:mimeType").getString());
desc.setSize(file.getNode("jcr:content").getProperty("jcr:data").getLength());
desc.setIdentifier(identifier);
if (file.hasProperty("sp:userId")) {
desc.setUserId(file.getProperty("sp:userId").getLong());
}
return desc;
} catch (Exception e) {
throw new FileStorageException("Error while retrieving file description", e);
}
}
public List<FileDescription> searchFiles(String searchPath, boolean recursive) {
List<FileDescription> result = new ArrayList<FileDescription>();
try {
Session session = repositoryManager.getDefaultSession();
if (!session.getRootNode().hasNode(searchPath)) {
return result;
}
Node node = session.getRootNode().getNode(searchPath);
NodeIterator ni = node.getNodes();
while (ni.hasNext()) {
Node file = ni.nextNode();
if (isFile(file)) {
FileDescription desc = new FileDescription();
desc.setPath(file.getPath());
desc.setName(Text.unescapeIllegalJcrChars(file.getName()));
Node fileNode = file.getNode("jcr:content");
desc.setTargetLastModified(fileNode.getProperty("jcr:lastModified").getDate().getTime());
desc.setMimeType(fileNode.getProperty("jcr:mimeType").getString());
desc.setSize(fileNode.getProperty("jcr:data").getLength());
desc.setIdentifier(fileNode.getIdentifier());
if (file.hasProperty("sp:userId")) {
desc.setUserId(file.getProperty("sp:userId").getLong());
}
if (file.hasProperty("sp:isThesisFile")) {
desc.setThesisFile(file.getProperty("sp:isThesisFile").getBoolean());
}
result.add(desc);
}
}
} catch (Exception e) {
throw new FileStorageException("Error while searching files", e);
}
if (recursive) {
final List<FolderDescription> folders = searchFolders(searchPath, true);
for (final FolderDescription folderDesc : folders) {
final String newPath = folderDesc.getName();
logger.debug("Searching for files inside: " + newPath);
final List<FileDescription> folderFiles = searchFiles(newPath, false);
logger.debug("Found " + folderFiles.size() + " files");
result.addAll(folderFiles);
}
}
return result;
}
public List<FolderDescription> searchFolders(String searchPath, boolean recursive) {
List<FolderDescription> result = new ArrayList<FolderDescription>();
try {
@ -224,9 +148,9 @@ public class FileRepositoryImpl implements FileRepository {
return result;
}
Node node = session.getRootNode().getNode(searchPath);
NodeIterator ni = node.getNodes();
while (ni.hasNext()) {
Node item = ni.nextNode();
NodeIterator nodeIterator = node.getNodes();
while (nodeIterator.hasNext()) {
Node item = nodeIterator.nextNode();
if (isFolder(item)) {
FolderDescription tmp = new FolderDescription();
tmp.setName(item.getName());
@ -246,14 +170,6 @@ public class FileRepositoryImpl implements FileRepository {
return result;
}
private boolean isFile(Node node) {
try {
return "nt:file".equals(node.getPrimaryNodeType().getName());
} catch (RepositoryException e) {
throw new FileStorageException("Error while checking node type", e);
}
}
private boolean isFolder(Node node) {
try {
return "nt:folder".equals(node.getPrimaryNodeType().getName()) || "nt:unstructured".equals(node.getPrimaryNodeType().getName());
@ -310,13 +226,6 @@ public class FileRepositoryImpl implements FileRepository {
return mimeString;
}
@Override
public SciProFileStream getFileStream(final FileDescription fileDescription) {
String path = fileDescription.getPath();
path = (path.startsWith("/") ? path.substring(1) : path);
return new SciProFileStream(retrieveFileByPath(path), fileDescription);
}
public String formatBytes(float size) {
NumberFormat nf = new DecimalFormat("#.00");
@ -331,28 +240,6 @@ public class FileRepositoryImpl implements FileRepository {
}
}//formatBytes
public String getProjectRootPath(Long projectId) {
return ROOT_PATH + PROJECTS_PATH + getIntervalSubFolder(projectId);
}
/**
* Method used to split the folders into sub folders containing for example projects. Precaution because jackrabbit can
* get slow when faced with huge number of sub nodes in one node (10.000+).
*
* @param id id of the domain object used as key, for example projectId, for example 54
* @return result looking like for example: "0-99/54
*/
@Override
public String getIntervalSubFolder(final Long id) {
if (id == null) {
throw new IllegalStateException("Attempting to calculate a repository path using a null-id, that's not allowed!");
}
Long startId = (id / STANDARD_INTERVAL_LENGTH) * STANDARD_INTERVAL_LENGTH;
Long endId = startId + STANDARD_INTERVAL_LENGTH - 1;
return startId.toString() + "-" + endId.toString() + "/" + id.toString() + "/";
}
@Override
public void sortFolderDescriptions(List<FolderDescription> list,
SortOrder sortOrder) {
@ -377,58 +264,6 @@ public class FileRepositoryImpl implements FileRepository {
}
}
@Override
public void sortFileDescriptions(List<FileDescription> list,
SortOrder sortOrder) {
if (sortOrder == null) {
Collections.sort(list);
} else {
switch (sortOrder) {
case NameDesc:
Collections.sort(list, new FileName(true));
break;
case Created:
Collections.sort(list, new FileCreated(false));
break;
case CreatedDesc:
Collections.sort(list, new FileCreated(true));
break;
case Size:
Collections.sort(list, new FileSize(false));
break;
case SizeDesc:
Collections.sort(list, new FileSize(true));
break;
case MimeType:
Collections.sort(list, new FileType(false));
break;
case MimeTypeDesc:
Collections.sort(list, new FileType(true));
break;
case User:
Collections.sort(list, new FileUser(false));
break;
case UserDesc:
Collections.sort(list, new FileUser(true));
break;
default:
Collections.sort(list, new FileName(false));
break;
}
}
}
@Override
public FileDescription latestUpload(Project project) {
List<FileDescription> rootFiles = searchFiles(getProjectRootPath(project.getId()), true);
sortFileDescriptions(rootFiles, SortOrder.CreatedDesc);
if (rootFiles.size() > 0) {
return rootFiles.get(0);
} else {
return null;
}
}
private class FolderName implements Comparator<FolderDescription> {
final private boolean reversed;
@ -464,94 +299,4 @@ public class FileRepositoryImpl implements FileRepository {
}
}
}
private class FileName implements Comparator<FileDescription> {
final private boolean reversed;
public FileName(boolean reversed) {
this.reversed = reversed;
}
@Override
public int compare(FileDescription o1, FileDescription o2) {
int result = o1.getName().compareToIgnoreCase(o2.getName());
if (reversed) {
return -result;
} else {
return result;
}
}
}
private class FileCreated implements Comparator<FileDescription> {
final private boolean reversed;
public FileCreated(boolean reversed) {
this.reversed = reversed;
}
@Override
public int compare(FileDescription o1, FileDescription o2) {
int result = o1.getTargetLastModified().compareTo(o2.getTargetLastModified());
if (reversed) {
return -result;
} else {
return result;
}
}
}
private class FileSize implements Comparator<FileDescription> {
final private boolean reversed;
public FileSize(boolean reversed) {
this.reversed = reversed;
}
@Override
public int compare(FileDescription o1, FileDescription o2) {
int result = o1.getSize().compareTo(o2.getSize());
if (reversed) {
return -result;
} else {
return result;
}
}
}
private class FileType implements Comparator<FileDescription> {
final private boolean reversed;
public FileType(boolean reversed) {
this.reversed = reversed;
}
@Override
public int compare(FileDescription o1, FileDescription o2) {
int result = o1.getMimeType().compareTo(o2.getMimeType());
if (reversed) {
return -result;
} else {
return result;
}
}
}
private class FileUser implements Comparator<FileDescription> {
final private boolean reversed;
public FileUser(boolean reversed) {
this.reversed = reversed;
}
@Override
public int compare(FileDescription o1, FileDescription o2) {
int result = o1.getUserId().compareTo(o2.getUserId());
if (reversed) {
return -result;
} else {
return result;
}
}
}
}

@ -21,70 +21,74 @@ import java.util.Date;
/**
* http://www.xaloon.org
*
*
* @author vytautas racelis
* @author Martin Peters - mpeters@dsv.su.se
*/
public class FolderDescription implements Serializable, Comparable<FolderDescription> {
private static final long serialVersionUID = 1L;
private String name;
private Date created;
private String identifier;
public String getIdentifier() {
return identifier;
}
public void setIdentifier(String identifier) {
this.identifier = identifier;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getCreated() {
return created;
}
public void setCreated(Date date) {
created = date;
}
private static final long serialVersionUID = 1L;
private String name;
private Date created;
private String identifier;
@Override
public boolean equals(Object other){
if(other == null) {
public String getIdentifier() {
return identifier;
}
public void setIdentifier(String identifier) {
this.identifier = identifier;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getCreated() {
return created;
}
public void setCreated(Date date) {
created = date;
}
@Override
public boolean equals(Object other) {
if (other == null) {
return false;
}
if(!(other instanceof FolderDescription)) {
if (!(other instanceof FolderDescription)) {
return false;
}
FolderDescription fDesc = (FolderDescription) other;
if(this.getIdentifier() == null || fDesc.getIdentifier() == null) {
FolderDescription fDesc = (FolderDescription) other;
if (this.getIdentifier() == null || fDesc.getIdentifier() == null) {
throw new IllegalStateException("Tried to check FolderDescription objects for equality where identifier was null");
}
if(!this.getIdentifier().equals(fDesc.identifier)) {
return false;
}
return true;
}
@Override
public int hashCode(){
if(this.getIdentifier() == null) {
return this.getIdentifier().equals(fDesc.identifier);
}
@Override
public int hashCode() {
if (this.getIdentifier() == null) {
throw new IllegalStateException("Tried to get hashCode fore FolderDescription where identifier was not set");
}
return this.getIdentifier().hashCode();
}
@Override
public int compareTo(FolderDescription other) {
return this.getName().compareToIgnoreCase(other.getName());
}
@Override
public String toString(){
return name;//+" "+created.toString();
}
return this.getIdentifier().hashCode();
}
@Override
public int compareTo(FolderDescription other) {
return this.getName().compareToIgnoreCase(other.getName());
}
@Override
public String toString() {
return name;//+" "+created.toString();
}
}

@ -12,13 +12,8 @@ import java.util.List;
@Transactional(readOnly = true)
public interface FileDescriptionRepo extends JpaRepository<FileDescription, Long>, QueryDslPredicateExecutor<FileDescription> {
@Query("SELECT COUNT (fd) FROM FileDescription fd WHERE fd.identifier = :identifier")
long countFileDescriptionByIdentifier(@Param("identifier") String identifier);
@Query("SELECT COUNT (fd) FROM FileDescription fd WHERE fd.path = :path")
long countFileDescriptionByPath(@Param("path") String path);
List<FileDescription> findByIdentifier(String identifier);
List<FileDescription> findByPath(String path);
}

@ -21,19 +21,25 @@ public interface UserRepo extends JpaRepository<User, Long>, QueryDslPredicateEx
User findByEmailAddress(String emailAddress);
// TODO: Upgrade hibernate so that this works
@Query("SELECT DISTINCT r.user FROM Role r WHERE r.deleted = false AND TYPE(r) in (:roles) AND " +
"(r.user.firstName || ' ' || r.user.lastName LIKE :name OR r.user.emailAddress LIKE :email)")
List<User> findWithFilter(@Param("roles") Collection<Class<? extends Role>> roles, @Param("name") String name, @Param("email") String email, Pageable pageable);
"CONCAT(r.user.firstName, ' ', r.user.lastName) LIKE :name")
List<User> findFilteredUsers(@Param("roles") Collection<Class<? extends Role>> roles, @Param("name") String name, Pageable pageable);
// TODO: Upgrade hibernate so that this works
@Query("SELECT COUNT(DISTINCT r.user) FROM Role r WHERE r.deleted = false AND TYPE(r) in (:roles) AND " +
"(r.user.firstName || ' ' || r.user.lastName LIKE :name OR r.user.emailAddress LIKE :email)")
long countWithFilter(@Param("roles") Collection<Class<? extends Role>> roles, @Param("name") String name, @Param("email") String email);
"CONCAT(r.user.firstName, ' ', r.user.lastName) LIKE :name")
long countFilteredUsers(@Param("roles") Collection<Class<? extends Role>> roles, @Param("name") String name);
@Query("SELECT u FROM User u, Username un WHERE un.username = :username AND un.realm = :realm AND un.user = u AND u.deleted = false")
User findByUsernameAndRealm(@Param("username") String username, @Param("realm") String realm);
@Query("SELECT u FROM User u WHERE u.identifier IS NULL")
@Query("SELECT u FROM User u WHERE u.identifier IS NULL ORDER BY u.firstName ASC")
List<User> findInternalUsers();
@Query("SELECT DISTINCT r.user FROM Role r WHERE r.deleted = false AND TYPE(r) in (:roles) AND " +
"CONCAT(r.user.firstName, ' ', r.user.lastName) LIKE :name AND r.user.identifier IS NULL")
List<User> findFilteredInternalUsers(@Param("roles") Collection<Class<? extends Role>> roles, @Param("name") String name, Pageable pageable);
@Query("SELECT COUNT(DISTINCT r.user) FROM Role r WHERE r.deleted = false AND TYPE(r) in (:roles) AND " +
"CONCAT(r.user.firstName, ' ', r.user.lastName) LIKE :name AND r.user.identifier IS NULL")
long countFilteredInternalUsers(@Param("roles") Collection<Class<? extends Role>> roles, @Param("name") String name);
}

@ -1,5 +1,8 @@
package se.su.dsv.scipro.springdata.serviceimpls;
import org.apache.jackrabbit.util.Text;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import se.su.dsv.scipro.data.dataobjects.FileDescription;
@ -9,13 +12,18 @@ import se.su.dsv.scipro.repository.FileRepository;
import se.su.dsv.scipro.repository.FolderDescription;
import se.su.dsv.scipro.repository.SciProFileStream;
import se.su.dsv.scipro.repository.SortOrder;
import se.su.dsv.scipro.repository.util.FileStorageException;
import se.su.dsv.scipro.repository.util.RepositoryManager;
import se.su.dsv.scipro.springdata.repos.FileDescriptionRepo;
import se.su.dsv.scipro.springdata.services.FileDescriptionService;
import javax.inject.Inject;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import java.io.InputStream;
import java.util.Date;
import java.util.List;
import java.util.*;
@Service("fileDescriptionService")
@Transactional(readOnly = true)
@ -23,11 +31,21 @@ public class FileDescriptionServiceImpl extends AbstractServiceImpl<FileDescript
private FileDescriptionRepo fileDescriptionRepo;
private FileRepository fileRepository;
protected static final int STANDARD_INTERVAL_LENGTH = 100;
protected static final String ROOT_PATH = "root/";
protected static final String PROJECTS_PATH = "projects/";
private static final Logger logger = LoggerFactory.getLogger(FileDescriptionServiceImpl.class);
@Inject
public FileDescriptionServiceImpl(FileDescriptionRepo fileDescriptionRepo, FileRepository fileRepository) {
private RepositoryManager repositoryManager;
@Inject
public FileDescriptionServiceImpl(FileDescriptionRepo fileDescriptionRepo, FileRepository fileRepository, RepositoryManager repositoryManager) {
super(fileDescriptionRepo);
this.fileRepository = fileRepository;
this.fileDescriptionRepo = fileDescriptionRepo;
this.repositoryManager = repositoryManager;
}
@Override
@ -49,22 +67,6 @@ public class FileDescriptionServiceImpl extends AbstractServiceImpl<FileDescript
return fileRepository.retrieveFileByPath(fd.getPath());
}
@Override
public FileDescription retrieveByIdentifier(String identifier) {
FileDescription result = null;
List<FileDescription> fileDescriptions = fileDescriptionRepo.findByIdentifier(identifier);
if (fileDescriptions != null && !fileDescriptions.isEmpty()) {
for (FileDescription fd : fileDescriptions) {
if (fileRepository.existsFileByPath(fd.getPath())) {
result = fd;
}
}
} else {
result = fileDescriptionRepo.save(fileRepository.retrieveFileDescriptionByIdentifier(identifier));
}
return result;
}
private FileDescription createFileDescriptionFromPath(String path, String fileName, byte[] content, boolean thesisFile, User uploader, String identifier) {
FileDescription fd = new FileDescription();
fd.setPath(path + fileName);
@ -80,12 +82,13 @@ public class FileDescriptionServiceImpl extends AbstractServiceImpl<FileDescript
@Override
public FileDescription latestUpload(Project project) {
return fileRepository.latestUpload(project);
}
@Override
public long countFileDescriptionByIdentifier(String identifier) {
return fileDescriptionRepo.countFileDescriptionByIdentifier(identifier);
List<FileDescription> rootFiles = searchFiles(getProjectRootPath(project.getId()), true);
sortFileDescriptions(rootFiles, SortOrder.CreatedDesc);
if (rootFiles.size() > 0) {
return rootFiles.get(0);
} else {
return null;
}
}
@Override
@ -95,12 +98,24 @@ public class FileDescriptionServiceImpl extends AbstractServiceImpl<FileDescript
@Override
public String getProjectRootPath(Long projectId) {
return fileRepository.getProjectRootPath(projectId);
return ROOT_PATH + PROJECTS_PATH + getIntervalSubFolder(projectId);
}
/**
* Method used to split the folders into sub folders containing for example projects. Precaution because jackrabbit can
* get slow when faced with huge number of sub nodes in one node (10.000+).
*
* @param id id of the domain object used as key, for example projectId, for example 54
* @return result looking like for example: "0-99/54
*/
@Override
public String getIntervalSubFolder(final Long id) {
return fileRepository.getIntervalSubFolder(id);
if (id == null) {
throw new IllegalStateException("Attempting to calculate a repository path using a null-id, that's not allowed!");
}
Long startId = (id / STANDARD_INTERVAL_LENGTH) * STANDARD_INTERVAL_LENGTH;
Long endId = startId + STANDARD_INTERVAL_LENGTH - 1;
return startId.toString() + "-" + endId.toString() + "/" + id.toString() + "/";
}
@Override
@ -127,7 +142,48 @@ public class FileDescriptionServiceImpl extends AbstractServiceImpl<FileDescript
@Override
public List<FileDescription> searchFiles(String searchPath, boolean recursive) {
return fileRepository.searchFiles(searchPath, recursive);
List<FileDescription> result = new ArrayList<FileDescription>();
try {
Session session = repositoryManager.getDefaultSession();
if (!session.getRootNode().hasNode(searchPath)) {
return result;
}
Node node = session.getRootNode().getNode(searchPath);
NodeIterator nodeIterator = node.getNodes();
while (nodeIterator.hasNext()) {
Node file = nodeIterator.nextNode();
if (isFile(file)) {
FileDescription desc = new FileDescription();
desc.setPath(file.getPath());
desc.setName(Text.unescapeIllegalJcrChars(file.getName()));
Node fileNode = file.getNode("jcr:content");
desc.setTargetLastModified(fileNode.getProperty("jcr:lastModified").getDate().getTime());
desc.setMimeType(fileNode.getProperty("jcr:mimeType").getString());
desc.setSize(fileNode.getProperty("jcr:data").getLength());
desc.setIdentifier(fileNode.getIdentifier());
if (file.hasProperty("sp:userId")) {
desc.setUserId(file.getProperty("sp:userId").getLong());
}
if (file.hasProperty("sp:isThesisFile")) {
desc.setThesisFile(file.getProperty("sp:isThesisFile").getBoolean());
}
result.add(desc);
}
}
} catch (Exception e) {
throw new FileStorageException("Error while searching files", e);
}
if (recursive) {
final List<FolderDescription> folders = searchFolders(searchPath, true);
for (final FolderDescription folderDesc : folders) {
final String newPath = folderDesc.getName();
logger.debug("Searching for files inside: " + newPath);
final List<FileDescription> folderFiles = searchFiles(newPath, false);
logger.debug("Found " + folderFiles.size() + " files");
result.addAll(folderFiles);
}
}
return result;
}
@Override
@ -139,7 +195,42 @@ public class FileDescriptionServiceImpl extends AbstractServiceImpl<FileDescript
@Override
public void sortFileDescriptions(List<FileDescription> fileDescriptions, SortOrder sortOrder) {
fileRepository.sortFileDescriptions(fileDescriptions, sortOrder);
if (sortOrder == null) {
Collections.sort(fileDescriptions);
} else {
switch (sortOrder) {
case NameDesc:
Collections.sort(fileDescriptions, new FileName(true));
break;
case Created:
Collections.sort(fileDescriptions, new FileCreated(false));
break;
case CreatedDesc:
Collections.sort(fileDescriptions, new FileCreated(true));
break;
case Size:
Collections.sort(fileDescriptions, new FileSize(false));
break;
case SizeDesc:
Collections.sort(fileDescriptions, new FileSize(true));
break;
case MimeType:
Collections.sort(fileDescriptions, new FileType(false));
break;
case MimeTypeDesc:
Collections.sort(fileDescriptions, new FileType(true));
break;
case User:
Collections.sort(fileDescriptions, new FileUser(false));
break;
case UserDesc:
Collections.sort(fileDescriptions, new FileUser(true));
break;
default:
Collections.sort(fileDescriptions, new FileName(false));
break;
}
}
}
@Override
@ -151,4 +242,102 @@ public class FileDescriptionServiceImpl extends AbstractServiceImpl<FileDescript
public String findOrCreateFolder(String name) {
return fileRepository.findOrCreateFolder(name);
}
private boolean isFile(Node node) {
try {
return "nt:file".equals(node.getPrimaryNodeType().getName());
} catch (RepositoryException e) {
throw new FileStorageException("Error while checking node type", e);
}
}
private class FileName implements Comparator<FileDescription> {
final private boolean reversed;
public FileName(boolean reversed) {
this.reversed = reversed;
}
@Override
public int compare(FileDescription o1, FileDescription o2) {
int result = o1.getName().compareToIgnoreCase(o2.getName());
if (reversed) {
return -result;
} else {
return result;
}
}
}
private class FileCreated implements Comparator<FileDescription> {
final private boolean reversed;
public FileCreated(boolean reversed) {
this.reversed = reversed;
}
@Override
public int compare(FileDescription o1, FileDescription o2) {
int result = o1.getTargetLastModified().compareTo(o2.getTargetLastModified());
if (reversed) {
return -result;
} else {
return result;
}
}
}
private class FileSize implements Comparator<FileDescription> {
final private boolean reversed;
public FileSize(boolean reversed) {
this.reversed = reversed;
}
@Override
public int compare(FileDescription o1, FileDescription o2) {
int result = o1.getSize().compareTo(o2.getSize());
if (reversed) {
return -result;
} else {
return result;
}
}
}
private class FileType implements Comparator<FileDescription> {
final private boolean reversed;
public FileType(boolean reversed) {
this.reversed = reversed;
}
@Override
public int compare(FileDescription o1, FileDescription o2) {
int result = o1.getMimeType().compareTo(o2.getMimeType());
if (reversed) {
return -result;
} else {
return result;
}
}
}
private class FileUser implements Comparator<FileDescription> {
final private boolean reversed;
public FileUser(boolean reversed) {
this.reversed = reversed;
}
@Override
public int compare(FileDescription o1, FileDescription o2) {
int result = o1.getUserId().compareTo(o2.getUserId());
if (reversed) {
return -result;
} else {
return result;
}
}
}
}

@ -10,7 +10,7 @@ import se.su.dsv.scipro.springdata.repos.UserRepo;
import se.su.dsv.scipro.springdata.services.UserService;
import javax.inject.Inject;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
@ -38,13 +38,19 @@ public class UserServiceImpl extends AbstractServiceImpl<User,Long> implements U
@Override
public List<User> findAll(Filter filter, Pageable pageable) {
if (filter.getRoles().isEmpty()) {
return new ArrayList<User>();
return Collections.emptyList();
}
String name = "%" + (filter.getName() != null ? filter.getName() : "") + "%";
String email = filter.getEmail() != null ? "%" + filter.getEmail() + "%" : name;
if (filter.isInternalUsersOnly()) {
return userRepo.findFilteredInternalUsers(filter.getRoles(), wildcard(filter.getName()), pageable);
}
else {
return userRepo.findFilteredUsers(filter.getRoles(), wildcard(filter.getName()), pageable);
}
}
return userRepo.findWithFilter(filter.getRoles(), name, email, pageable);
private String wildcard(String string) {
return "%" + (string != null ? string : "") + "%";
}
@Override
@ -53,10 +59,12 @@ public class UserServiceImpl extends AbstractServiceImpl<User,Long> implements U
return 0;
}
String name = "%" + (filter.getName() != null ? filter.getName() : "") + "%";
String email = filter.getEmail() != null ? "%" + filter.getEmail() + "%" : name;
return userRepo.countWithFilter(filter.getRoles(), name, email);
if (filter.isInternalUsersOnly()) {
return userRepo.countFilteredInternalUsers(filter.getRoles(), wildcard(filter.getName()));
}
else {
return userRepo.countFilteredUsers(filter.getRoles(), wildcard(filter.getName()));
}
}
@Override

@ -16,12 +16,8 @@ public interface FileDescriptionService extends GenericService<FileDescription,
InputStream retrieveFileByFileDescription(FileDescription fd);
FileDescription retrieveByIdentifier(String identifier);
FileDescription latestUpload(Project project);
long countFileDescriptionByIdentifier(final String identifier);
long countFileDescriptionByPath(final String path);
String getProjectRootPath(Long projectId);

@ -33,7 +33,7 @@ public interface UserService extends GenericService<User, Long> {
private Collection<Class<? extends Role>> roles = new ArrayList<Class<? extends Role>>();
private String name;
private String email;
private boolean internalUsersOnly;
public Filter() {
for (Roles role : Roles.managed()) {
@ -67,12 +67,12 @@ public interface UserService extends GenericService<User, Long> {
this.name = name;
}
public String getEmail() {
return email;
public boolean isInternalUsersOnly() {
return internalUsersOnly;
}
public void setEmail(String email) {
this.email = email;
public void setInternalUsersOnly(boolean internalUsersOnly) {
this.internalUsersOnly = internalUsersOnly;
}
}
}

@ -1,11 +1,7 @@
package se.su.dsv.scipro.repository;
import se.su.dsv.scipro.data.dataobjects.FileDescription;
import se.su.dsv.scipro.data.dataobjects.Project;
import se.su.dsv.scipro.data.dataobjects.User;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.List;
@ -27,11 +23,6 @@ public class TestFileRepositoryImpl implements FileRepository {
return null;
}
@Override
public List<FileDescription> searchFiles(String searchPath, boolean recursive) {
return null;
}
@Override
public boolean delete(String path) {
return false;
@ -47,54 +38,19 @@ public class TestFileRepositoryImpl implements FileRepository {
return null;
}
@Override
public SciProFileStream getFileStream(FileDescription fileDescription) {
FileInputStream file = null;
try {
file = new FileInputStream("core/src/test/resources/turnitInTest.txt");
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return new SciProFileStream(file, fileDescription);
}
@Override
public String formatBytes(float size) {
return null;
}
@Override
public String getProjectRootPath(Long projectId) {
return null;
}
@Override
public void sortFolderDescriptions(List<FolderDescription> list, SortOrder sortOrder) {
}
@Override
public void sortFileDescriptions(List<FileDescription> list, SortOrder sortOrder) {
}
@Override
public FileDescription latestUpload(Project project) {
return null;
}
@Override
public String detectMimeTypeFromFileExtension(String fileName) {
return null;
}
@Override
public FileDescription retrieveFileDescriptionByIdentifier(String identifier) {
throw new UnsupportedOperationException("TestFileRepositoryImpl#retrieveFileDescriptionByIdentifier not implemented yet.");
}
@Override
public String getIntervalSubFolder(Long id) {
return null;
}
}

@ -0,0 +1,247 @@
package se.su.dsv.scipro.springdata.serviceimpls;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import se.su.dsv.scipro.data.dataobjects.FileDescription;
import se.su.dsv.scipro.data.dataobjects.Project;
import se.su.dsv.scipro.data.dataobjects.ProjectClass;
import se.su.dsv.scipro.repository.FileRepository;
import se.su.dsv.scipro.repository.SortOrder;
import se.su.dsv.scipro.repository.util.RepositoryManager;
import se.su.dsv.scipro.springdata.repos.FileDescriptionRepo;
import se.su.dsv.scipro.test.UserBuilder;
import javax.inject.Inject;
import javax.inject.Named;
import java.util.List;
import static org.junit.Assert.assertEquals;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath*:test-applicationContext.xml")
public class FileDescriptionServiceImplIntegrationTest {
public static final Project SOME_PROJECT = Project.builder().title("title").projectClass(new ProjectClass()).build();
private FileDescriptionServiceImpl fileDescriptionService;
@Inject
private FileDescriptionRepo fileDescriptionRepo;
@Inject
@Named("fileRepositoryImpl")
private FileRepository fileRepository;
@Inject
private RepositoryManager repositoryManager;
public static final String SEARCH_PATH = "root/projects/0-99/1/";
private FileDescription latestUploadedFile;
@Before
public void setUp() throws Exception {
fileDescriptionService = new FileDescriptionServiceImpl(fileDescriptionRepo, fileRepository, repositoryManager);
SOME_PROJECT.setId(1L);
}
@After
public void tearDown() throws Exception {
fileDescriptionRepo.deleteAll();
fileRepository.delete(SEARCH_PATH);
}
@Test
public void search_files_shallow() throws Exception {
String path = "/" + SEARCH_PATH;
store4Files(path);
assertEquals(4, fileDescriptionService.searchFiles(SEARCH_PATH, false).size());
}
@Test
public void search_folders_shallow() throws Exception {
String path = "/" + SEARCH_PATH + "/" + SEARCH_PATH;
store4Files(path);
assertEquals(1, fileDescriptionService.searchFolders(SEARCH_PATH, false).size());
}
@Test
public void search_files_recursive() throws Exception {
String path = "/" + SEARCH_PATH + "/" + SEARCH_PATH;
store4Files(path);
assertEquals(4, fileDescriptionService.searchFiles(SEARCH_PATH, true).size());
}
@Test
public void search_folders_recursive() throws Exception {
String path = "/" + SEARCH_PATH + "/" + "path";
store4Files(path);
String path2 = "/" + SEARCH_PATH + "/" + "otherPath";
store4Files(path2);
assertEquals(2, fileDescriptionService.searchFolders(SEARCH_PATH, true).size());
}
@Test
public void search_files_recursive_two_levels() throws Exception {
String path = "/" + SEARCH_PATH;
store4Files(path);
String path2 = "/" + SEARCH_PATH + "/" + SEARCH_PATH;
store4Files(path2);
assertEquals(8, fileDescriptionService.searchFiles(SEARCH_PATH, true).size());
}
@Test
public void search_folders_recursive_two_levels() throws Exception {
String path = "/" + SEARCH_PATH + "/" + "path";
store4Files(path);
String path2 = "/" + SEARCH_PATH + "/" + "otherPath";
store4Files(path2);
String path3 = "/" + SEARCH_PATH + "/" + "path" + "/" + "deepPath";
store4Files(path3);
assertEquals(3, fileDescriptionService.searchFolders(SEARCH_PATH, true).size());
}
@Test
public void get_latest_upload() throws Exception {
store4Files("/" + SEARCH_PATH);
assertEquals(latestUploadedFile, fileDescriptionService.latestUpload(SOME_PROJECT));
}
@Test
public void sort_file_descriptions_by_name() throws Exception {
store4Files("/" + SEARCH_PATH);
List<FileDescription> fileDescriptions = fileDescriptionService.searchFiles(SEARCH_PATH, false);
fileDescriptionService.sortFileDescriptions(fileDescriptions, SortOrder.Name);
assertEquals("name1", fileDescriptions.get(0).getName());
assertEquals("name2", fileDescriptions.get(1).getName());
assertEquals("name3", fileDescriptions.get(2).getName());
assertEquals("name4", fileDescriptions.get(3).getName());
}
@Test
public void sort_file_descriptions_by_name_desc() throws Exception {
store4Files("/" + SEARCH_PATH);
List<FileDescription> fileDescriptions = fileDescriptionService.searchFiles(SEARCH_PATH, false);
fileDescriptionService.sortFileDescriptions(fileDescriptions, SortOrder.NameDesc);
assertEquals("name4", fileDescriptions.get(0).getName());
assertEquals("name3", fileDescriptions.get(1).getName());
assertEquals("name2", fileDescriptions.get(2).getName());
assertEquals("name1", fileDescriptions.get(3).getName());
}
@Test
public void sort_file_descriptions_by_created() throws Exception {
store4Files("/" + SEARCH_PATH);
List<FileDescription> fileDescriptions = fileDescriptionService.searchFiles(SEARCH_PATH, false);
fileDescriptionService.sortFileDescriptions(fileDescriptions, SortOrder.Created);
assertEquals("name4", fileDescriptions.get(0).getName());
assertEquals("name2", fileDescriptions.get(1).getName());
assertEquals("name1", fileDescriptions.get(2).getName());
assertEquals("name3", fileDescriptions.get(3).getName());
}
@Test
public void sort_file_descriptions_by_created_desc() throws Exception {
store4Files("/" + SEARCH_PATH);
List<FileDescription> fileDescriptions = fileDescriptionService.searchFiles(SEARCH_PATH, false);
fileDescriptionService.sortFileDescriptions(fileDescriptions, SortOrder.CreatedDesc);
assertEquals("name3", fileDescriptions.get(0).getName());
assertEquals("name1", fileDescriptions.get(1).getName());
assertEquals("name2", fileDescriptions.get(2).getName());
assertEquals("name4", fileDescriptions.get(3).getName());
}
@Test
public void sort_file_descriptions_by_size() throws Exception {
store4Files("/" + SEARCH_PATH);
List<FileDescription> fileDescriptions = fileDescriptionService.searchFiles(SEARCH_PATH, false);
fileDescriptionService.sortFileDescriptions(fileDescriptions, SortOrder.Size);
assertEquals("name1", fileDescriptions.get(0).getName());
assertEquals("name2", fileDescriptions.get(1).getName());
assertEquals("name3", fileDescriptions.get(2).getName());
assertEquals("name4", fileDescriptions.get(3).getName());
}
@Test
public void sort_file_descriptions_by_size_desc() throws Exception {
store4Files("/" + SEARCH_PATH);
List<FileDescription> fileDescriptions = fileDescriptionService.searchFiles(SEARCH_PATH, false);
fileDescriptionService.sortFileDescriptions(fileDescriptions, SortOrder.SizeDesc);
assertEquals("name4", fileDescriptions.get(0).getName());
assertEquals("name3", fileDescriptions.get(1).getName());
assertEquals("name2", fileDescriptions.get(2).getName());
assertEquals("name1", fileDescriptions.get(3).getName());
}
@Test
@Ignore
public void sort_file_descriptions_by_user() throws Exception {
store4Files("/" + SEARCH_PATH);
List<FileDescription> fileDescriptions = fileDescriptionService.searchFiles(SEARCH_PATH, false);
fileDescriptionService.sortFileDescriptions(fileDescriptions, SortOrder.User);
assertEquals("name1", fileDescriptions.get(0).getName());
assertEquals("name2", fileDescriptions.get(1).getName());
assertEquals("name3", fileDescriptions.get(2).getName());
assertEquals("name4", fileDescriptions.get(3).getName());
}
@Test
@Ignore
public void sort_file_descriptions_by_user_desc() throws Exception {
store4Files("/" + SEARCH_PATH);
List<FileDescription> fileDescriptions = fileDescriptionService.searchFiles(SEARCH_PATH, false);
fileDescriptionService.sortFileDescriptions(fileDescriptions, SortOrder.UserDesc);
assertEquals("name4", fileDescriptions.get(0).getName());
assertEquals("name3", fileDescriptions.get(1).getName());
assertEquals("name2", fileDescriptions.get(2).getName());
assertEquals("name1", fileDescriptions.get(3).getName());
}
private void store4Files(String path) throws InterruptedException {
fileDescriptionService.storeFile(path, "name4", new byte[4], true, new UserBuilder().setLastName("D").create());
Thread.sleep(1);
fileDescriptionService.storeFile(path, "name2", new byte[2], true, new UserBuilder().setLastName("B").create());
Thread.sleep(1);
fileDescriptionService.storeFile(path, "name1", new byte[1], true, new UserBuilder().setLastName("A").create());
Thread.sleep(1);
latestUploadedFile = fileDescriptionService.storeFile(path, "name3", new byte[3], true, new UserBuilder().setLastName("C").create());
}
}

@ -9,16 +9,14 @@ import org.mockito.invocation.InvocationOnMock;
import org.mockito.runners.MockitoJUnitRunner;
import org.mockito.stubbing.Answer;
import se.su.dsv.scipro.data.dataobjects.FileDescription;
import se.su.dsv.scipro.data.dataobjects.Project;
import se.su.dsv.scipro.data.dataobjects.User;
import se.su.dsv.scipro.repository.FileRepository;
import se.su.dsv.scipro.repository.FileRepositoryImpl;
import se.su.dsv.scipro.repository.util.RepositoryManager;
import se.su.dsv.scipro.springdata.repos.FileDescriptionRepo;
import se.su.dsv.scipro.test.ProjectBuilder;
import se.su.dsv.scipro.test.UserBuilder;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Date;
import static org.junit.Assert.assertEquals;
@ -36,12 +34,10 @@ public class FileDescriptionServiceImplTest {
private FileRepository fileRepository;
@Mock
private FileRepositoryImpl fileRepositoryImpl;
@Mock
private RepositoryManager repositoryManager;
private FileDescriptionServiceImpl fileDescriptionService;
private byte[] array;
private FileDescription fileDescription;
private Project project;
private String string;
private String path = "path/to/";
private String fileName = "file.pdf";
@ -54,20 +50,8 @@ public class FileDescriptionServiceImplTest {
@Before
public void setUp() throws Exception {
fileDescriptionService = new FileDescriptionServiceImpl(fileDescriptionRepo, fileRepository);
fileDescriptionService = new FileDescriptionServiceImpl(fileDescriptionRepo, fileRepository, repositoryManager);
user = new UserBuilder().create();
array = new byte[0];
fileDescription = new FileDescription();
project = new ProjectBuilder().create();
string = "String";
}
@Test
public void countFileDescriptionByIdentifier() throws Exception {
String identifier = "identifier";
long expectedNumber = 3L;
when(fileDescriptionRepo.countFileDescriptionByIdentifier(identifier)).thenReturn(expectedNumber);
assertEquals(expectedNumber, fileDescriptionService.countFileDescriptionByIdentifier(identifier));
}
@Test
@ -78,12 +62,6 @@ public class FileDescriptionServiceImplTest {
assertEquals(expectedNumber, fileDescriptionService.countFileDescriptionByPath(path));
}
@Test
public void testLatestUpload() throws Exception {
when(fileRepository.latestUpload(isA(Project.class))).thenReturn(fileDescription);
assertEquals(fileDescription, fileDescriptionService.latestUpload(project));
}
@Test
public void calls_storeFile() throws Exception {
fileDescriptionService.storeFile(path, fileName, bytes, isThesisFile, user);
@ -126,20 +104,6 @@ public class FileDescriptionServiceImplTest {
verify(fileDescriptionRepo).save(isA(FileDescription.class));
}
@Test
public void retrieveByIdentifier() throws Exception {
fileDescriptionService.retrieveByIdentifier("blabla");
verify(fileDescriptionRepo).findByIdentifier("blabla");
}
@Test
public void retrieveByIdentifierReturns() throws Exception {
FileDescription fd = new FileDescription();
when(fileDescriptionRepo.findByIdentifier("blabla")).thenReturn(Arrays.asList(fd));
when(fileRepository.existsFileByPath(fd.getPath())).thenReturn(true);
Assert.assertEquals(fd, fileDescriptionService.retrieveByIdentifier("blabla"));
}
@Test
public void retrieveFile() throws Exception {
fileDescriptionService.retrieveFileByFileDescription(new FileDescription());

@ -0,0 +1,141 @@
package se.su.dsv.scipro.springdata.serviceimpls;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.data.domain.PageRequest;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional;
import se.su.dsv.scipro.data.dataobjects.Admin;
import se.su.dsv.scipro.data.dataobjects.SysAdmin;
import se.su.dsv.scipro.data.dataobjects.User;
import se.su.dsv.scipro.security.auth.roles.Roles;
import se.su.dsv.scipro.springdata.repos.PasswordRepo;
import se.su.dsv.scipro.springdata.repos.RoleRepo;
import se.su.dsv.scipro.springdata.repos.UserRepo;
import se.su.dsv.scipro.springdata.services.UserService;
import javax.inject.Inject;
import java.util.Collections;
import java.util.List;
import static org.hamcrest.CoreMatchers.hasItem;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath*:test-applicationContext.xml")
@Transactional
public class UserServiceImplIntegrationTest {
@Inject
private UserRepo userRepo;
@Inject
private PasswordRepo passwordRepo;
@Inject
private RoleRepo roleRepo;
@Inject
private UserService userService;
private User billGates;
private User steveJobs;
private UserService.Filter filter;
@Before
public void setUp() throws Exception {
billGates = userRepo.save(newUser("Bill", "Gates", "bill.gates@microsoft.com"));
makeSysAdmin(billGates);
makeExternal(billGates);
steveJobs = userRepo.save(newUser("Steve", "Jobs", "steve.jobs@apple.com"));
makeAdmin(steveJobs);
filter = new UserService.Filter();
filter.setRoles(Roles.SYSADMIN, Roles.EMPLOYEE, Roles.ADMIN, Roles.EXAMINER, Roles.STUDENT);
}
@Test
@Rollback
public void filter_by_name() throws Exception {
filter.setName(billGates.getFirstName());
List<User> users = findUsers();
assertThat(users.size(), is(1));
assertThat(users, hasItem(billGates));
assertThat(countUsers(), is(1L));
}
@Test
@Rollback
public void filter_by_role() throws Exception {
filter.setRoles(Roles.SYSADMIN);
List<User> users = findUsers();
assertThat(users.size(), is(1));
assertThat(users, hasItem(billGates));
assertThat(countUsers(), is(1L));
}
@Test
@Rollback
public void empty_filter_returns_everyone() throws Exception {
List<User> users = findUsers();
assertThat(users.size(), is(2));
assertThat(users, hasItem(billGates));
assertThat(users, hasItem(steveJobs));
assertThat(countUsers(), is(2L));
}
@Test
public void filter_by_internal_users_only() throws Exception {
filter.setInternalUsersOnly(true);
List<User> users = findUsers();
assertThat(users.size(), is(1));
assertThat(users, hasItem(steveJobs));
assertThat(countUsers(), is(1L));
}
@Test
public void filter_with_no_roles_should_result_in_no_users() throws Exception {
filter.setRoles(Collections.<Roles>emptySet());
assertThat(findUsers().size(), is(0));
assertThat(countUsers(), is(0L));
}
private long countUsers() {
return userService.count(filter);
}
private List<User> findUsers() {
return userService.findAll(filter, new PageRequest(0, Integer.MAX_VALUE));
}
private User newUser(String firstName, String lastName, String emailAddress) {
User user = new User();
user.setFirstName(firstName);
user.setLastName(lastName);
user.setEmailAddress(emailAddress);
return user;
}
private void makeSysAdmin(User user) {
SysAdmin sysAdmin = new SysAdmin();
sysAdmin.setUser(user);
roleRepo.save(sysAdmin);
}
private void makeAdmin(User user) {
Admin admin = new Admin();
admin.setUser(user);
roleRepo.save(admin);
}
private void makeExternal(User user) {
user.setIdentifier(42L);
userRepo.save(user);
}
}

@ -5,22 +5,16 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.data.domain.PageRequest;
import se.su.dsv.scipro.data.dataobjects.QUser;
import se.su.dsv.scipro.data.dataobjects.User;
import se.su.dsv.scipro.security.auth.roles.Roles;
import se.su.dsv.scipro.springdata.repos.UserRepo;
import se.su.dsv.scipro.test.UserBuilder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import static java.util.Arrays.asList;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.when;
import static se.su.dsv.scipro.springdata.services.UserService.Filter;
@RunWith(MockitoJUnitRunner.class)
public class UserServiceImplTest {
@ -30,17 +24,11 @@ public class UserServiceImplTest {
private UserServiceImpl userService;
private User user;
private PageRequest pageable;
private List<User> expectedList;
private long expectedCount;
@Before
public void setUp() throws Exception {
userService = new UserServiceImpl(userRepo);
user = new UserBuilder().create();
pageable = new PageRequest(0, 5);
expectedList = asList(new User());
expectedCount = 3;
}
@Test
@ -67,94 +55,10 @@ public class UserServiceImplTest {
assertEquals(user, userService.findByExternalIdentifier(identifier));
}
@Test
public void findAllWithEmptyRoles() throws Exception {
Filter filter = new Filter();
filter.setRoles(Collections.EMPTY_LIST);
assertEquals(new ArrayList<User>(), userService.findAll(filter, pageable));
}
@Test
public void findAllWithRolesWithoutNameAndEmail() throws Exception {
Filter filter = createFilter(Roles.STUDENT, null, null);
when(userRepo.findWithFilter(filter.getRoles(), "%%", "%%", pageable)).thenReturn(expectedList);
assertEquals(expectedList, userService.findAll(filter, pageable));
}
@Test
public void findAllWithRolesWithNameAndWithoutEmail() throws Exception {
Filter filter = createFilter(Roles.STUDENT, "Rolf", null);
String name = "%"+filter.getName()+"%";
when(userRepo.findWithFilter(filter.getRoles(), name, name, pageable)).thenReturn(expectedList);
assertEquals(expectedList, userService.findAll(filter, pageable));
}
@Test
public void findAllWithRolesWithoutNameAndWithEmail() throws Exception {
Filter filter = createFilter(Roles.STUDENT, null, "rolf@dsv.su.se");
when(userRepo.findWithFilter(filter.getRoles(), "%%", "%"+filter.getEmail()+"%", pageable)).thenReturn(expectedList);
assertEquals(expectedList, userService.findAll(filter, pageable));
}
@Test
public void findAllWithRolesWithNameAndWithEmail() throws Exception {
Filter filter = createFilter(Roles.STUDENT, "rolf", "rolf@dsv.su.se");
when(userRepo.findWithFilter(filter.getRoles(), "%"+filter.getName()+"%", "%"+filter.getEmail()+"%", pageable)).thenReturn(expectedList);
assertEquals(expectedList, userService.findAll(filter, pageable));
}
@Test
public void countAllWithEmptyRoles() throws Exception {
Filter filter = new Filter();
filter.setRoles(Collections.EMPTY_LIST);
assertEquals(0, userService.count(filter));
}
@Test
public void countAllWithRolesWithoutNameAndEmail() throws Exception {
Filter filter = createFilter(Roles.STUDENT, null, null);
when(userRepo.countWithFilter(filter.getRoles(), "%%", "%%")).thenReturn(expectedCount);
assertEquals(expectedCount, userService.count(filter));
}
@Test
public void countAllWithRolesWithNameAndWithoutEmail() throws Exception {
Filter filter = createFilter(Roles.STUDENT, "Rolf", null);
String name = "%"+filter.getName()+"%";
when(userRepo.countWithFilter(filter.getRoles(), name, name)).thenReturn(expectedCount);
assertEquals(expectedCount, userService.count(filter));
}
@Test
public void countAllWithRolesWithoutNameAndWithEmail() throws Exception {
Filter filter = createFilter(Roles.STUDENT, null, "rolf@dsv.su.se");
when(userRepo.countWithFilter(filter.getRoles(), "%%", "%"+filter.getEmail()+"%")).thenReturn(expectedCount);
assertEquals(expectedCount, userService.count(filter));
}
@Test
public void countAllWithRolesWithNameAndWithEmail() throws Exception {
Filter filter = createFilter(Roles.STUDENT, "rolf", "rolf@dsv.su.se");
when(userRepo.countWithFilter(filter.getRoles(), "%"+filter.getName()+"%", "%"+filter.getEmail()+"%")).thenReturn(expectedCount);
assertEquals(expectedCount, userService.count(filter));
}
@Test
public void find_internal_users() throws Exception {
List<User> users = Arrays.asList(new UserBuilder().create());
when(userRepo.findInternalUsers()).thenReturn(users);
assertEquals(users, userService.findInternalUsers());
}
private Filter createFilter(Roles role, String name, String email) {
Filter filter = new Filter();
filter.setRoles(asList(role));
if(name!=null) {
filter.setName(name);
}
if(email!=null) {
filter.setEmail(email);
}
return filter;
}
}

@ -6,7 +6,6 @@ import org.apache.wicket.Session;
import org.apache.wicket.authorization.strategies.CompoundAuthorizationStrategy;
import org.apache.wicket.protocol.http.WebApplication;
import org.apache.wicket.protocol.http.servlet.ServletWebRequest;
import org.apache.wicket.protocol.http.servlet.ServletWebResponse;
import org.apache.wicket.request.Request;
import org.apache.wicket.request.Response;
import org.apache.wicket.request.http.WebRequest;
@ -59,7 +58,6 @@ import se.su.dsv.scipro.settings.pages.BasicProfilePage;
import se.su.dsv.scipro.supervisor.pages.*;
import se.su.dsv.scipro.util.AdditionalExceptionLogger;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.net.URL;
@ -186,7 +184,6 @@ public class SciProApplication extends RepositoryApplication {
mountPage("admin/settings/notifications", AdminNotificationSettingsPage.class);
mountPage("admin/settings/milestones", AdminMileStoneSettingsPage.class);
mountPage("admin/settings/nonworkdays", NonWorkDaysPage.class);
mountPage("admin/roles", AdminRolePage.class);
mountPage("admin/allpeers", AdminPeerListPage.class);
mountPage("admin/peer/review", AdminPeerReviewPage.class);
mountPage("admin/projectpartner", AdminProjectPartnerPage.class);
@ -207,6 +204,12 @@ public class SciProApplication extends RepositoryApplication {
mountPage("admin/statistics/ideas", AdminIdeaStatisticsPage.class);
mountPage("admin/statistics/milestones", AdminMileStoneStatisticsPage.class);
mountPage("admin/settings/turnitin", TurnitinSettingsPage.class);
mountPage("admin/users/roles", AdminRolePage.class);
mountPage("admin/users/internal", AdminInternalUsersPage.class);
mountPage("admin/users/internal/edit", AdminEditInternalUserPage.class);
mountPage("admin/users/register", AdminRegistrationPage.class);
mountPage("admin/users/switch", AdminSwitchUserPage.class);
/*
* Project pages

@ -1,6 +1,7 @@
package se.su.dsv.scipro.admin.pages;
import se.su.dsv.scipro.components.AbstractMenuPanel;
import se.su.dsv.scipro.components.menuhighlighting.MenuHighlightAdminInternalUsers;
import java.util.List;
@ -16,8 +17,7 @@ public class AbstractAdminUsersPage extends AbstractAdminPage {
protected List<MenuItem> getItemList() {
return asList(
new MenuItem("Roles", AdminRolePage.class),
new MenuItem("Internal users", AdminInternalUsersPage.class),
new MenuItem("Registration", AdminRegistrationPage.class),
new MenuItem("Internal users", AdminInternalUsersPage.class, MenuHighlightAdminInternalUsers.class),
new MenuItem("Switch user", AdminSwitchUserPage.class));
}

@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
<body>
<wicket:extend>
<div class="row">
<div wicket:id="feedback"></div>
</div>
<form wicket:id="form">
<div class="row">
<span class="col-md-2">First name</span>
<div class="row">
<div class="col-md-3">
<input class="form-control" type="text" wicket:id="firstName"/>
</div>
</div>
</div>
<div class="row">
<br>
<span class="col-md-2">Last name</span>
<div class="row">
<div class="col-md-3">
<input class="form-control" type="text" wicket:id="lastName"/>
</div>
</div>
</div>
<div class="row">
<br>
<span class="col-md-2">Email address</span>
<div class="row">
<div class="col-md-3">
<input class="form-control" type="text" wicket:id="emailAddress" />
</div>
</div>
</div>
<input class="btn btn-success" type="submit" value="Save" />
</form>
</wicket:extend>
</body>
</html>

@ -0,0 +1,72 @@
package se.su.dsv.scipro.admin.pages;
import org.apache.wicket.RestartResponseException;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.panel.FeedbackPanel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.PropertyModel;
import org.apache.wicket.request.mapper.parameter.PageParameters;
import org.apache.wicket.validation.IValidator;
import org.apache.wicket.validation.validator.EmailAddressValidator;
import org.apache.wicket.validation.validator.StringValidator;
import se.su.dsv.scipro.components.menuhighlighting.MenuHighlightAdminInternalUsers;
import se.su.dsv.scipro.data.dataobjects.User;
import se.su.dsv.scipro.springdata.services.RoleService;
import se.su.dsv.scipro.springdata.services.UserService;
import javax.inject.Inject;
import static se.su.dsv.scipro.data.dataobjects.User.USER_ID;
public class AdminEditInternalUserPage extends AbstractAdminUsersPage implements MenuHighlightAdminInternalUsers {
public static final String FORM = "form";
public static final String FIRST_NAME = "firstName";
public static final String LAST_NAME = "lastName";
public static final String EMAIL_ADDRESS = "emailAddress";
public static final int MIN_LENGTH = 2;
public static final String FEEDBACK = "feedback";
@Inject
private UserService userService;
@Inject
private RoleService roleService;
public AdminEditInternalUserPage(PageParameters pp) {
add(new FeedbackPanel(FEEDBACK));
if (pp.get(USER_ID).isNull()) {
throw new RestartResponseException(AdminInternalUsersPage.class);
}
User user = userService.findOne(pp.get(USER_ID).toLong());
add(new EditUserForm(FORM, Model.of(user)));
}
private class EditUserForm extends Form<User> {
public EditUserForm(String id, IModel<User> model) {
super(id, model);
add(newTextField(FIRST_NAME, StringValidator.minimumLength(MIN_LENGTH)));
add(newTextField(LAST_NAME, StringValidator.minimumLength(MIN_LENGTH)));
add(newTextField(EMAIL_ADDRESS, EmailAddressValidator.getInstance()));
}
@Override
protected void onSubmit() {
userService.save(getModelObject());
setResponsePage(AdminInternalUsersPage.class);
}
private TextField<String> newTextField(String name, IValidator<String> validator) {
TextField<String> textField = new TextField<String>(name, new PropertyModel<String>(getModel(), name));
textField.setRequired(true);
textField.add(validator);
return textField;
}
}
}

@ -7,11 +7,13 @@
<thead>
<tr>
<th>Name</th>
<th>Edit</th>
</tr>
</thead>
<tbody>
<tr wicket:id="userList">
<td wicket:id="name"></td>
<td><a href="#" wicket:id="edit">edit</a></td>
</tr>
</tbody>
</table>

@ -2,22 +2,28 @@ package se.su.dsv.scipro.admin.pages;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.link.BookmarkablePageLink;
import org.apache.wicket.markup.html.link.Link;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.ListView;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.LoadableDetachableModel;
import org.apache.wicket.model.PropertyModel;
import org.apache.wicket.request.mapper.parameter.PageParameters;
import se.su.dsv.scipro.data.dataobjects.User;
import se.su.dsv.scipro.security.auth.Authorization;
import se.su.dsv.scipro.security.auth.roles.Roles;
import se.su.dsv.scipro.springdata.services.UserService;
import javax.inject.Inject;
import java.util.List;
@Authorization(authorizedRoles = Roles.SYSADMIN)
public class AdminInternalUsersPage extends AbstractAdminUsersPage {
public static final String REGISTRATION_LINK = "registrationLink";
public static final String USER_LIST = "userList";
public static final String NAME = "name";
public static final String EDIT = "edit";
@Inject
private UserService userService;
@ -30,6 +36,14 @@ public class AdminInternalUsersPage extends AbstractAdminUsersPage {
@Override
protected void populateItem(ListItem<User> item) {
item.add(new Label(NAME, new PropertyModel<String>(item.getModel(), "fullName")));
item.add(new Link<User>(EDIT, item.getModel()) {
@Override
public void onClick() {
PageParameters parameters = new PageParameters();
parameters.set(User.USER_ID, getModelObject().getId());
setResponsePage(AdminEditInternalUserPage.class, parameters);
}
});
}
});
}

@ -1,11 +1,12 @@
package se.su.dsv.scipro.admin.pages;
import se.su.dsv.scipro.components.menuhighlighting.MenuHighlightAdminInternalUsers;
import se.su.dsv.scipro.registration.RegistrationPanel;
import se.su.dsv.scipro.security.auth.Authorization;
import se.su.dsv.scipro.security.auth.roles.Roles;
@Authorization(authorizedRoles = {Roles.ADMIN})
public class AdminRegistrationPage extends AbstractAdminUsersPage {
public class AdminRegistrationPage extends AbstractAdminUsersPage implements MenuHighlightAdminInternalUsers {
public AdminRegistrationPage() {
add(new RegistrationPanel("registrationPanel"));

@ -1,8 +1,22 @@
<!DOCTYPE html>
<html xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd">
<body>
<wicket:extend>
<div wicket:id="adminRolesPanel"></div>
<wicket:extend>
<div class="row">
<div class="col-md-12">
<div wicket:id="feedback"></div>
</div>
</div>
<div wicket:id="editUserDialog"></div>
<div class="row">
<div class="col-md-5 col-md-offset-1">
<label>Search: <input type="text" wicket:id="searchField" /></label>
<label><input type="checkbox" wicket:id="internalUsersOnly" /> <wicket:message key="internal.users.only"/></label>
</div>
<div wicket:id="view" class="col-md-6"></div>
</div>
<div wicket:id="userDataView"></div>
<wicket:fragment wicket:id="roleCheckbox"><input type="checkbox" wicket:id="checkbox" /></wicket:fragment>
</wicket:extend>
</body>
</html>

@ -1,12 +1,212 @@
package se.su.dsv.scipro.admin.pages;
import se.su.dsv.scipro.admin.panels.AdminRolesPanel;
import org.apache.wicket.Component;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.attributes.AjaxRequestAttributes;
import org.apache.wicket.ajax.attributes.ThrottlingSettings;
import org.apache.wicket.ajax.form.OnChangeAjaxBehavior;
import org.apache.wicket.ajax.markup.html.form.AjaxCheckBox;
import org.apache.wicket.extensions.ajax.markup.html.AjaxLazyLoadPanel;
import org.apache.wicket.extensions.markup.html.repeater.data.grid.ICellPopulator;
import org.apache.wicket.extensions.markup.html.repeater.data.table.AbstractColumn;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.panel.FeedbackPanel;
import org.apache.wicket.markup.html.panel.Fragment;
import org.apache.wicket.markup.repeater.Item;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.PropertyModel;
import org.apache.wicket.util.time.Duration;
import org.springframework.data.domain.PageRequest;
import se.su.dsv.scipro.components.ModalWindowPlus;
import se.su.dsv.scipro.data.dataobjects.Employee;
import se.su.dsv.scipro.data.dataobjects.Role;
import se.su.dsv.scipro.data.dataobjects.User;
import se.su.dsv.scipro.datatables.AjaxLinkColumn;
import se.su.dsv.scipro.datatables.GenericDataPanel;
import se.su.dsv.scipro.match.panel.FilterFormCheckBoxPanel;
import se.su.dsv.scipro.reusable.SciProUtilities;
import se.su.dsv.scipro.security.auth.Authorization;
import se.su.dsv.scipro.security.auth.roles.Roles;
import se.su.dsv.scipro.springdata.services.GenericService;
import se.su.dsv.scipro.springdata.services.RoleService;
import se.su.dsv.scipro.springdata.services.UserService;
import se.su.dsv.scipro.user.panels.UserProfilePanelFactory;
import javax.inject.Inject;
import java.text.MessageFormat;
import java.util.Iterator;
import java.util.List;
@Authorization(authorizedRoles={Roles.ADMIN})
public class AdminRolePage extends AbstractAdminUsersPage {
public AdminRolePage() {
add(new AdminRolesPanel("adminRolesPanel"));
}
@Inject
private UserProfilePanelFactory userProfilePanelFactory;
@Inject
private UserService userService;
@Inject
private RoleService roleService;
private UserService.Filter filter = new UserService.Filter();
private GenericDataPanel<User> dataPanel;
private ModalWindowPlus editUserModalWindowPlus;
public AdminRolePage() {
add(new FeedbackPanel("feedback"));
addFilter();
addDataPanel();
setupEditUserDialog();
}
private void addFilter() {
addRoleFilter();
addNameFilter();
addInternalUserFilter();
}
private void addInternalUserFilter() {
add(new AjaxCheckBox(INTERNAL_USER_FILTER, new PropertyModel<Boolean>(filter, "internalUsersOnly")) {
@Override
protected void onUpdate(AjaxRequestTarget target) {
target.add(dataPanel);
}
});
}
private void addNameFilter() {
TextField<String> searchField = new TextField<String>(NAME_FILTER, new PropertyModel<String>(filter, "name"));
OnChangeAjaxBehavior userSearchTextBehaviour = new OnChangeAjaxBehavior() {
@Override
protected void onUpdate(AjaxRequestTarget target) {
target.add(dataPanel.getWMC());
}
@Override
protected void updateAjaxAttributes(AjaxRequestAttributes attributes) {
super.updateAjaxAttributes(attributes);
attributes.setThrottlingSettings(new ThrottlingSettings(getId(), Duration.milliseconds(500L), true));
}
};
searchField.add(userSearchTextBehaviour);
add(searchField);
}
private void addRoleFilter() {
add(new FilterFormCheckBoxPanel<Roles>(ROLE_FILTER, "Role") {
@Override
public void ajaxUpdate(AjaxRequestTarget target) {
filter.setRoles(getSelection());
target.add(dataPanel.getWMC());
}
@Override
protected List<Roles> choices() {
return Roles.managed();
}
});
}
private void setupEditUserDialog() {
editUserModalWindowPlus = new ModalWindowPlus("editUserDialog");
add(editUserModalWindowPlus);
}
public void addDataPanel() {
add(new AjaxLazyLoadPanel(USER_DATA_PANEL) {
@Override
public Component getLazyLoadComponent(String markupId) {
return createDataPanel(markupId);
}
});
}
private GenericDataPanel<User> createDataPanel(final String markupId) {
return dataPanel = new GenericDataPanel<User>(markupId) {
@Override
public Iterator<? extends User> getIterator() {
return userService.findAll(filter, new PageRequest((int) getTable().getCurrentPage(), (int) getTable().getItemsPerPage(), getSort())).iterator();
}
@Override
public long getSize() {
return SciProUtilities.safeLongToInt(userService.count(filter));
}
@Override
public GenericService<User, Long> getService() {
return userService;
}
@Override
public String getSortString() {
return "dateCreated";
}
@Override
public void addColumns() {
List<Roles> roles = Roles.managed();
getColumns().add(createUserColumn());
for (final Roles role : roles) {
getColumns().add(createRoleColumn(role));
}
}
};
}
private AbstractColumn<User, String> createUserColumn() {
return new AbstractColumn<User, String>(Model.of("Name"), "fullName") {
@Override
public void populateItem(Item<ICellPopulator<User>> cellItem, String componentId, final IModel<User> rowModel) {
cellItem.add(new AjaxLinkColumn<User>(componentId, rowModel) {
@Override
public void onClick(AjaxRequestTarget target, IModel<User> clickedModel) {
editUserModalWindowPlus.setContent(userProfilePanelFactory.createUserProfilePanelForUser(editUserModalWindowPlus.getContentId(), clickedModel.getObject(), editUserModalWindowPlus));
editUserModalWindowPlus.setTitle("Edit user");
editUserModalWindowPlus.show(target);
}
@Override
public String labelString() {
User user = rowModel.getObject();
return MessageFormat.format("{0} {1} <{2}>", user.getFirstName(), user.getLastName(), user.getEmailAddress());
}
});
}
};
}
private AbstractColumn<User, String> createRoleColumn(final Roles role) {
return new AbstractColumn<User, String>(Model.of(role.name())) {
@Override
public void populateItem(Item<ICellPopulator<User>> cellItem, String componentId, final IModel<User> rowModel) {
Fragment fragment = new Fragment(componentId, "roleCheckbox", AdminRolePage.this);
fragment.add(new AjaxCheckBox("checkbox", Model.of(roleService.hasRole(rowModel.getObject(), role))) {
@Override
protected void onUpdate(AjaxRequestTarget target) {
if (getModelObject()) {
Role r = roleService.addRole(rowModel.getObject(), role);
if (role.equals(Roles.EMPLOYEE)) {
roleService.addLanguages((Employee) r);
}
} else {
roleService.deleteRole(rowModel.getObject(), role);
}
}
});
cellItem.add(fragment);
}
};
}
static final String INTERNAL_USER_FILTER = "internalUsersOnly";
static final String NAME_FILTER = "searchField";
static final String ROLE_FILTER = "view";
static final String USER_DATA_PANEL = "userDataView";
}

@ -0,0 +1 @@
internal.users.only: Only show internal users

@ -1,22 +0,0 @@
<!DOCTYPE html>
<html
xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd">
<body>
<wicket:panel>
<div class="row">
<div class="col-md-12">
<div wicket:id="feedback"></div>
</div>
</div>
<div wicket:id="editUserDialog"></div>
<div class="row">
<div class="col-md-5 col-md-offset-1">
<label>Search: <input type="text" wicket:id="searchField" /></label>
</div>
<div wicket:id="view" class="col-md-6"></div>
</div>
<div wicket:id="userDataView"></div>
<wicket:fragment wicket:id="roleCheckbox"><input type="checkbox" wicket:id="checkbox" /></wicket:fragment>
</wicket:panel>
</body>
</html>

@ -1,201 +0,0 @@
package se.su.dsv.scipro.admin.panels;
import org.apache.wicket.Component;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.attributes.AjaxRequestAttributes;
import org.apache.wicket.ajax.attributes.ThrottlingSettings;
import org.apache.wicket.ajax.form.OnChangeAjaxBehavior;
import org.apache.wicket.ajax.markup.html.form.AjaxCheckBox;
import org.apache.wicket.extensions.ajax.markup.html.AjaxLazyLoadPanel;
import org.apache.wicket.extensions.markup.html.repeater.data.grid.ICellPopulator;
import org.apache.wicket.extensions.markup.html.repeater.data.table.AbstractColumn;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.panel.FeedbackPanel;
import org.apache.wicket.markup.html.panel.Fragment;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.markup.repeater.Item;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.PropertyModel;
import org.apache.wicket.util.time.Duration;
import org.springframework.data.domain.PageRequest;
import se.su.dsv.scipro.components.ModalWindowPlus;
import se.su.dsv.scipro.data.dataobjects.Employee;
import se.su.dsv.scipro.data.dataobjects.Role;
import se.su.dsv.scipro.data.dataobjects.User;
import se.su.dsv.scipro.datatables.AjaxLinkColumn;
import se.su.dsv.scipro.datatables.GenericDataPanel;
import se.su.dsv.scipro.match.panel.FilterFormCheckBoxPanel;
import se.su.dsv.scipro.reusable.SciProUtilities;
import se.su.dsv.scipro.security.auth.roles.Roles;
import se.su.dsv.scipro.springdata.services.GenericService;
import se.su.dsv.scipro.springdata.services.RoleService;
import se.su.dsv.scipro.springdata.services.UserService;
import se.su.dsv.scipro.user.panels.UserProfilePanelFactory;
import javax.inject.Inject;
import java.text.MessageFormat;
import java.util.Iterator;
import java.util.List;
public class AdminRolesPanel extends Panel {
@Inject
UserProfilePanelFactory userProfilePanelFactory;
@Inject
UserService userService;
@Inject
RoleService roleService;
private UserService.Filter filter = new UserService.Filter();
private GenericDataPanel<User> dataPanel;
private ModalWindowPlus editUserModalWindowPlus;
public AdminRolesPanel(String id) {
super(id);
add(new FeedbackPanel("feedback"));
addFilter();
addDataPanel();
setupEditUserDialog();
}
private void addFilter() {
addRoleFilter();
addNameFilter();
}
private void addNameFilter() {
TextField<String> searchField = new TextField<String>(NAME_FILTER, new PropertyModel<String>(filter, "name"));
OnChangeAjaxBehavior userSearchTextBehaviour = new OnChangeAjaxBehavior() {
@Override
protected void onUpdate(AjaxRequestTarget target) {
target.add(dataPanel.getWMC());
}
@Override
protected void updateAjaxAttributes(AjaxRequestAttributes attributes) {
super.updateAjaxAttributes(attributes);
attributes.setThrottlingSettings(new ThrottlingSettings(getId(), Duration.milliseconds(500L), true));
}
};
searchField.add(userSearchTextBehaviour);
add(searchField);
}
private void addRoleFilter() {
add(new FilterFormCheckBoxPanel<Roles>(ROLE_FILTER, "Role") {
@Override
public void ajaxUpdate(AjaxRequestTarget target) {
filter.setRoles(getSelection());
target.add(dataPanel.getWMC());
}
@Override
protected List<Roles> choices() {
return Roles.managed();
}
});
}
private void setupEditUserDialog() {
editUserModalWindowPlus = new ModalWindowPlus("editUserDialog");
add(editUserModalWindowPlus);
}
public void addDataPanel() {
add(new AjaxLazyLoadPanel(USER_DATA_PANEL) {
@Override
public Component getLazyLoadComponent(String markupId) {
return createDataPanel(markupId);
}
});
}
private GenericDataPanel<User> createDataPanel(final String markupId) {
return dataPanel = new GenericDataPanel<User>(markupId) {
@Override
public Iterator<? extends User> getIterator() {
return userService.findAll(filter, new PageRequest((int) getTable().getCurrentPage(), (int) getTable().getItemsPerPage(), getSort())).iterator();
}
@Override
public long getSize() {
return SciProUtilities.safeLongToInt(userService.count(filter));
}
@Override
public GenericService<User, Long> getService() {
return userService;
}
@Override
public String getSortString() {
return "dateCreated";
}
@Override
public void addColumns() {
List<Roles> roles = Roles.managed();
getColumns().add(createUserColumn());
for (final Roles role : roles) {
getColumns().add(createRoleColumn(role));
}
}
};
}
private AbstractColumn<User, String> createUserColumn() {
return new AbstractColumn<User, String>(Model.of("Name"), "fullName") {
@Override
public void populateItem(Item<ICellPopulator<User>> cellItem, String componentId, final IModel<User> rowModel) {
cellItem.add(new AjaxLinkColumn<User>(componentId, rowModel) {
@Override
public void onClick(AjaxRequestTarget target, IModel<User> clickedModel) {
editUserModalWindowPlus.setContent(userProfilePanelFactory.createUserProfilePanelForUser(editUserModalWindowPlus.getContentId(), clickedModel.getObject(), editUserModalWindowPlus));
editUserModalWindowPlus.setTitle("Edit user");
editUserModalWindowPlus.show(target);
}
@Override
public String labelString() {
User user = rowModel.getObject();
return MessageFormat.format("{0} {1} <{2}>", user.getFirstName(), user.getLastName(), user.getEmailAddress());
}
});
}
};
}
private AbstractColumn<User, String> createRoleColumn(final Roles role) {
return new AbstractColumn<User, String>(Model.of(role.name())) {
@Override
public void populateItem(Item<ICellPopulator<User>> cellItem, String componentId, final IModel<User> rowModel) {
Fragment fragment = new Fragment(componentId, "roleCheckbox", AdminRolesPanel.this);
fragment.add(new AjaxCheckBox("checkbox", Model.of(roleService.hasRole(rowModel.getObject(), role))) {
@Override
protected void onUpdate(AjaxRequestTarget target) {
if (getModelObject()) {
Role r = roleService.addRole(rowModel.getObject(), role);
if (role.equals(Roles.EMPLOYEE)) {
roleService.addLanguages((Employee) r);
}
} else {
roleService.deleteRole(rowModel.getObject(), role);
}
}
});
cellItem.add(fragment);
}
};
}
static final String NAME_FILTER = "searchField";
static final String ROLE_FILTER = "view";
static final String USER_DATA_PANEL = "userDataView";
}

@ -0,0 +1,4 @@
package se.su.dsv.scipro.components.menuhighlighting;
public interface MenuHighlightAdminInternalUsers extends MenuHighlight {
}

@ -36,8 +36,8 @@ public class RepositoryDownloadPage extends WebPage {
}
try {
String uuid = pp != null ? pp.get(PP_KEY).toString() : "";
FileDescription fd = fileDescriptionService.retrieveByIdentifier(uuid);
Long uuid = pp.get(PP_KEY).toLong();
FileDescription fd = fileDescriptionService.findOne(uuid);
final SciProFileStream sciProFileStream = fileDescriptionService.getFileStream(fd);
IResourceStream stream = new SciProViewResourceStream(sciProFileStream);
getRequestCycle().scheduleRequestHandlerAfterCurrent(new ResourceStreamRequestHandler(stream, fd.getName()));
@ -78,7 +78,7 @@ public class RepositoryDownloadPage extends WebPage {
*/
public static synchronized PageParameters getPageParameters(FileDescription fileDescription) {
PageParameters result = new PageParameters();
result.add(PP_KEY, fileDescription.getIdentifier());
result.add(PP_KEY, fileDescription.getId());
return result;
}

@ -0,0 +1,85 @@
package se.su.dsv.scipro.admin.pages;
import org.apache.wicket.request.mapper.parameter.PageParameters;
import org.apache.wicket.util.tester.FormTester;
import org.junit.Test;
import se.su.dsv.scipro.SciProTest;
import se.su.dsv.scipro.data.dataobjects.User;
import se.su.dsv.scipro.test.UserBuilder;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyLong;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static se.su.dsv.scipro.admin.pages.AdminEditInternalUserPage.EMAIL_ADDRESS;
import static se.su.dsv.scipro.admin.pages.AdminEditInternalUserPage.FIRST_NAME;
import static se.su.dsv.scipro.admin.pages.AdminEditInternalUserPage.FORM;
import static se.su.dsv.scipro.admin.pages.AdminEditInternalUserPage.LAST_NAME;
import static se.su.dsv.scipro.data.dataobjects.User.USER_ID;
public class AdminEditInternalUserPageTest extends SciProTest {
private User user;
@Test
public void renders_with_user_parameters() throws Exception {
startPageWithPageParameters();
tester.assertRenderedPage(AdminEditInternalUserPage.class);
}
@Test
public void redirects_without_valid_parameter() throws Exception {
tester.startPage(AdminEditInternalUserPage.class);
tester.assertRenderedPage(AdminInternalUsersPage.class);
}
@Test
public void assert_form_fields() throws Exception {
startPageWithPageParameters();
tester.assertModelValue(path(FORM, FIRST_NAME), user.getFirstName());
tester.assertModelValue(path(FORM, LAST_NAME), user.getLastName());
tester.assertModelValue(path(FORM, EMAIL_ADDRESS), user.getEmailAddress());
}
@Test
public void submit_with_valid_data_saves_user() throws Exception {
startPageWithPageParameters();
submitForm("valid@email.com");
verify(userService).save(user);
}
@Test
public void submit_with_invalid_email_does_not_save() throws Exception {
startPageWithPageParameters();
submitForm("invalid email");
verify(userService, never()).save(any(User.class));
}
@Test
public void submit_redirects_to_user_list_page() throws Exception {
startPageWithPageParameters();
submitForm("valid@email.com");
tester.assertRenderedPage(AdminInternalUsersPage.class);
}
private void submitForm(String emailAddress) {
FormTester formTester = tester.newFormTester(FORM);
formTester.setValue(FIRST_NAME, "new first name");
formTester.setValue(LAST_NAME, "new last name");
formTester.setValue(EMAIL_ADDRESS, emailAddress);
formTester.submit();
}
private AdminEditInternalUserPage startPageWithPageParameters() {
user = new UserBuilder().setFirstName("First").setLastName("Last").create();
when(userService.findOne(anyLong())).thenReturn(user);
return tester.startPage(AdminEditInternalUserPage.class, getPageParameters());
}
private PageParameters getPageParameters() {
PageParameters parameters = new PageParameters();
parameters.set(USER_ID, 1L);
return parameters;
}
}

@ -8,6 +8,7 @@ import se.su.dsv.scipro.test.UserBuilder;
import java.util.Arrays;
import java.util.List;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static se.su.dsv.scipro.admin.pages.AdminInternalUsersPage.NAME;
import static se.su.dsv.scipro.admin.pages.AdminInternalUsersPage.REGISTRATION_LINK;
@ -20,6 +21,7 @@ public class AdminInternalUsersPageTest extends SciProTest {
@Test
public void renders() throws Exception {
startPage();
tester.assertRenderedPage(AdminInternalUsersPage.class);
}
@Test
@ -43,6 +45,14 @@ public class AdminInternalUsersPageTest extends SciProTest {
tester.assertLabel(path(USER_LIST, FIRST_USER, NAME), users.get(FIRST_USER).getFullName());
}
@Test
public void edit_user() throws Exception {
mockUserList();
startPage();
tester.clickLink(path(USER_LIST, FIRST_USER, AdminInternalUsersPage.EDIT));
tester.assertRenderedPage(AdminEditInternalUserPage.class);
}
private List<User> mockUserList() {
List<User> users = Arrays.asList(createUser());
when(userService.findInternalUsers()).thenReturn(users);

@ -1,17 +1,70 @@
package se.su.dsv.scipro.admin.pages;
import org.apache.wicket.extensions.ajax.markup.html.AjaxLazyLoadPanel;
import org.apache.wicket.extensions.ajax.markup.html.AjaxLazyLoadPanelTester;
import org.apache.wicket.markup.html.form.CheckBox;
import org.apache.wicket.markup.html.form.FormComponent;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import se.su.dsv.scipro.SciProTest;
import se.su.dsv.scipro.springdata.services.UserService;
import se.su.dsv.scipro.user.panels.UserProfilePanelFactory;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.verify;
import static se.su.dsv.scipro.admin.pages.AdminRolePage.INTERNAL_USER_FILTER;
import static se.su.dsv.scipro.admin.pages.AdminRolePage.USER_DATA_PANEL;
public class AdminRolePageTest extends SciProTest {
@Mock
private UserProfilePanelFactory userProfilePanelFactory;
@Test
public void renders() throws Exception {
tester.startPage(AdminRolePage.class);
startPage();
tester.assertRenderedPage(AdminRolePage.class);
}
@Test
public void has_checkbox_for_internal_users_only() throws Exception {
startPage();
tester.assertComponent(path(INTERNAL_USER_FILTER), CheckBox.class);
}
@Test
public void checking_internal_users_should_refresh_table() throws Exception {
startPage();
clickInternalUsersCheckbox();
tester.assertComponentOnAjaxResponse(path(USER_DATA_PANEL, AjaxLazyLoadPanel.LAZY_LOAD_COMPONENT_ID));
}
@Test
public void checking_internal_users_should_set_filter() throws Exception {
startPage();
selectInternalUsersCheckbox();
assertInternalUserFlagIsSetOnFilter();
}
private void assertInternalUserFlagIsSetOnFilter() {
ArgumentCaptor<UserService.Filter> captor = ArgumentCaptor.forClass(UserService.Filter.class);
verify(userService, atLeastOnce()).count(captor.capture());
assertTrue(captor.getValue().isInternalUsersOnly());
}
private void selectInternalUsersCheckbox() {
FormComponent<?> internalUsersOnly = (FormComponent<?>) tester.getComponentFromLastRenderedPage(path(INTERNAL_USER_FILTER));
tester.getRequest().setParameter(internalUsersOnly.getInputName(), Boolean.toString(true));
clickInternalUsersCheckbox();
}
private void clickInternalUsersCheckbox() {
tester.executeAjaxEvent(path(INTERNAL_USER_FILTER), "click");
}
private void startPage() {
tester.startPage(AdminRolePage.class);
AjaxLazyLoadPanelTester.executeAjaxLazyLoadPanel(tester, tester.getLastRenderedPage());
}
}

@ -31,7 +31,7 @@ public class ExaminerReviewDialogPanelTest extends SciProTest {
when(generalSystemSettingsService.getGeneralSystemSettingsInstance()).thenReturn(new GeneralSystemSettings());
FinalSeminarSettings settings = new FinalSeminarSettings();
when(finalSeminarSettingsService.getInstance()).thenReturn(settings);
startPanel();
startPanel();
}
@Test
@ -41,7 +41,7 @@ public class ExaminerReviewDialogPanelTest extends SciProTest {
@Test
public void panelContainsThesisPanel() throws Exception {
tester.assertComponent(path(panel.getId(), ExaminerReviewDialogPanel.THESIS), SeminarThesisPanel.class);
tester.assertComponent(path(panel.getId(), ExaminerReviewDialogPanel.THESIS), SeminarThesisPanel.class);
}
@Test
@ -53,14 +53,15 @@ public class ExaminerReviewDialogPanelTest extends SciProTest {
public void panelContainsViewThesisCommentPanel() throws Exception {
tester.assertComponent(path(panel.getId(), ExaminerReviewDialogPanel.VIEW_COMMENTS), ViewThesisCommentsPanel.class);
}
private void startPanel() {
final FinalSeminar seminar = new SeminarBuilder().create();
private void startPanel() {
final FinalSeminar seminar = new SeminarBuilder().create();
seminar.setExaminer(examiner);
FileDescription document = new FileDescription();
document.setIdentifier("1");
document.setId(1L);
seminar.setDocument(document);
panel = tester.startComponentInPage(new ExaminerReviewDialogPanel("panel", Model.of(seminar)));
}
}
}

@ -36,6 +36,7 @@ public class FileDescriptionPanelTest extends SciProTest {
User user = new UserBuilder().create();
fileDescription = new FileDescription();
fileDescription.setIdentifier("1");
fileDescription.setId(1L);
fileDescription.setUserId(user.getId());
when(dateService.getFormat(isA(DateStyle.class))).thenReturn("yyyy-mm-dd");

@ -68,6 +68,7 @@ public class LatestUploadPanelTest extends SciProTest {
FileDescription fd = new FileDescription();
fd.setUserId(1L);
fd.setIdentifier("1");
fd.setId(1L);
when(fileDescriptionService.latestUpload(isA(Project.class))).thenReturn(fd);
when(userService.findOne(isA(Long.class))).thenReturn(project.getHeadSupervisor().getUser());
startPanel();

@ -95,6 +95,7 @@ public class ForumPostDetailsPanelTest extends SciProTest {
FileDescription attachment = new FileDescription();
attachment.setPath("/foo");
attachment.setIdentifier("1");
attachment.setId(1L);
post.setAttachment(attachment);
startPanel(post);

@ -38,6 +38,7 @@ public class AdminPeerReviewPageTest extends SciProTest {
FileDescription fileDescription = new FileDescription();
fileDescription.setIdentifier("some_file.pdf");
fileDescription.setId(1L);
PeerRequest peerRequest = new PeerRequest();
peerRequest.setProject(project);

@ -47,6 +47,7 @@ public class ProjectPeerReviewPageTest extends PageTest {
file.setIdentifier("identifier");
file.setName("some file name");
file.setPath("/fake/path");
file.setId(1L);
peerRequest.setFile(file);
peerReview.setPeerRequest(peerRequest);
peerReview.setReviewer(RoleBuilder.asStudent(user));

@ -76,6 +76,7 @@ public class SupervisorPeerReviewPageTest extends PageTest {
FileDescription fileDescription = new FileDescription();
fileDescription.setMimeType("");
fileDescription.setIdentifier("");
fileDescription.setId(1L);
return fileDescription;
}
}

@ -166,6 +166,7 @@ public class FinalThesisPanelTest extends SciProTest {
FileDescription fileDescription = new FileDescription();
fileDescription.setIdentifier("identifier");
fileDescription.setUserId(1L);
fileDescription.setId(1L);
when(finalThesisService.hasFinalThesis(SOME_PROJECT)).thenReturn(true);
when(finalThesisService.getFinalThesisFileDescription(SOME_PROJECT)).thenReturn(fileDescription);
return fileDescription;

@ -37,6 +37,7 @@ public class FileDownloadLinkTest extends SciProTest {
FileDescription fileDescription = new FileDescription();
fileDescription.setName(SOME_FILE_NAME);
fileDescription.setIdentifier("identifier");
fileDescription.setId(1L);
tester.startComponentInPage(new FileDownloadLink("id", Model.of(fileDescription), body));
}

@ -21,6 +21,7 @@ public class ViewAttachmentPanelTest extends SciProTest {
public void setUp() throws Exception {
fileDescription = new FileDescription();
fileDescription.setIdentifier("1");
fileDescription.setId(1L);
}
@Test

@ -36,6 +36,7 @@ public class SeminarThesisPanelTest extends SciProTest {
fileDescription = new FileDescription();
fileDescription.setIdentifier("1");
fileDescription.setId(1L);
}
@Test

@ -109,6 +109,7 @@ public class ViewThesisCommentsPanelTest extends SciProTest {
review.setFinalSeminar(seminar);
FileDescription thesisReview = new FileDescription();
thesisReview.setIdentifier("1");
thesisReview.setId(1L);
review.setThesisReview(thesisReview);
review.setUploader(uploader);
return review;

@ -229,6 +229,7 @@ public class ApproveFinalThesisPanelTest extends SciProTest {
FileDescription fileDescription = new FileDescription();
fileDescription.setName("this is the file");
fileDescription.setIdentifier("file");
fileDescription.setId(1L);
FinalThesis finalThesis = new FinalThesis();
finalThesis.setProject(SOME_PROJECT);