--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/java/org/iri_research/renkan/controller/admin/GroupsAdminController.java Wed Dec 11 10:23:05 2013 +0100
@@ -0,0 +1,188 @@
+package org.iri_research.renkan.controller.admin;
+
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.util.Locale;
+
+import javax.inject.Inject;
+import javax.servlet.http.HttpServletRequest;
+import javax.validation.Valid;
+
+import org.apache.commons.codec.binary.Hex;
+import org.iri_research.renkan.Constants;
+import org.iri_research.renkan.RenkanException;
+import org.iri_research.renkan.controller.Utils;
+import org.iri_research.renkan.forms.GroupForm;
+import org.iri_research.renkan.forms.GroupFormValidator;
+import org.iri_research.renkan.models.Group;
+import org.iri_research.renkan.repositories.GroupsRepository;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.propertyeditors.StringTrimmerEditor;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.domain.Sort.Direction;
+import org.springframework.data.web.PageableDefault;
+import org.springframework.http.HttpStatus;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.validation.BindingResult;
+import org.springframework.web.bind.WebDataBinder;
+import org.springframework.web.bind.annotation.InitBinder;
+import org.springframework.web.bind.annotation.ModelAttribute;
+import org.springframework.web.bind.annotation.PathVariable;
+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.client.HttpClientErrorException;
+
+@Controller
+@RequestMapping("/admin/groups")
+public class GroupsAdminController {
+
+ private final Logger logger = LoggerFactory
+ .getLogger(GroupsAdminController.class);
+
+ @Inject
+ private GroupsRepository groupsRepository;
+
+
+ @InitBinder(value = { "group" })
+ protected void initBinder(WebDataBinder binder) {
+ binder.setValidator(new GroupFormValidator());
+ }
+
+ @InitBinder
+ public void initDateBinder(final WebDataBinder dataBinder, final Locale locale) {
+ dataBinder.registerCustomEditor(String.class, new StringTrimmerEditor(true));
+ }
+
+ @RequestMapping(value = "", method = RequestMethod.GET, produces = { "text/html;charset=UTF-8" })
+ public String groupsList(
+ Model model,
+ @PageableDefault(sort = { "title" }, direction = Direction.DESC, page = 0, value = Constants.PAGINATION_SIZE) Pageable p,
+ HttpServletRequest request) {
+
+ Page<Group> page = this.groupsRepository.findAll(p);
+
+ model.addAttribute("page", page);
+ model.addAttribute("baseUrl", Utils.buildBaseUrl(request));
+ //TODO: add user count
+
+ return "admin/groupsList";
+ }
+
+ @RequestMapping(value = "/edit/", method = RequestMethod.GET, produces = { "text/html;charset=UTF-8" })
+ public String editGroup(Model model) {
+ return editGroup(model, null);
+ }
+
+ @RequestMapping(value = "/edit/{groupId}", method = RequestMethod.GET, produces = { "text/html;charset=UTF-8" })
+ public String editGroup(Model model,
+ @PathVariable(value = "groupId") String groupId) {
+
+ GroupForm groupForm = null;
+ Group group = null;
+
+ if (groupId != null && groupId.length() > 0 && !"_".equals(groupId)) {
+ group = this.groupsRepository.findOne(groupId);
+ if (group == null) {
+ throw new HttpClientErrorException(HttpStatus.NOT_FOUND,
+ "group " + groupId + " not found");
+ }
+ }
+ groupForm = new GroupForm(group);
+
+ model.addAttribute("group", groupForm);
+
+ return "admin/groupEdit";
+ }
+
+ @RequestMapping(value = "/save", method = RequestMethod.POST)
+ public String saveGroup(Model model,
+ @ModelAttribute("group") @Valid GroupForm groupForm,
+ BindingResult bindingResult) {
+
+ logger.debug("group title " + groupForm.getTitle());
+ logger.debug("user description " + groupForm.getDescription());
+
+ if (bindingResult.hasErrors()) {
+ return "admin/groupEdit";
+ }
+
+ groupForm.setGroupsRepository(groupsRepository);
+
+ try {
+ groupForm.save();
+ } catch (RenkanException e) {
+ throw new HttpClientErrorException(HttpStatus.NOT_FOUND, "group "
+ + groupForm.getId()==null?"":groupForm.getId() + " not found");
+ }
+
+ return "redirect:/admin/groups";
+ }
+
+ @RequestMapping(value = "/delete/{groupId}")
+ public String deleteGroup(HttpServletRequest request, Model model,
+ @PathVariable(value = "groupId") String groupId,
+ @RequestParam(value = "key", required = false) String key,
+ @RequestParam(value = "salt", required = false) String salt)
+ throws NoSuchAlgorithmException, RenkanException {
+
+ if (groupId == null || groupId.length() == 0) {
+ throw new HttpClientErrorException(HttpStatus.BAD_REQUEST,
+ "Null or empty user id");
+ }
+
+ RequestMethod method = RequestMethod.valueOf(request.getMethod());
+
+ //TODO: check that group have no user
+
+
+ if (RequestMethod.GET.equals(method)) {
+
+ Group group = this.groupsRepository.findOne(groupId);
+
+ if (group == null) {
+ throw new HttpClientErrorException(HttpStatus.NOT_FOUND,
+ "group " + groupId + " not found");
+ }
+
+ SecureRandom rand = SecureRandom.getInstance("SHA1PRNG");
+ rand.setSeed(System.currentTimeMillis());
+ byte[] rawSalt = new byte[50];
+ rand.nextBytes(rawSalt);
+ String newSalt = Hex.encodeHexString(rawSalt);
+
+ model.addAttribute("groupObj", group);
+ model.addAttribute("salt", newSalt);
+ model.addAttribute("key", group.getKey(newSalt));
+
+ return "admin/groupDeleteConfirm";
+
+ } else if (RequestMethod.POST.equals(method) && key != null
+ && !key.isEmpty() && salt != null && !salt.isEmpty()) {
+
+ if (groupId != null && groupId.length() > 0) {
+
+ Group group = this.groupsRepository.findOne(groupId);
+ if (group != null) {
+ if (group.checkKey(key, salt)) {
+ this.groupsRepository.delete(groupId);
+ } else {
+ throw new HttpClientErrorException(
+ HttpStatus.BAD_REQUEST, "Key not ckecked");
+ }
+ }
+
+ }
+ return "redirect:/admin/groups";
+
+ } else {
+ throw new HttpClientErrorException(HttpStatus.BAD_REQUEST,
+ "Bad request method or parameters");
+ }
+
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/java/org/iri_research/renkan/forms/GroupForm.java Wed Dec 11 10:23:05 2013 +0100
@@ -0,0 +1,66 @@
+package org.iri_research.renkan.forms;
+
+import org.iri_research.renkan.Constants;
+import org.iri_research.renkan.models.Group;
+import org.iri_research.renkan.repositories.GroupsRepository;
+import org.iri_research.renkan.repositories.IRenkanRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+
+public class GroupForm extends RenkanForm<String, Group> {
+
+ private String avatar;
+
+ private GroupsRepository groupsRepository;
+
+
+ public GroupForm() {
+ super();
+ }
+
+ public GroupForm(Group model) {
+ super(model);
+ if (model != null) {
+ this.avatar = model.getAvatar();
+ }
+ }
+
+ public String getAvatar() {
+ return avatar;
+ }
+
+ @Override
+ protected Group getModelInstance() {
+ return new Group();
+ }
+
+ @Override
+ protected IRenkanRepository<Group, String> getRepository() {
+ return this.groupsRepository;
+ }
+
+ public GroupsRepository getGroupsRepository() {
+ return groupsRepository;
+ }
+
+
+ @Override
+ protected void saveToModel() {
+ if (this.getId() == null || this.getId().length() == 0) {
+ this.model.setId(Constants.UUID_GENERATOR.generate().toString());
+ }
+ this.model.setAvatar(this.avatar);
+
+ }
+
+ public void setAvatar(String avatar) {
+ this.avatar = avatar;
+ }
+
+
+ @Autowired
+ public void setGroupsRepository(GroupsRepository groupsRepository) {
+ this.groupsRepository = groupsRepository;
+ }
+
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/java/org/iri_research/renkan/forms/GroupFormValidator.java Wed Dec 11 10:23:05 2013 +0100
@@ -0,0 +1,27 @@
+package org.iri_research.renkan.forms;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+import org.springframework.validation.Errors;
+import org.springframework.validation.ValidationUtils;
+import org.springframework.validation.Validator;
+
+@Component
+public class GroupFormValidator implements Validator {
+
+ @SuppressWarnings("unused")
+ private Logger logger = LoggerFactory.getLogger(GroupFormValidator.class);
+
+ @Override
+ public boolean supports(Class<?> clazz) {
+ return GroupForm.class.equals(clazz);
+ }
+
+ @Override
+ public void validate(Object target, Errors errors) {
+ ValidationUtils.rejectIfEmptyOrWhitespace(errors, "title",
+ "renkan.error.name.empty");
+ }
+
+}
--- a/server/src/main/java/org/iri_research/renkan/models/Group.java Mon Dec 09 10:23:30 2013 +0100
+++ b/server/src/main/java/org/iri_research/renkan/models/Group.java Wed Dec 11 10:23:05 2013 +0100
@@ -5,6 +5,24 @@
@Document(collection = "groups")
public class Group extends AbstractRenkanModel<String> {
+ private String avatar;
+
+ public Group() {
+ }
+
+ public Group(String id, String title, String description, String uri,
+ String color) {
+ super(id, title, description, uri, color);
+ }
+
+ public String getAvatar() {
+ return avatar;
+ }
+
+ public void setAvatar(String avatar) {
+ this.avatar = avatar;
+ }
+
public String getGroupName() {
return this.getTitle();
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/java/org/iri_research/renkan/repositories/GroupsRepository.java Wed Dec 11 10:23:05 2013 +0100
@@ -0,0 +1,15 @@
+package org.iri_research.renkan.repositories;
+
+import java.util.List;
+
+import org.iri_research.renkan.models.Group;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+
+public interface GroupsRepository extends IRenkanRepository<Group, String> {
+
+ public List<Group> findByTitle(String title);
+
+ public Page<Group> findByTitle(String title, Pageable p);
+
+}
--- a/server/src/main/webapp/WEB-INF/i18n/messages.properties Mon Dec 09 10:23:30 2013 +0100
+++ b/server/src/main/webapp/WEB-INF/i18n/messages.properties Wed Dec 11 10:23:05 2013 +0100
@@ -106,3 +106,17 @@
renkan.user.roles.ROLE_SPACES_ADMIN = Space admin
renkan.user.roles.ROLE_GROUPS_ADMIN = Groups admin
+renkanAdmin.user_objects_name = Users
+renkanAdmin.user_add = Add user
+renkanAdmin.user_edit = Edit user
+renkanAdmin.user_delete = Del. user
+renkanIndex.user_url = Url
+renkanAdmin.user_confirm_delete = Do you want to delete the user with username "{0}" ?
+
+renkanAdmin.group_objects_name = Groups
+renkanAdmin.group_add = Add group
+renkanAdmin.group_edit = Edit group
+renkanAdmin.group_delete = Del. group
+renkanIndex.group_url = Url
+renkanAdmin.group_confirm_delete = Do you want to delete the group with groupname "{0}" ?
+
--- a/server/src/main/webapp/WEB-INF/i18n/messages_en.properties Mon Dec 09 10:23:30 2013 +0100
+++ b/server/src/main/webapp/WEB-INF/i18n/messages_en.properties Wed Dec 11 10:23:05 2013 +0100
@@ -116,3 +116,11 @@
renkan.user.roles.ROLE_SPACES_ADMIN = Space admin
renkan.user.roles.ROLE_GROUPS_ADMIN = Groups admin
+
+renkanAdmin.group_objects_name = Groups
+renkanAdmin.group_add = Add group
+renkanAdmin.group_edit = Edit group
+renkanAdmin.group_delete = Del. group
+renkanIndex.group_url = Url
+renkanAdmin.group_confirm_delete = Do you want to delete the group with groupname "{0}" ?
+
--- a/server/src/main/webapp/WEB-INF/i18n/messages_fr.properties Mon Dec 09 10:23:30 2013 +0100
+++ b/server/src/main/webapp/WEB-INF/i18n/messages_fr.properties Wed Dec 11 10:23:05 2013 +0100
@@ -113,3 +113,9 @@
renkan.user.roles.ROLE_SPACES_ADMIN = Admin. espace
renkan.user.roles.ROLE_GROUPS_ADMIN = Admin. groupes
+renkanAdmin.group_objects_name = Groupes
+renkanAdmin.group_add = aj. group
+renkanAdmin.group_edit = Edit. group
+renkanAdmin.group_delete = eff. group
+renkanIndex.group_url = Url
+renkanAdmin.group_confirm_delete = Voulez vous effacer le groupe "{0}" ?
--- a/server/src/main/webapp/WEB-INF/templates/admin/adminIndex.html Mon Dec 09 10:23:30 2013 +0100
+++ b/server/src/main/webapp/WEB-INF/templates/admin/adminIndex.html Wed Dec 11 10:23:05 2013 +0100
@@ -35,6 +35,9 @@
<tr>
<td colspan="2"><a href="usersList.html" th:href="@{/admin/users}" th:text="#{renkanAdmin.user_objects_name}">Users</a></td>
</tr>
+ <tr>
+ <td colspan="2"><a href="groupsList.html" th:href="@{/admin/groups}" th:text="#{renkanAdmin.group_objects_name}">Groups</a></td>
+ </tr>
</tbody>
</table>
</div>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/webapp/WEB-INF/templates/admin/groupDeleteConfirm.html Wed Dec 11 10:23:05 2013 +0100
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" th:lang="${#ctx.getLocale().toLanguageTag()}" >
+ <head>
+ <title>Renkan Admin - delete group</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <meta charset="utf-8"/>
+ <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0"/>
+
+ <link rel="shortcut icon" href="../../../static/img/favicon.ico" th:href="@{/static/img/favicon.ico}" />
+
+ <link href="../../../static/css/style.css" rel="stylesheet" th:href="@{/static/css/style.css}"/>
+ <link href="../../../static/css/index.css" rel="stylesheet" th:href="@{/static/css/index.css}"/>
+
+ <script th:remove="all" type="text/javascript" src="../../../static/lib/jquery.min.js" th:src="@{/static/lib/jquery.min.js}" ></script>
+ <script th:remove="all" type="text/javascript" src="../../../static/js/thymol.js"></script>
+ </head>
+ <body>
+ <div id="container">
+ <div id="wrapper">
+ <header id="header">
+ <h1><a href="renkanIndex.html" th:href="@{/admin}" th:text="#{renkanAdmin.renkan_admin}" id="home-link">Renkan administration</a></h1>
+ <div id="headerNav" th:include="fragment/pageFragment :: headerNavFragment"></div>
+ </header>
+ <h2><a href="groupsList.html" th:href="@{/admin/groups}" th:text="#{renkanAdmin.object_list(#{renkanAdmin.group_objects_name})}">Groups List</a> / <span th:text="#{renkanAdmin.group_delete}">Delete group</span></h2>
+ <div id="object-delete-container">
+ <div id="object-delete-question" th:text="#{renkanAdmin.group_confirm_delete(${groupObj.title})}">Do you want to Delete group with name</div>
+ <div id="object-delete-confirm-buttons"><form action="groupsList.html" th:action="@{'/admin/groups/delete/'+${groupObj.id}(key=${key},salt=${salt})}" method="post" id="yes-form"><input type="submit" name="ok" value="yes" th:value="#{question.yes}" id="yes-button"/></form><form action="groupsList.html" method="get" th:action="@{/admin/groups}" id="no-form" onsubmit="return false"><input type="submit" name="ok" value="no" th:value="#{question.no}" id="no-button" onclick="window.location.href='groupsList.html'" th:onclick="'window.location.href=\''+@{/admin/groups}+'\''"/></form></div>
+ </div>
+ </div>
+ <footer id="footer" th:substituteby="fragment/pageFragment::footerFragment">
+ <div id="version">© <span class="version-date">2013</span> <a href="http://www.iri.centrepompidou.fr" target="_blank">IRI</a> - Version <span class="version-version">0.0</span></div>
+ </footer>
+ </div>
+ </body>
+</html>
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/webapp/WEB-INF/templates/admin/groupEdit.html Wed Dec 11 10:23:05 2013 +0100
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" th:lang="${#ctx.getLocale().toLanguageTag()}" >
+ <head>
+ <title>Renkan Admin - edit user</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <meta charset="utf-8"/>
+ <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0"/>
+
+ <link rel="shortcut icon" href="../../../static/img/favicon.ico" th:href="@{/static/img/favicon.ico}" />
+
+ <link href="../../../static/css/style.css" rel="stylesheet" th:href="@{/static/css/style.css}"/>
+ <link href="../../../static/css/index.css" rel="stylesheet" th:href="@{/static/css/index.css}"/>
+ <link href='../../../static/css/spectrum.css' rel="stylesheet" th:href="@{/static/css/spectrum.css}"/>
+ <link href='../../../static/lib/jquery-ui/css/ui-lightness/jquery-ui.min.css' rel="stylesheet" th:href="@{/static/lib/jquery-ui/css/ui-lightness/jquery-ui.min.css}"/>
+
+ <script type="text/javascript" src="../../../static/lib/jquery.min.js" th:src="@{/static/lib/jquery.min.js}" ></script>
+ <script type="text/javascript" src="../../../static/lib/jquery-ui/jquery-ui.min.js" th:src="@{/static/lib/jquery-ui/jquery-ui.min.js}" ></script>
+ <script type="text/javascript" src="../../../static/lib/jquery-ui/i18n/jquery-ui-i18n.min.js" th:src="@{/static/lib/jquery-ui/i18n/jquery-ui-i18n.min.js}" ></script>
+ <script type="text/javascript" src='../../../static/lib/spectrum.js' th:src="@{/static/lib/spectrum.js}"></script>
+ <script type="text/javascript" src='../../../static/js/admin_form.js' th:src="@{/static/js/admin_form.js}"></script>
+ <script th:remove="all" type="text/javascript" src="../../../static/js/thymol.js"></script>
+ </head>
+ <body>
+ <div id="container">
+ <div id="wrapper">
+ <header id="header">
+ <h1><a href="renkanIndex.html" th:href="@{/admin}" th:text="#{renkanAdmin.renkan_admin}" id="home-link">Renkan administration</a></h1>
+ <div id="headerNav" th:include="fragment/pageFragment :: headerNavFragment"></div>
+ </header>
+ <h2><a href="groupsList.html" th:href="@{/admin/groups}" th:text="#{renkanAdmin.object_list(#{renkanAdmin.group_objects_name})}">Groups List</a> / <span th:text="#{renkanAdmin.group_edit}">Edit group</span></h2>
+ <div th:include="fragment/groupForm::groupFormFragment" id="inner-container">
+ </div>
+ </div>
+ <footer id="footer" th:substituteby="fragment/pageFragment::footerFragment">
+ <div id="version">© <span class="version-date">2013</span> <a href="http://www.iri.centrepompidou.fr" target="_blank">IRI</a> - Version <span class="version-version">0.0</span></div>
+ </footer>
+ </div>
+ </body>
+</html>
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/webapp/WEB-INF/templates/admin/groupsList.html Wed Dec 11 10:23:05 2013 +0100
@@ -0,0 +1,68 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" th:lang="${#ctx.getLocale().toLanguageTag()}" >
+ <head>
+ <title>Renkan Admin - Groups</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <meta charset="utf-8"/>
+ <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0"/>
+
+ <link rel="shortcut icon" href="../../../static/img/favicon.ico" th:href="@{/static/img/favicon.ico}"/>
+
+ <link href="../../../static/css/style.css" rel="stylesheet" th:href="@{/static/css/style.css}"/>
+ <link href="../../../static/css/index.css" rel="stylesheet" th:href="@{/static/css/index.css}"/>
+
+ <script th:remove="all" type="text/javascript" src="../../../static/lib/jquery.min.js"></script>
+ <script th:remove="all" type="text/javascript" src="../../../static/js/thymol.js"></script>
+ </head>
+ <body>
+ <div id="container">
+ <div id="wrapper">
+ <header id="header">
+ <h1><a href="renkanIndex.html" th:href="@{/admin}" th:text="#{renkanAdmin.renkan_admin}" id="home-link">Renkan administration</a></h1>
+ <div id="headerNav" th:include="fragment/pageFragment :: headerNavFragment"></div>
+ </header>
+ <h2 th:text="#{renkanAdmin.object_list(#{renkanAdmin.user_objects_name})}">List of objects</h2>
+ <div th:include="fragment/paginationFragment :: paginationFragment" class="pagination-container">
+ <div>
+ <a href="#?p.page=1"><<</a>
+ <a href="#?p.page=3"><</a>
+ <span>...</span>
+ <a href="#?p.page=2">2</a>
+ <a href="#?p.page=3">3</a>
+ <span>4</span>
+ <a href="#?p.page=5">5</a>
+ <a href="#?p.page=6">6</a>
+ <span>...</span>
+ <a href="#?p.page=5">></a>
+ <a href="#?p.page=7">>></a>
+ </div>
+ </div>
+ <div id="objects-content">
+ <ul class="object-tools">
+ <li><a href="groupEdit.html" th:href="@{/admin/groups/edit/}" th:text="#{renkanAdmin.group_add}">Add group</a></li>
+ </ul>
+ <table>
+ <thead>
+ <tr>
+ <th th:text="#{renkanAdmin.object_name}" class="object-table-title">Groupname</th>
+ <th th:text="#{renkanAdmin.object_edit}" class="object-table-actions">Edit</th>
+ <th th:text="#{renkanAdmin.object_delete}" class="object-table-actions">Delete</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr th:each="object: ${page.content}" >
+ <td th:text="${object.title}" class="object-table-title" >groupname</td>
+ <td><a href="groupEdit.html" th:href="@{'/admin/groups/edit/'+${object.id}}" th:text="#{renkanAdmin.object_edit_link}" class="object-table-actions">Edit</a></td>
+ <td><a href="#" th:href="@{'/admin/groups/delete/'+${object.id}}" th:text="#{renkanAdmin.object_delete_link}" class="users-table-actions">Delete</a></td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+
+ </div>
+ <footer id="footer" th:substituteby="fragment/pageFragment::footerFragment">
+ <div id="version">© <span class="version-date">2013</span> <a href="http://www.iri.centrepompidou.fr" target="_blank">IRI</a> - Version <span class="version-version">0.0</span></div>
+ </footer>
+ </div>
+ </body>
+</html>
\ No newline at end of file
--- a/server/src/main/webapp/WEB-INF/templates/admin/spaceDeleteConfirm.html Mon Dec 09 10:23:30 2013 +0100
+++ b/server/src/main/webapp/WEB-INF/templates/admin/spaceDeleteConfirm.html Wed Dec 11 10:23:05 2013 +0100
@@ -28,7 +28,7 @@
</div>
</div>
<footer id="footer" th:substituteby="fragment/pageFragment::footerFragment">
- <div id="version">© <span class="version-date">2013</span> <a href="http://www.iri.centrepompidou.fr" target="_blanck">IRI</a> - Version <span class="version-version">0.0</span></div>
+ <div id="version">© <span class="version-date">2013</span> <a href="http://www.iri.centrepompidou.fr" target="_blank">IRI</a> - Version <span class="version-version">0.0</span></div>
</footer>
</div>
</body>
--- a/server/src/main/webapp/WEB-INF/templates/admin/spaceEdit.html Mon Dec 09 10:23:30 2013 +0100
+++ b/server/src/main/webapp/WEB-INF/templates/admin/spaceEdit.html Wed Dec 11 10:23:05 2013 +0100
@@ -31,7 +31,7 @@
</div>
</div>
<footer id="footer" th:substituteby="fragment/pageFragment::footerFragment">
- <div id="version">© <span class="version-date">2013</span> <a href="http://www.iri.centrepompidou.fr" target="_blanck">IRI</a> - Version <span class="version-version">0.0</span></div>
+ <div id="version">© <span class="version-date">2013</span> <a href="http://www.iri.centrepompidou.fr" target="_blank">IRI</a> - Version <span class="version-version">0.0</span></div>
</footer>
</div>
</body>
--- a/server/src/main/webapp/WEB-INF/templates/admin/spacesList.html Mon Dec 09 10:23:30 2013 +0100
+++ b/server/src/main/webapp/WEB-INF/templates/admin/spacesList.html Wed Dec 11 10:23:05 2013 +0100
@@ -67,7 +67,7 @@
</div>
<footer id="footer" th:substituteby="fragment/pageFragment::footerFragment">
- <div id="version">© <span class="version-date">2013</span> <a href="http://www.iri.centrepompidou.fr" target="_blanck">IRI</a> - Version <span class="version-version">0.0</span></div>
+ <div id="version">© <span class="version-date">2013</span> <a href="http://www.iri.centrepompidou.fr" target="_blank">IRI</a> - Version <span class="version-version">0.0</span></div>
</footer>
</div>
</body>
--- a/server/src/main/webapp/WEB-INF/templates/admin/userDeleteConfirm.html Mon Dec 09 10:23:30 2013 +0100
+++ b/server/src/main/webapp/WEB-INF/templates/admin/userDeleteConfirm.html Wed Dec 11 10:23:05 2013 +0100
@@ -28,7 +28,7 @@
</div>
</div>
<footer id="footer" th:substituteby="fragment/pageFragment::footerFragment">
- <div id="version">© <span class="version-date">2013</span> <a href="http://www.iri.centrepompidou.fr" target="_blanck">IRI</a> - Version <span class="version-version">0.0</span></div>
+ <div id="version">© <span class="version-date">2013</span> <a href="http://www.iri.centrepompidou.fr" target="_blank">IRI</a> - Version <span class="version-version">0.0</span></div>
</footer>
</div>
</body>
--- a/server/src/main/webapp/WEB-INF/templates/admin/userEdit.html Mon Dec 09 10:23:30 2013 +0100
+++ b/server/src/main/webapp/WEB-INF/templates/admin/userEdit.html Wed Dec 11 10:23:05 2013 +0100
@@ -32,7 +32,7 @@
</div>
</div>
<footer id="footer" th:substituteby="fragment/pageFragment::footerFragment">
- <div id="version">© <span class="version-date">2013</span> <a href="http://www.iri.centrepompidou.fr" target="_blanck">IRI</a> - Version <span class="version-version">0.0</span></div>
+ <div id="version">© <span class="version-date">2013</span> <a href="http://www.iri.centrepompidou.fr" target="_blank">IRI</a> - Version <span class="version-version">0.0</span></div>
</footer>
</div>
</body>
--- a/server/src/main/webapp/WEB-INF/templates/admin/usersList.html Mon Dec 09 10:23:30 2013 +0100
+++ b/server/src/main/webapp/WEB-INF/templates/admin/usersList.html Wed Dec 11 10:23:05 2013 +0100
@@ -63,7 +63,7 @@
</div>
<footer id="footer" th:substituteby="fragment/pageFragment::footerFragment">
- <div id="version">© <span class="version-date">2013</span> <a href="http://www.iri.centrepompidou.fr" target="_blanck">IRI</a> - Version <span class="version-version">0.0</span></div>
+ <div id="version">© <span class="version-date">2013</span> <a href="http://www.iri.centrepompidou.fr" target="_blank">IRI</a> - Version <span class="version-version">0.0</span></div>
</footer>
</div>
</body>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/webapp/WEB-INF/templates/fragment/groupForm.html Wed Dec 11 10:23:05 2013 +0100
@@ -0,0 +1,77 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" th:lang="${#ctx.getLocale().toLanguageTag()}" >
+ <head>
+ <meta charset="utf-8"/>
+ <title>User form</title>
+ </head>
+<body>
+<div id="groupForm" th:fragment="groupFormFragment" >
+ <script type="text/javascript" th:inline="javascript">
+ //<![CDATA[
+
+ function groupFormSubmit() {
+
+ var errors = {};
+ var valid = true;
+
+ if(!$('#title').val()) {
+ errors['title'] = /*[[#{renkan.error.title.empty}]]*/"renkan.error.title.empty";
+ valid = false;
+ }
+
+ showformErrors(errors);
+
+ return valid;
+ }
+
+
+ $(function(){
+
+ $('#color').spectrum({
+ showInput: true,
+ showAlpha: true,
+ showPalette: true,
+ showInitial: true,
+ preferredFormat: 'hex'
+ });
+ $("#model-form").submit(function(e) {
+ return groupFormSubmit();
+ });
+
+ });
+ //]]>
+ </script>
+ <form action="#" th:object="${group}" th:action="@{/admin/groups/save}" method="post" id="model-form">
+ <fieldset class="form-fields">
+ <input type="hidden" th:field="*{id}" th:if="*{id}" />
+ <div>
+ <label for="title" th:text="#{renkanAdmin.form.name}">Name: </label>
+ <input type="text" th:field="*{title}" />
+ <div th:if="${#fields.hasErrors('title')}" th:errors="*{title}" class="form-error"></div>
+ </div>
+ <div>
+ <label for="uri" th:text="#{renkanAdmin.form.uri}">Uri: </label>
+ <input type="text" th:field="*{uri}" />
+ </div>
+ <div>
+ <label for="description" th:text="#{renkanAdmin.form.description}">Description: </label>
+ <textarea th:field="*{description}"></textarea>
+ </div>
+ <div>
+ <label for="color" th:text="#{renkanAdmin.form.color}">Color: </label>
+ <input type="text" th:field="*{color}" />
+ </div>
+ <div>
+ <label for="avatar" th:text="#{renkanAdmin.form.avatar}">Avatar: </label>
+ <input type="text" th:field="*{avatar}" />
+ </div>
+ <div class="submit">
+ <button type="submit" name="save" th:text="#{renkanAdmin.form.user.submit}">Save</button>
+ <!--button type="button" name="cancel" th:text="#{renkanAdmin.form.user.cancel}" th:onclick="location">Cancel</button-->
+ </div>
+
+ </fieldset>
+ </form>
+</div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/test/java/org/iri_research/renkan/test/controller/GroupsAdminControllerTest.java Wed Dec 11 10:23:05 2013 +0100
@@ -0,0 +1,451 @@
+package org.iri_research.renkan.test.controller;
+
+import java.security.SecureRandom;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.TimeZone;
+import java.util.UUID;
+
+import org.apache.commons.codec.binary.Hex;
+import org.iri_research.renkan.models.Group;
+import org.iri_research.renkan.models.Project;
+import org.iri_research.renkan.models.Space;
+import org.iri_research.renkan.models.User;
+import org.iri_research.renkan.repositories.GroupsRepository;
+import org.iri_research.renkan.repositories.ProjectsRepository;
+import org.iri_research.renkan.repositories.SpacesRepository;
+import org.iri_research.renkan.repositories.UsersRepository;
+import org.joda.time.DateTime;
+import org.joda.time.LocalDate;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.web.WebAppConfiguration;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.MvcResult;
+import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
+import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
+import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
+import org.springframework.web.client.HttpClientErrorException;
+import org.springframework.web.context.WebApplicationContext;
+import org.springframework.web.util.NestedServletException;
+
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@WebAppConfiguration
+@ContextConfiguration(locations = { "controller-context.xml",
+ "file:src/main/webapp/WEB-INF/spring-servlet.xml" })
+public class GroupsAdminControllerTest {
+
+ private final static int SPACE_NB = 3;
+ private final static int USER_NB = 3;
+ private final static int GROUP_NB = 3;
+
+ private Logger logger = LoggerFactory.getLogger(GroupsAdminControllerTest.class);
+
+ @Autowired
+ private SpacesRepository spacesRepository;
+ @Autowired
+ private ProjectsRepository projectsRepository;
+ @Autowired
+ private UsersRepository usersRepository;
+ @Autowired
+ private GroupsRepository groupsRepository;
+
+
+
+ @Autowired
+ private PasswordEncoder renkanPasswordEncoder;
+
+ private Map<String, Space> spacesList = new HashMap<String, Space>(SPACE_NB);
+ private List<String> spacesUuids = new ArrayList<>(SPACE_NB);
+
+ private ArrayList<Project> testProjects = new ArrayList<Project>();
+
+ private Map<String, User> usersList = new HashMap<String, User>(USER_NB);
+ private List<String> usersUuids = new ArrayList<>(USER_NB);
+
+ private Map<String, Group> groupsList = new HashMap<String, Group>(GROUP_NB);
+ private List<String> groupsUuids = new ArrayList<>(GROUP_NB);
+
+
+
+ @Autowired
+ private WebApplicationContext context;
+ private MockMvc mvc;
+
+ @Before
+ public void setup() {
+
+ logger.debug("Setup");
+ TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
+ spacesRepository.deleteAll();
+ projectsRepository.deleteAll();
+ usersRepository.deleteAll();
+ groupsRepository.deleteAll();
+
+ for(int i=0; i < USER_NB; i++) {
+ String uuid = UUID.randomUUID().toString();
+ User user = new User(uuid, "user" + i, "User nb " + i, "http://www.iri.centrepompidou.fr", "#ababab");
+ user.setLocked(false);
+ user.setEnabled(true);
+ user.setAvatar("A pretty picture");
+ user.setExpirationDate(new LocalDate());
+ user.setCredentialExpirationDate(new LocalDate());
+ user.setEmail(String.format("user%d@mail.com", i));
+ user = usersRepository.save(user);
+ this.usersUuids.add(uuid);
+ this.usersList.put(uuid, user);
+ }
+
+
+ for(int i=0; i < GROUP_NB; i++) {
+ String uuid = UUID.randomUUID().toString();
+ Group group = new Group(uuid, "group" + i, "Group nb " + i, "http://www.iri.centrepompidou.fr/group/"+uuid, "#ababab");
+ group.setAvatar("A pretty group picture " + i);
+ group = groupsRepository.save(group);
+ this.groupsUuids.add(uuid);
+ this.groupsList.put(uuid, group);
+ }
+
+ ArrayList<Project> pl = new ArrayList<Project>();
+ for (int i = 0; i < SPACE_NB; i++) {
+ DateTime creationDate = new DateTime();
+ String uuid = UUID.randomUUID().toString();
+ spacesUuids.add(uuid);
+ Space testSpace = new Space(uuid, "test " + i, "Test space " + 1,
+ "{}", "http://ldt.iri.centrepompidou.fr", "#ababab",
+ "test_user", "http://ldt.iri.centrepompidou.fr",
+ creationDate);
+ testSpace = spacesRepository.save(testSpace);
+ this.spacesList.put(uuid, testSpace);
+ for (int j = 0; j < SPACE_NB - 1 - i; j++) {
+ Project p = new Project(testSpace.getId(), UUID.randomUUID()
+ .toString(), "test" + ((SPACE_NB - 1) * i + j + 1),
+ "desc" + ((SPACE_NB - 1) * i + j + 1),
+ "http://localhost:8080/rest/projects/id"
+ + ((SPACE_NB - 1) * i + j + 1), creationDate);
+ p.addUser(this.usersList.get(this.usersUuids.get(0)));
+ pl.add(p);
+ }
+ try {
+ Thread.sleep(1);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+
+ for (Project p : projectsRepository.save(pl)) {
+ this.testProjects.add(p);
+ }
+
+
+
+ this.mvc = MockMvcBuilders.webAppContextSetup(this.context).build();
+ }
+
+ @After
+ public void teardown() {
+ spacesRepository.deleteAll();
+ projectsRepository.deleteAll();
+ usersRepository.deleteAll();
+ groupsRepository.deleteAll();
+
+ }
+
+ @Test
+ public void testGroupPostUpdate() throws Exception {
+
+ MockHttpServletRequestBuilder post = MockMvcRequestBuilders
+ .post("/admin/groups/save");
+ post = post.param("id", this.groupsUuids.get(0));
+ post = post.param("title", "New name");
+ post = post.param("description", "New description");
+ post = post.param("uri", "http://ldt.iri.centrepompidou.fr/new/uri");
+ post = post.param("color", "#ffffff");
+
+ this.mvc.perform(post)
+ .andExpect(MockMvcResultMatchers.status().isSeeOther())
+ .andExpect(MockMvcResultMatchers.redirectedUrl("/admin/groups"));
+
+ Group group = this.groupsRepository.findOne(this.groupsUuids.get(0));
+
+ Assert.assertNotNull("Should find space", group);
+ Assert.assertEquals("Title equals", "New name", group.getTitle());
+ Assert.assertEquals("Description equals", "New description",
+ group.getDescription());
+ Assert.assertEquals("Uri equals",
+ "http://ldt.iri.centrepompidou.fr/new/uri", group.getUri());
+ Assert.assertEquals("Color equals", "#ffffff", group.getColor());
+ }
+
+ @Test
+ public void testGroupPostCreate() throws Exception {
+
+ MockHttpServletRequestBuilder post = MockMvcRequestBuilders
+ .post("/admin/groups/save")
+ .param("title", "New name")
+ .param("description", "New description")
+ .param("uri", "http://ldt.iri.centrepompidou.fr/new/uri")
+ .param("color", "#ffffff")
+ .param("avatar", "A pretty avatar");
+
+ this.mvc.perform(post)
+ .andExpect(MockMvcResultMatchers.status().isSeeOther())
+ .andExpect(MockMvcResultMatchers.redirectedUrl("/admin/groups"));
+
+ Assert.assertEquals("Must have one more group", GROUP_NB + 1,
+ this.groupsRepository.count());
+
+ for (Group group : this.groupsRepository.findAll()) {
+ if (this.groupsList.containsKey(group.getId())) {
+ continue;
+ }
+ else {
+ Assert.assertNotNull("Should find group", group);
+ Assert.assertEquals("Title equals", "New name", group.getTitle());
+ Assert.assertEquals("Description equals", "New description",
+ group.getDescription());
+ Assert.assertEquals("Uri equals",
+ "http://ldt.iri.centrepompidou.fr/new/uri", group.getUri());
+ Assert.assertEquals("Color equals", "#ffffff", group.getColor());
+ Assert.assertEquals("Avatar equals", "A pretty avatar", group.getAvatar());
+ Assert.assertTrue(
+ "id sould match uuid regex",
+ group.getId()
+ .matches(
+ "[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}"));
+ }
+ }
+ }
+
+ @Test
+ public void testGroupPostUpdateEmptyTitle() throws Exception {
+
+ MockHttpServletRequestBuilder post = MockMvcRequestBuilders
+ .post("/admin/groups/save")
+ .param("id", this.groupsUuids.get(0))
+ .param("title", "")
+ .param("description", "New description")
+ .param("uri", "http://ldt.iri.centrepompidou.fr/new/uri")
+ .param("color", "#ffffff")
+ .param("avatar", "A pretty avatar");
+
+ this.mvc.perform(post)
+ .andExpect(MockMvcResultMatchers.status().isOk())
+ .andExpect(MockMvcResultMatchers.view().name("admin/groupEdit"))
+ .andExpect(MockMvcResultMatchers.model().hasErrors())
+ .andExpect(MockMvcResultMatchers.model().errorCount(1))
+ .andExpect(MockMvcResultMatchers.model().attributeHasErrors("group"))
+ .andExpect(MockMvcResultMatchers.model().attributeHasFieldErrors("group", "title"));
+
+ Group group = this.groupsRepository.findOne(this.groupsUuids.get(0));
+
+ Assert.assertNotNull("Should find group", group);
+ Assert.assertEquals("name equals", "group0", group.getTitle());
+
+ Assert.assertEquals("name equals", "Group nb 0", group.getDescription());
+
+ }
+
+ @Test
+ public void testGroupPostCreateEmptyName() throws Exception {
+
+ MockHttpServletRequestBuilder post = MockMvcRequestBuilders
+ .post("/admin/groups/save")
+ .param("title", "")
+ .param("description", "New description")
+ .param("uri", "http://ldt.iri.centrepompidou.fr/new/uri")
+ .param("color", "#ffffff")
+ .param("avatar", "A pretty avatar");
+
+
+ this.mvc.perform(post)
+ .andExpect(MockMvcResultMatchers.status().isOk())
+ .andExpect(MockMvcResultMatchers.view().name("admin/groupEdit"))
+ .andExpect(MockMvcResultMatchers.model().hasErrors())
+ .andExpect(MockMvcResultMatchers.model().errorCount(1))
+ .andExpect(MockMvcResultMatchers.model().attributeHasErrors("group"))
+ .andExpect(MockMvcResultMatchers.model().attributeHasFieldErrors("group", "title"));
+
+ Assert.assertEquals("Must not have one more group", GROUP_NB,this.groupsRepository.count());
+
+ }
+
+ @Test
+ public void testUserPostCreateBadPassword() throws Exception {
+
+ MockHttpServletRequestBuilder post = MockMvcRequestBuilders
+ .post("/admin/users/save")
+ .param("title", "user")
+ .param("description", "New description")
+ .param("uri", "http://ldt.iri.centrepompidou.fr/new/uri")
+ .param("color", "#ffffff")
+ .param("expirationDate","2007-11-24")
+ .param("credentialExpirationDate","2009-11-29")
+ .param("password", "test")
+ .param("passwordConfirm", "test2");
+
+ this.mvc.perform(post)
+ .andExpect(MockMvcResultMatchers.status().isOk())
+ .andExpect(MockMvcResultMatchers.view().name("admin/userEdit"))
+ .andExpect(MockMvcResultMatchers.model().hasErrors())
+ .andExpect(MockMvcResultMatchers.model().errorCount(1))
+ .andExpect(MockMvcResultMatchers.model().attributeHasErrors("user"))
+ .andExpect(MockMvcResultMatchers.model().attributeHasFieldErrors("user", "password"));
+
+ Assert.assertEquals("Must not have one more user", USER_NB,this.usersRepository.count());
+
+ }
+
+
+ @Test
+ public void testDeleteGroup() throws Exception {
+
+ MockHttpServletRequestBuilder get = MockMvcRequestBuilders
+ .get("/admin/groups/delete/"
+ + this.groupsUuids.get(GROUP_NB - 1));
+
+ MvcResult res = this.mvc
+ .perform(get)
+ .andExpect(MockMvcResultMatchers.status().isOk())
+ .andExpect(
+ MockMvcResultMatchers.view().name(
+ "admin/groupDeleteConfirm"))
+ .andExpect(
+ MockMvcResultMatchers.model().attributeExists(
+ "groupObj", "key", "salt")).andReturn();
+
+ Map<String, Object> model = res.getModelAndView().getModel();
+
+ Group group = (Group) model.get("groupObj");
+ Assert.assertNotNull("Group is not null", group);
+ Assert.assertEquals("Must be first group id",
+ this.groupsUuids.get(GROUP_NB - 1), group.getId());
+
+ String key = (String) model.get("key");
+ Assert.assertNotNull("key is not null", key);
+
+ String salt = (String) model.get("salt");
+ Assert.assertNotNull("salt is not null", salt);
+
+ Assert.assertTrue("Key must be checked", group.checkKey(key, salt));
+
+ }
+
+ @Test
+ public void testDeleteFakeGroup() throws Exception {
+
+ MockHttpServletRequestBuilder get = MockMvcRequestBuilders
+ .get("/admin/groups/delete/" + UUID.randomUUID().toString());
+
+ try {
+ this.mvc.perform(get).andExpect(
+ MockMvcResultMatchers.status().isNotFound());
+ } catch (NestedServletException e) {
+ Assert.assertNotNull("Nested exception must not be null",
+ e.getCause());
+ Assert.assertEquals(
+ "Inner exception must be a HttpClientErrorException",
+ HttpClientErrorException.class, e.getCause().getClass());
+ Assert.assertEquals("Exception error status must be not found",
+ HttpStatus.NOT_FOUND,
+ ((HttpClientErrorException) e.getCause()).getStatusCode());
+ }
+
+ }
+
+ @Test
+ public void testDoDeleteGroupNoKey() throws Exception {
+ MockHttpServletRequestBuilder post = MockMvcRequestBuilders
+ .post("/admin/groups/delete/"
+ + this.spacesUuids.get(GROUP_NB - 1));
+
+ try {
+ this.mvc.perform(post).andExpect(
+ MockMvcResultMatchers.status().isBadRequest());
+ } catch (NestedServletException e) {
+ Assert.assertNotNull("Nested exception must not be null",
+ e.getCause());
+ Assert.assertEquals(
+ "Inner exception must be a HttpClientErrorException",
+ HttpClientErrorException.class, e.getCause().getClass());
+ Assert.assertEquals("Exception error status must be not found",
+ HttpStatus.BAD_REQUEST,
+ ((HttpClientErrorException) e.getCause()).getStatusCode());
+ }
+
+ Assert.assertEquals("Must have same nb of group", GROUP_NB,
+ this.groupsRepository.count());
+
+ }
+
+ @Test
+ public void testDoDeleteGroup() throws Exception {
+
+ Group group = this.groupsList.get(this.groupsUuids.get(GROUP_NB - 1));
+
+ SecureRandom rand = SecureRandom.getInstance("SHA1PRNG");
+ rand.setSeed(System.currentTimeMillis());
+ byte[] rawSalt = new byte[50];
+ rand.nextBytes(rawSalt);
+ String salt = Hex.encodeHexString(rawSalt);
+ String key = group.getKey(salt);
+
+ MockHttpServletRequestBuilder post = MockMvcRequestBuilders.post(String
+ .format("/admin/groups/delete/%s?key=%s&salt=%s",
+ this.groupsUuids.get(GROUP_NB - 1), key, salt));
+
+ this.mvc.perform(post)
+ .andExpect(MockMvcResultMatchers.status().isSeeOther())
+ .andExpect(MockMvcResultMatchers.redirectedUrl("/admin/groups"));
+
+ Assert.assertEquals("Must have one less space", GROUP_NB - 1,
+ this.groupsRepository.count());
+
+ group = this.groupsRepository.findOne(this.groupsUuids
+ .get(GROUP_NB - 1));
+
+ Assert.assertNull("Group " + this.groupsUuids.get(GROUP_NB - 1)
+ + " deleted", group);
+
+ }
+
+ @Test
+ public void testDoDeleteGroupFake() throws Exception {
+
+ Group group = this.groupsList.get(this.groupsUuids.get(GROUP_NB - 1));
+
+ SecureRandom rand = SecureRandom.getInstance("SHA1PRNG");
+ rand.setSeed(System.currentTimeMillis());
+ byte[] rawSalt = new byte[50];
+ rand.nextBytes(rawSalt);
+ String salt = Hex.encodeHexString(rawSalt);
+ String key = group.getKey(salt);
+
+ MockHttpServletRequestBuilder post = MockMvcRequestBuilders.post(String
+ .format("/admin/groups/delete/%s?key=%s&salt=%s",
+ UUID.randomUUID(), key, salt));
+
+ this.mvc.perform(post)
+ .andExpect(MockMvcResultMatchers.status().isSeeOther())
+ .andExpect(MockMvcResultMatchers.redirectedUrl("/admin/groups"));
+
+ Assert.assertEquals("Must have the same nb of group", GROUP_NB,
+ this.groupsRepository.count());
+
+ }
+
+}
--- a/server/src/test/java/org/iri_research/renkan/test/controller/UsersAdminControllerTest.java Mon Dec 09 10:23:30 2013 +0100
+++ b/server/src/test/java/org/iri_research/renkan/test/controller/UsersAdminControllerTest.java Wed Dec 11 10:23:05 2013 +0100
@@ -132,6 +132,7 @@
public void teardown() {
spacesRepository.deleteAll();
projectsRepository.deleteAll();
+ usersRepository.deleteAll();
}
@Test
@@ -151,7 +152,7 @@
User user = this.usersRepository.findOne(this.usersUuids.get(0));
- Assert.assertNotNull("Should find space", user);
+ Assert.assertNotNull("Should find user", user);
Assert.assertEquals("Title equals", "New name", user.getTitle());
Assert.assertEquals("Description equals", "New description",
user.getDescription());
@@ -186,7 +187,7 @@
continue;
}
else {
- Assert.assertNotNull("Should find space", user);
+ Assert.assertNotNull("Should find user", user);
Assert.assertEquals("Title equals", "New name", user.getTitle());
Assert.assertEquals("Description equals", "New description",
user.getDescription());