--- a/server/pom.xml Tue Apr 02 14:05:56 2013 +0200
+++ b/server/pom.xml Wed Apr 03 17:47:23 2013 +0200
@@ -398,6 +398,11 @@
<artifactId>hibernate-validator</artifactId>
<version>4.2.0.Final</version>
</dependency>
+ <dependency>
+ <groupId>com.fasterxml.uuid</groupId>
+ <artifactId>java-uuid-generator</artifactId>
+ <version>3.1.3</version>
+ </dependency>
</dependencies>
<organization>
<name>IRI</name>
--- a/server/src/main/java/org/iri_research/renkan/controller/AdminController.java Tue Apr 02 14:05:56 2013 +0200
+++ b/server/src/main/java/org/iri_research/renkan/controller/AdminController.java Wed Apr 03 17:47:23 2013 +0200
@@ -1,13 +1,20 @@
package org.iri_research.renkan.controller;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.util.Arrays;
+import java.util.Map;
+
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.forms.SpaceForm;
import org.iri_research.renkan.forms.SpaceFormValidator;
import org.iri_research.renkan.models.Space;
+import org.iri_research.renkan.repositories.ProjectsRepository;
import org.iri_research.renkan.repositories.SpacesRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -26,6 +33,7 @@
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
@@ -37,6 +45,8 @@
@Autowired
private SpacesRepository spacesRepository;
+ @Autowired
+ private ProjectsRepository projectsRepository;
@InitBinder(value={"space"})
protected void initBinder(WebDataBinder binder) {
@@ -59,6 +69,7 @@
model.addAttribute("page", page);
model.addAttribute("baseUrl", Utils.buildBaseUrl(request));
+ model.addAttribute("projectsCount", this.projectsRepository.getCountBySpace());
return "admin/spacesList";
}
@@ -108,7 +119,78 @@
throw new HttpClientErrorException(HttpStatus.NOT_FOUND, "space " + spaceForm.getId() + " not found");
}
- return "redirect:";
+ return "redirect:/admin/spaces";
+ }
+
+ //@RequestMapping(value="/spaces/confirmdelete/{spaceId}", method = RequestMethod.GET)
+ //public String askDeleteSpace(Model model, @PathVariable(value="spaceId") String spaceId) {
+
+
+ //}
+
+ @RequestMapping(value="/spaces/delete/{spaceId}")
+ public String deleteSpace(
+ HttpServletRequest request,
+ Model model,
+ @PathVariable(value="spaceId") String spaceId,
+ @RequestParam(value="key", required=false) String key,
+ @RequestParam(value="salt", required=false) String salt) throws NoSuchAlgorithmException, RenkanException
+ {
+
+ if(spaceId == null || spaceId.length() == 0) {
+ throw new HttpClientErrorException(HttpStatus.BAD_REQUEST, "Null or empty space id");
+ }
+
+ RequestMethod method = RequestMethod.valueOf(request.getMethod());
+
+ Map<String, Integer> nbProj = this.projectsRepository.getCountBySpace(Arrays.asList(spaceId));
+ if(nbProj.containsKey(spaceId) && nbProj.get(spaceId).intValue()>0) {
+ throw new HttpClientErrorException(HttpStatus.BAD_REQUEST, "This space have projects");
+ }
+
+ if(RequestMethod.GET.equals(method)) {
+
+ Space space = this.spacesRepository.findOne(spaceId);
+
+ if(space == null) {
+ throw new HttpClientErrorException(HttpStatus.NOT_FOUND, "space " + spaceId + " 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("spaceObj", space);
+ model.addAttribute("salt", newSalt);
+ model.addAttribute("key", space.getKey(newSalt));
+
+ return "admin/spaceDeleteConfirm";
+ }
+ else if (RequestMethod.POST.equals(method) && key != null && !key.isEmpty() && salt != null && !salt.isEmpty()) {
+
+ if(spaceId != null && spaceId.length() > 0) {
+
+ Space space = this.spacesRepository.findOne(spaceId);
+ if(space != null) {
+ if(space.checkKey(key, salt)) {
+ this.spacesRepository.delete(spaceId);
+ }
+ else {
+ throw new HttpClientErrorException(HttpStatus.BAD_REQUEST, "Key not ckecked");
+ }
+ }
+
+ }
+ return "redirect:/admin/spaces";
+
+ }
+ else {
+ throw new HttpClientErrorException(HttpStatus.BAD_REQUEST, "Bad request method or parameters");
+ }
+
}
}
--- a/server/src/main/java/org/iri_research/renkan/models/Space.java Tue Apr 02 14:05:56 2013 +0200
+++ b/server/src/main/java/org/iri_research/renkan/models/Space.java Wed Apr 03 17:47:23 2013 +0200
@@ -1,7 +1,15 @@
package org.iri_research.renkan.models;
+import java.io.UnsupportedEncodingException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
import java.util.Date;
+import javax.crypto.spec.SecretKeySpec;
+
+import org.apache.commons.codec.binary.Hex;
+import org.iri_research.renkan.Constants;
+import org.iri_research.renkan.RenkanException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.Field;
@@ -69,4 +77,48 @@
this.image = image;
}
+ private String getRawKey(String salt) {
+ StringBuffer key = new StringBuffer(salt!=null?salt+"|":"");
+ key.append(this.getId());
+ key.append('|');
+ key.append(this.getCreated().getTime());
+ return key.toString();
+ }
+
+ public String getKey(String salt) throws RenkanException {
+
+ String rawKey = this.getRawKey(salt);
+
+ MessageDigest md;
+ try {
+ md = MessageDigest.getInstance("SHA-256");
+ } catch (NoSuchAlgorithmException e) {
+ throw new RenkanException("NoSuchAlgorithmException digest: " + e.getMessage(), e);
+ }
+ String key;
+ final SecretKeySpec secret_key = new SecretKeySpec(Constants.KEYHEX.getBytes(), "HmacSHA256");
+ md.update(secret_key.getEncoded());
+ try {
+ key = Hex.encodeHexString(md.digest(rawKey.getBytes("UTF-8")));
+ } catch (UnsupportedEncodingException e) {
+ throw new RenkanException("UnsupportedEncodingException digest: " + e.getMessage(), e);
+ }
+
+ return key;
+ }
+
+ public boolean checkKey(String key, String salt) throws RenkanException {
+
+
+ if(key == null || key.isEmpty()) {
+ return false;
+ }
+
+ String signature = key;
+
+ String new_key = this.getKey(salt);
+
+ return new_key.equals(signature);
+ }
+
}
\ No newline at end of file
--- a/server/src/main/java/org/iri_research/renkan/repositories/ProjectsRepositoryCustom.java Tue Apr 02 14:05:56 2013 +0200
+++ b/server/src/main/java/org/iri_research/renkan/repositories/ProjectsRepositoryCustom.java Wed Apr 03 17:47:23 2013 +0200
@@ -1,5 +1,6 @@
package org.iri_research.renkan.repositories;
+import java.util.Collection;
import java.util.Map;
import org.iri_research.renkan.models.Project;
@@ -8,6 +9,7 @@
public int getRevCounter(String projectId);
public Map<String, Integer> getCountBySpace();
+ public Map<String, Integer> getCountBySpace(Collection<String> spaceIds);
public void deleteRecursive(String projectId);
public void deleteRecursive(Project project);
--- a/server/src/main/java/org/iri_research/renkan/repositories/ProjectsRepositoryImpl.java Tue Apr 02 14:05:56 2013 +0200
+++ b/server/src/main/java/org/iri_research/renkan/repositories/ProjectsRepositoryImpl.java Wed Apr 03 17:47:23 2013 +0200
@@ -1,6 +1,7 @@
package org.iri_research.renkan.repositories;
import java.util.Arrays;
+import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
@@ -14,6 +15,7 @@
import org.springframework.data.mongodb.core.mapreduce.GroupBy;
import org.springframework.data.mongodb.core.mapreduce.GroupByResults;
+import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Update;
@Component
@@ -49,11 +51,19 @@
}
return p.getRevCounter();
}
+
@Override
- public Map<String, Integer> getCountBySpace() {
+ public Map<String, Integer> getCountBySpace(Collection<String> spaceIds) {
+
+ Criteria filter = null;
+
+ if(spaceIds != null) {
+ filter = Criteria.where("space_id").in(spaceIds);
+ }
GroupByResults<GroupResult> groupResult = this.mongoTemplate.group(
+ filter,
this.mongoTemplate.getCollectionName(Project.class),
GroupBy.key("space_id").initialDocument("{ count: 0 }").reduceFunction("function(doc, prev) { prev.count += 1; }"),
GroupResult.class);
@@ -66,6 +76,12 @@
return res;
}
+
+ @Override
+ public Map<String, Integer> getCountBySpace() {
+ return this.getCountBySpace(null);
+ }
+
@Override
public Project copy(Project p, String newTitle) {
@@ -107,5 +123,4 @@
this.projectsRepository.delete(p);
}
}
-
}
--- a/server/src/main/webapp/WEB-INF/i18n/messages_en.properties Tue Apr 02 14:05:56 2013 +0200
+++ b/server/src/main/webapp/WEB-INF/i18n/messages_en.properties Wed Apr 03 17:47:23 2013 +0200
@@ -1,5 +1,7 @@
date.format = yyyy/MM/dd HH:mm
+question.yes = yes
+question.no = no
renkanIndex.renkan_exp = Create a Renkan
renkanIndex.project_list = Renkan list
@@ -40,6 +42,8 @@
renkanAdmin.space_add = Add space
renkanAdmin.space_edit = Edit space
+renkanAdmin.space_delete = Delete space
+renkanAdmin.space_confirm_delete = Do you want to delete the space entitled "{0}" ?
renkanAdmin.object_name = Name
renkanAdmin.object_edit = Edit
--- a/server/src/main/webapp/WEB-INF/i18n/messages_fr.properties Tue Apr 02 14:05:56 2013 +0200
+++ b/server/src/main/webapp/WEB-INF/i18n/messages_fr.properties Wed Apr 03 17:47:23 2013 +0200
@@ -1,5 +1,7 @@
date.format = dd/MM/yyyy HH:mm
+question.yes = oui
+question.no = non
renkanIndex.renkan_exp = Créer un Renkan
@@ -38,6 +40,8 @@
renkanAdmin.space_objects_name = Espaces
renkanAdmin.space_add = Nouvel espace
renkanAdmin.space_edit = Edition espaces
+renkanAdmin.space_delete = Supression espace
+renkanAdmin.space_confirm_delete = Confirmez-vous l'effacement de l'espace intitulé "{0}" ?
renkanAdmin.object_name = Nom
renkanAdmin.object_edit = Modif.
--- a/server/src/main/webapp/WEB-INF/spring-servlet.xml Tue Apr 02 14:05:56 2013 +0200
+++ b/server/src/main/webapp/WEB-INF/spring-servlet.xml Wed Apr 03 17:47:23 2013 +0200
@@ -40,6 +40,7 @@
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
<property name="order" value="2" />
+ <property name="redirectHttp10Compatible" value="false" />
</bean>
<bean id="templateResolver" class="org.thymeleaf.templateresolver.ServletContextTemplateResolver">
@@ -59,6 +60,7 @@
<property name="order" value="1" />
<!--property name="viewNames" value="*.html,*.xhtml" /-->
<property name="characterEncoding" value="UTF-8"/>
+ <property name="redirectHttp10Compatible" value="false" />
</bean>
<bean class="org.springframework.context.support.ReloadableResourceBundleMessageSource" id="messageSource">
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/webapp/WEB-INF/templates/admin/spaceDeleteConfirm.html Wed Apr 03 17:47:23 2013 +0200
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" >
+ <head>
+ <title>Renkan Admin - edit space</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">
+ <h1><a href="renkanIndex.html" th:href="@{/admin}" th:text="#{renkanAdmin.renkan_admin}" id="home-link">Renkan administration</a></h1>
+ <h2><a href="spacesList.html" th:href="@{/admin/spaces}" th:text="#{renkanAdmin.object_list(#{renkanAdmin.space_objects_name})}">Spaces List</a> / <span th:text="#{renkanAdmin.space_delete}">Delete space</span></h2>
+ <div id="space-delete-container">
+ <div id="space-delete-question" th:text="#{renkanAdmin.space_confirm_delete(${spaceObj.title})}">Do you want to delete space with title</div>
+ <div id="space-delete-confirm-buttons"><form action="spacesList.html" th:action="@{'/admin/spaces/delete/'+${spaceObj.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="spacesList.html" method="get" th:action="@{/admin/spaces}" id="no-form" onsubmit="return false"><input type="submit" name="ok" value="no" th:value="#{question.no}" id="no-button" onclick="window.location.href='spacesList.html'" th:onclick="'window.location.href=\''+@{/admin/spaces}+'\''"/></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="_blanck">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/spacesList.html Tue Apr 02 14:05:56 2013 +0200
+++ b/server/src/main/webapp/WEB-INF/templates/admin/spacesList.html Wed Apr 03 17:47:23 2013 +0200
@@ -43,16 +43,18 @@
<tr>
<th th:text="#{renkanAdmin.object_name}" class="spaces-table-title">Name</th>
<th th:text="#{renkanAdmin.object_name}" class="spaces-table-created">Created</th>
+ <th th:text="#{renkanIndex.space_proj_count}">Project count</th>
<th th:text="#{renkanAdmin.object_edit}" class="spaces-table-actions">Edit</th>
<th th:text="#{renkanAdmin.object_delete}" class="spaces-table-actions">Delete</th>
</tr>
</thead>
<tbody>
- <tr th:each="object: ${page.content}">
+ <tr th:each="object: ${page.content}" th:with="spaceProjCount=${#maps.containsKey(projectsCount, object.id)}? ${projectsCount[object.id]} : 0">
<td th:text="${object.title}" class="spaces-table-title" >title</td>
<td th:text="${object.created}?${#dates.format(object.created, #messages.msg('date.format'))}:'n/a'" class="spaces-table-created">created</td>
+ <td th:text="${spaceProjCount}">nb. proj</td>
<td><a href="spaceEdit.html" th:href="@{'/admin/spaces/edit/'+${object.id}}" th:text="#{renkanAdmin.object_edit_link}" class="spaces-table-actions">Edit</a></td>
- <td><a href="#" th:href="@{'/s/'+${object.id}}" th:text="#{renkanAdmin.object_delete_link}" class="spaces-table-actions">Delete</a></td>
+ <td><a href="#" th:if="${spaceProjCount==0}" th:href="@{'/admin/spaces/delete/'+${object.id}}" th:text="#{renkanAdmin.object_delete_link}" class="spaces-table-actions">Delete</a><span th:if="${spaceProjCount>0}" class="spaces-table-actions spaces-table-actions-disabled" th:text="#{renkanAdmin.object_delete_link}">Delete</span></td>
</tr>
</tbody>
</table>
--- a/server/src/main/webapp/static/css/index.css Tue Apr 02 14:05:56 2013 +0200
+++ b/server/src/main/webapp/static/css/index.css Wed Apr 03 17:47:23 2013 +0200
@@ -212,6 +212,12 @@
width: 40px;
}
+.spaces-table-actions-disabled, .spaces-table-actions-disabled:link, .spaces-table-actions-disabled:visited, .spaces-table-actions-disabled:hover, .spaces-table-actions-disabled:active, .spaces-table-actions-disabled:focus {
+ color: gray;
+ text-decoration: none;
+ cursor: default;
+}
+
td.spaces-table-created {
text-align: center;
}
@@ -247,6 +253,27 @@
width: 650px;
height: 150px;
}
+
#binConfigDiv div {
margin-bottom: 0;
}
+
+#space-delete-container {
+ margin-left: 12px;
+ margin-top: 1em;
+}
+
+
+#space-delete-confirm-buttons {
+ margin-top: 1em;
+}
+
+#space-delete-confirm-buttons form {
+ margin: 0;
+ padding: 0;
+ display: inline;
+}
+
+#space-delete-confirm-buttons input[type=submit] {
+ margin-right: 12px;
+}
--- a/server/src/test/java/org/iri_research/renkan/test/controller/AdminControllerTest.java Tue Apr 02 14:05:56 2013 +0200
+++ b/server/src/test/java/org/iri_research/renkan/test/controller/AdminControllerTest.java Wed Apr 03 17:47:23 2013 +0200
@@ -1,5 +1,6 @@
package org.iri_research.renkan.test.controller;
+import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
@@ -7,7 +8,10 @@
import java.util.Map;
import java.util.UUID;
+import org.apache.commons.codec.binary.Hex;
+import org.iri_research.renkan.models.Project;
import org.iri_research.renkan.models.Space;
+import org.iri_research.renkan.repositories.ProjectsRepository;
import org.iri_research.renkan.repositories.SpacesRepository;
import org.junit.After;
import org.junit.Assert;
@@ -17,6 +21,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
@@ -26,7 +31,9 @@
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
@@ -39,10 +46,14 @@
@Autowired
private SpacesRepository spacesRepository;
+ @Autowired
+ private ProjectsRepository projectsRepository;
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>();
+
@Autowired
private WebApplicationContext context;
private MockMvc mvc;
@@ -53,6 +64,9 @@
logger.debug("Setup");
spacesRepository.deleteAll();
+ projectsRepository.deleteAll();
+
+ ArrayList<Project> pl = new ArrayList<Project>();
for(int i=0;i<SPACE_NB;i++) {
Date creationDate = new Date();
String uuid = UUID.randomUUID().toString();
@@ -60,6 +74,9 @@
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++) {
+ pl.add(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));
+ }
try {
Thread.sleep(1);
} catch (InterruptedException e) {
@@ -67,9 +84,20 @@
}
}
+ 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();
+ }
+
+
@Test
public void testContext() throws Exception {
MockHttpServletRequestBuilder get = MockMvcRequestBuilders.get("/");
@@ -93,8 +121,8 @@
post = post.param("binConfig", "{}");
this.mvc.perform(post)
- .andExpect(MockMvcResultMatchers.status().isMovedTemporarily())
- .andExpect(MockMvcResultMatchers.redirectedUrl(""));
+ .andExpect(MockMvcResultMatchers.status().isSeeOther())
+ .andExpect(MockMvcResultMatchers.redirectedUrl("/admin/spaces"));
Space sp = this.spacesRepository.findOne(this.spacesUuids.get(0));
@@ -118,8 +146,8 @@
post = post.param("binConfig", "{}");
this.mvc.perform(post)
- .andExpect(MockMvcResultMatchers.status().isMovedTemporarily())
- .andExpect(MockMvcResultMatchers.redirectedUrl(""));
+ .andExpect(MockMvcResultMatchers.status().isSeeOther())
+ .andExpect(MockMvcResultMatchers.redirectedUrl("/admin/spaces"));
Assert.assertEquals("Must have one more space", SPACE_NB + 1, this.spacesRepository.count());
@@ -288,10 +316,164 @@
}
+ @Test
+ public void testDeleteSpace() throws Exception {
+
+ MockHttpServletRequestBuilder get = MockMvcRequestBuilders.get("/admin/spaces/delete/"+this.spacesUuids.get(SPACE_NB-1));
+
+ MvcResult res = this.mvc.perform(get)
+ .andExpect(MockMvcResultMatchers.status().isOk())
+ .andExpect(MockMvcResultMatchers.view().name("admin/spaceDeleteConfirm"))
+ .andExpect(MockMvcResultMatchers.model().attributeExists("spaceObj", "key", "salt"))
+ .andReturn();
+
+ Map<String, Object> model = res.getModelAndView().getModel();
+
+ Space space = (Space)model.get("spaceObj");
+ Assert.assertNotNull("Space is not null", space);
+ Assert.assertEquals("Must be first space id", this.spacesUuids.get(SPACE_NB-1), space.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", space.checkKey(key, salt));
+
+ }
+
+ @Test
+ public void testDeleteFakeSpace() throws Exception {
+
+ MockHttpServletRequestBuilder get = MockMvcRequestBuilders.get("/admin/spaces/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());
+ }
+
+ }
- @After
- public void teardown() {
- spacesRepository.deleteAll();
+ @Test
+ public void testDeleteSpaceProject() throws Exception {
+
+ MockHttpServletRequestBuilder get = MockMvcRequestBuilders.get("/admin/spaces/delete/" + this.spacesUuids.get(0));
+
+ try {
+ this.mvc.perform(get)
+ .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());
+ }
+
+ }
+
+ @Test
+ public void testDoDeleteSpaceNoKey() throws Exception {
+ MockHttpServletRequestBuilder post = MockMvcRequestBuilders.post("/admin/spaces/delete/"+this.spacesUuids.get(SPACE_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 space", SPACE_NB, this.spacesRepository.count());
+
+ }
+
+ @Test
+ public void testDoDeleteSpace() throws Exception {
+
+ Space space = this.spacesList.get(this.spacesUuids.get(SPACE_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 = space.getKey(salt);
+
+
+ MockHttpServletRequestBuilder post = MockMvcRequestBuilders.post(String.format("/admin/spaces/delete/%s?key=%s&salt=%s",this.spacesUuids.get(SPACE_NB-1), key, salt));
+
+ this.mvc.perform(post)
+ .andExpect(MockMvcResultMatchers.status().isSeeOther())
+ .andExpect(MockMvcResultMatchers.redirectedUrl("/admin/spaces"));
+
+ Assert.assertEquals("Must have one less space", SPACE_NB-1, this.spacesRepository.count());
+
+ space = this.spacesRepository.findOne(this.spacesUuids.get(SPACE_NB-1));
+
+ Assert.assertNull("Space " + this.spacesUuids.get(SPACE_NB-1) + " deleted", space);
+
+ }
+
+
+ @Test
+ public void testDoDeleteSpaceFake() throws Exception {
+
+ Space space = this.spacesList.get(this.spacesUuids.get(SPACE_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 = space.getKey(salt);
+
+
+ MockHttpServletRequestBuilder post = MockMvcRequestBuilders.post(String.format("/admin/spaces/delete/%s?key=%s&salt=%s",UUID.randomUUID(), key, salt));
+
+ this.mvc.perform(post)
+ .andExpect(MockMvcResultMatchers.status().isSeeOther())
+ .andExpect(MockMvcResultMatchers.redirectedUrl("/admin/spaces"));
+
+ Assert.assertEquals("Must have the same nb of space", SPACE_NB, this.spacesRepository.count());
+
+ }
+
+ @Test
+ public void testDoDeleteSpaceProject() throws Exception {
+
+ Space space = this.spacesList.get(this.spacesUuids.get(0));
+
+ SecureRandom rand = SecureRandom.getInstance("SHA1PRNG");
+ rand.setSeed(System.currentTimeMillis());
+ byte[] rawSalt = new byte[50];
+ rand.nextBytes(rawSalt);
+ String salt = Hex.encodeHexString(rawSalt);
+ String key = space.getKey(salt);
+
+
+ MockHttpServletRequestBuilder post = MockMvcRequestBuilders.post(String.format("/admin/spaces/delete/%s?key=%s&salt=%s",this.spacesUuids.get(0), key, salt));
+
+ 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 the same nb of space", SPACE_NB, this.spacesRepository.count());
+
}
}
--- a/server/src/test/java/org/iri_research/renkan/test/repositories/ProjectsRepositoryTest.java Tue Apr 02 14:05:56 2013 +0200
+++ b/server/src/test/java/org/iri_research/renkan/test/repositories/ProjectsRepositoryTest.java Wed Apr 03 17:47:23 2013 +0200
@@ -2,6 +2,7 @@
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
@@ -206,6 +207,25 @@
}
@Test
+ public void testGetCountBySpaceFilter() {
+
+ List<String> spacesIdsFilter = Arrays.asList(this.spaceIds.get(0));
+
+ Map<String, Integer> groupRes = projectsRepository.getCountBySpace(spacesIdsFilter);
+
+ Assert.assertNotNull("GroupRes not null", groupRes);
+ Assert.assertEquals("Group res size", 1, groupRes.size());
+
+ Integer count = groupRes.get(this.spaceIds.get(0));
+ Assert.assertNotNull("count not null", count);
+ Assert.assertEquals("Nb of project/space", 2, count.intValue());
+
+ for(int i=1; i<SPACE_NB; i++) {
+ Assert.assertNull("other space id has no project i.e count is null", groupRes.get(this.spaceIds.get(i)));
+ }
+ }
+
+ @Test
public void testCopyProjectCreation() {
DBCollection coll = mongoTemplate.getCollection(mongoTemplate.getCollectionName(Project.class));