# HG changeset patch # User ymh # Date 1366728858 -7200 # Node ID a282eebbc5e0c03e8de8ca41e4e59b5ac2e0decb # Parent ff3b21d62eb8139ee5175a9d6d47daa90b98be21 - add users to Renkan diff -r ff3b21d62eb8 -r a282eebbc5e0 .classpath --- a/.classpath Tue May 14 14:10:23 2013 +0200 +++ b/.classpath Tue Apr 23 16:54:18 2013 +0200 @@ -67,7 +67,7 @@ - + @@ -195,7 +195,7 @@ - + diff -r ff3b21d62eb8 -r a282eebbc5e0 server/README.md --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/server/README.md Tue Apr 23 16:54:18 2013 +0200 @@ -0,0 +1,7 @@ +Dependencies + +- Icon user from echo-icon-theme (echo) (Open Icon Library - http://openiconlibrary.sourceforge.net/) +licence CC BY-SA - Creative Commons + +- cf pom.xml for dependencies + diff -r ff3b21d62eb8 -r a282eebbc5e0 server/pom.xml --- a/server/pom.xml Tue May 14 14:10:23 2013 +0200 +++ b/server/pom.xml Tue Apr 23 16:54:18 2013 +0200 @@ -13,6 +13,7 @@ 1.0 1.17.1 3.2.1.RELEASE + 1.2.0.RELEASE 3.1.3.RELEASE 8.1.10.v20130312 4.10 @@ -21,6 +22,7 @@ 2.5.1 2.1.4 2.1 + 2.11.0 UTF-8 @@ -125,6 +127,11 @@ maven-surefire-plugin ${surefire-version} + + org.apache.maven.plugins + maven-jar-plugin + 2.4 + @@ -238,7 +245,7 @@ org.mongodb mongo-java-driver - 2.10.1 + ${mongo-driver-version} org.slf4j @@ -284,7 +291,7 @@ org.springframework.data spring-data-mongodb - 1.2.0.RELEASE + ${spring-data-mongodb-version} javax.persistence diff -r ff3b21d62eb8 -r a282eebbc5e0 server/src/main/java/org/iri_research/renkan/Constants.java --- a/server/src/main/java/org/iri_research/renkan/Constants.java Tue May 14 14:10:23 2013 +0200 +++ b/server/src/main/java/org/iri_research/renkan/Constants.java Tue Apr 23 16:54:18 2013 +0200 @@ -49,6 +49,7 @@ public final static int PAGINATION_SIZE = 10; public final static String PROPERTIES_SERVLET_CONTEXT_NAME = "renkan.properties"; public final static String PROPERTIES_CLASSPATH_NAME = "renkan_run.properties"; + public final static String ANONYMOUS_USER_BASE_NAME = "Anonymous"; private final static EthernetAddress ETHERNET_ADRESS = EthernetAddress.fromInterface(); public final static NoArgGenerator UUID_GENERATOR = Generators.timeBasedGenerator(ETHERNET_ADRESS); diff -r ff3b21d62eb8 -r a282eebbc5e0 server/src/main/java/org/iri_research/renkan/controller/AdminController.java --- a/server/src/main/java/org/iri_research/renkan/controller/AdminController.java Tue May 14 14:10:23 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,195 +0,0 @@ -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; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Sort.Direction; -import org.springframework.data.web.PageableDefaults; -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") -public class AdminController { - - private final Logger logger = LoggerFactory.getLogger(AdminController.class); - - @Autowired - private SpacesRepository spacesRepository; - @Autowired - private ProjectsRepository projectsRepository; - - @InitBinder(value={"space"}) - protected void initBinder(WebDataBinder binder) { - binder.setValidator(new SpaceFormValidator()); - } - - @RequestMapping(value="", method = RequestMethod.GET, produces={"text/html;charset=UTF-8"}) - public String adminIndex() { - - return "admin/adminIndex"; - } - - @RequestMapping(value="/spaces", method = RequestMethod.GET, produces={"text/html;charset=UTF-8"}) - public String spacesList( - Model model, - @PageableDefaults(sort={"created"}, sortDir=Direction.DESC, pageNumber=0, value=Constants.PAGINATION_SIZE) Pageable p, - HttpServletRequest request) { - - Page page = this.spacesRepository.findAll(p); - - model.addAttribute("page", page); - model.addAttribute("baseUrl", Utils.buildBaseUrl(request)); - model.addAttribute("projectsCount", this.projectsRepository.getCountBySpace()); - - return "admin/spacesList"; - } - - @RequestMapping(value="/spaces/edit/", method = RequestMethod.GET, produces={"text/html;charset=UTF-8"}) - public String editSpace(Model model) { - return editSpace(model, null); - } - - @RequestMapping(value="/spaces/edit/{spaceId}", method = RequestMethod.GET, produces={"text/html;charset=UTF-8"}) - public String editSpace(Model model, @PathVariable(value="spaceId") String spaceId) { - - SpaceForm spaceForm = null; - - if(spaceId == null || spaceId.length() == 0 || "_".equals(spaceId)) { - spaceForm = new SpaceForm(); - } - else { - Space space = this.spacesRepository.findOne(spaceId); - if(space == null) { - throw new HttpClientErrorException(HttpStatus.NOT_FOUND, "space " + spaceId + " not found"); - } - spaceForm = new SpaceForm(space); - } - - model.addAttribute("space", spaceForm); - - return "admin/spaceEdit"; - } - - - @RequestMapping(value="/spaces/save", method = RequestMethod.POST) - public String saveSpace(Model model, @ModelAttribute("space") @Valid SpaceForm spaceForm, BindingResult bindingResult) { - - logger.debug("space title " + spaceForm.getTitle()); - logger.debug("space description " + spaceForm.getDescription()); - - if(bindingResult.hasErrors()) { - return "admin/spaceEdit"; - } - - spaceForm.setSpacesRepository(spacesRepository); - - try { - spaceForm.save(); - } catch (RenkanException e) { - throw new HttpClientErrorException(HttpStatus.NOT_FOUND, "space " + spaceForm.getId() + " not found"); - } - - 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 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"); - } - - } - -} diff -r ff3b21d62eb8 -r a282eebbc5e0 server/src/main/java/org/iri_research/renkan/controller/admin/AdminController.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/server/src/main/java/org/iri_research/renkan/controller/admin/AdminController.java Tue Apr 23 16:54:18 2013 +0200 @@ -0,0 +1,23 @@ +package org.iri_research.renkan.controller.admin; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; + +@Controller +@RequestMapping("/admin") +public class AdminController { + + + @SuppressWarnings("unused") + private final Logger logger = LoggerFactory.getLogger(AdminController.class); + + @RequestMapping(value="", method = RequestMethod.GET, produces={"text/html;charset=UTF-8"}) + public String adminIndex() { + + return "admin/adminIndex"; + } + +} diff -r ff3b21d62eb8 -r a282eebbc5e0 server/src/main/java/org/iri_research/renkan/controller/admin/SpacesAdminController.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/server/src/main/java/org/iri_research/renkan/controller/admin/SpacesAdminController.java Tue Apr 23 16:54:18 2013 +0200 @@ -0,0 +1,184 @@ +package org.iri_research.renkan.controller.admin; + +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.controller.Utils; +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; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort.Direction; +import org.springframework.data.web.PageableDefaults; +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/spaces") +public class SpacesAdminController { + + private final Logger logger = LoggerFactory.getLogger(SpacesAdminController.class); + + @Autowired + private SpacesRepository spacesRepository; + @Autowired + private ProjectsRepository projectsRepository; + + @InitBinder(value={"space"}) + protected void initBinder(WebDataBinder binder) { + binder.setValidator(new SpaceFormValidator()); + } + + @RequestMapping(value="/", method = RequestMethod.GET, produces={"text/html;charset=UTF-8"}) + public String spacesList( + Model model, + @PageableDefaults(sort={"created"}, sortDir=Direction.DESC, pageNumber=0, value=Constants.PAGINATION_SIZE) Pageable p, + HttpServletRequest request) { + + Page page = this.spacesRepository.findAll(p); + + model.addAttribute("page", page); + model.addAttribute("baseUrl", Utils.buildBaseUrl(request)); + model.addAttribute("projectsCount", this.projectsRepository.getCountBySpace()); + + return "admin/spacesList"; + } + + @RequestMapping(value="/edit/", method = RequestMethod.GET, produces={"text/html;charset=UTF-8"}) + public String editSpace(Model model) { + return editSpace(model, null); + } + + @RequestMapping(value="/edit/{spaceId}", method = RequestMethod.GET, produces={"text/html;charset=UTF-8"}) + public String editSpace(Model model, @PathVariable(value="spaceId") String spaceId) { + + SpaceForm spaceForm = null; + + if(spaceId == null || spaceId.length() == 0 || "_".equals(spaceId)) { + spaceForm = new SpaceForm(); + } + else { + Space space = this.spacesRepository.findOne(spaceId); + if(space == null) { + throw new HttpClientErrorException(HttpStatus.NOT_FOUND, "space " + spaceId + " not found"); + } + spaceForm = new SpaceForm(space); + } + + model.addAttribute("space", spaceForm); + + return "admin/spaceEdit"; + } + + + @RequestMapping(value="/save", method = RequestMethod.POST) + public String saveSpace(Model model, @ModelAttribute("space") @Valid SpaceForm spaceForm, BindingResult bindingResult) { + + logger.debug("space title " + spaceForm.getTitle()); + logger.debug("space description " + spaceForm.getDescription()); + + if(bindingResult.hasErrors()) { + return "admin/spaceEdit"; + } + + spaceForm.setSpacesRepository(spacesRepository); + + try { + spaceForm.save(); + } catch (RenkanException e) { + throw new HttpClientErrorException(HttpStatus.NOT_FOUND, "space " + spaceForm.getId() + " not found"); + } + + return "redirect:/admin/spaces"; + } + + @RequestMapping(value="/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 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"); + } + + } + +} diff -r ff3b21d62eb8 -r a282eebbc5e0 server/src/main/java/org/iri_research/renkan/coweb/RenkanSessionModerator.java --- a/server/src/main/java/org/iri_research/renkan/coweb/RenkanSessionModerator.java Tue May 14 14:10:23 2013 +0200 +++ b/server/src/main/java/org/iri_research/renkan/coweb/RenkanSessionModerator.java Tue Apr 23 16:54:18 2013 +0200 @@ -123,7 +123,7 @@ return; } for (RosterUser rosterUser : r_user_list) { - if( rosterUser.getClient_id().equals(clientId)) { + if( rosterUser.getClientId().equals(clientId)) { r_user_list.remove(rosterUser); } } diff -r ff3b21d62eb8 -r a282eebbc5e0 server/src/main/java/org/iri_research/renkan/coweb/event/UserSyncEventManager.java --- a/server/src/main/java/org/iri_research/renkan/coweb/event/UserSyncEventManager.java Tue May 14 14:10:23 2013 +0200 +++ b/server/src/main/java/org/iri_research/renkan/coweb/event/UserSyncEventManager.java Tue Apr 23 16:54:18 2013 +0200 @@ -1,5 +1,6 @@ package org.iri_research.renkan.coweb.event; +import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -8,6 +9,7 @@ import org.coweb.CowebException; import org.iri_research.renkan.models.Project; +import org.iri_research.renkan.models.RenkanUser; import org.iri_research.renkan.models.User; import org.iri_research.renkan.repositories.IRenkanRepository; import org.iri_research.renkan.repositories.UsersRepository; @@ -56,7 +58,7 @@ color = UserSyncEventManager.DEFAULT_COLOR; } - User user = new User(user_id, (String)values.get("title"), (String)values.get("description"), (String)values.get("uri"), color, project_id); + User user = new User(user_id, (String)values.get("title"), (String)values.get("description"), (String)values.get("uri"), color); Integer position = (Integer)data.get("position"); @@ -64,7 +66,8 @@ throw new CowebException("node insert: bad insert position", String.format("Bad position %s not found", position==null?"null":position.toString())); } int index = position.intValue(); - List users = project.getUsers(); + //TODO: correct this. done that to compile + List users = new ArrayList();//project.getUsers(); if(index > users.size()) { index = users.size(); } @@ -82,7 +85,9 @@ @Override protected List getObjectList(Project project) { - return project.getUsers(); + //TODO: correct this, this is wrong, just put here to cpmpile + return null; + //return project.getUsers(); } } diff -r ff3b21d62eb8 -r a282eebbc5e0 server/src/main/java/org/iri_research/renkan/management/MigrateRenkanUser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/server/src/main/java/org/iri_research/renkan/management/MigrateRenkanUser.java Tue Apr 23 16:54:18 2013 +0200 @@ -0,0 +1,72 @@ +package org.iri_research.renkan.management; + +import org.iri_research.renkan.models.Project; +import org.iri_research.renkan.models.RenkanUser; +import org.iri_research.renkan.models.User; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.stereotype.Component; + +import com.mongodb.BasicDBObject; +import com.mongodb.DBCollection; +import com.mongodb.DBObject; +import com.mongodb.WriteConcern; + +@Component +public class MigrateRenkanUser { + + public static void main(String[] args) { + + @SuppressWarnings("resource") + ApplicationContext context = new ClassPathXmlApplicationContext("classpath:WEB-INF/applicationContext.xml"); + + MigrateRenkanUser p = context.getBean(MigrateRenkanUser.class); + p.start(args); + + } + + @Autowired + private MongoTemplate template; + + private void start(String[] args) { + + DBCollection userColl = template.getCollection(template.getCollectionName(User.class)); + DBCollection renkanUserColl = template.getCollection(template.getCollectionName(RenkanUser.class)); + DBCollection projectColl = template.getCollection(template.getCollectionName(Project.class)); + + for (DBObject user: userColl.find()) { + if(!user.containsField("project_id")) { + continue; + } + String projectId = (String) user.get("project_id"); + if(projectId == null || projectId.isEmpty()) { + user.removeField("project_id"); + userColl.save(user); + continue; + } + DBObject proj = new BasicDBObject(); + proj.put("_id", projectId); + if(projectColl.findOne(proj) != null) { + DBObject renkanUser = new BasicDBObject(); + renkanUser.put("project_id", projectId); + renkanUser.put("user_id", user.get("_id")); + if(renkanUserColl.findOne(renkanUser) == null) { + System.out.println(String.format("%s : %s : %s", user.get("_id"),user.get("title"),user.get("project_id"))); + renkanUser = new BasicDBObject(); + renkanUser.put("project_id", user.get("project_id")); + renkanUser.put("user_id", user.get("_id")); + renkanUser.put("color", user.get("color")); + renkanUserColl.insert(renkanUser); + } + user.removeField("project_id"); + userColl.save(user); + } + else { + userColl.remove(user, WriteConcern.ACKNOWLEDGED); + } + } + + } +} diff -r ff3b21d62eb8 -r a282eebbc5e0 server/src/main/java/org/iri_research/renkan/models/Group.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/server/src/main/java/org/iri_research/renkan/models/Group.java Tue Apr 23 16:54:18 2013 +0200 @@ -0,0 +1,14 @@ +package org.iri_research.renkan.models; + +import org.springframework.data.mongodb.core.mapping.Document; + +@Document(collection="groups") +public class Group extends AbstractRenkanModel { + + public String getGroupName() { + return this.getTitle(); + } + + + +} diff -r ff3b21d62eb8 -r a282eebbc5e0 server/src/main/java/org/iri_research/renkan/models/Project.java --- a/server/src/main/java/org/iri_research/renkan/models/Project.java Tue May 14 14:10:23 2013 +0200 +++ b/server/src/main/java/org/iri_research/renkan/models/Project.java Tue Apr 23 16:54:18 2013 +0200 @@ -14,6 +14,7 @@ import org.apache.commons.codec.binary.Hex; import org.iri_research.renkan.Constants; import org.iri_research.renkan.Constants.EditMode; +import org.iri_research.renkan.utils.ColorGenerator; import org.iri_research.renkan.RenkanException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -50,8 +51,7 @@ private List edges = new ArrayList(); // Users - @DBRef - private List users = new ArrayList(); + private List users = new ArrayList(); public Project(Project project) { @@ -67,8 +67,8 @@ for (Edge edge : project.edges) { this.edges.add(new Edge(edge, nodeCloneMap.get(edge.getFrom()), nodeCloneMap.get(edge.getTo()), this.id)); } - for(User user : project.users) { - this.users.add(user); + for(RenkanUser user : project.users) { + this.users.add(new RenkanUser(user)); } } @@ -105,7 +105,7 @@ return this.edges; } - public List getUsers() { + public List getUsers() { return this.users; } @@ -183,4 +183,62 @@ this.updated = updated; } + public void addUser(User user) { + + if(user == null) { + // we add an anonymous user + // find an unique user name + this.addUser(null, null); + } + else { + // if user is already in list do nothing + for (RenkanUser renkanUser : this.users) { + if(renkanUser.getUserId() != null && renkanUser.getUserId().equals(user.getId())) { + return; + } + } + // user not found + this.users.add(new RenkanUser(this.getId(), user.getId(), user.getColor(), user.getUsername())); + + } + + } + + public void addUser(String username, String color) { + + if(username == null) { + //find a new username + int i = 0; + boolean usernameFound = true; + while(i++<1000000 && usernameFound) { + username = String.format("%s-%s", Constants.ANONYMOUS_USER_BASE_NAME, i); + usernameFound = false; + for(RenkanUser renkanUser : this.users) { + if(username.equals(renkanUser.getUsername())) { + usernameFound = true; + break; + } + } + } + } + + if(color == null) { + int i=0; + boolean colorFound = true; + while(i++<10000000 && colorFound) { + color = "#" + ColorGenerator.randomColorHex(); + colorFound = false; + for(RenkanUser renkanUser : this.users) { + if(username.equals(renkanUser.getUsername())) { + colorFound = true; + break; + } + } + } + } + + RenkanUser ruser = new RenkanUser(this.getId(), null, color, username); + this.users.add(ruser); + } + } diff -r ff3b21d62eb8 -r a282eebbc5e0 server/src/main/java/org/iri_research/renkan/models/RenkanUser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/server/src/main/java/org/iri_research/renkan/models/RenkanUser.java Tue Apr 23 16:54:18 2013 +0200 @@ -0,0 +1,63 @@ +package org.iri_research.renkan.models; + +import org.springframework.data.mongodb.core.mapping.Field; + + +public class RenkanUser { + + @Field(value="user_id") + private String userId; + private String color; + private String username; + + + @SuppressWarnings("unused") + private RenkanUser() { + } + + public RenkanUser(String projectId, String userId, String color, + String username) { + this.userId = userId; + this.color = color; + this.username = username; + } + + public RenkanUser(RenkanUser user) { + if(user != null) { + this.setUserId(user.getUserId()); + this.setColor(user.getColor()); + this.setUsername(user.getUsername()); + } + } + + @Field(value="user_id") + public String getUserId() { + return userId; + } + + @Field(value="user_id") + public void setUserId(String userId) { + this.userId = userId; + } + + public String getColor() { + return color; + } + + public void setColor(String color) { + this.color = color; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public boolean isAnonymous() { + return this.getUserId() == null; + } + +} diff -r ff3b21d62eb8 -r a282eebbc5e0 server/src/main/java/org/iri_research/renkan/models/RosterUser.java --- a/server/src/main/java/org/iri_research/renkan/models/RosterUser.java Tue May 14 14:10:23 2013 +0200 +++ b/server/src/main/java/org/iri_research/renkan/models/RosterUser.java Tue Apr 23 16:54:18 2013 +0200 @@ -1,17 +1,19 @@ package org.iri_research.renkan.models; +import com.fasterxml.jackson.annotation.JsonProperty; + public class RosterUser extends AbstractRenkanModel { - private String project_id; - private Long site_id; - private String client_id; + private String projectId; + private Long siteId; + private String clientId; public RosterUser(String id, String title, String description, String uri, String color, String project_id, Long site_id, String client_id) { super(id, title, description, uri, color); - this.project_id = project_id; - this.site_id = site_id; - this.client_id = client_id; + this.projectId = project_id; + this.siteId = site_id; + this.clientId = client_id; } public void setTitle(String title) { @@ -30,16 +32,19 @@ this.color = color; } - public String getProject_id() { - return project_id; + @JsonProperty(value="project_id") + public String getProjectId() { + return projectId; } - public Long getSite_id() { - return site_id; + @JsonProperty(value="site_id") + public Long getSiteId() { + return siteId; } - public String getClient_id() { - return client_id; + @JsonProperty(value="client_id") + public String getClientId() { + return clientId; } diff -r ff3b21d62eb8 -r a282eebbc5e0 server/src/main/java/org/iri_research/renkan/models/User.java --- a/server/src/main/java/org/iri_research/renkan/models/User.java Tue May 14 14:10:23 2013 +0200 +++ b/server/src/main/java/org/iri_research/renkan/models/User.java Tue Apr 23 16:54:18 2013 +0200 @@ -1,24 +1,86 @@ package org.iri_research.renkan.models; +import java.util.Collection; +import java.util.Date; + import org.springframework.data.mongodb.core.mapping.Document; +import org.springframework.data.mongodb.core.mapping.Field; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; @Document(collection="users") -public class User extends AbstractRenkanModel { +public class User extends AbstractRenkanModel implements UserDetails { + + private static final long serialVersionUID = 6972038893086220548L; - private String project_id; + private String email; + private String password; + private String salt; + private String avatar; + private boolean enabled; + private boolean locked; + + @Field("expiration_date") + private Date expirationDate; + + @Field("credentials_expiration_date") + private Date credentialExpirationDate; - public User(String id, String title, String description, String uri, String color, String project_id) { + public User(String id, String title, String description, String uri, String color) { super(id, title, description, uri, color); - - this.project_id = project_id; } public String getColor() { return this.color; } - public String getProject_id() { - return project_id; + @Override + public Collection getAuthorities() { + // TODO Auto-generated method stub + return null; + } + + @Override + @JsonIgnore + public String getPassword() { + return this.password; + } + + @Override + @JsonIgnore + public String getUsername() { + return this.title; + } + + @Override + public boolean isAccountNonExpired() { + return this.expirationDate == null || this.expirationDate.after(new Date()); + } + + @Override + public boolean isAccountNonLocked() { + return !this.locked; + } + + @Override + public boolean isCredentialsNonExpired() { + return this.credentialExpirationDate == null || this.credentialExpirationDate.after(new Date()); + } + + @Override + public boolean isEnabled() { + return this.enabled; + } + + public String getEmail() { + return email; + } + + public String getAvatar() { + return avatar; } } diff -r ff3b21d62eb8 -r a282eebbc5e0 server/src/main/java/org/iri_research/renkan/repositories/ProjectsRepositoryCustom.java --- a/server/src/main/java/org/iri_research/renkan/repositories/ProjectsRepositoryCustom.java Tue May 14 14:10:23 2013 +0200 +++ b/server/src/main/java/org/iri_research/renkan/repositories/ProjectsRepositoryCustom.java Tue Apr 23 16:54:18 2013 +0200 @@ -10,6 +10,11 @@ public int getRevCounter(String projectId); public Map getCountBySpace(); public Map getCountBySpace(Collection spaceIds); + + public Map getCountByUser(); + public Map getCountByUser(Collection userIds); + public Map getCountByUsername(); + public Map getCountByUsername(Collection usernames); public void deleteRecursive(String projectId); public void deleteRecursive(Project project); diff -r ff3b21d62eb8 -r a282eebbc5e0 server/src/main/java/org/iri_research/renkan/repositories/ProjectsRepositoryImpl.java --- a/server/src/main/java/org/iri_research/renkan/repositories/ProjectsRepositoryImpl.java Tue May 14 14:10:23 2013 +0200 +++ b/server/src/main/java/org/iri_research/renkan/repositories/ProjectsRepositoryImpl.java Tue Apr 23 16:54:18 2013 +0200 @@ -5,8 +5,13 @@ import java.util.HashMap; import java.util.Map; +import org.eclipse.jetty.util.component.AggregateLifeCycle; +import org.iri_research.renkan.RenkanProperties; import org.iri_research.renkan.models.Project; import org.iri_research.renkan.models.ProjectRevision; +import org.iri_research.renkan.models.RenkanUser; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.stereotype.Component; @@ -18,9 +23,15 @@ import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Update; +import com.mongodb.AggregationOutput; +import com.mongodb.BasicDBObject; +import com.mongodb.DBObject; + @Component public class ProjectsRepositoryImpl implements ProjectsRepositoryCustom { + private final Logger logger = LoggerFactory.getLogger(ProjectsRepositoryImpl.class); + @Autowired private ProjectsRepository projectsRepository; @@ -34,10 +45,15 @@ private ProjectRevisionsRepository projectRevisionsRepository; - private class GroupResult { + private class GroupSpaceResult { public String space_id; public int count; } + + private class GroupUsernameResult { + public String username; + public int count; + } @Autowired private MongoTemplate mongoTemplate; @@ -62,14 +78,14 @@ filter = Criteria.where("space_id").in(spaceIds); } - GroupByResults groupResult = this.mongoTemplate.group( + GroupByResults 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); + GroupSpaceResult.class); HashMap res = new HashMap<>(); - for (GroupResult gr : groupResult) { + for (GroupSpaceResult gr : groupResult) { res.put(gr.space_id, new Integer(gr.count)); } @@ -123,4 +139,49 @@ this.projectsRepository.delete(p); } } + + + @Override + public Map getCountByUser() { + return getCountByUser(null); + } + + + @Override + public Map getCountByUser(Collection userIds) { + + Criteria filter = null; + + if(userIds != null) { + filter = Criteria.where("users.user_id").in(userIds); + } + + DBObject projectOp = new BasicDBObject("$project", new BasicDBObject("users", 1)); + DBObject unwindOp = new BasicDBObject("$unwind","$users"); + DBObject groupOpFields = new BasicDBObject("_id", "$users.user_id"); + groupOpFields.put("count", new BasicDBObject("$sum", 1)); + DBObject groupOp = new BasicDBObject("$group",groupOpFields); + + AggregationOutput output = this.projectsRepository.getCollection().aggregate(projectOp, unwindOp, groupOp); + HashMap res = new HashMap<>(); + + for (DBObject groupRes : output.results()) { + res.put((String)groupRes.get("_id"), (Integer)groupRes.get("count")); + } + + return res; + } + + + @Override + public Map getCountByUsername() { + return this.getCountByUsername(null); + } + + + @Override + public Map getCountByUsername(Collection usernames) { + // TODO Auto-generated method stub + return null; + } } diff -r ff3b21d62eb8 -r a282eebbc5e0 server/src/main/java/org/iri_research/renkan/repositories/UsersRepository.java --- a/server/src/main/java/org/iri_research/renkan/repositories/UsersRepository.java Tue May 14 14:10:23 2013 +0200 +++ b/server/src/main/java/org/iri_research/renkan/repositories/UsersRepository.java Tue Apr 23 16:54:18 2013 +0200 @@ -1,7 +1,14 @@ package org.iri_research.renkan.repositories; +import java.util.List; + import org.iri_research.renkan.models.User; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; public interface UsersRepository extends IRenkanRepository { + + public List findByTitle(String title); + public Page findByTitle(String title, Pageable p); } diff -r ff3b21d62eb8 -r a282eebbc5e0 server/src/main/java/org/iri_research/renkan/services/RenkanUserDetailsService.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/server/src/main/java/org/iri_research/renkan/services/RenkanUserDetailsService.java Tue Apr 23 16:54:18 2013 +0200 @@ -0,0 +1,29 @@ +package org.iri_research.renkan.services; + +import java.util.List; + +import org.iri_research.renkan.models.User; +import org.iri_research.renkan.repositories.UsersRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.stereotype.Service; + +@Service +public class RenkanUserDetailsService implements UserDetailsService { + + @Autowired + private UsersRepository usersRepository; + + @Override + public UserDetails loadUserByUsername(String username) + throws UsernameNotFoundException { + List res = this.usersRepository.findByTitle(username); + if(res == null || res.size() == 0) { + throw new UsernameNotFoundException(String.format("User {0} not found.", username)); + } + return res.get(0); + } + +} diff -r ff3b21d62eb8 -r a282eebbc5e0 server/src/main/java/org/iri_research/renkan/utils/ColorGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/server/src/main/java/org/iri_research/renkan/utils/ColorGenerator.java Tue Apr 23 16:54:18 2013 +0200 @@ -0,0 +1,24 @@ +package org.iri_research.renkan.utils; + +import java.awt.Color; +import java.util.Random; + +public class ColorGenerator { + + public static Color randomColor() { + + Random rand = new Random(); + + float r = rand.nextFloat()*0.5f + 0.5f; + float g = rand.nextFloat()*0.5f + 0.5f; + float b = rand.nextFloat()*0.5f + 0.5f; + + return new Color(r, g, b); + } + + public static String randomColorHex() { + Color resColor = ColorGenerator.randomColor(); + return Integer.toHexString(resColor.getRGB()); + } + +} diff -r ff3b21d62eb8 -r a282eebbc5e0 server/src/main/webapp/WEB-INF/applicationContext.xml --- a/server/src/main/webapp/WEB-INF/applicationContext.xml Tue May 14 14:10:23 2013 +0200 +++ b/server/src/main/webapp/WEB-INF/applicationContext.xml Tue Apr 23 16:54:18 2013 +0200 @@ -69,6 +69,7 @@ +