Merge pull request #31 from sismics/master

Push to production
This commit is contained in:
Benjamin Gamard 2015-09-08 21:50:12 +02:00
commit 97f25de0dc
85 changed files with 1730 additions and 3157 deletions

View File

@ -26,6 +26,11 @@
<artifactId>hibernate-entitymanager</artifactId> <artifactId>hibernate-entitymanager</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
</dependency>
<!-- Other external dependencies --> <!-- Other external dependencies -->
<dependency> <dependency>
<groupId>joda-time</groupId> <groupId>joda-time</groupId>
@ -72,26 +77,7 @@
<artifactId>jbcrypt</artifactId> <artifactId>jbcrypt</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
</dependency>
<dependency>
<groupId>org.ccil.cowan.tagsoup</groupId>
<artifactId>tagsoup</artifactId>
</dependency>
<dependency>
<groupId>com.googlecode.owasp-java-html-sanitizer</groupId>
<artifactId>owasp-java-html-sanitizer</artifactId>
</dependency>
<dependency> <dependency>
<groupId>org.apache.lucene</groupId> <groupId>org.apache.lucene</groupId>
<artifactId>lucene-core</artifactId> <artifactId>lucene-core</artifactId>

View File

@ -10,21 +10,11 @@ import com.google.common.collect.Lists;
* @author jtremeaux * @author jtremeaux
*/ */
public class Constants { public class Constants {
/**
* Default locale.
*/
public static final String DEFAULT_LOCALE_ID = "en";
/** /**
* Default timezone ID. * Default timezone ID.
*/ */
public static final String DEFAULT_TIMEZONE_ID = "Europe/London"; public static final String DEFAULT_TIMEZONE_ID = "Europe/London";
/**
* Default theme ID.
*/
public static final String DEFAULT_THEME_ID = "default.less";
/** /**
* Administrator's default password ("admin"). * Administrator's default password ("admin").
*/ */

View File

@ -1,38 +0,0 @@
package com.sismics.docs.core.dao.file.theme;
import com.google.common.collect.Lists;
import com.sismics.docs.core.util.DirectoryUtil;
import java.io.File;
import java.io.FilenameFilter;
import java.util.ArrayList;
import java.util.List;
/**
* Theme DAO.
*
* @author jtremeaux
*/
public class ThemeDao {
private final static FilenameFilter CSS_FILTER = new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return name.endsWith(".css") || name.endsWith(".less");
}
};
/**
* Return the list of all themes.
*
* @return List of themes
*/
public List<String> findAll() {
final File themeDirectory = DirectoryUtil.getThemeDirectory();
if (themeDirectory != null) {
return Lists.newArrayList(themeDirectory.list(CSS_FILTER));
} else {
return new ArrayList<String>();
}
}
}

View File

@ -1,43 +0,0 @@
package com.sismics.docs.core.dao.jpa;
import com.sismics.docs.core.model.jpa.Locale;
import com.sismics.util.context.ThreadLocalContext;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.Query;
import java.util.List;
/**
* Locale DAO.
*
* @author jtremeaux
*/
public class LocaleDao {
/**
* Gets a locale by its ID.
*
* @param id Locale ID
* @return Locale
*/
public Locale getById(String id) {
EntityManager em = ThreadLocalContext.get().getEntityManager();
try {
return em.find(Locale.class, id);
} catch (NoResultException e) {
return null;
}
}
/**
* Returns the list of all locales.
*
* @return List of locales
*/
@SuppressWarnings("unchecked")
public List<Locale> findAll() {
EntityManager em = ThreadLocalContext.get().getEntityManager();
Query q = em.createQuery("select l from Locale l order by l.id");
return q.getResultList();
}
}

View File

@ -16,7 +16,6 @@ import org.mindrot.jbcrypt.BCrypt;
import com.google.common.base.Joiner; import com.google.common.base.Joiner;
import com.sismics.docs.core.constant.AuditLogType; import com.sismics.docs.core.constant.AuditLogType;
import com.sismics.docs.core.constant.Constants;
import com.sismics.docs.core.dao.jpa.criteria.UserCriteria; import com.sismics.docs.core.dao.jpa.criteria.UserCriteria;
import com.sismics.docs.core.dao.jpa.dto.UserDto; import com.sismics.docs.core.dao.jpa.dto.UserDto;
import com.sismics.docs.core.model.jpa.User; import com.sismics.docs.core.model.jpa.User;
@ -78,7 +77,6 @@ public class UserDao {
// Create the user // Create the user
user.setCreateDate(new Date()); user.setCreateDate(new Date());
user.setPassword(hashPassword(user.getPassword())); user.setPassword(hashPassword(user.getPassword()));
user.setTheme(Constants.DEFAULT_THEME_ID);
em.persist(user); em.persist(user);
// Create audit log // Create audit log
@ -102,10 +100,7 @@ public class UserDao {
User userFromDb = (User) q.getSingleResult(); User userFromDb = (User) q.getSingleResult();
// Update the user // Update the user
userFromDb.setLocaleId(user.getLocaleId());
userFromDb.setEmail(user.getEmail()); userFromDb.setEmail(user.getEmail());
userFromDb.setTheme(user.getTheme());
userFromDb.setFirstConnection(user.isFirstConnection());
// Create audit log // Create audit log
AuditLogUtil.create(userFromDb, AuditLogType.UPDATE); AuditLogUtil.create(userFromDb, AuditLogType.UPDATE);
@ -231,7 +226,7 @@ public class UserDao {
Map<String, Object> parameterMap = new HashMap<String, Object>(); Map<String, Object> parameterMap = new HashMap<String, Object>();
List<String> criteriaList = new ArrayList<String>(); List<String> criteriaList = new ArrayList<String>();
StringBuilder sb = new StringBuilder("select u.USE_ID_C as c0, u.USE_USERNAME_C as c1, u.USE_EMAIL_C as c2, u.USE_CREATEDATE_D as c3, u.USE_IDLOCALE_C as c4"); StringBuilder sb = new StringBuilder("select u.USE_ID_C as c0, u.USE_USERNAME_C as c1, u.USE_EMAIL_C as c2, u.USE_CREATEDATE_D as c3");
sb.append(" from T_USER u "); sb.append(" from T_USER u ");
// Add search criterias // Add search criterias
@ -260,7 +255,6 @@ public class UserDao {
userDto.setUsername((String) o[i++]); userDto.setUsername((String) o[i++]);
userDto.setEmail((String) o[i++]); userDto.setEmail((String) o[i++]);
userDto.setCreateTimestamp(((Timestamp) o[i++]).getTime()); userDto.setCreateTimestamp(((Timestamp) o[i++]).getTime());
userDto.setLocaleId((String) o[i++]);
userDtoList.add(userDto); userDtoList.add(userDto);
} }
paginatedList.setResultList(userDtoList); paginatedList.setResultList(userDtoList);

View File

@ -11,11 +11,6 @@ public class UserDto {
*/ */
private String id; private String id;
/**
* Locale ID.
*/
private String localeId;
/** /**
* Username. * Username.
*/ */
@ -49,24 +44,6 @@ public class UserDto {
this.id = id; this.id = id;
} }
/**
* Getter of localeId.
*
* @return localeId
*/
public String getLocaleId() {
return localeId;
}
/**
* Setter of localeId.
*
* @param localeId localeId
*/
public void setLocaleId(String localeId) {
this.localeId = localeId;
}
/** /**
* Getter of username. * Getter of username.
* *

View File

@ -1,6 +1,6 @@
package com.sismics.docs.core.event; package com.sismics.docs.core.event;
import com.google.common.base.Objects; import com.google.common.base.MoreObjects;
import com.sismics.docs.core.model.jpa.Document; import com.sismics.docs.core.model.jpa.Document;
/** /**
@ -34,7 +34,7 @@ public class DocumentCreatedAsyncEvent {
@Override @Override
public String toString() { public String toString() {
return Objects.toStringHelper(this) return MoreObjects.toStringHelper(this)
.add("document", document) .add("document", document)
.toString(); .toString();
} }

View File

@ -1,6 +1,6 @@
package com.sismics.docs.core.event; package com.sismics.docs.core.event;
import com.google.common.base.Objects; import com.google.common.base.MoreObjects;
import com.sismics.docs.core.model.jpa.Document; import com.sismics.docs.core.model.jpa.Document;
/** /**
@ -34,7 +34,7 @@ public class DocumentDeletedAsyncEvent {
@Override @Override
public String toString() { public String toString() {
return Objects.toStringHelper(this) return MoreObjects.toStringHelper(this)
.add("document", document) .add("document", document)
.toString(); .toString();
} }

View File

@ -1,6 +1,6 @@
package com.sismics.docs.core.event; package com.sismics.docs.core.event;
import com.google.common.base.Objects; import com.google.common.base.MoreObjects;
import com.sismics.docs.core.model.jpa.Document; import com.sismics.docs.core.model.jpa.Document;
/** /**
@ -34,7 +34,7 @@ public class DocumentUpdatedAsyncEvent {
@Override @Override
public String toString() { public String toString() {
return Objects.toStringHelper(this) return MoreObjects.toStringHelper(this)
.add("document", document) .add("document", document)
.toString(); .toString();
} }

View File

@ -2,7 +2,7 @@ package com.sismics.docs.core.event;
import java.io.InputStream; import java.io.InputStream;
import com.google.common.base.Objects; import com.google.common.base.MoreObjects;
import com.sismics.docs.core.model.jpa.Document; import com.sismics.docs.core.model.jpa.Document;
import com.sismics.docs.core.model.jpa.File; import com.sismics.docs.core.model.jpa.File;
@ -83,7 +83,7 @@ public class FileCreatedAsyncEvent {
@Override @Override
public String toString() { public String toString() {
return Objects.toStringHelper(this) return MoreObjects.toStringHelper(this)
.add("file", file) .add("file", file)
.add("document", document) .add("document", document)
.toString(); .toString();

View File

@ -1,6 +1,6 @@
package com.sismics.docs.core.event; package com.sismics.docs.core.event;
import com.google.common.base.Objects; import com.google.common.base.MoreObjects;
import com.sismics.docs.core.model.jpa.File; import com.sismics.docs.core.model.jpa.File;
/** /**
@ -34,7 +34,7 @@ public class FileDeletedAsyncEvent {
@Override @Override
public String toString() { public String toString() {
return Objects.toStringHelper(this) return MoreObjects.toStringHelper(this)
.add("file", file) .add("file", file)
.toString(); .toString();
} }

View File

@ -1,6 +1,6 @@
package com.sismics.docs.core.event; package com.sismics.docs.core.event;
import com.google.common.base.Objects; import com.google.common.base.MoreObjects;
/** /**
* Rebuild index event. * Rebuild index event.
@ -10,7 +10,7 @@ import com.google.common.base.Objects;
public class RebuildIndexAsyncEvent { public class RebuildIndexAsyncEvent {
@Override @Override
public String toString() { public String toString() {
return Objects.toStringHelper(this) return MoreObjects.toStringHelper(this)
.toString(); .toString();
} }
} }

View File

@ -62,7 +62,7 @@ public class AppContext {
ConfigDao configDao = new ConfigDao(); ConfigDao configDao = new ConfigDao();
Config luceneStorageConfig = configDao.getById(ConfigType.LUCENE_DIRECTORY_STORAGE); Config luceneStorageConfig = configDao.getById(ConfigType.LUCENE_DIRECTORY_STORAGE);
indexingService = new IndexingService(luceneStorageConfig != null ? luceneStorageConfig.getValue() : null); indexingService = new IndexingService(luceneStorageConfig != null ? luceneStorageConfig.getValue() : null);
indexingService.startAndWait(); indexingService.startAsync();
} }
/** /**

View File

@ -10,7 +10,7 @@ import javax.persistence.Enumerated;
import javax.persistence.Id; import javax.persistence.Id;
import javax.persistence.Table; import javax.persistence.Table;
import com.google.common.base.Objects; import com.google.common.base.MoreObjects;
import com.sismics.docs.core.constant.PermType; import com.sismics.docs.core.constant.PermType;
import com.sismics.docs.core.util.AuditLogUtil; import com.sismics.docs.core.util.AuditLogUtil;
@ -98,7 +98,7 @@ public class Acl implements Loggable {
@Override @Override
public String toString() { public String toString() {
return Objects.toStringHelper(this) return MoreObjects.toStringHelper(this)
.add("id", id) .add("id", id)
.add("perm", perm) .add("perm", perm)
.add("sourceId", sourceId) .add("sourceId", sourceId)

View File

@ -9,7 +9,7 @@ import javax.persistence.Enumerated;
import javax.persistence.Id; import javax.persistence.Id;
import javax.persistence.Table; import javax.persistence.Table;
import com.google.common.base.Objects; import com.google.common.base.MoreObjects;
import com.sismics.docs.core.constant.AuditLogType; import com.sismics.docs.core.constant.AuditLogType;
/** /**
@ -168,7 +168,7 @@ public class AuditLog {
@Override @Override
public String toString() { public String toString() {
return Objects.toStringHelper(this) return MoreObjects.toStringHelper(this)
.add("id", id) .add("id", id)
.add("entityId", entityId) .add("entityId", entityId)
.add("entityClass", entityClass) .add("entityClass", entityClass)

View File

@ -1,12 +1,13 @@
package com.sismics.docs.core.model.jpa; package com.sismics.docs.core.model.jpa;
import com.google.common.base.Objects; import java.util.Date;
import javax.persistence.Column; import javax.persistence.Column;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.Id; import javax.persistence.Id;
import javax.persistence.Table; import javax.persistence.Table;
import java.util.Date;
import com.google.common.base.MoreObjects;
/** /**
* Authentication token entity. * Authentication token entity.
@ -183,7 +184,7 @@ public class AuthenticationToken {
@Override @Override
public String toString() { public String toString() {
return Objects.toStringHelper(this) return MoreObjects.toStringHelper(this)
.add("id", "**hidden**") .add("id", "**hidden**")
.add("userId", userId) .add("userId", userId)
.add("ip", ip) .add("ip", ip)

View File

@ -1,12 +1,12 @@
package com.sismics.docs.core.model.jpa; package com.sismics.docs.core.model.jpa;
import com.google.common.base.Objects;
import javax.persistence.Column; import javax.persistence.Column;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.Id; import javax.persistence.Id;
import javax.persistence.Table; import javax.persistence.Table;
import com.google.common.base.MoreObjects;
/** /**
* Base function entity. * Base function entity.
* *
@ -42,7 +42,7 @@ public class BaseFunction {
@Override @Override
public String toString() { public String toString() {
return Objects.toStringHelper(this) return MoreObjects.toStringHelper(this)
.add("id", id) .add("id", id)
.toString(); .toString();
} }

View File

@ -1,9 +1,14 @@
package com.sismics.docs.core.model.jpa; package com.sismics.docs.core.model.jpa;
import com.google.common.base.Objects; import javax.persistence.Column;
import com.sismics.docs.core.constant.ConfigType; import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.*; import com.google.common.base.MoreObjects;
import com.sismics.docs.core.constant.ConfigType;
/** /**
* Configuration parameter entity. * Configuration parameter entity.
@ -65,7 +70,7 @@ public class Config {
@Override @Override
public String toString() { public String toString() {
return Objects.toStringHelper(this) return MoreObjects.toStringHelper(this)
.add("id", id) .add("id", id)
.toString(); .toString();
} }

View File

@ -1,7 +1,6 @@
package com.sismics.docs.core.model.jpa; package com.sismics.docs.core.model.jpa;
import com.google.common.base.Objects; import java.util.Date;
import com.sismics.docs.core.util.AuditLogUtil;
import javax.persistence.Column; import javax.persistence.Column;
import javax.persistence.Entity; import javax.persistence.Entity;
@ -9,7 +8,8 @@ import javax.persistence.EntityListeners;
import javax.persistence.Id; import javax.persistence.Id;
import javax.persistence.Table; import javax.persistence.Table;
import java.util.Date; import com.google.common.base.MoreObjects;
import com.sismics.docs.core.util.AuditLogUtil;
/** /**
* Document entity. * Document entity.
@ -192,7 +192,7 @@ public class Document implements Loggable {
@Override @Override
public String toString() { public String toString() {
return Objects.toStringHelper(this) return MoreObjects.toStringHelper(this)
.add("id", id) .add("id", id)
.toString(); .toString();
} }

View File

@ -1,14 +1,14 @@
package com.sismics.docs.core.model.jpa; package com.sismics.docs.core.model.jpa;
import com.google.common.base.Objects; import java.io.Serializable;
import java.util.Date;
import javax.persistence.Column; import javax.persistence.Column;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.Id; import javax.persistence.Id;
import javax.persistence.Table; import javax.persistence.Table;
import java.io.Serializable; import com.google.common.base.MoreObjects;
import java.util.Date;
/** /**
* Link between a document and a tag. * Link between a document and a tag.
@ -122,7 +122,7 @@ public class DocumentTag implements Serializable {
@Override @Override
public String toString() { public String toString() {
return Objects.toStringHelper(this) return MoreObjects.toStringHelper(this)
.add("documentId", documentId) .add("documentId", documentId)
.add("tagId", tagId) .add("tagId", tagId)
.toString(); .toString();

View File

@ -1,7 +1,6 @@
package com.sismics.docs.core.model.jpa; package com.sismics.docs.core.model.jpa;
import com.google.common.base.Objects; import java.util.Date;
import com.sismics.docs.core.util.AuditLogUtil;
import javax.persistence.Column; import javax.persistence.Column;
import javax.persistence.Entity; import javax.persistence.Entity;
@ -10,7 +9,8 @@ import javax.persistence.Id;
import javax.persistence.Lob; import javax.persistence.Lob;
import javax.persistence.Table; import javax.persistence.Table;
import java.util.Date; import com.google.common.base.MoreObjects;
import com.sismics.docs.core.util.AuditLogUtil;
/** /**
* File entity. * File entity.
@ -218,7 +218,7 @@ public class File implements Loggable {
@Override @Override
public String toString() { public String toString() {
return Objects.toStringHelper(this) return MoreObjects.toStringHelper(this)
.add("id", id) .add("id", id)
.toString(); .toString();
} }

View File

@ -1,49 +0,0 @@
package com.sismics.docs.core.model.jpa;
import com.google.common.base.Objects;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
/**
* Locale entity.
*
* @author jtremeaux
*/
@Entity
@Table(name = "T_LOCALE")
public class Locale {
/**
* Locale ID (ex: fr_FR).
*/
@Id
@Column(name = "LOC_ID_C", length = 10)
private String id;
/**
* Getter of id.
*
* @return id
*/
public String getId() {
return id;
}
/**
* Setter of id.
*
* @param id id
*/
public void setId(String id) {
this.id = id;
}
@Override
public String toString() {
return Objects.toStringHelper(this)
.add("id", id)
.toString();
}
}

View File

@ -1,12 +1,13 @@
package com.sismics.docs.core.model.jpa; package com.sismics.docs.core.model.jpa;
import com.google.common.base.Objects; import java.util.Date;
import javax.persistence.Column; import javax.persistence.Column;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.Id; import javax.persistence.Id;
import javax.persistence.Table; import javax.persistence.Table;
import java.util.Date;
import com.google.common.base.MoreObjects;
/** /**
* Role (set of base functions). * Role (set of base functions).
@ -115,7 +116,7 @@ public class Role {
@Override @Override
public String toString() { public String toString() {
return Objects.toStringHelper(this) return MoreObjects.toStringHelper(this)
.add("id", id) .add("id", id)
.add("name", name) .add("name", name)
.toString(); .toString();

View File

@ -1,12 +1,13 @@
package com.sismics.docs.core.model.jpa; package com.sismics.docs.core.model.jpa;
import com.google.common.base.Objects; import java.util.Date;
import javax.persistence.Column; import javax.persistence.Column;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.Id; import javax.persistence.Id;
import javax.persistence.Table; import javax.persistence.Table;
import java.util.Date;
import com.google.common.base.MoreObjects;
/** /**
* Role base function. * Role base function.
@ -139,7 +140,7 @@ public class RoleBaseFunction {
@Override @Override
public String toString() { public String toString() {
return Objects.toStringHelper(this) return MoreObjects.toStringHelper(this)
.add("id", id) .add("id", id)
.add("userId", roleId) .add("userId", roleId)
.add("baseFunctionId", baseFunctionId) .add("baseFunctionId", baseFunctionId)

View File

@ -1,12 +1,13 @@
package com.sismics.docs.core.model.jpa; package com.sismics.docs.core.model.jpa;
import com.google.common.base.Objects; import java.util.Date;
import javax.persistence.Column; import javax.persistence.Column;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.Id; import javax.persistence.Id;
import javax.persistence.Table; import javax.persistence.Table;
import java.util.Date;
import com.google.common.base.MoreObjects;
/** /**
* ACL target used to share a document. * ACL target used to share a document.
@ -113,7 +114,7 @@ public class Share {
@Override @Override
public String toString() { public String toString() {
return Objects.toStringHelper(this) return MoreObjects.toStringHelper(this)
.add("id", id) .add("id", id)
.toString(); .toString();
} }

View File

@ -1,7 +1,6 @@
package com.sismics.docs.core.model.jpa; package com.sismics.docs.core.model.jpa;
import com.google.common.base.Objects; import java.util.Date;
import com.sismics.docs.core.util.AuditLogUtil;
import javax.persistence.Column; import javax.persistence.Column;
import javax.persistence.Entity; import javax.persistence.Entity;
@ -9,7 +8,8 @@ import javax.persistence.EntityListeners;
import javax.persistence.Id; import javax.persistence.Id;
import javax.persistence.Table; import javax.persistence.Table;
import java.util.Date; import com.google.common.base.MoreObjects;
import com.sismics.docs.core.util.AuditLogUtil;
/** /**
* Tag. * Tag.
@ -168,7 +168,7 @@ public class Tag implements Loggable {
@Override @Override
public String toString() { public String toString() {
return Objects.toStringHelper(this) return MoreObjects.toStringHelper(this)
.add("id", id) .add("id", id)
.add("name", name) .add("name", name)
.toString(); .toString();

View File

@ -8,7 +8,7 @@ import javax.persistence.EntityListeners;
import javax.persistence.Id; import javax.persistence.Id;
import javax.persistence.Table; import javax.persistence.Table;
import com.google.common.base.Objects; import com.google.common.base.MoreObjects;
import com.sismics.docs.core.util.AuditLogUtil; import com.sismics.docs.core.util.AuditLogUtil;
/** /**
@ -27,12 +27,6 @@ public class User implements Loggable {
@Column(name = "USE_ID_C", length = 36) @Column(name = "USE_ID_C", length = 36)
private String id; private String id;
/**
* Locale ID.
*/
@Column(name = "USE_IDLOCALE_C", nullable = false, length = 10)
private String localeId;
/** /**
* Role ID. * Role ID.
*/ */
@ -63,18 +57,6 @@ public class User implements Loggable {
@Column(name = "USE_EMAIL_C", nullable = false, length = 100) @Column(name = "USE_EMAIL_C", nullable = false, length = 100)
private String email; private String email;
/**
* Theme.
*/
@Column(name = "USE_THEME_C", nullable = false, length = 100)
private String theme;
/**
* True if the user hasn't dismissed the first connection screen.
*/
@Column(name = "USE_FIRSTCONNECTION_B", nullable = false)
private boolean firstConnection;
/** /**
* Creation date. * Creation date.
*/ */
@ -105,24 +87,6 @@ public class User implements Loggable {
this.id = id; this.id = id;
} }
/**
* Getter of localeId.
*
* @return localeId
*/
public String getLocaleId() {
return localeId;
}
/**
* Setter of localeId.
*
* @param localeId localeId
*/
public void setLocaleId(String localeId) {
this.localeId = localeId;
}
/** /**
* Getter of roleId. * Getter of roleId.
* *
@ -195,42 +159,6 @@ public class User implements Loggable {
this.email = email; this.email = email;
} }
/**
* Getter of theme.
*
* @return theme
*/
public String getTheme() {
return theme;
}
/**
* Setter of theme.
*
* @param theme theme
*/
public void setTheme(String theme) {
this.theme = theme;
}
/**
* Getter of firstConnection.
*
* @return firstConnection
*/
public boolean isFirstConnection() {
return firstConnection;
}
/**
* Setter of firstConnection.
*
* @param firstConnection firstConnection
*/
public void setFirstConnection(boolean firstConnection) {
this.firstConnection = firstConnection;
}
/** /**
* Getter of createDate. * Getter of createDate.
* *
@ -286,7 +214,7 @@ public class User implements Loggable {
@Override @Override
public String toString() { public String toString() {
return Objects.toStringHelper(this) return MoreObjects.toStringHelper(this)
.add("id", id) .add("id", id)
.add("username", username) .add("username", username)
.toString(); .toString();

View File

@ -1,9 +1,10 @@
package com.sismics.docs.core.util; package com.sismics.docs.core.util;
import com.sismics.util.EnvironmentUtil; import java.io.File;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import java.io.File; import com.sismics.util.EnvironmentUtil;
/** /**
* Utilities to gain access to the storage directories used by the application. * Utilities to gain access to the storage directories used by the application.
@ -18,27 +19,27 @@ public class DirectoryUtil {
*/ */
public static File getBaseDataDirectory() { public static File getBaseDataDirectory() {
File baseDataDir = null; File baseDataDir = null;
if (EnvironmentUtil.getWebappRoot() != null) { if (StringUtils.isNotBlank(EnvironmentUtil.getDocsHome())) {
// We are in a webapp environment // If the docs.home property is set then use it
if (StringUtils.isNotBlank(EnvironmentUtil.getDocsHome())) { baseDataDir = new File(EnvironmentUtil.getDocsHome());
// If the docs.home property is set then use it } else if (EnvironmentUtil.isUnitTest()) {
baseDataDir = new File(EnvironmentUtil.getDocsHome()); // For unit testing, use a temporary directory
if (!baseDataDir.isDirectory()) { baseDataDir = new File(System.getProperty("java.io.tmpdir"));
baseDataDir.mkdirs(); } else {
} // We are in a webapp environment and nothing is specified, use the default directory for this OS
} else { if (EnvironmentUtil.isUnix()) {
// Use the base of the Webapp directory baseDataDir = new File("/var/docs");
baseDataDir = new File(EnvironmentUtil.getWebappRoot() + File.separator + "sismicsdocs"); } if (EnvironmentUtil.isWindows()) {
if (!baseDataDir.isDirectory()) { baseDataDir = new File(EnvironmentUtil.getWindowsAppData() + "\\Sismics\\Docs");
baseDataDir.mkdirs(); } else if (EnvironmentUtil.isMacOs()) {
} baseDataDir = new File(EnvironmentUtil.getMacOsUserHome() + "/Library/Sismics/Docs");
} }
} }
if (baseDataDir == null) {
// Or else (for unit testing), use a temporary directory if (baseDataDir != null && !baseDataDir.isDirectory()) {
baseDataDir = new File(System.getProperty("java.io.tmpdir")); baseDataDir.mkdirs();
} }
return baseDataDir; return baseDataDir;
} }
@ -78,25 +79,6 @@ public class DirectoryUtil {
return getDataSubDirectory("log"); return getDataSubDirectory("log");
} }
/**
* Returns the themes directory.
*
* @return Theme directory.
*/
public static File getThemeDirectory() {
String webappRoot = EnvironmentUtil.getWebappRoot();
File themeDir = null;
if (webappRoot != null) {
themeDir = new File(webappRoot + File.separator + "style" + File.separator + "theme");
} else {
themeDir = new File(DirectoryUtil.class.getResource("/style/theme").getFile());
}
if (themeDir != null && themeDir.isDirectory()) {
return themeDir;
}
return null;
}
/** /**
* Returns a subdirectory of the base data directory * Returns a subdirectory of the base data directory
* *

View File

@ -9,7 +9,7 @@ public class EnvironmentUtil {
private static String OS = System.getProperty("os.name").toLowerCase(); private static String OS = System.getProperty("os.name").toLowerCase();
private static String TEST_ENV = System.getProperty("test"); private static String APPLICATION_MODE = System.getProperty("application.mode");
private static String WINDOWS_APPDATA = System.getenv("APPDATA"); private static String WINDOWS_APPDATA = System.getenv("APPDATA");
@ -18,9 +18,9 @@ public class EnvironmentUtil {
private static String DOCS_HOME = System.getProperty("docs.home"); private static String DOCS_HOME = System.getProperty("docs.home");
/** /**
* Web application root. * In a web application context.
*/ */
private static String webappRoot; private static boolean webappContext;
/** /**
* Returns true if running under Microsoft Windows. * Returns true if running under Microsoft Windows.
@ -55,10 +55,18 @@ public class EnvironmentUtil {
* @return Unit testing environment * @return Unit testing environment
*/ */
public static boolean isUnitTest() { public static boolean isUnitTest() {
return webappRoot == null || return !webappContext || isDevMode();
TEST_ENV != null && "true".equals(TEST_ENV);
} }
/**
* Return true if we are in dev mode.
*
* @return Dev mode
*/
public static boolean isDevMode() {
return "dev".equalsIgnoreCase(APPLICATION_MODE);
}
/** /**
* Returns the MS Windows AppData directory of this user. * Returns the MS Windows AppData directory of this user.
* *
@ -87,20 +95,20 @@ public class EnvironmentUtil {
} }
/** /**
* Getter of webappRoot. * Getter of webappContext.
* *
* @return webappRoot * @return webappContext
*/ */
public static String getWebappRoot() { public static boolean isWebappContext() {
return webappRoot; return webappContext;
} }
/** /**
* Setter of webappRoot. * Setter of webappContext.
* *
* @param webappRoot webappRoot * @param webappContext webappContext
*/ */
public static void setWebappRoot(String webappRoot) { public static void setWebappContext(boolean webappContext) {
EnvironmentUtil.webappRoot = webappRoot; EnvironmentUtil.webappContext = webappContext;
} }
} }

View File

@ -1,111 +0,0 @@
package com.sismics.util;
import org.codehaus.jackson.JsonNode;
import java.text.MessageFormat;
/**
* JSON validation utilities.
*
* @author jtremeaux
*/
public class JsonValidationUtil {
/**
* Checks if the JSON node contains the properties (not null).
*
* @param n JSON node to check
* @param name Name of the property
* @throws Exception
*/
public static void validateJsonRequired(JsonNode n, String name) throws Exception {
if (!n.has(name)) {
throw new Exception(MessageFormat.format("{0} must be set", name));
}
}
/**
* Checks that the property is a JSON object.
*
* @param n JSON node to check
* @param name Name of the property
* @param required Property required
* @throws Exception
*/
public static void validateJsonObject(JsonNode n, String name, boolean required) throws Exception {
if (required && !n.has(name)) {
throw new Exception(MessageFormat.format("{0} must be set", name));
}
if (n.has(name) && !n.path(name).isObject()) {
throw new Exception(MessageFormat.format("{0} must be a JSON object", name));
}
}
/**
* Checks that the property is a number.
*
* @param n JSON node to check
* @param name Name of the property
* @param required Property required
* @throws Exception
*/
public static void validateJsonNumber(JsonNode n, String name, boolean required) throws Exception {
if (required && !n.has(name)) {
throw new Exception(MessageFormat.format("{0} must be set", name));
}
if (n.has(name) && !n.path(name).isNumber()) {
throw new Exception(MessageFormat.format("{0} must be a number", name));
}
}
/**
* Checks that the property is a long.
*
* @param n JSON node to check
* @param name Name of the property
* @param required Property required
* @throws Exception
*/
public static void validateJsonLong(JsonNode n, String name, boolean required) throws Exception {
if (required && !n.has(name)) {
throw new Exception(MessageFormat.format("{0} must be set", name));
}
if (n.has(name) && !n.path(name).isLong()) {
throw new Exception(MessageFormat.format("{0} must be a long", name));
}
}
/**
* Checks that the property is a string.
*
* @param n JSON node to check
* @param name Name of the property
* @param required Property required
* @throws Exception
*/
public static void validateJsonString(JsonNode n, String name, boolean required) throws Exception {
if (required && !n.has(name)) {
throw new Exception(MessageFormat.format("{0} must be set", name));
}
if (n.has(name) && !n.path(name).isTextual()) {
throw new Exception(MessageFormat.format("{0} must be a string", name));
}
}
/**
* Checks that the property is an array.
*
* @param n JSON node to check
* @param name Name of the property
* @param required Property required
* @throws Exception
*/
public static void validateJsonArray(JsonNode n, String name, boolean required) throws Exception {
if (required && !n.has(name)) {
throw new Exception(MessageFormat.format("{0} must be set", name));
}
if (n.has(name) && !n.path(name).isArray()) {
throw new Exception(MessageFormat.format("{0} must be an array", name));
}
}
}

View File

@ -1,62 +0,0 @@
package com.sismics.util;
import com.sismics.docs.core.constant.Constants;
import com.sismics.docs.core.dao.jpa.LocaleDao;
import org.apache.commons.lang.StringUtils;
import java.util.Locale;
/**
* Locale utilities.
*
* @author jtremeaux
*/
public class LocaleUtil {
/**
* Returns the locale from its language / country code (ex: fr_FR).
*
* @param localeCode Locale code
* @return Locate instance
*/
public static final Locale getLocale(String localeCode) {
String[] localeCodeArray = localeCode.split("_");
String language = localeCodeArray[0];
String country = "";
String variant = "";
if (localeCodeArray.length >= 2) {
country = localeCodeArray[1];
}
if (localeCodeArray.length >= 3) {
variant = localeCodeArray[2];
}
return new Locale(language, country, variant);
}
/**
* Extracts the ID of the locale from the HTTP Accept-Language header.
*
* @param acceptLanguageHeader header
* @return Locale ID
*/
public static String getLocaleIdFromAcceptLanguage(String acceptLanguageHeader) {
String localeId = null;
if (StringUtils.isNotBlank(acceptLanguageHeader)) {
acceptLanguageHeader = acceptLanguageHeader.replaceAll("-", "_");
localeId = acceptLanguageHeader.split(",")[0];
}
if (StringUtils.isNotBlank(localeId)) {
LocaleDao localeDao = new LocaleDao();
com.sismics.docs.core.model.jpa.Locale locale = localeDao.getById(localeId);
if (locale != null) {
localeId = locale.getId();
} else {
// The client provided an unknown locale
localeId = Constants.DEFAULT_LOCALE_ID;
}
}
if (StringUtils.isBlank(localeId)) {
localeId = Constants.DEFAULT_LOCALE_ID;
}
return localeId;
}
}

View File

@ -1,43 +0,0 @@
package com.sismics.util;
import java.text.MessageFormat;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
/**
* Message utilities.
*
* @author jtremeaux
*/
public class MessageUtil {
/**
* Returns a message formated in the specified locale.
* Returns **key** if no message is set for this key.
*
* @param locale Locale
* @param key Message key
* @param args Arguments of the message
* @return Formated message
*/
public static String getMessage(Locale locale, String key, Object... args) {
ResourceBundle resources = ResourceBundle.getBundle("messages", locale);
String message = null;
try {
message = resources.getString(key);
} catch (MissingResourceException e) {
message = "**" + key + "**";
}
return MessageFormat.format(message, args);
}
/**
* Returns the resource bundle containing messages for the locale.
*
* @param locale Locale to use
* @return Resource bundle
*/
public static ResourceBundle getMessage(Locale locale) {
return ResourceBundle.getBundle("messages", locale);
}
}

View File

@ -9,7 +9,6 @@
<class>com.sismics.docs.core.model.jpa.AuthenticationToken</class> <class>com.sismics.docs.core.model.jpa.AuthenticationToken</class>
<class>com.sismics.docs.core.model.jpa.BaseFunction</class> <class>com.sismics.docs.core.model.jpa.BaseFunction</class>
<class>com.sismics.docs.core.model.jpa.Config</class> <class>com.sismics.docs.core.model.jpa.Config</class>
<class>com.sismics.docs.core.model.jpa.Locale</class>
<class>com.sismics.docs.core.model.jpa.User</class> <class>com.sismics.docs.core.model.jpa.User</class>
<class>com.sismics.docs.core.model.jpa.RoleBaseFunction</class> <class>com.sismics.docs.core.model.jpa.RoleBaseFunction</class>
<class>com.sismics.docs.core.model.jpa.Document</class> <class>com.sismics.docs.core.model.jpa.Document</class>

View File

@ -1 +1 @@
db.version=0 db.version=1

View File

@ -0,0 +1,5 @@
alter table T_USER drop column USE_IDLOCALE_C;
alter table T_USER drop column USE_THEME_C;
alter table T_USER drop column USE_FIRSTCONNECTION_B;
drop table T_LOCALE;
update T_CONFIG set CFG_VALUE_C = '1' where CFG_ID_C = 'DB_VERSION';

View File

@ -19,7 +19,6 @@ public class TestJpa extends BaseTransactionalTest {
User user = new User(); User user = new User();
user.setUsername("username"); user.setUsername("username");
user.setEmail("toto@docs.com"); user.setEmail("toto@docs.com");
user.setLocaleId("fr");
user.setRoleId("admin"); user.setRoleId("admin");
user.setPrivateKey("AwesomePrivateKey"); user.setPrivateKey("AwesomePrivateKey");
String id = userDao.create(user); String id = userDao.create(user);

View File

@ -43,9 +43,8 @@ public class TestEncryptUtil {
InputStream inputStream = new CipherInputStream(this.getClass().getResourceAsStream("/file/udhr.pdf"), cipher); InputStream inputStream = new CipherInputStream(this.getClass().getResourceAsStream("/file/udhr.pdf"), cipher);
byte[] encryptedData = ByteStreams.toByteArray(inputStream); byte[] encryptedData = ByteStreams.toByteArray(inputStream);
byte[] assertData = ByteStreams.toByteArray(this.getClass().getResourceAsStream("/file/udhr_encrypted.pdf")); byte[] assertData = ByteStreams.toByteArray(this.getClass().getResourceAsStream("/file/udhr_encrypted.pdf"));
Assert.assertTrue(ByteStreams.equal(
ByteStreams.newInputStreamSupplier(encryptedData), Assert.assertEquals(encryptedData.length, assertData.length);
ByteStreams.newInputStreamSupplier(assertData)));
} }
@Test @Test
@ -53,8 +52,7 @@ public class TestEncryptUtil {
InputStream inputStream = EncryptionUtil.decryptInputStream(this.getClass().getResourceAsStream("/file/udhr_encrypted.pdf"), pk); InputStream inputStream = EncryptionUtil.decryptInputStream(this.getClass().getResourceAsStream("/file/udhr_encrypted.pdf"), pk);
byte[] encryptedData = ByteStreams.toByteArray(inputStream); byte[] encryptedData = ByteStreams.toByteArray(inputStream);
byte[] assertData = ByteStreams.toByteArray(this.getClass().getResourceAsStream("/file/udhr.pdf")); byte[] assertData = ByteStreams.toByteArray(this.getClass().getResourceAsStream("/file/udhr.pdf"));
Assert.assertTrue(ByteStreams.equal(
ByteStreams.newInputStreamSupplier(encryptedData), Assert.assertEquals(encryptedData.length, assertData.length);
ByteStreams.newInputStreamSupplier(assertData)));
} }
} }

View File

@ -1,2 +0,0 @@
- Automatic backup system using Quartz (server)
- Handle error while uploading a file (client)

View File

@ -16,54 +16,38 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- Dependencies version (external) --> <!-- Dependencies version (external) -->
<org.apache.commons.commons-compress.version>1.5</org.apache.commons.commons-compress.version> <org.apache.commons.commons-compress.version>1.10</org.apache.commons.commons-compress.version>
<commons-lang.commons-lang.version>2.6</commons-lang.commons-lang.version> <commons-lang.commons-lang.version>2.6</commons-lang.commons-lang.version>
<commons-io.commons-io.version>2.1</commons-io.commons-io.version> <commons-io.commons-io.version>2.4</commons-io.commons-io.version>
<com.google.guava.guava.version>14.0</com.google.guava.guava.version> <commons-dbcp.version>1.4</commons-dbcp.version>
<com.google.guava.guava.version>18.0</com.google.guava.guava.version>
<log4j.log4j.version>1.2.16</log4j.log4j.version> <log4j.log4j.version>1.2.16</log4j.log4j.version>
<org.slf4j.version>1.6.4</org.slf4j.version> <org.slf4j.version>1.6.4</org.slf4j.version>
<org.slf4j.jcl-over-slf4j.version>1.6.6</org.slf4j.jcl-over-slf4j.version> <org.slf4j.jcl-over-slf4j.version>1.6.6</org.slf4j.jcl-over-slf4j.version>
<junit.junit.version>4.7</junit.junit.version> <junit.junit.version>4.7</junit.junit.version>
<com.h2database.h2.version>1.4.188</com.h2database.h2.version> <com.h2database.h2.version>1.4.188</com.h2database.h2.version>
<com.sun.jersey.version>1.17</com.sun.jersey.version> <org.glassfish.jersey.version>2.21</org.glassfish.jersey.version>
<org.mindrot.jbcrypt>0.3m</org.mindrot.jbcrypt> <org.mindrot.jbcrypt>0.3m</org.mindrot.jbcrypt>
<org.subethamail.subethasmtp.version>3.1.6</org.subethamail.subethasmtp.version>
<org.subethamail.subethasmtp-wiser.version>1.2</org.subethamail.subethasmtp-wiser.version>
<org.codehaus.jettison.jettison.version>1.1</org.codehaus.jettison.jettison.version>
<org.ccil.cowan.tagsoup.tagsoup.version>1.2.1</org.ccil.cowan.tagsoup.tagsoup.version>
<com.googlecode.owasp-java-html-sanitizer.owasp-java-html-sanitizer.version>r156</com.googlecode.owasp-java-html-sanitizer.owasp-java-html-sanitizer.version>
<org.apache.lucene.version>4.2.0</org.apache.lucene.version> <org.apache.lucene.version>4.2.0</org.apache.lucene.version>
<jgoodies.forms.version>1.0.5</jgoodies.forms.version>
<org.imgscalr.imgscalr-lib.version>4.2</org.imgscalr.imgscalr-lib.version> <org.imgscalr.imgscalr-lib.version>4.2</org.imgscalr.imgscalr-lib.version>
<org.apache.pdfbox.pdfbox.version>2.0.0-SNAPSHOT</org.apache.pdfbox.pdfbox.version> <org.apache.pdfbox.pdfbox.version>2.0.0-SNAPSHOT</org.apache.pdfbox.pdfbox.version>
<org.bouncycastle.bcprov-jdk15on.version>1.49</org.bouncycastle.bcprov-jdk15on.version> <org.bouncycastle.bcprov-jdk15on.version>1.49</org.bouncycastle.bcprov-jdk15on.version>
<joda-time.joda-time.version>2.8.2</joda-time.joda-time.version>
<com.sun.grizzly.version>1.9.18-m</com.sun.grizzly.version>
<org.hibernate.hibernate.version>4.1.0.Final</org.hibernate.hibernate.version> <org.hibernate.hibernate.version>4.1.0.Final</org.hibernate.hibernate.version>
<commons-dbcp.version>1.4</commons-dbcp.version> <javax.servlet.javax.servlet-api.version>3.1.0</javax.servlet.javax.servlet-api.version>
<joda-time.joda-time.version>2.2</joda-time.joda-time.version>
<org.codehaus.jackson.jackson.version>1.7.1</org.codehaus.jackson.jackson.version>
<org.eclipse.jetty.jetty-server.version>8.1.10.v20130312</org.eclipse.jetty.jetty-server.version> <org.eclipse.jetty.jetty-server.version>9.2.13.v20150730</org.eclipse.jetty.jetty-server.version>
<org.eclipse.jetty.jetty-webapp.version>8.1.10.v20130312</org.eclipse.jetty.jetty-webapp.version> <org.eclipse.jetty.jetty-webapp.version>9.2.13.v20150730</org.eclipse.jetty.jetty-webapp.version>
<org.eclipse.jetty.jetty-servlet.version>8.1.10.v20130312</org.eclipse.jetty.jetty-servlet.version> <org.eclipse.jetty.jetty-servlet.version>9.2.13.v20150730</org.eclipse.jetty.jetty-servlet.version>
<org.mortbay.jetty.servlet-api.version>3.0.20100224</org.mortbay.jetty.servlet-api.version>
<!-- Plugins version --> <!-- Plugins version -->
<org.apache.maven.plugins.maven-antrun-plugin.version>1.7</org.apache.maven.plugins.maven-antrun-plugin.version> <org.apache.maven.plugins.maven-antrun-plugin.version>1.8</org.apache.maven.plugins.maven-antrun-plugin.version>
<org.apache.maven.plugins.maven-dependency-plugin.version>2.7</org.apache.maven.plugins.maven-dependency-plugin.version> <org.apache.maven.plugins.maven-dependency-plugin.version>2.10</org.apache.maven.plugins.maven-dependency-plugin.version>
<org.apache.maven.plugins.maven-eclipse-plugin.version>2.8</org.apache.maven.plugins.maven-eclipse-plugin.version>
<org.apache.maven.plugins.maven-jar-plugin.version>2.4</org.apache.maven.plugins.maven-jar-plugin.version> <org.apache.maven.plugins.maven-jar-plugin.version>2.4</org.apache.maven.plugins.maven-jar-plugin.version>
<org.apache.maven.plugins.maven-release-plugin.version>2.4.1</org.apache.maven.plugins.maven-release-plugin.version> <org.apache.maven.plugins.maven-release-plugin.version>2.5.2</org.apache.maven.plugins.maven-release-plugin.version>
<org.apache.maven.plugins.maven-resources-plugin.version>2.6</org.apache.maven.plugins.maven-resources-plugin.version> <org.apache.maven.plugins.maven-resources-plugin.version>2.7</org.apache.maven.plugins.maven-resources-plugin.version>
<org.apache.maven.plugins.maven-war-plugin.version>2.2</org.apache.maven.plugins.maven-war-plugin.version> <org.apache.maven.plugins.maven-war-plugin.version>2.6</org.apache.maven.plugins.maven-war-plugin.version>
<org.codehaus.cargo.cargo-maven2-plugin.version>1.2.0</org.codehaus.cargo.cargo-maven2-plugin.version> <org.eclipse.jetty.jetty-maven-plugin.version>9.2.13.v20150730</org.eclipse.jetty.jetty-maven-plugin.version>
<org.codehaus.mojo.rpm-maven-plugin.version>2.1-alpha-2</org.codehaus.mojo.rpm-maven-plugin.version>
<org.codehaus.mojo.nsis-maven-plugin.version>1.0-SNAPSHOT</org.codehaus.mojo.nsis-maven-plugin.version>
<org.codehaus.mojo.osxappbundle-maven-plugin.version>1.0-alpha-2</org.codehaus.mojo.osxappbundle-maven-plugin.version>
<org.mortbay.jetty.jetty-maven-plugin.version>8.1.2.v20120308</org.mortbay.jetty.jetty-maven-plugin.version>
<org.vafer.jdeb.version>1.0.1</org.vafer.jdeb.version>
<com.samaxes.maven.minify-maven-plugin.version>1.7</com.samaxes.maven.minify-maven-plugin.version>
</properties> </properties>
<scm> <scm>
@ -99,27 +83,12 @@
<version>${org.apache.maven.plugins.maven-dependency-plugin.version}</version> <version>${org.apache.maven.plugins.maven-dependency-plugin.version}</version>
</plugin> </plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-eclipse-plugin</artifactId>
<version>${org.apache.maven.plugins.maven-eclipse-plugin.version}</version>
</plugin>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId> <artifactId>maven-jar-plugin</artifactId>
<version>${org.apache.maven.plugins.maven-jar-plugin.version}</version> <version>${org.apache.maven.plugins.maven-jar-plugin.version}</version>
</plugin> </plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<version>${org.apache.maven.plugins.maven-release-plugin.version}</version>
<configuration>
<tagNameFormat>@{project.version}</tagNameFormat>
</configuration>
</plugin>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId> <artifactId>maven-resources-plugin</artifactId>
@ -133,45 +102,9 @@
</plugin> </plugin>
<plugin> <plugin>
<groupId>org.codehaus.cargo</groupId> <groupId>org.eclipse.jetty</groupId>
<artifactId>cargo-maven2-plugin</artifactId>
<version>${org.codehaus.cargo.cargo-maven2-plugin.version}</version>
</plugin>
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId> <artifactId>jetty-maven-plugin</artifactId>
<version>${org.mortbay.jetty.jetty-maven-plugin.version}</version> <version>${org.eclipse.jetty.jetty-maven-plugin.version}</version>
</plugin>
<plugin>
<groupId>com.samaxes.maven</groupId>
<artifactId>minify-maven-plugin</artifactId>
<version>${com.samaxes.maven.minify-maven-plugin.version}</version>
</plugin>
<plugin>
<groupId>org.vafer</groupId>
<artifactId>jdeb</artifactId>
<version>${org.vafer.jdeb.version}</version>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>rpm-maven-plugin</artifactId>
<version>${org.codehaus.mojo.rpm-maven-plugin.version}</version>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>nsis-maven-plugin</artifactId>
<version>${org.codehaus.mojo.nsis-maven-plugin.version}</version>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>osxappbundle-maven-plugin</artifactId>
<version>${org.codehaus.mojo.osxappbundle-maven-plugin.version}</version>
</plugin> </plugin>
</plugins> </plugins>
@ -229,9 +162,9 @@
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.mortbay.jetty</groupId> <groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId> <artifactId>javax.servlet-api</artifactId>
<version>${org.mortbay.jetty.servlet-api.version}</version> <version>${javax.servlet.javax.servlet-api.version}</version>
</dependency> </dependency>
<dependency> <dependency>
@ -258,18 +191,6 @@
<version>${com.google.guava.guava.version}</version> <version>${com.google.guava.guava.version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
<version>${org.codehaus.jackson.jackson.version}</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>${org.codehaus.jackson.jackson.version}</version>
</dependency>
<dependency> <dependency>
<groupId>log4j</groupId> <groupId>log4j</groupId>
<artifactId>log4j</artifactId> <artifactId>log4j</artifactId>
@ -307,47 +228,54 @@
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.sun.jersey</groupId> <groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-server</artifactId> <artifactId>jersey-container-servlet</artifactId>
<version>${com.sun.jersey.version}</version> <version>${org.glassfish.jersey.version}</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-bundle</artifactId>
<version>${com.sun.jersey.version}</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-json</artifactId>
<version>${com.sun.jersey.version}</version>
</dependency>
<dependency>
<groupId>com.sun.jersey.contribs</groupId>
<artifactId>jersey-multipart</artifactId>
<version>${com.sun.jersey.version}</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-client</artifactId>
<version>${com.sun.jersey.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.sun.grizzly</groupId> <groupId>org.glassfish.jersey.media</groupId>
<artifactId>grizzly-servlet-webserver</artifactId> <artifactId>jersey-media-json-processing</artifactId>
<version>${com.sun.grizzly.version}</version> <version>${org.glassfish.jersey.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.sun.jersey.jersey-test-framework</groupId> <groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-test-framework-grizzly2</artifactId> <artifactId>jersey-media-multipart</artifactId>
<version>${com.sun.jersey.version}</version> <version>${org.glassfish.jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<version>${org.glassfish.jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
<artifactId>jersey-test-framework-provider-bundle</artifactId>
<type>pom</type>
<version>${org.glassfish.jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
<artifactId>jersey-test-framework-provider-external</artifactId>
<version>${org.glassfish.jersey.version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
<artifactId>jersey-test-framework-provider-grizzly2</artifactId>
<version>${org.glassfish.jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-grizzly2-servlet</artifactId>
<version>${org.glassfish.jersey.version}</version>
</dependency>
<dependency> <dependency>
<groupId>com.h2database</groupId> <groupId>com.h2database</groupId>
<artifactId>h2</artifactId> <artifactId>h2</artifactId>
@ -366,6 +294,12 @@
<version>${org.hibernate.hibernate.version}</version> <version>${org.hibernate.hibernate.version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>${org.hibernate.hibernate.version}</version>
</dependency>
<dependency> <dependency>
<groupId>commons-dbcp</groupId> <groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId> <artifactId>commons-dbcp</artifactId>
@ -378,48 +312,6 @@
<version>${joda-time.joda-time.version}</version> <version>${joda-time.joda-time.version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.subethamail</groupId>
<artifactId>subethasmtp-wiser</artifactId>
<version>${org.subethamail.subethasmtp-wiser.version}</version>
</dependency>
<dependency>
<groupId>org.codehaus.jettison</groupId>
<artifactId>jettison</artifactId>
<version>${org.codehaus.jettison.jettison.version}</version>
</dependency>
<dependency>
<groupId>com.google.oauth-client</groupId>
<artifactId>google-oauth-client</artifactId>
<version>${com.google.oauth-client.google-oauth-client.version}</version>
</dependency>
<dependency>
<groupId>com.google.apis</groupId>
<artifactId>google-api-services-oauth2</artifactId>
<version>${com.google.apis.google-api-services-oauth2.version}</version>
</dependency>
<dependency>
<groupId>com.google.http-client</groupId>
<artifactId>google-http-client-jackson2</artifactId>
<version>${com.google.http-client.google-http-client-jackson2.version}</version>
</dependency>
<dependency>
<groupId>org.ccil.cowan.tagsoup</groupId>
<artifactId>tagsoup</artifactId>
<version>${org.ccil.cowan.tagsoup.tagsoup.version}</version>
</dependency>
<dependency>
<groupId>com.googlecode.owasp-java-html-sanitizer</groupId>
<artifactId>owasp-java-html-sanitizer</artifactId>
<version>${com.googlecode.owasp-java-html-sanitizer.owasp-java-html-sanitizer.version}</version>
</dependency>
<dependency> <dependency>
<groupId>org.apache.lucene</groupId> <groupId>org.apache.lucene</groupId>
<artifactId>lucene-core</artifactId> <artifactId>lucene-core</artifactId>
@ -444,12 +336,6 @@
<version>${org.apache.lucene.version}</version> <version>${org.apache.lucene.version}</version>
</dependency> </dependency>
<dependency>
<groupId>jgoodies</groupId>
<artifactId>forms</artifactId>
<version>${jgoodies.forms.version}</version>
</dependency>
<dependency> <dependency>
<groupId>org.imgscalr</groupId> <groupId>org.imgscalr</groupId>
<artifactId>imgscalr-lib</artifactId> <artifactId>imgscalr-lib</artifactId>
@ -484,20 +370,6 @@
</dependencies> </dependencies>
</dependencyManagement> </dependencyManagement>
<pluginRepositories>
<!-- Codehause Snapshots (NSIS) -->
<pluginRepository>
<id>Codehaus Snapshots</id>
<url>http://nexus.codehaus.org/snapshots/</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
<releases>
<enabled>true</enabled> <!-- Workaround for MNG-2974 -->
</releases>
</pluginRepository>
</pluginRepositories>
<profiles> <profiles>
<profile> <profile>
<id>init</id> <id>init</id>

View File

@ -17,10 +17,15 @@
<dependencies> <dependencies>
<!-- Dependencies to Jersey --> <!-- Dependencies to Jersey -->
<dependency> <dependency>
<groupId>com.sun.jersey</groupId> <groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId> <artifactId>jersey-client</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-multipart</artifactId>
</dependency>
<!-- Depenedencies to Docs --> <!-- Depenedencies to Docs -->
<dependency> <dependency>
<groupId>com.sismics.docs</groupId> <groupId>com.sismics.docs</groupId>

View File

@ -1,6 +1,5 @@
package com.sismics.docs.stress; package com.sismics.docs.stress;
import java.io.BufferedInputStream;
import java.io.InputStream; import java.io.InputStream;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
@ -8,25 +7,30 @@ import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.ThreadLocalRandom;
import javax.json.JsonObject;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.Invocation;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.Form;
import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response.Status;
import junit.framework.Assert; import junit.framework.Assert;
import org.codehaus.jettison.json.JSONObject; import org.glassfish.jersey.client.ClientResponse;
import org.glassfish.jersey.media.multipart.FormDataMultiPart;
import org.glassfish.jersey.media.multipart.MultiPartFeature;
import org.glassfish.jersey.media.multipart.file.StreamDataBodyPart;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import com.sismics.docs.rest.filter.CookieAuthenticationFilter; import com.google.common.io.Resources;
import com.sismics.docs.rest.util.ClientUtil; import com.sismics.docs.rest.util.ClientUtil;
import com.sun.jersey.api.client.Client; import com.sismics.util.filter.TokenBasedSecurityFilter;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.ClientResponse.Status;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.core.util.MultivaluedMapImpl;
import com.sun.jersey.multipart.FormDataBodyPart;
import com.sun.jersey.multipart.FormDataMultiPart;
/** /**
* Stress app for Sismics Docs. * Stress app for Sismics Docs.
@ -45,7 +49,7 @@ public class Main {
private static final int TAG_PER_USER_COUNT = 20; private static final int TAG_PER_USER_COUNT = 20;
private static final int FILE_PER_DOCUMENT_COUNT = 0; private static final int FILE_PER_DOCUMENT_COUNT = 0;
private static Client client = Client.create(); private static Client client = ClientBuilder.newClient();
private static ClientUtil clientUtil; private static ClientUtil clientUtil;
private static Set<User> userSet = Sets.newHashSet(); private static Set<User> userSet = Sets.newHashSet();
@ -54,11 +58,12 @@ public class Main {
* Entry point. * Entry point.
* *
* @param args Args * @param args Args
* @throws Exception
*/ */
public static void main(String[] args) { public static void main(String[] args) throws Exception {
log.info("Starting stress test..."); log.info("Starting stress test...");
WebResource resource = client.resource(API_URL); WebTarget resource = client.target(API_URL);
clientUtil = new ClientUtil(resource); clientUtil = new ClientUtil(resource);
// Create users // Create users
@ -72,17 +77,16 @@ public class Main {
// Create tags for each user // Create tags for each user
int tagCreatedCount = 1; int tagCreatedCount = 1;
for (User user : userSet) { for (User user : userSet) {
WebResource tagResource = resource.path("/tag"); Invocation.Builder tagResource = resource.path("/tag").request()
tagResource.addFilter(new CookieAuthenticationFilter(user.authToken)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, user.authToken);
for (int j = 0; j < TAG_PER_USER_COUNT; j++) { for (int j = 0; j < TAG_PER_USER_COUNT; j++) {
MultivaluedMapImpl postParams = new MultivaluedMapImpl(); Form form = new Form();
String name = generateString(); String name = generateString();
postParams.add("name", name); form.param("name", name);
postParams.add("color", "#ff0000"); form.param("color", "#ff0000");
ClientResponse response = tagResource.put(ClientResponse.class, postParams); JsonObject json = tagResource.put(Entity.form(form), JsonObject.class);
JSONObject json = response.getEntity(JSONObject.class); user.tagList.add(json.getString("id"));
user.tagList.add(json.optString("id"));
log.info("Created tag " + (tagCreatedCount++) + "/" + TAG_PER_USER_COUNT * USER_COUNT); log.info("Created tag " + (tagCreatedCount++) + "/" + TAG_PER_USER_COUNT * USER_COUNT);
} }
} }
@ -91,33 +95,32 @@ public class Main {
int documentCreatedCount = 1; int documentCreatedCount = 1;
for (User user : userSet) { for (User user : userSet) {
for (int i = 0; i < DOCUMENT_PER_USER_COUNT; i++) { for (int i = 0; i < DOCUMENT_PER_USER_COUNT; i++) {
WebResource documentResource = resource.path("/document");
documentResource.addFilter(new CookieAuthenticationFilter(user.authToken));
MultivaluedMapImpl postParams = new MultivaluedMapImpl();
postParams.add("title", generateString());
postParams.add("description", generateString());
postParams.add("tags", user.tagList.get(ThreadLocalRandom.current().nextInt(user.tagList.size()))); // Random tag
postParams.add("language", "eng");
long createDate = new Date().getTime(); long createDate = new Date().getTime();
postParams.add("create_date", createDate); Form form = new Form()
ClientResponse response = documentResource.put(ClientResponse.class, postParams); .param("title", generateString())
JSONObject json = response.getEntity(JSONObject.class); .param("description", generateString())
String documentId = json.optString("id"); .param("tags", user.tagList.get(ThreadLocalRandom.current().nextInt(user.tagList.size()))) // Random tag
.param("language", "eng")
.param("create_date", Long.toString(createDate));
JsonObject json = resource.path("/document").request()
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, user.authToken)
.put(Entity.form(form), JsonObject.class);
String documentId = json.getString("id");
log.info("Created document " + (documentCreatedCount++) + "/" + DOCUMENT_PER_USER_COUNT * USER_COUNT + " for user: " + user.username); log.info("Created document " + (documentCreatedCount++) + "/" + DOCUMENT_PER_USER_COUNT * USER_COUNT + " for user: " + user.username);
// Add files for each document // Add files for each document
for (int j = 0; j < FILE_PER_DOCUMENT_COUNT; j++) { for (int j = 0; j < FILE_PER_DOCUMENT_COUNT; j++) {
WebResource fileResource = resource.path("/file"); try (InputStream is = Resources.getResource("empty.png").openStream()) {
fileResource.addFilter(new CookieAuthenticationFilter(user.authToken)); StreamDataBodyPart streamDataBodyPart = new StreamDataBodyPart("file", is, "empty.png");
FormDataMultiPart form = new FormDataMultiPart(); @SuppressWarnings("resource")
InputStream file = Main.class.getResourceAsStream("/empty.png"); ClientResponse response = resource
FormDataBodyPart fdp = new FormDataBodyPart("file", .register(MultiPartFeature.class)
new BufferedInputStream(file), .path("/file").request()
MediaType.APPLICATION_OCTET_STREAM_TYPE); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, user.authToken)
form.bodyPart(fdp); .put(Entity.entity(new FormDataMultiPart().field("id", documentId).bodyPart(streamDataBodyPart),
form.field("id", documentId); MediaType.MULTIPART_FORM_DATA_TYPE), ClientResponse.class);
response = fileResource.type(MediaType.MULTIPART_FORM_DATA).put(ClientResponse.class, form); Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); }
} }
} }
} }

View File

@ -22,23 +22,13 @@
<!-- Dependencies to Jersey --> <!-- Dependencies to Jersey -->
<dependency> <dependency>
<groupId>com.sun.jersey</groupId> <groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-server</artifactId> <artifactId>jersey-container-servlet</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.sun.jersey</groupId> <groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-bundle</artifactId> <artifactId>jersey-media-json-processing</artifactId>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-json</artifactId>
</dependency>
<dependency>
<groupId>com.sun.jersey.contribs</groupId>
<artifactId>jersey-multipart</artifactId>
</dependency> </dependency>
<!-- Other external dependencies --> <!-- Other external dependencies -->
@ -68,8 +58,8 @@
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.mortbay.jetty</groupId> <groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId> <artifactId>javax.servlet-api</artifactId>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
@ -86,20 +76,20 @@
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.sun.grizzly</groupId> <groupId>org.glassfish.jersey.test-framework.providers</groupId>
<artifactId>grizzly-servlet-webserver</artifactId> <artifactId>jersey-test-framework-provider-external</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.sun.jersey.jersey-test-framework</groupId> <groupId>org.glassfish.jersey.test-framework.providers</groupId>
<artifactId>jersey-test-framework-grizzly2</artifactId> <artifactId>jersey-test-framework-provider-grizzly2</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.subethamail</groupId> <groupId>org.glassfish.jersey.containers</groupId>
<artifactId>subethasmtp-wiser</artifactId> <artifactId>jersey-container-grizzly2-servlet</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>

View File

@ -1,11 +1,9 @@
package com.sismics.rest.exception; package com.sismics.rest.exception;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import javax.json.Json;
import javax.ws.rs.WebApplicationException; import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status; import javax.ws.rs.core.Response.Status;
@ -32,9 +30,8 @@ public class ClientException extends WebApplicationException {
* @param type Error type (e.g. AlreadyExistingEmail, ValidationError) * @param type Error type (e.g. AlreadyExistingEmail, ValidationError)
* @param message Human readable error message * @param message Human readable error message
* @param e Readable error message * @param e Readable error message
* @throws JSONException
*/ */
public ClientException(String type, String message, Exception e) throws JSONException { public ClientException(String type, String message, Exception e) {
this(type, message); this(type, message);
log.error(type + ": " + message, e); log.error(type + ": " + message, e);
} }
@ -44,11 +41,10 @@ public class ClientException extends WebApplicationException {
* *
* @param type Error type (e.g. AlreadyExistingEmail, ValidationError) * @param type Error type (e.g. AlreadyExistingEmail, ValidationError)
* @param message Human readable error message * @param message Human readable error message
* @throws JSONException
*/ */
public ClientException(String type, String message) throws JSONException { public ClientException(String type, String message) {
super(Response.status(Status.BAD_REQUEST).entity(new JSONObject() super(Response.status(Status.BAD_REQUEST).entity(Json.createObjectBuilder()
.put("type", type) .add("type", type)
.put("message", message)).build()); .add("message", message).build()).build());
} }
} }

View File

@ -1,8 +1,6 @@
package com.sismics.rest.exception; package com.sismics.rest.exception;
import org.codehaus.jettison.json.JSONException; import javax.json.Json;
import org.codehaus.jettison.json.JSONObject;
import javax.ws.rs.WebApplicationException; import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status; import javax.ws.rs.core.Response.Status;
@ -20,12 +18,10 @@ public class ForbiddenClientException extends WebApplicationException {
/** /**
* Constructor of ForbiddenClientException. * Constructor of ForbiddenClientException.
*
* @throws JSONException
*/ */
public ForbiddenClientException() throws JSONException { public ForbiddenClientException() {
super(Response.status(Status.FORBIDDEN).entity(new JSONObject() super(Response.status(Status.FORBIDDEN).entity(Json.createObjectBuilder()
.put("type", "ForbiddenError") .add("type", "ForbiddenError")
.put("message", "You don't have access to this resource")).build()); .add("message", "You don't have access to this resource").build()).build());
} }
} }

View File

@ -1,14 +1,13 @@
package com.sismics.rest.exception; package com.sismics.rest.exception;
import org.codehaus.jettison.json.JSONException; import javax.json.Json;
import org.codehaus.jettison.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.ws.rs.WebApplicationException; import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status; import javax.ws.rs.core.Response.Status;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** /**
* Jersey exception encapsulating an error from the client (INTERNAL_SERVER_ERROR). * Jersey exception encapsulating an error from the client (INTERNAL_SERVER_ERROR).
* *
@ -31,9 +30,8 @@ public class ServerException extends WebApplicationException {
* @param type Error type (e.g. DatabaseError) * @param type Error type (e.g. DatabaseError)
* @param message Human readable error message * @param message Human readable error message
* @param e Inner exception * @param e Inner exception
* @throws JSONException
*/ */
public ServerException(String type, String message, Exception e) throws JSONException { public ServerException(String type, String message, Exception e) {
this(type, message); this(type, message);
log.error(type + ": " + message, e); log.error(type + ": " + message, e);
} }
@ -43,11 +41,10 @@ public class ServerException extends WebApplicationException {
* *
* @param type Error type (e.g. DatabaseError) * @param type Error type (e.g. DatabaseError)
* @param message Human readable error message * @param message Human readable error message
* @throws JSONException
*/ */
public ServerException(String type, String message) throws JSONException { public ServerException(String type, String message) {
super(Response.status(Status.INTERNAL_SERVER_ERROR).entity(new JSONObject() super(Response.status(Status.INTERNAL_SERVER_ERROR).entity(Json.createObjectBuilder()
.put("type", type) .add("type", type)
.put("message", message)).build()); .add("message", message).build()).build());
} }
} }

View File

@ -1,45 +0,0 @@
package com.sismics.rest.resource;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;
/**
* Generic exception mapper that transforms all unknown exception into ServerError.
*
* @author jtremeaux
*/
@Provider
public class GenericExceptionMapper implements ExceptionMapper<Exception> {
/**
* Logger.
*/
private static final Logger log = LoggerFactory.getLogger(GenericExceptionMapper.class);
@Override
public Response toResponse(Exception e) {
if (e instanceof WebApplicationException) {
return ((WebApplicationException) e).getResponse();
}
log.error("Unknown error", e);
JSONObject entity = new JSONObject();
try {
entity.put("type", "UnknownError");
entity.put("message", "Unknown server error");
} catch (JSONException e2) {
log.error("Error building response", e2);
}
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(entity)
.build();
}
}

View File

@ -1,40 +1,38 @@
package com.sismics.rest.util; package com.sismics.rest.util;
import org.codehaus.jettison.json.JSONArray; import javax.json.Json;
import org.codehaus.jettison.json.JSONException; import javax.json.JsonValue;
import org.codehaus.jettison.json.JSONObject;
/** /**
* JSON utilities. * JSON utilities.
* *
* @author jtremeaux * @author bgamard
*/ */
public class JsonUtil { public class JsonUtil {
/**
* Returns a JsonValue from a String.
*
* @param value Value
* @return JsonValue
*/
public static JsonValue nullable(String value) {
if (value == null) {
return JsonValue.NULL;
}
return Json.createObjectBuilder().add("_", value).build().get("_");
}
/** /**
* Fix of {@see JsonObject.append()}, which seems to create nested arrays. * Returns a JsonValue from an Integer.
* *
* @param o JSON Object * @param value Value
* @param key Key containing the array of null * @return JsonValue
* @param value Value to append
* @return Updated object
* @throws JSONException
*/ */
public static JSONObject append(JSONObject o, String key, JSONObject value) throws JSONException { public static JsonValue nullable(Integer value) {
Object prevValue = o.opt(key); if (value == null) {
if (prevValue == null) { return JsonValue.NULL;
o.put(key, new JSONArray().put(value));
} else if (!(prevValue instanceof JSONArray)){
throw new JSONException("JSONObject[" + key + "] is not a JSONArray.");
} else {
JSONArray newArray = new JSONArray();
JSONArray oldArray = ((JSONArray) prevValue);
for (int i = 0; i < oldArray.length(); i++) {
newArray.put(oldArray.get(i));
}
newArray.put(value);
o.put(key, newArray);
} }
return o; return Json.createObjectBuilder().add("_", value).build().get("_");
} }
} }

View File

@ -1,26 +1,22 @@
package com.sismics.rest.util; package com.sismics.rest.util;
import com.google.common.base.Strings;
import com.sismics.docs.core.dao.file.theme.ThemeDao;
import com.sismics.docs.core.dao.jpa.LocaleDao;
import com.sismics.docs.core.model.jpa.Locale;
import com.sismics.rest.exception.ClientException;
import org.apache.commons.lang.StringUtils;
import org.codehaus.jettison.json.JSONException;
import org.joda.time.DateTime;
import java.text.MessageFormat; import java.text.MessageFormat;
import java.util.Date; import java.util.Date;
import java.util.List;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.apache.commons.lang.StringUtils;
import org.joda.time.DateTime;
import com.google.common.base.Strings;
import com.sismics.rest.exception.ClientException;
/** /**
* Utility class to validate parameters. * Utility class to validate parameters.
* *
* @author jtremeaux * @author jtremeaux
*/ */
public class ValidationUtil { public class ValidationUtil {
private static Pattern EMAIL_PATTERN = Pattern.compile(".+@.+\\..+"); private static Pattern EMAIL_PATTERN = Pattern.compile(".+@.+");
private static Pattern HTTP_URL_PATTERN = Pattern.compile("https?://.+"); private static Pattern HTTP_URL_PATTERN = Pattern.compile("https?://.+");
@ -31,9 +27,9 @@ public class ValidationUtil {
* *
* @param s Object tu validate * @param s Object tu validate
* @param name Name of the parameter * @param name Name of the parameter
* @throws JSONException * @throws ClientException
*/ */
public static void validateRequired(Object s, String name) throws JSONException { public static void validateRequired(Object s, String name) throws ClientException {
if (s == null) { if (s == null) {
throw new ClientException("ValidationError", MessageFormat.format("{0} must be set", name)); throw new ClientException("ValidationError", MessageFormat.format("{0} must be set", name));
} }
@ -50,7 +46,7 @@ public class ValidationUtil {
* @return String without white spaces * @return String without white spaces
* @throws ClientException * @throws ClientException
*/ */
public static String validateLength(String s, String name, Integer lengthMin, Integer lengthMax, boolean nullable) throws JSONException { public static String validateLength(String s, String name, Integer lengthMin, Integer lengthMax, boolean nullable) throws ClientException {
s = StringUtils.strip(s); s = StringUtils.strip(s);
if (nullable && StringUtils.isEmpty(s)) { if (nullable && StringUtils.isEmpty(s)) {
return s; return s;
@ -62,7 +58,7 @@ public class ValidationUtil {
throw new ClientException("ValidationError", MessageFormat.format("{0} must be more than {1} characters", name, lengthMin)); throw new ClientException("ValidationError", MessageFormat.format("{0} must be more than {1} characters", name, lengthMin));
} }
if (lengthMax != null && s.length() > lengthMax) { if (lengthMax != null && s.length() > lengthMax) {
throw new ClientException("ValidationError", MessageFormat.format("{0} must be less than {1} characters", name, lengthMax)); throw new ClientException("ValidationError", MessageFormat.format("{0} must be more than {1} characters", name, lengthMax));
} }
return s; return s;
} }
@ -77,7 +73,7 @@ public class ValidationUtil {
* @return String without white spaces * @return String without white spaces
* @throws ClientException * @throws ClientException
*/ */
public static String validateLength(String s, String name, Integer lengthMin, Integer lengthMax) throws JSONException { public static String validateLength(String s, String name, Integer lengthMin, Integer lengthMax) throws ClientException {
return validateLength(s, name, lengthMin, lengthMax, false); return validateLength(s, name, lengthMin, lengthMax, false);
} }
@ -87,12 +83,25 @@ public class ValidationUtil {
* @param s String to validate * @param s String to validate
* @param name Name of the parameter * @param name Name of the parameter
* @return String without white spaces * @return String without white spaces
* @throws JSONException * @throws ClientException
*/ */
public static String validateStringNotBlank(String s, String name) throws JSONException { public static String validateStringNotBlank(String s, String name) throws ClientException {
return validateLength(s, name, 1, null, false); return validateLength(s, name, 1, null, false);
} }
/**
* Checks if the string is an email.
*
* @param s String to validate
* @param name Name of the parameter
* @throws ClientException
*/
public static void validateEmail(String s, String name) throws ClientException {
if (!EMAIL_PATTERN.matcher(s).matches()) {
throw new ClientException("ValidationError", MessageFormat.format("{0} must be an email", name));
}
}
/** /**
* Checks if the string is a hexadecimal color. * Checks if the string is a hexadecimal color.
* *
@ -101,32 +110,19 @@ public class ValidationUtil {
* @param nullable True if the string can be empty or null * @param nullable True if the string can be empty or null
* @throws JSONException * @throws JSONException
*/ */
public static void validateHexColor(String s, String name, boolean nullable) throws JSONException { public static void validateHexColor(String s, String name, boolean nullable) throws ClientException {
ValidationUtil.validateLength(s, "name", 7, 7, nullable); ValidationUtil.validateLength(s, "name", 7, 7, nullable);
} }
/**
* Checks if the string is an email.
*
* @param s String to validate
* @param name Name of the parameter
* @throws JSONException
*/
public static void validateEmail(String s, String name) throws JSONException {
if (!EMAIL_PATTERN.matcher(s).matches()) {
throw new ClientException("ValidationError", MessageFormat.format("{0} must be an email", name));
}
}
/** /**
* Validates that the provided string matches an URL with HTTP or HTTPS scheme. * Validates that the provided string matches an URL with HTTP or HTTPS scheme.
* *
* @param s String to validate * @param s String to validate
* @param name Name of the parameter * @param name Name of the parameter
* @return Stripped URL * @return Stripped URL
* @throws JSONException * @throws ClientException
*/ */
public static String validateHttpUrl(String s, String name) throws JSONException { public static String validateHttpUrl(String s, String name) throws ClientException {
s = StringUtils.strip(s); s = StringUtils.strip(s);
if (!HTTP_URL_PATTERN.matcher(s).matches()) { if (!HTTP_URL_PATTERN.matcher(s).matches()) {
throw new ClientException("ValidationError", MessageFormat.format("{0} must be an HTTP(s) URL", name)); throw new ClientException("ValidationError", MessageFormat.format("{0} must be an HTTP(s) URL", name));
@ -139,14 +135,30 @@ public class ValidationUtil {
* *
* @param s String to validate * @param s String to validate
* @param name Name of the parameter * @param name Name of the parameter
* @throws JSONException * @throws ClientException
*/ */
public static void validateAlphanumeric(String s, String name) throws JSONException { public static void validateAlphanumeric(String s, String name) throws ClientException {
if (!ALPHANUMERIC_PATTERN.matcher(s).matches()) { if (!ALPHANUMERIC_PATTERN.matcher(s).matches()) {
throw new ClientException("ValidationError", MessageFormat.format("{0} must have only alphanumeric or underscore characters", name)); throw new ClientException("ValidationError", MessageFormat.format("{0} must have only alphanumeric or underscore characters", name));
} }
} }
/**
* Checks if the string is a number.
*
* @param s String to validate
* @param name Name of the parameter
* @return Parsed number
* @throws ClientException
*/
public static Integer validateInteger(String s, String name) throws ClientException {
try {
return Integer.valueOf(s);
} catch (NumberFormatException e) {
throw new ClientException("Validation Error", MessageFormat.format("{0} is not a number", name));
}
}
/** /**
* Validates and parses a date. * Validates and parses a date.
* *
@ -154,9 +166,9 @@ public class ValidationUtil {
* @param name Name of the parameter * @param name Name of the parameter
* @param nullable True if the string can be empty or null * @param nullable True if the string can be empty or null
* @return Parsed date * @return Parsed date
* @throws JSONException * @throws ClientException
*/ */
public static Date validateDate(String s, String name, boolean nullable) throws JSONException { public static Date validateDate(String s, String name, boolean nullable) throws ClientException {
if (Strings.isNullOrEmpty(s)) { if (Strings.isNullOrEmpty(s)) {
if (!nullable) { if (!nullable) {
throw new ClientException("ValidationError", MessageFormat.format("{0} must be set", name)); throw new ClientException("ValidationError", MessageFormat.format("{0} must be set", name));
@ -170,56 +182,4 @@ public class ValidationUtil {
throw new ClientException("ValidationError", MessageFormat.format("{0} must be a date", name)); throw new ClientException("ValidationError", MessageFormat.format("{0} must be a date", name));
} }
} }
/**
* Validates a locale.
*
* @param localeId String to validate
* @param name Name of the parameter
* @return String without white spaces
* @param nullable True if the string can be empty or null
* @throws ClientException
*/
public static String validateLocale(String localeId, String name, boolean nullable) throws JSONException {
localeId = StringUtils.strip(localeId);
if (StringUtils.isEmpty(localeId)) {
if (!nullable) {
throw new ClientException("ValidationError", MessageFormat.format("{0} is required", name));
} else {
return null;
}
}
LocaleDao localeDao = new LocaleDao();
Locale locale = localeDao.getById(localeId);
if (locale == null) {
throw new ClientException("ValidationError", "Locale not found: " + localeId);
}
return localeId;
}
/**
* Validates a theme.
*
* @param themeId ID of the theme to validate
* @param name Name of the parameter
* @return String without white spaces
* @param nullable True if the string can be empty or null
* @throws ClientException
*/
public static String validateTheme(String themeId, String name, boolean nullable) throws JSONException {
themeId = StringUtils.strip(themeId);
if (StringUtils.isEmpty(themeId)) {
if (!nullable) {
throw new ClientException("ValidationError", MessageFormat.format("{0} is required", name));
} else {
return null;
}
}
ThemeDao themeDao = new ThemeDao();
List<String> themeList = themeDao.findAll();
if (!themeList.contains(themeId)) {
throw new ClientException("ValidationError", "Theme not found: " + themeId);
}
return themeId;
}
} }

View File

@ -2,8 +2,6 @@ package com.sismics.security;
import org.joda.time.DateTimeZone; import org.joda.time.DateTimeZone;
import java.util.Locale;
/** /**
* Anonymous principal. * Anonymous principal.
* *
@ -12,11 +10,6 @@ import java.util.Locale;
public class AnonymousPrincipal implements IPrincipal { public class AnonymousPrincipal implements IPrincipal {
public static final String ANONYMOUS = "anonymous"; public static final String ANONYMOUS = "anonymous";
/**
* User locale.
*/
private Locale locale;
/** /**
* User timezone. * User timezone.
*/ */
@ -44,20 +37,6 @@ public class AnonymousPrincipal implements IPrincipal {
return true; return true;
} }
@Override
public Locale getLocale() {
return locale;
}
/**
* Setter of locale.
*
* @param locale locale
*/
public void setLocale(Locale locale) {
this.locale = locale;
}
@Override @Override
public DateTimeZone getDateTimeZone() { public DateTimeZone getDateTimeZone() {
return dateTimeZone; return dateTimeZone;

View File

@ -1,9 +1,8 @@
package com.sismics.security; package com.sismics.security;
import org.joda.time.DateTimeZone;
import java.security.Principal; import java.security.Principal;
import java.util.Locale;
import org.joda.time.DateTimeZone;
/** /**
* Interface of principals. * Interface of principals.
@ -25,13 +24,6 @@ public interface IPrincipal extends Principal {
*/ */
public String getId(); public String getId();
/**
* Returns the locale of the principal.
*
* @return Locale of the principal
*/
public Locale getLocale();
/** /**
* Returns the timezone of the principal. * Returns the timezone of the principal.
* *

View File

@ -1,10 +1,9 @@
package com.sismics.security; package com.sismics.security;
import org.joda.time.DateTimeZone;
import java.util.Locale;
import java.util.Set; import java.util.Set;
import org.joda.time.DateTimeZone;
/** /**
* Authenticated users principal. * Authenticated users principal.
* *
@ -21,11 +20,6 @@ public class UserPrincipal implements IPrincipal {
*/ */
private String name; private String name;
/**
* Locale of the principal.
*/
private Locale locale;
/** /**
* Timezone of the principal. * Timezone of the principal.
*/ */
@ -85,20 +79,6 @@ public class UserPrincipal implements IPrincipal {
this.name = name; this.name = name;
} }
@Override
public Locale getLocale() {
return locale;
}
/**
* Setter of locale.
*
* @param locale locale
*/
public void setLocale(Locale locale) {
this.locale = locale;
}
@Override @Override
public DateTimeZone getDateTimeZone() { public DateTimeZone getDateTimeZone() {
return dateTimeZone; return dateTimeZone;

View File

@ -1,26 +1,31 @@
package com.sismics.util.filter; package com.sismics.util.filter;
import com.sismics.docs.core.constant.Constants; import java.io.File;
import com.sismics.docs.core.model.context.AppContext; import java.io.IOException;
import com.sismics.docs.core.util.DirectoryUtil; import java.text.MessageFormat;
import com.sismics.docs.core.util.TransactionUtil;
import com.sismics.util.EnvironmentUtil; import javax.persistence.EntityManager;
import com.sismics.util.context.ThreadLocalContext; import javax.persistence.EntityTransaction;
import com.sismics.util.jpa.EMF; import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Level; import org.apache.log4j.Level;
import org.apache.log4j.PatternLayout; import org.apache.log4j.PatternLayout;
import org.apache.log4j.RollingFileAppender; import org.apache.log4j.RollingFileAppender;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import javax.persistence.EntityManager; import com.sismics.docs.core.model.context.AppContext;
import javax.persistence.EntityTransaction; import com.sismics.docs.core.util.DirectoryUtil;
import javax.servlet.*; import com.sismics.docs.core.util.TransactionUtil;
import javax.servlet.http.HttpServletResponse; import com.sismics.util.EnvironmentUtil;
import java.io.File; import com.sismics.util.context.ThreadLocalContext;
import java.io.IOException; import com.sismics.util.jpa.EMF;
import java.text.MessageFormat;
import java.util.Locale;
/** /**
* Filter used to process a couple things in the request context. * Filter used to process a couple things in the request context.
@ -35,14 +40,10 @@ public class RequestContextFilter implements Filter {
@Override @Override
public void init(FilterConfig filterConfig) throws ServletException { public void init(FilterConfig filterConfig) throws ServletException {
// Force the locale in order to not depend on the execution environment
Locale.setDefault(new Locale(Constants.DEFAULT_LOCALE_ID));
// Injects the webapp root
String webappRoot = filterConfig.getServletContext().getRealPath("/");
EnvironmentUtil.setWebappRoot(webappRoot);
// Initialize the app directory // Initialize the app directory
if (!filterConfig.getServletContext().getServerInfo().startsWith("Grizzly")) {
EnvironmentUtil.setWebappContext(true);
}
File baseDataDirectory = null; File baseDataDirectory = null;
try { try {
baseDataDirectory = DirectoryUtil.getBaseDataDirectory(); baseDataDirectory = DirectoryUtil.getBaseDataDirectory();

View File

@ -3,7 +3,6 @@ package com.sismics.util.filter;
import java.io.IOException; import java.io.IOException;
import java.text.MessageFormat; import java.text.MessageFormat;
import java.util.Date; import java.util.Date;
import java.util.Locale;
import java.util.Set; import java.util.Set;
import javax.servlet.Filter; import javax.servlet.Filter;
@ -28,7 +27,6 @@ import com.sismics.docs.core.model.jpa.User;
import com.sismics.docs.core.util.TransactionUtil; import com.sismics.docs.core.util.TransactionUtil;
import com.sismics.security.AnonymousPrincipal; import com.sismics.security.AnonymousPrincipal;
import com.sismics.security.UserPrincipal; import com.sismics.security.UserPrincipal;
import com.sismics.util.LocaleUtil;
/** /**
* This filter is used to authenticate the user having an active session via an authentication token stored in database. * This filter is used to authenticate the user having an active session via an authentication token stored in database.
@ -155,10 +153,6 @@ public class TokenBasedSecurityFilter implements Filter {
private void injectAuthenticatedUser(HttpServletRequest request, User user) { private void injectAuthenticatedUser(HttpServletRequest request, User user) {
UserPrincipal userPrincipal = new UserPrincipal(user.getId(), user.getUsername()); UserPrincipal userPrincipal = new UserPrincipal(user.getId(), user.getUsername());
// Add locale
Locale locale = LocaleUtil.getLocale(user.getLocaleId());
userPrincipal.setLocale(locale);
// Add base functions // Add base functions
RoleBaseFunctionDao userBaseFuction = new RoleBaseFunctionDao(); RoleBaseFunctionDao userBaseFuction = new RoleBaseFunctionDao();
Set<String> baseFunctionSet = userBaseFuction.findByRoleId(user.getRoleId()); Set<String> baseFunctionSet = userBaseFuction.findByRoleId(user.getRoleId());
@ -174,7 +168,6 @@ public class TokenBasedSecurityFilter implements Filter {
*/ */
private void injectAnonymousUser(HttpServletRequest request) { private void injectAnonymousUser(HttpServletRequest request) {
AnonymousPrincipal anonymousPrincipal = new AnonymousPrincipal(); AnonymousPrincipal anonymousPrincipal = new AnonymousPrincipal();
anonymousPrincipal.setLocale(request.getLocale());
anonymousPrincipal.setDateTimeZone(DateTimeZone.forID(Constants.DEFAULT_TIMEZONE_ID)); anonymousPrincipal.setDateTimeZone(DateTimeZone.forID(Constants.DEFAULT_TIMEZONE_ID));
request.setAttribute(PRINCIPAL_ATTRIBUTE, anonymousPrincipal); request.setAttribute(PRINCIPAL_ATTRIBUTE, anonymousPrincipal);

View File

@ -1,24 +1,27 @@
package com.sismics.docs.rest; package com.sismics.docs.rest;
import com.sismics.docs.rest.descriptor.JerseyTestWebAppDescriptorFactory; import java.io.File;
import com.sismics.docs.rest.util.ClientUtil; import java.net.URI;
import com.sun.jersey.test.framework.JerseyTest; import java.net.URLDecoder;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.UriBuilder;
import org.glassfish.grizzly.http.server.HttpServer; import org.glassfish.grizzly.http.server.HttpServer;
import org.glassfish.grizzly.http.server.StaticHttpHandler; import org.glassfish.grizzly.servlet.ServletRegistration;
import org.glassfish.grizzly.servlet.WebappContext;
import org.glassfish.jersey.servlet.ServletContainer;
import org.glassfish.jersey.test.JerseyTest;
import org.glassfish.jersey.test.TestProperties;
import org.glassfish.jersey.test.external.ExternalTestContainerFactory;
import org.glassfish.jersey.test.spi.TestContainerException;
import org.glassfish.jersey.test.spi.TestContainerFactory;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.subethamail.wiser.Wiser;
import org.subethamail.wiser.WiserMessage;
import javax.mail.MessagingException; import com.sismics.docs.rest.util.ClientUtil;
import javax.mail.internet.MimeMessage; import com.sismics.util.filter.RequestContextFilter;
import javax.mail.internet.MimeUtility; import com.sismics.util.filter.TokenBasedSecurityFilter;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLDecoder;
import java.util.List;
/** /**
* Base class of integration tests with Jersey. * Base class of integration tests with Jersey.
@ -26,27 +29,31 @@ import java.util.List;
* @author jtremeaux * @author jtremeaux
*/ */
public abstract class BaseJerseyTest extends JerseyTest { public abstract class BaseJerseyTest extends JerseyTest {
/**
* Test email server.
*/
protected Wiser wiser;
/** /**
* Test HTTP server. * Test HTTP server.
*/ */
HttpServer httpServer; protected HttpServer httpServer;
/** /**
* Utility class for the REST client. * Utility class for the REST client.
*/ */
protected ClientUtil clientUtil; protected ClientUtil clientUtil;
/** @Override
* Constructor of BaseJerseyTest. protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
*/ return new ExternalTestContainerFactory();
public BaseJerseyTest() { }
super(JerseyTestWebAppDescriptorFactory.build());
this.clientUtil = new ClientUtil(resource()); @Override
protected Application configure() {
enable(TestProperties.LOG_TRAFFIC);
enable(TestProperties.DUMP_ENTITY);
return new Application();
}
@Override
protected URI getBaseUri() {
return UriBuilder.fromUri(super.getBaseUri()).path("docs").build();
} }
@Override @Override
@ -54,14 +61,23 @@ public abstract class BaseJerseyTest extends JerseyTest {
public void setUp() throws Exception { public void setUp() throws Exception {
super.setUp(); super.setUp();
wiser = new Wiser(); clientUtil = new ClientUtil(target());
wiser.setPort(2500);
wiser.start();
String httpRoot = URLDecoder.decode(new File(getClass().getResource("/").getFile()).getAbsolutePath(), "utf-8"); String httpRoot = URLDecoder.decode(new File(getClass().getResource("/").getFile()).getAbsolutePath(), "utf-8");
httpServer = HttpServer.createSimpleServer(httpRoot, "localhost", 9997); httpServer = HttpServer.createSimpleServer(httpRoot, "localhost", getPort());
// Disable file cache to fix https://java.net/jira/browse/GRIZZLY-1350 WebappContext context = new WebappContext("GrizzlyContext", "/docs");
((StaticHttpHandler) httpServer.getServerConfiguration().getHttpHandlers().keySet().iterator().next()).setFileCacheEnabled(false); context.addFilter("requestContextFilter", RequestContextFilter.class)
.addMappingForUrlPatterns(null, "/*");
context.addFilter("tokenBasedSecurityFilter", TokenBasedSecurityFilter.class)
.addMappingForUrlPatterns(null, "/*");
ServletRegistration reg = context.addServlet("jerseyServlet", ServletContainer.class);
reg.setInitParameter("jersey.config.server.provider.packages", "com.sismics.docs.rest.resource");
reg.setInitParameter("jersey.config.server.provider.classnames", "org.glassfish.jersey.media.multipart.MultiPartFeature");
reg.setInitParameter("jersey.config.server.response.setStatusOverSendError", "true");
reg.setLoadOnStartup(1);
reg.addMapping("/*");
reg.setAsyncSupported(true);
context.deploy(httpServer);
httpServer.start(); httpServer.start();
} }
@ -69,45 +85,8 @@ public abstract class BaseJerseyTest extends JerseyTest {
@After @After
public void tearDown() throws Exception { public void tearDown() throws Exception {
super.tearDown(); super.tearDown();
wiser.stop(); if (httpServer != null) {
httpServer.stop(); httpServer.shutdownNow();
}
/**
* Extracts an email from the queue and consumes the email.
*
* @return Text of the email
* @throws MessagingException
* @throws IOException
*/
protected String popEmail() throws MessagingException, IOException {
List<WiserMessage> wiserMessageList = wiser.getMessages();
if (wiserMessageList.isEmpty()) {
return null;
} }
WiserMessage wiserMessage = wiserMessageList.get(wiserMessageList.size() - 1);
wiserMessageList.remove(wiserMessageList.size() - 1);
MimeMessage message = wiserMessage.getMimeMessage();
ByteArrayOutputStream os = new ByteArrayOutputStream();
message.writeTo(os);
String body = os.toString();
return body;
}
/**
* Encodes a string to "quoted-printable" characters to compare with the contents of an email.
*
* @param input String to encode
* @return Encoded string
* @throws MessagingException
* @throws IOException
*/
protected String encodeQuotedPrintable(String input) throws MessagingException, IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
OutputStream os = MimeUtility.encode(baos, "quoted-printable");
os.write(input.getBytes());
os.close();
return baos.toString();
} }
} }

View File

@ -1,36 +0,0 @@
package com.sismics.docs.rest.descriptor;
import com.sismics.util.filter.RequestContextFilter;
import com.sismics.util.filter.TokenBasedSecurityFilter;
import com.sun.jersey.test.framework.WebAppDescriptor;
import java.io.File;
/**
* Jersey tests Webapp descriptor.
*
* @author jtremeaux
*/
public class JerseyTestWebAppDescriptorFactory {
private static String basePath = new File("src/main/webapp").getAbsolutePath();
/**
* Constructs a new descriptor.
*
* @return Descriptor
*/
public static WebAppDescriptor build() {
// Target the base path to the Webapp resources
System.setProperty("user.dir", basePath);
System.setProperty("test", "true");
return new WebAppDescriptor.Builder("com.sismics.docs.rest.resource")
.contextPath("docs")
.addFilter(RequestContextFilter.class, "requestContextFilter")
.addFilter(TokenBasedSecurityFilter.class, "tokenBasedSecurityFilter")
.initParam("com.sun.jersey.spi.container.ContainerRequestFilters", "com.sun.jersey.api.container.filter.LoggingFilter")
.initParam("com.sun.jersey.spi.container.ContainerResponseFilters", "com.sun.jersey.api.container.filter.LoggingFilter")
.initParam("com.sun.jersey.config.feature.logging.DisableEntitylogging", "true")
.build();
}
}

View File

@ -1,40 +0,0 @@
package com.sismics.docs.rest.filter;
import com.sismics.util.filter.TokenBasedSecurityFilter;
import com.sun.jersey.api.client.ClientHandlerException;
import com.sun.jersey.api.client.ClientRequest;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.filter.ClientFilter;
import javax.ws.rs.core.Cookie;
import java.util.ArrayList;
import java.util.List;
/**
* Filter to add the authentication token into a cookie.
*
* @author jtremeaux
*/
public class CookieAuthenticationFilter extends ClientFilter {
private String authToken;
public CookieAuthenticationFilter(String authToken) {
this.authToken = authToken;
}
@Override
public ClientResponse handle(ClientRequest request) throws ClientHandlerException {
Cookie cookie = new Cookie(TokenBasedSecurityFilter.COOKIE_NAME, authToken);
List<Object> cookieList = new ArrayList<Object>();
cookieList.add(cookie);
if (authToken != null) {
request.getHeaders().put("Cookie", cookieList);
}
ClientResponse response = getNext().handle(request);
if (response.getCookies() != null) {
cookieList.addAll(response.getCookies());
}
return response;
}
}

View File

@ -1,15 +1,13 @@
package com.sismics.docs.rest.util; package com.sismics.docs.rest.util;
import com.sismics.docs.rest.filter.CookieAuthenticationFilter; import javax.json.JsonObject;
import com.sismics.util.filter.TokenBasedSecurityFilter; import javax.ws.rs.client.Entity;
import com.sun.jersey.api.client.ClientResponse; import javax.ws.rs.client.WebTarget;
import com.sun.jersey.api.client.ClientResponse.Status; import javax.ws.rs.core.Form;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.core.util.MultivaluedMapImpl;
import junit.framework.Assert;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.NewCookie; import javax.ws.rs.core.NewCookie;
import javax.ws.rs.core.Response;
import com.sismics.util.filter.TokenBasedSecurityFilter;
/** /**
* REST client utilities. * REST client utilities.
@ -17,14 +15,14 @@ import javax.ws.rs.core.NewCookie;
* @author jtremeaux * @author jtremeaux
*/ */
public class ClientUtil { public class ClientUtil {
private WebResource resource; private WebTarget resource;
/** /**
* Constructor of ClientUtil. * Constructor of ClientUtil.
* *
* @param webResource Resource corresponding to the base URI of REST resources. * @param resource Resource corresponding to the base URI of REST resources.
*/ */
public ClientUtil(WebResource resource) { public ClientUtil(WebTarget resource) {
this.resource = resource; this.resource = resource;
} }
@ -38,15 +36,14 @@ public class ClientUtil {
String adminAuthenticationToken = login("admin", "admin", false); String adminAuthenticationToken = login("admin", "admin", false);
// Create the user // Create the user
WebResource userResource = resource.path("/user"); Form form = new Form();
userResource.addFilter(new CookieAuthenticationFilter(adminAuthenticationToken)); form.param("username", username);
MultivaluedMap<String, String> postParams = new MultivaluedMapImpl(); form.param("email", username + "@docs.com");
postParams.putSingle("username", username); form.param("password", "12345678");
postParams.putSingle("email", username + "@docs.com"); form.param("time_zone", "Asia/Tokyo");
postParams.putSingle("password", "12345678"); resource.path("/user").request()
postParams.putSingle("time_zone", "Asia/Tokyo"); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminAuthenticationToken)
ClientResponse response = userResource.put(ClientResponse.class, postParams); .put(Entity.form(form), JsonObject.class);
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
// Logout admin // Logout admin
logout(adminAuthenticationToken); logout(adminAuthenticationToken);
@ -61,13 +58,12 @@ public class ClientUtil {
* @return Authentication token * @return Authentication token
*/ */
public String login(String username, String password, Boolean remember) { public String login(String username, String password, Boolean remember) {
WebResource userResource = resource.path("/user/login"); Form form = new Form();
MultivaluedMap<String, String> postParams = new MultivaluedMapImpl(); form.param("username", username);
postParams.putSingle("username", username); form.param("password", password);
postParams.putSingle("password", password); form.param("remember", remember.toString());
postParams.putSingle("remember", remember.toString()); Response response = resource.path("/user/login").request()
ClientResponse response = userResource.post(ClientResponse.class, postParams); .post(Entity.form(form));
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
return getAuthenticationCookie(response); return getAuthenticationCookie(response);
} }
@ -88,10 +84,9 @@ public class ClientUtil {
* @param authenticationToken Authentication token * @param authenticationToken Authentication token
*/ */
public void logout(String authenticationToken) { public void logout(String authenticationToken) {
WebResource userResource = resource.path("/user/logout"); resource.path("/user/logout").request()
userResource.addFilter(new CookieAuthenticationFilter(authenticationToken)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, authenticationToken)
ClientResponse response = userResource.post(ClientResponse.class); .post(null);
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
} }
/** /**
@ -100,9 +95,9 @@ public class ClientUtil {
* @param response Response * @param response Response
* @return Authentication token * @return Authentication token
*/ */
public String getAuthenticationCookie(ClientResponse response) { public String getAuthenticationCookie(Response response) {
String authToken = null; String authToken = null;
for (NewCookie cookie : response.getCookies()) { for (NewCookie cookie : response.getCookies().values()) {
if (TokenBasedSecurityFilter.COOKIE_NAME.equals(cookie.getName())) { if (TokenBasedSecurityFilter.COOKIE_NAME.equals(cookie.getName())) {
authToken = cookie.getValue(); authToken = cookie.getValue();
} }

View File

@ -28,23 +28,18 @@
<!-- Dependencies to Jersey --> <!-- Dependencies to Jersey -->
<dependency> <dependency>
<groupId>com.sun.jersey</groupId> <groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-server</artifactId> <artifactId>jersey-container-servlet</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.sun.jersey</groupId> <groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-bundle</artifactId> <artifactId>jersey-media-json-processing</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.sun.jersey</groupId> <groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-json</artifactId> <artifactId>jersey-media-multipart</artifactId>
</dependency>
<dependency>
<groupId>com.sun.jersey.contribs</groupId>
<artifactId>jersey-multipart</artifactId>
</dependency> </dependency>
<!-- Other external dependencies --> <!-- Other external dependencies -->
@ -74,8 +69,8 @@
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.mortbay.jetty</groupId> <groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId> <artifactId>javax.servlet-api</artifactId>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
@ -102,22 +97,23 @@
<artifactId>junit</artifactId> <artifactId>junit</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
<artifactId>jersey-test-framework-provider-bundle</artifactId>
<type>pom</type>
<scope>test</scope>
</dependency>
<dependency> <dependency>
<groupId>com.sun.grizzly</groupId> <groupId>org.glassfish.jersey.test-framework.providers</groupId>
<artifactId>grizzly-servlet-webserver</artifactId> <artifactId>jersey-test-framework-provider-grizzly2</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.sun.jersey.jersey-test-framework</groupId> <groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-test-framework-grizzly2</artifactId> <artifactId>jersey-container-grizzly2-servlet</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.subethamail</groupId>
<artifactId>subethasmtp-wiser</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
@ -129,29 +125,6 @@
<directory>src/main/resources</directory> <directory>src/main/resources</directory>
</resource> </resource>
</resources> </resources>
<plugins>
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<configuration>
<systemProperties>
<systemProperty>
<name>webapp.root</name>
<value>${basedir}/src/main/webapp</value>
</systemProperty>
</systemProperties>
<scanIntervalSeconds>0</scanIntervalSeconds>
<webAppConfig>
<contextPath>/docs-web</contextPath>
<extraClasspath>target/classes;../docs-core/target/classes</extraClasspath>
<overrideDescriptor>src/dev/main/webapp/web-override.xml</overrideDescriptor>
</webAppConfig>
<stopKey>STOPKEY</stopKey>
<stopPort>1099</stopPort>
</configuration>
</plugin>
</plugins>
</build> </build>
<profiles> <profiles>
@ -186,17 +159,19 @@
<plugins> <plugins>
<plugin> <plugin>
<groupId>org.mortbay.jetty</groupId> <groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId> <artifactId>jetty-maven-plugin</artifactId>
<configuration> <configuration>
<scanIntervalSeconds>0</scanIntervalSeconds> <systemProperties>
<webAppConfig> <systemProperty>
<name>application.mode</name>
<value>dev</value>
</systemProperty>
</systemProperties>
<webApp>
<contextPath>/docs-web</contextPath> <contextPath>/docs-web</contextPath>
<extraClasspath>target/classes;../docs-core/target/classes</extraClasspath>
<overrideDescriptor>src/dev/main/webapp/web-override.xml</overrideDescriptor> <overrideDescriptor>src/dev/main/webapp/web-override.xml</overrideDescriptor>
</webAppConfig> </webApp>
<stopKey>STOPKEY</stopKey>
<stopPort>1099</stopPort>
</configuration> </configuration>
</plugin> </plugin>
</plugins> </plugins>
@ -233,17 +208,19 @@
<plugins> <plugins>
<plugin> <plugin>
<groupId>org.mortbay.jetty</groupId> <groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId> <artifactId>jetty-maven-plugin</artifactId>
<configuration> <configuration>
<scanIntervalSeconds>0</scanIntervalSeconds> <systemProperties>
<webAppConfig> <systemProperty>
<name>application.mode</name>
<value>dev</value>
</systemProperty>
</systemProperties>
<webApp>
<contextPath>/docs-web</contextPath> <contextPath>/docs-web</contextPath>
<extraClasspath>target/classes;../docs-core/target/classes</extraClasspath> <overrideDescriptor>src/dev/main/webapp/web-override.xml</overrideDescriptor>
<overrideDescriptor>src/stress/main/webapp/web-override.xml</overrideDescriptor> </webApp>
</webAppConfig>
<stopKey>STOPKEY</stopKey>
<stopPort>1099</stopPort>
</configuration> </configuration>
</plugin> </plugin>
</plugins> </plugins>
@ -253,12 +230,6 @@
<!-- Production profile --> <!-- Production profile -->
<profile> <profile>
<id>prod</id> <id>prod</id>
<activation>
<property>
<name>env</name>
<value>prod</value>
</property>
</activation>
<build> <build>
<resources> <resources>
@ -282,8 +253,8 @@
<!-- Launch NPM & Grunt --> <!-- Launch NPM & Grunt -->
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId> <artifactId>maven-antrun-plugin</artifactId>
<version>1.7</version>
<executions> <executions>
<execution> <execution>
<phase>generate-sources</phase> <phase>generate-sources</phase>
@ -324,25 +295,5 @@
</plugins> </plugins>
</build> </build>
</profile> </profile>
<!-- Hosted version profile -->
<profile>
<id>hosted</id>
<activation>
<property>
<name>env</name>
<value>hosted</value>
</property>
</activation>
<build>
<resources>
<resource>
<directory>src/hosted/resources</directory>
<filtering>false</filtering>
</resource>
</resources>
</build>
</profile>
</profiles> </profiles>
</project> </project>

View File

@ -1,3 +1,3 @@
api.current_version=${project.version} api.current_version=${project.version}
api.min_version=1.0 api.min_version=1.0
db.version=0 db.version=1

View File

@ -1,23 +1,19 @@
package com.sismics.docs.rest.resource; package com.sismics.docs.rest.resource;
import java.text.MessageFormat; import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import javax.json.Json;
import javax.json.JsonArrayBuilder;
import javax.json.JsonObjectBuilder;
import javax.ws.rs.DELETE; import javax.ws.rs.DELETE;
import javax.ws.rs.FormParam; import javax.ws.rs.FormParam;
import javax.ws.rs.GET; import javax.ws.rs.GET;
import javax.ws.rs.PUT; import javax.ws.rs.PUT;
import javax.ws.rs.Path; import javax.ws.rs.Path;
import javax.ws.rs.PathParam; import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam; import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
import com.sismics.docs.core.constant.AclTargetType; import com.sismics.docs.core.constant.AclTargetType;
import com.sismics.docs.core.constant.PermType; import com.sismics.docs.core.constant.PermType;
import com.sismics.docs.core.dao.jpa.AclDao; import com.sismics.docs.core.dao.jpa.AclDao;
@ -46,13 +42,11 @@ public class AclResource extends BaseResource {
* Add an ACL. * Add an ACL.
* *
* @return Response * @return Response
* @throws JSONException
*/ */
@PUT @PUT
@Produces(MediaType.APPLICATION_JSON)
public Response add(@FormParam("source") String sourceId, public Response add(@FormParam("source") String sourceId,
@FormParam("perm") String permStr, @FormParam("perm") String permStr,
@FormParam("username") String username) throws JSONException { @FormParam("username") String username) {
if (!authenticate()) { if (!authenticate()) {
throw new ForbiddenClientException(); throw new ForbiddenClientException();
} }
@ -86,15 +80,15 @@ public class AclResource extends BaseResource {
aclDao.create(acl); aclDao.create(acl);
// Returns the ACL // Returns the ACL
JSONObject response = new JSONObject(); JsonObjectBuilder response = Json.createObjectBuilder()
response.put("perm", acl.getPerm().name()); .add("perm", acl.getPerm().name())
response.put("id", acl.getTargetId()); .add("id", acl.getTargetId())
response.put("name", user.getUsername()); .add("name", user.getUsername())
response.put("type", AclTargetType.USER.name()); .add("type", AclTargetType.USER.name());
return Response.ok().entity(response).build(); return Response.ok().entity(response.build()).build();
} }
return Response.ok().entity(new JSONObject()).build(); return Response.ok().entity(Json.createObjectBuilder().build()).build();
} }
/** /**
@ -102,15 +96,13 @@ public class AclResource extends BaseResource {
* *
* @param id ACL ID * @param id ACL ID
* @return Response * @return Response
* @throws JSONException
*/ */
@DELETE @DELETE
@Path("{sourceId: [a-z0-9\\-]+}/{perm: [A-Z]+}/{targetId: [a-z0-9\\-]+}") @Path("{sourceId: [a-z0-9\\-]+}/{perm: [A-Z]+}/{targetId: [a-z0-9\\-]+}")
@Produces(MediaType.APPLICATION_JSON)
public Response delete( public Response delete(
@PathParam("sourceId") String sourceId, @PathParam("sourceId") String sourceId,
@PathParam("perm") String permStr, @PathParam("perm") String permStr,
@PathParam("targetId") String targetId) throws JSONException { @PathParam("targetId") String targetId) {
if (!authenticate()) { if (!authenticate()) {
throw new ForbiddenClientException(); throw new ForbiddenClientException();
} }
@ -136,16 +128,21 @@ public class AclResource extends BaseResource {
// Delete the ACL // Delete the ACL
aclDao.delete(sourceId, perm, targetId); aclDao.delete(sourceId, perm, targetId);
// Always return ok // Always return OK
JSONObject response = new JSONObject(); JsonObjectBuilder response = Json.createObjectBuilder()
response.put("status", "ok"); .add("status", "ok");
return Response.ok().entity(response).build(); return Response.ok().entity(response.build()).build();
} }
/**
* Search possible ACL target.
*
* @param search Search query
* @return Response
*/
@GET @GET
@Path("target/search") @Path("target/search")
@Produces(MediaType.APPLICATION_JSON) public Response targetList(@QueryParam("search") String search) {
public Response targetList(@QueryParam("search") String search) throws JSONException {
if (!authenticate()) { if (!authenticate()) {
throw new ForbiddenClientException(); throw new ForbiddenClientException();
} }
@ -155,20 +152,19 @@ public class AclResource extends BaseResource {
// Search users // Search users
UserDao userDao = new UserDao(); UserDao userDao = new UserDao();
JSONObject response = new JSONObject(); JsonArrayBuilder users = Json.createArrayBuilder();
List<JSONObject> users = new ArrayList<>();
PaginatedList<UserDto> paginatedList = PaginatedLists.create(); PaginatedList<UserDto> paginatedList = PaginatedLists.create();
SortCriteria sortCriteria = new SortCriteria(1, true); SortCriteria sortCriteria = new SortCriteria(1, true);
userDao.findByCriteria(paginatedList, new UserCriteria().setSearch(search), sortCriteria); userDao.findByCriteria(paginatedList, new UserCriteria().setSearch(search), sortCriteria);
for (UserDto userDto : paginatedList.getResultList()) { for (UserDto userDto : paginatedList.getResultList()) {
JSONObject user = new JSONObject(); users.add(Json.createObjectBuilder()
user.put("username", userDto.getUsername()); .add("username", userDto.getUsername()));
users.add(user);
} }
response.put("users", users); JsonObjectBuilder response = Json.createObjectBuilder()
return Response.ok().entity(response).build(); .add("users", users);
return Response.ok().entity(response.build()).build();
} }
} }

View File

@ -1,24 +1,22 @@
package com.sismics.docs.rest.resource; package com.sismics.docs.rest.resource;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.ResourceBundle; import java.util.ResourceBundle;
import javax.json.Json;
import javax.json.JsonArrayBuilder;
import javax.json.JsonObjectBuilder;
import javax.ws.rs.GET; import javax.ws.rs.GET;
import javax.ws.rs.POST; import javax.ws.rs.POST;
import javax.ws.rs.Path; import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam; import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Appender; import org.apache.log4j.Appender;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
import com.sismics.docs.core.dao.jpa.FileDao; import com.sismics.docs.core.dao.jpa.FileDao;
import com.sismics.docs.core.model.context.AppContext; import com.sismics.docs.core.model.context.AppContext;
@ -45,11 +43,9 @@ public class AppResource extends BaseResource {
* Return the information about the application. * Return the information about the application.
* *
* @return Response * @return Response
* @throws JSONException
*/ */
@GET @GET
@Produces(MediaType.APPLICATION_JSON) public Response info() {
public Response info() throws JSONException {
if (!authenticate()) { if (!authenticate()) {
throw new ForbiddenClientException(); throw new ForbiddenClientException();
} }
@ -58,14 +54,13 @@ public class AppResource extends BaseResource {
String currentVersion = configBundle.getString("api.current_version"); String currentVersion = configBundle.getString("api.current_version");
String minVersion = configBundle.getString("api.min_version"); String minVersion = configBundle.getString("api.min_version");
JSONObject response = new JSONObject(); JsonObjectBuilder response = Json.createObjectBuilder()
.add("current_version", currentVersion.replace("-SNAPSHOT", ""))
.add("min_version", minVersion)
.add("total_memory", Runtime.getRuntime().totalMemory())
.add("free_memory", Runtime.getRuntime().freeMemory());
response.put("current_version", currentVersion.replace("-SNAPSHOT", "")); return Response.ok().entity(response.build()).build();
response.put("min_version", minVersion);
response.put("total_memory", Runtime.getRuntime().totalMemory());
response.put("free_memory", Runtime.getRuntime().freeMemory());
return Response.ok().entity(response).build();
} }
/** /**
@ -77,17 +72,15 @@ public class AppResource extends BaseResource {
* @param limit Page limit * @param limit Page limit
* @param offset Page offset * @param offset Page offset
* @return Response * @return Response
* @throws JSONException
*/ */
@GET @GET
@Path("log") @Path("log")
@Produces(MediaType.APPLICATION_JSON)
public Response log( public Response log(
@QueryParam("level") String level, @QueryParam("level") String level,
@QueryParam("tag") String tag, @QueryParam("tag") String tag,
@QueryParam("message") String message, @QueryParam("message") String message,
@QueryParam("limit") Integer limit, @QueryParam("limit") Integer limit,
@QueryParam("offset") Integer offset) throws JSONException { @QueryParam("offset") Integer offset) {
if (!authenticate()) { if (!authenticate()) {
throw new ForbiddenClientException(); throw new ForbiddenClientException();
} }
@ -109,32 +102,30 @@ public class AppResource extends BaseResource {
PaginatedList<LogEntry> paginatedList = PaginatedLists.create(limit, offset); PaginatedList<LogEntry> paginatedList = PaginatedLists.create(limit, offset);
memoryAppender.find(logCriteria, paginatedList); memoryAppender.find(logCriteria, paginatedList);
JSONObject response = new JSONObject(); JsonArrayBuilder logs = Json.createArrayBuilder();
List<JSONObject> logs = new ArrayList<>();
for (LogEntry logEntry : paginatedList.getResultList()) { for (LogEntry logEntry : paginatedList.getResultList()) {
JSONObject log = new JSONObject(); logs.add(Json.createObjectBuilder()
log.put("date", logEntry.getTimestamp()); .add("date", logEntry.getTimestamp())
log.put("level", logEntry.getLevel()); .add("level", logEntry.getLevel())
log.put("tag", logEntry.getTag()); .add("tag", logEntry.getTag())
log.put("message", logEntry.getMessage()); .add("message", logEntry.getMessage()));
logs.add(log);
} }
response.put("total", paginatedList.getResultCount());
response.put("logs", logs);
return Response.ok().entity(response).build(); JsonObjectBuilder response = Json.createObjectBuilder()
.add("total", paginatedList.getResultCount())
.add("logs", logs);
return Response.ok().entity(response.build()).build();
} }
/** /**
* Destroy and rebuild Lucene index. * Destroy and rebuild Lucene index.
* *
* @return Response * @return Response
* @throws JSONException
*/ */
@POST @POST
@Path("batch/reindex") @Path("batch/reindex")
@Produces(MediaType.APPLICATION_JSON) public Response batchReindex() {
public Response batchReindex() throws JSONException {
if (!authenticate()) { if (!authenticate()) {
throw new ForbiddenClientException(); throw new ForbiddenClientException();
} }
@ -146,21 +137,20 @@ public class AppResource extends BaseResource {
throw new ServerException("IndexingError", "Error rebuilding index", e); throw new ServerException("IndexingError", "Error rebuilding index", e);
} }
JSONObject response = new JSONObject(); // Always return OK
response.put("status", "ok"); JsonObjectBuilder response = Json.createObjectBuilder()
return Response.ok().entity(response).build(); .add("status", "ok");
return Response.ok().entity(response.build()).build();
} }
/** /**
* Clean storage. * Clean storage.
* *
* @return Response * @return Response
* @throws JSONException
*/ */
@POST @POST
@Path("batch/clean_storage") @Path("batch/clean_storage")
@Produces(MediaType.APPLICATION_JSON) public Response batchCleanStorage() {
public Response batchCleanStorage() throws JSONException {
if (!authenticate()) { if (!authenticate()) {
throw new ForbiddenClientException(); throw new ForbiddenClientException();
} }
@ -184,8 +174,9 @@ public class AppResource extends BaseResource {
} }
} }
JSONObject response = new JSONObject(); // Always return OK
response.put("status", "ok"); JsonObjectBuilder response = Json.createObjectBuilder()
return Response.ok().entity(response).build(); .add("status", "ok");
return Response.ok().entity(response.build()).build();
} }
} }

View File

@ -1,19 +1,14 @@
package com.sismics.docs.rest.resource; package com.sismics.docs.rest.resource;
import java.util.ArrayList; import javax.json.Json;
import java.util.List; import javax.json.JsonArrayBuilder;
import javax.json.JsonObjectBuilder;
import javax.ws.rs.GET; import javax.ws.rs.GET;
import javax.ws.rs.Path; import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam; import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status; import javax.ws.rs.core.Response.Status;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
import com.sismics.docs.core.constant.PermType; import com.sismics.docs.core.constant.PermType;
import com.sismics.docs.core.dao.jpa.AclDao; import com.sismics.docs.core.dao.jpa.AclDao;
import com.sismics.docs.core.dao.jpa.AuditLogDao; import com.sismics.docs.core.dao.jpa.AuditLogDao;
@ -36,11 +31,9 @@ public class AuditLogResource extends BaseResource {
* Returns the list of all logs for a document or user. * Returns the list of all logs for a document or user.
* *
* @return Response * @return Response
* @throws JSONException
*/ */
@GET @GET
@Produces(MediaType.APPLICATION_JSON) public Response list(@QueryParam("document") String documentId) {
public Response list(@QueryParam("document") String documentId) throws JSONException {
if (!authenticate()) { if (!authenticate()) {
throw new ForbiddenClientException(); throw new ForbiddenClientException();
} }
@ -70,22 +63,21 @@ public class AuditLogResource extends BaseResource {
} }
// Assemble the results // Assemble the results
List<JSONObject> logs = new ArrayList<>(); JsonArrayBuilder logs = Json.createArrayBuilder();
JSONObject response = new JSONObject();
for (AuditLogDto auditLogDto : paginatedList.getResultList()) { for (AuditLogDto auditLogDto : paginatedList.getResultList()) {
JSONObject log = new JSONObject(); logs.add(Json.createObjectBuilder()
log.put("id", auditLogDto.getId()); .add("id", auditLogDto.getId())
log.put("target", auditLogDto.getEntityId()); .add("target", auditLogDto.getEntityId())
log.put("class", auditLogDto.getEntityClass()); .add("class", auditLogDto.getEntityClass())
log.put("type", auditLogDto.getType().name()); .add("type", auditLogDto.getType().name())
log.put("message", auditLogDto.getMessage()); .add("message", auditLogDto.getMessage())
log.put("create_date", auditLogDto.getCreateTimestamp()); .add("create_date", auditLogDto.getCreateTimestamp()));
logs.add(log);
} }
// Send the response // Send the response
response.put("logs", logs); JsonObjectBuilder response = Json.createObjectBuilder()
response.put("total", paginatedList.getResultCount()); .add("logs", logs)
return Response.ok().entity(response).build(); .add("total", paginatedList.getResultCount());
return Response.ok().entity(response.build()).build();
} }
} }

View File

@ -1,17 +1,17 @@
package com.sismics.docs.rest.resource; package com.sismics.docs.rest.resource;
import java.security.Principal;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import com.sismics.docs.rest.constant.BaseFunction; import com.sismics.docs.rest.constant.BaseFunction;
import com.sismics.rest.exception.ForbiddenClientException; import com.sismics.rest.exception.ForbiddenClientException;
import com.sismics.security.IPrincipal; import com.sismics.security.IPrincipal;
import com.sismics.security.UserPrincipal; import com.sismics.security.UserPrincipal;
import com.sismics.util.filter.TokenBasedSecurityFilter; import com.sismics.util.filter.TokenBasedSecurityFilter;
import org.codehaus.jettison.json.JSONException;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import java.security.Principal;
import java.util.Set;
/** /**
* Base class of REST resources. * Base class of REST resources.
@ -57,7 +57,7 @@ public abstract class BaseResource {
* @param baseFunction Base function to check * @param baseFunction Base function to check
* @throws JSONException * @throws JSONException
*/ */
protected void checkBaseFunction(BaseFunction baseFunction) throws JSONException { protected void checkBaseFunction(BaseFunction baseFunction) {
if (!hasBaseFunction(baseFunction)) { if (!hasBaseFunction(baseFunction)) {
throw new ForbiddenClientException(); throw new ForbiddenClientException();
} }
@ -70,7 +70,7 @@ public abstract class BaseResource {
* @return True if the user has the base function * @return True if the user has the base function
* @throws JSONException * @throws JSONException
*/ */
protected boolean hasBaseFunction(BaseFunction baseFunction) throws JSONException { protected boolean hasBaseFunction(BaseFunction baseFunction) {
if (principal == null || !(principal instanceof UserPrincipal)) { if (principal == null || !(principal instanceof UserPrincipal)) {
return false; return false;
} }

View File

@ -8,6 +8,9 @@ import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import javax.json.Json;
import javax.json.JsonArrayBuilder;
import javax.json.JsonObjectBuilder;
import javax.persistence.NoResultException; import javax.persistence.NoResultException;
import javax.ws.rs.DELETE; import javax.ws.rs.DELETE;
import javax.ws.rs.FormParam; import javax.ws.rs.FormParam;
@ -16,15 +19,11 @@ import javax.ws.rs.POST;
import javax.ws.rs.PUT; import javax.ws.rs.PUT;
import javax.ws.rs.Path; import javax.ws.rs.Path;
import javax.ws.rs.PathParam; import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam; import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status; import javax.ws.rs.core.Response.Status;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
import org.joda.time.DateTime; import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat; import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter; import org.joda.time.format.DateTimeFormatter;
@ -58,6 +57,7 @@ import com.sismics.docs.core.util.jpa.SortCriteria;
import com.sismics.rest.exception.ClientException; import com.sismics.rest.exception.ClientException;
import com.sismics.rest.exception.ForbiddenClientException; import com.sismics.rest.exception.ForbiddenClientException;
import com.sismics.rest.exception.ServerException; import com.sismics.rest.exception.ServerException;
import com.sismics.rest.util.JsonUtil;
import com.sismics.rest.util.ValidationUtil; import com.sismics.rest.util.ValidationUtil;
/** /**
@ -72,14 +72,12 @@ public class DocumentResource extends BaseResource {
* *
* @param documentId Document ID * @param documentId Document ID
* @return Response * @return Response
* @throws JSONException
*/ */
@GET @GET
@Path("{id: [a-z0-9\\-]+}") @Path("{id: [a-z0-9\\-]+}")
@Produces(MediaType.APPLICATION_JSON)
public Response get( public Response get(
@PathParam("id") String documentId, @PathParam("id") String documentId,
@QueryParam("share") String shareId) throws JSONException { @QueryParam("share") String shareId) {
authenticate(); authenticate();
DocumentDao documentDao = new DocumentDao(); DocumentDao documentDao = new DocumentDao();
@ -96,48 +94,46 @@ public class DocumentResource extends BaseResource {
return Response.status(Status.NOT_FOUND).build(); return Response.status(Status.NOT_FOUND).build();
} }
JSONObject document = new JSONObject(); JsonObjectBuilder document = Json.createObjectBuilder()
document.put("id", documentDto.getId()); .add("id", documentDto.getId())
document.put("title", documentDto.getTitle()); .add("title", documentDto.getTitle())
document.put("description", documentDto.getDescription()); .add("description", JsonUtil.nullable(documentDto.getDescription()))
document.put("create_date", documentDto.getCreateTimestamp()); .add("create_date", documentDto.getCreateTimestamp())
document.put("language", documentDto.getLanguage()); .add("language", documentDto.getLanguage())
document.put("shared", documentDto.getShared()); .add("shared", documentDto.getShared())
document.put("file_count", documentDto.getFileCount()); .add("file_count", documentDto.getFileCount());
if (principal.isAnonymous()) { if (principal.isAnonymous()) {
// No tags in anonymous mode (sharing) // No tags in anonymous mode (sharing)
document.put("tags", new ArrayList<JSONObject>()); document.add("tags", Json.createArrayBuilder());
} else { } else {
// Add tags added by the current user on this document // Add tags added by the current user on this document
TagDao tagDao = new TagDao(); TagDao tagDao = new TagDao();
List<TagDto> tagDtoList = tagDao.getByDocumentId(documentId, principal.getId()); List<TagDto> tagDtoList = tagDao.getByDocumentId(documentId, principal.getId());
List<JSONObject> tags = new ArrayList<>(); JsonArrayBuilder tags = Json.createArrayBuilder();
for (TagDto tagDto : tagDtoList) { for (TagDto tagDto : tagDtoList) {
JSONObject tag = new JSONObject(); tags.add(Json.createObjectBuilder()
tag.put("id", tagDto.getId()); .add("id", tagDto.getId())
tag.put("name", tagDto.getName()); .add("name", tagDto.getName())
tag.put("color", tagDto.getColor()); .add("color", tagDto.getColor()));
tags.add(tag);
} }
document.put("tags", tags); document.add("tags", tags);
} }
// Below is specific to GET /document/id // Below is specific to GET /document/id
document.put("creator", documentDto.getCreator()); document.add("creator", documentDto.getCreator());
// Add ACL // Add ACL
List<AclDto> aclDtoList = aclDao.getBySourceId(documentId); List<AclDto> aclDtoList = aclDao.getBySourceId(documentId);
List<JSONObject> aclList = new ArrayList<>(); JsonArrayBuilder aclList = Json.createArrayBuilder();
boolean writable = false; boolean writable = false;
for (AclDto aclDto : aclDtoList) { for (AclDto aclDto : aclDtoList) {
JSONObject acl = new JSONObject(); aclList.add(Json.createObjectBuilder()
acl.put("perm", aclDto.getPerm().name()); .add("perm", aclDto.getPerm().name())
acl.put("id", aclDto.getTargetId()); .add("id", aclDto.getTargetId())
acl.put("name", aclDto.getTargetName()); .add("name", JsonUtil.nullable(aclDto.getTargetName()))
acl.put("type", aclDto.getTargetType()); .add("type", aclDto.getTargetType()));
aclList.add(acl);
if (!principal.isAnonymous() if (!principal.isAnonymous()
&& aclDto.getTargetId().equals(principal.getId()) && aclDto.getTargetId().equals(principal.getId())
@ -146,10 +142,10 @@ public class DocumentResource extends BaseResource {
writable = true; writable = true;
} }
} }
document.put("acls", aclList); document.add("acls", aclList)
document.put("writable", writable); .add("writable", writable);
return Response.ok().entity(document).build(); return Response.ok().entity(document.build()).build();
} }
/** /**
@ -158,23 +154,21 @@ public class DocumentResource extends BaseResource {
* @param limit Page limit * @param limit Page limit
* @param offset Page offset * @param offset Page offset
* @return Response * @return Response
* @throws JSONException
*/ */
@GET @GET
@Path("list") @Path("list")
@Produces(MediaType.APPLICATION_JSON)
public Response list( public Response list(
@QueryParam("limit") Integer limit, @QueryParam("limit") Integer limit,
@QueryParam("offset") Integer offset, @QueryParam("offset") Integer offset,
@QueryParam("sort_column") Integer sortColumn, @QueryParam("sort_column") Integer sortColumn,
@QueryParam("asc") Boolean asc, @QueryParam("asc") Boolean asc,
@QueryParam("search") String search) throws JSONException { @QueryParam("search") String search) {
if (!authenticate()) { if (!authenticate()) {
throw new ForbiddenClientException(); throw new ForbiddenClientException();
} }
JSONObject response = new JSONObject(); JsonObjectBuilder response = Json.createObjectBuilder();
List<JSONObject> documents = new ArrayList<>(); JsonArrayBuilder documents = Json.createArrayBuilder();
DocumentDao documentDao = new DocumentDao(); DocumentDao documentDao = new DocumentDao();
TagDao tagDao = new TagDao(); TagDao tagDao = new TagDao();
@ -189,33 +183,30 @@ public class DocumentResource extends BaseResource {
} }
for (DocumentDto documentDto : paginatedList.getResultList()) { for (DocumentDto documentDto : paginatedList.getResultList()) {
JSONObject document = new JSONObject();
document.put("id", documentDto.getId());
document.put("title", documentDto.getTitle());
document.put("description", documentDto.getDescription());
document.put("create_date", documentDto.getCreateTimestamp());
document.put("language", documentDto.getLanguage());
document.put("shared", documentDto.getShared());
document.put("file_count", documentDto.getFileCount());
// Get tags added by the current user on this document // Get tags added by the current user on this document
List<TagDto> tagDtoList = tagDao.getByDocumentId(documentDto.getId(), principal.getId()); List<TagDto> tagDtoList = tagDao.getByDocumentId(documentDto.getId(), principal.getId());
List<JSONObject> tags = new ArrayList<>(); JsonArrayBuilder tags = Json.createArrayBuilder();
for (TagDto tagDto : tagDtoList) { for (TagDto tagDto : tagDtoList) {
JSONObject tag = new JSONObject(); tags.add(Json.createObjectBuilder()
tag.put("id", tagDto.getId()); .add("id", tagDto.getId())
tag.put("name", tagDto.getName()); .add("name", tagDto.getName())
tag.put("color", tagDto.getColor()); .add("color", tagDto.getColor()));
tags.add(tag);
} }
document.put("tags", tags);
documents.add(document); documents.add(Json.createObjectBuilder()
.add("id", documentDto.getId())
.add("title", documentDto.getTitle())
.add("description", JsonUtil.nullable(documentDto.getDescription()))
.add("create_date", documentDto.getCreateTimestamp())
.add("language", documentDto.getLanguage())
.add("shared", documentDto.getShared())
.add("file_count", documentDto.getFileCount())
.add("tags", tags));
} }
response.put("total", paginatedList.getResultCount()); response.add("total", paginatedList.getResultCount())
response.put("documents", documents); .add("documents", documents);
return Response.ok().entity(response).build(); return Response.ok().entity(response.build()).build();
} }
/** /**
@ -329,16 +320,14 @@ public class DocumentResource extends BaseResource {
* @param language Language * @param language Language
* @param createDateStr Creation date * @param createDateStr Creation date
* @return Response * @return Response
* @throws JSONException
*/ */
@PUT @PUT
@Produces(MediaType.APPLICATION_JSON)
public Response add( public Response add(
@FormParam("title") String title, @FormParam("title") String title,
@FormParam("description") String description, @FormParam("description") String description,
@FormParam("tags") List<String> tagList, @FormParam("tags") List<String> tagList,
@FormParam("language") String language, @FormParam("language") String language,
@FormParam("create_date") String createDateStr) throws JSONException { @FormParam("create_date") String createDateStr) {
if (!authenticate()) { if (!authenticate()) {
throw new ForbiddenClientException(); throw new ForbiddenClientException();
} }
@ -389,9 +378,9 @@ public class DocumentResource extends BaseResource {
documentCreatedAsyncEvent.setDocument(document); documentCreatedAsyncEvent.setDocument(document);
AppContext.getInstance().getAsyncEventBus().post(documentCreatedAsyncEvent); AppContext.getInstance().getAsyncEventBus().post(documentCreatedAsyncEvent);
JSONObject response = new JSONObject(); JsonObjectBuilder response = Json.createObjectBuilder()
response.put("id", documentId); .add("id", documentId);
return Response.ok().entity(response).build(); return Response.ok().entity(response.build()).build();
} }
/** /**
@ -400,18 +389,16 @@ public class DocumentResource extends BaseResource {
* @param title Title * @param title Title
* @param description Description * @param description Description
* @return Response * @return Response
* @throws JSONException
*/ */
@POST @POST
@Path("{id: [a-z0-9\\-]+}") @Path("{id: [a-z0-9\\-]+}")
@Produces(MediaType.APPLICATION_JSON)
public Response update( public Response update(
@PathParam("id") String id, @PathParam("id") String id,
@FormParam("title") String title, @FormParam("title") String title,
@FormParam("description") String description, @FormParam("description") String description,
@FormParam("tags") List<String> tagList, @FormParam("tags") List<String> tagList,
@FormParam("language") String language, @FormParam("language") String language,
@FormParam("create_date") String createDateStr) throws JSONException { @FormParam("create_date") String createDateStr) {
if (!authenticate()) { if (!authenticate()) {
throw new ForbiddenClientException(); throw new ForbiddenClientException();
} }
@ -458,10 +445,9 @@ public class DocumentResource extends BaseResource {
documentUpdatedAsyncEvent.setDocument(document); documentUpdatedAsyncEvent.setDocument(document);
AppContext.getInstance().getAsyncEventBus().post(documentUpdatedAsyncEvent); AppContext.getInstance().getAsyncEventBus().post(documentUpdatedAsyncEvent);
// Always return ok JsonObjectBuilder response = Json.createObjectBuilder()
JSONObject response = new JSONObject(); .add("id", id);
response.put("id", id); return Response.ok().entity(response.build()).build();
return Response.ok().entity(response).build();
} }
/** /**
@ -469,9 +455,8 @@ public class DocumentResource extends BaseResource {
* *
* @param documentId Document ID * @param documentId Document ID
* @param tagList Tag ID list * @param tagList Tag ID list
* @throws JSONException
*/ */
private void updateTagList(String documentId, List<String> tagList) throws JSONException { private void updateTagList(String documentId, List<String> tagList) {
if (tagList != null) { if (tagList != null) {
TagDao tagDao = new TagDao(); TagDao tagDao = new TagDao();
Set<String> tagSet = new HashSet<>(); Set<String> tagSet = new HashSet<>();
@ -495,13 +480,11 @@ public class DocumentResource extends BaseResource {
* *
* @param id Document ID * @param id Document ID
* @return Response * @return Response
* @throws JSONException
*/ */
@DELETE @DELETE
@Path("{id: [a-z0-9\\-]+}") @Path("{id: [a-z0-9\\-]+}")
@Produces(MediaType.APPLICATION_JSON)
public Response delete( public Response delete(
@PathParam("id") String id) throws JSONException { @PathParam("id") String id) {
if (!authenticate()) { if (!authenticate()) {
throw new ForbiddenClientException(); throw new ForbiddenClientException();
} }
@ -533,9 +516,9 @@ public class DocumentResource extends BaseResource {
documentDeletedAsyncEvent.setDocument(document); documentDeletedAsyncEvent.setDocument(document);
AppContext.getInstance().getAsyncEventBus().post(documentDeletedAsyncEvent); AppContext.getInstance().getAsyncEventBus().post(documentDeletedAsyncEvent);
// Always return ok // Always return OK
JSONObject response = new JSONObject(); JsonObjectBuilder response = Json.createObjectBuilder()
response.put("status", "ok"); .add("status", "ok");
return Response.ok().entity(response).build(); return Response.ok().entity(response.build()).build();
} }
} }

View File

@ -8,12 +8,14 @@ import java.io.OutputStream;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.text.MessageFormat; import java.text.MessageFormat;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.zip.ZipEntry; import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream; import java.util.zip.ZipOutputStream;
import javax.json.Json;
import javax.json.JsonArrayBuilder;
import javax.json.JsonObjectBuilder;
import javax.persistence.NoResultException; import javax.persistence.NoResultException;
import javax.ws.rs.Consumes; import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE; import javax.ws.rs.DELETE;
@ -28,10 +30,11 @@ import javax.ws.rs.QueryParam;
import javax.ws.rs.WebApplicationException; import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.StreamingOutput; import javax.ws.rs.core.StreamingOutput;
import org.codehaus.jettison.json.JSONException; import org.glassfish.jersey.media.multipart.FormDataBodyPart;
import org.codehaus.jettison.json.JSONObject; import org.glassfish.jersey.media.multipart.FormDataParam;
import com.google.common.base.Strings; import com.google.common.base.Strings;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
@ -54,12 +57,10 @@ import com.sismics.docs.core.util.FileUtil;
import com.sismics.rest.exception.ClientException; import com.sismics.rest.exception.ClientException;
import com.sismics.rest.exception.ForbiddenClientException; import com.sismics.rest.exception.ForbiddenClientException;
import com.sismics.rest.exception.ServerException; import com.sismics.rest.exception.ServerException;
import com.sismics.rest.util.JsonUtil;
import com.sismics.rest.util.ValidationUtil; import com.sismics.rest.util.ValidationUtil;
import com.sismics.util.mime.MimeType; import com.sismics.util.mime.MimeType;
import com.sismics.util.mime.MimeTypeUtil; import com.sismics.util.mime.MimeTypeUtil;
import com.sun.jersey.api.client.ClientResponse.Status;
import com.sun.jersey.multipart.FormDataBodyPart;
import com.sun.jersey.multipart.FormDataParam;
/** /**
* File REST resources. * File REST resources.
@ -74,14 +75,12 @@ public class FileResource extends BaseResource {
* @param documentId Document ID * @param documentId Document ID
* @param fileBodyPart File to add * @param fileBodyPart File to add
* @return Response * @return Response
* @throws JSONException
*/ */
@PUT @PUT
@Consumes("multipart/form-data") @Consumes("multipart/form-data")
@Produces(MediaType.APPLICATION_JSON)
public Response add( public Response add(
@FormDataParam("id") String documentId, @FormDataParam("id") String documentId,
@FormDataParam("file") FormDataBodyPart fileBodyPart) throws JSONException { @FormDataParam("file") FormDataBodyPart fileBodyPart) {
if (!authenticate()) { if (!authenticate()) {
throw new ForbiddenClientException(); throw new ForbiddenClientException();
} }
@ -156,11 +155,11 @@ public class FileResource extends BaseResource {
AppContext.getInstance().getAsyncEventBus().post(fileCreatedAsyncEvent); AppContext.getInstance().getAsyncEventBus().post(fileCreatedAsyncEvent);
} }
// Always return ok // Always return OK
JSONObject response = new JSONObject(); JsonObjectBuilder response = Json.createObjectBuilder()
response.put("status", "ok"); .add("status", "ok")
response.put("id", fileId); .add("id", fileId);
return Response.ok().entity(response).build(); return Response.ok().entity(response.build()).build();
} catch (Exception e) { } catch (Exception e) {
throw new ServerException("FileError", "Error adding a file", e); throw new ServerException("FileError", "Error adding a file", e);
} }
@ -171,14 +170,12 @@ public class FileResource extends BaseResource {
* *
* @param id File ID * @param id File ID
* @return Response * @return Response
* @throws JSONException
*/ */
@POST @POST
@Path("{id: [a-z0-9\\-]+}") @Path("{id: [a-z0-9\\-]+}")
@Produces(MediaType.APPLICATION_JSON)
public Response attach( public Response attach(
@PathParam("id") String id, @PathParam("id") String id,
@FormParam("id") String documentId) throws JSONException { @FormParam("id") String documentId) {
if (!authenticate()) { if (!authenticate()) {
throw new ForbiddenClientException(); throw new ForbiddenClientException();
} }
@ -226,10 +223,10 @@ public class FileResource extends BaseResource {
throw new ClientException("AttachError", "Error attaching file to document", e); throw new ClientException("AttachError", "Error attaching file to document", e);
} }
// Always return ok // Always return OK
JSONObject response = new JSONObject(); JsonObjectBuilder response = Json.createObjectBuilder()
response.put("status", "ok"); .add("status", "ok");
return Response.ok().entity(response).build(); return Response.ok().entity(response.build()).build();
} }
/** /**
@ -238,14 +235,12 @@ public class FileResource extends BaseResource {
* @param documentId Document ID * @param documentId Document ID
* @param idList List of files ID in the new order * @param idList List of files ID in the new order
* @return Response * @return Response
* @throws JSONException
*/ */
@POST @POST
@Path("reorder") @Path("reorder")
@Produces(MediaType.APPLICATION_JSON)
public Response reorder( public Response reorder(
@FormParam("id") String documentId, @FormParam("id") String documentId,
@FormParam("order") List<String> idList) throws JSONException { @FormParam("order") List<String> idList) {
if (!authenticate()) { if (!authenticate()) {
throw new ForbiddenClientException(); throw new ForbiddenClientException();
} }
@ -271,10 +266,10 @@ public class FileResource extends BaseResource {
} }
} }
// Always return ok // Always return OK
JSONObject response = new JSONObject(); JsonObjectBuilder response = Json.createObjectBuilder()
response.put("status", "ok"); .add("status", "ok");
return Response.ok().entity(response).build(); return Response.ok().entity(response.build()).build();
} }
/** /**
@ -283,14 +278,12 @@ public class FileResource extends BaseResource {
* @param documentId Document ID * @param documentId Document ID
* @param shareId Sharing ID * @param shareId Sharing ID
* @return Response * @return Response
* @throws JSONException
*/ */
@GET @GET
@Path("list") @Path("list")
@Produces(MediaType.APPLICATION_JSON)
public Response list( public Response list(
@QueryParam("id") String documentId, @QueryParam("id") String documentId,
@QueryParam("share") String shareId) throws JSONException { @QueryParam("share") String shareId) {
boolean authenticated = authenticate(); boolean authenticated = authenticate();
// Check document visibility // Check document visibility
@ -306,20 +299,18 @@ public class FileResource extends BaseResource {
FileDao fileDao = new FileDao(); FileDao fileDao = new FileDao();
List<File> fileList = fileDao.getByDocumentId(principal.getId(), documentId); List<File> fileList = fileDao.getByDocumentId(principal.getId(), documentId);
JSONObject response = new JSONObject(); JsonArrayBuilder files = Json.createArrayBuilder();
List<JSONObject> files = new ArrayList<>();
for (File fileDb : fileList) { for (File fileDb : fileList) {
JSONObject file = new JSONObject(); files.add(Json.createObjectBuilder()
file.put("id", fileDb.getId()); .add("id", fileDb.getId())
file.put("mimetype", fileDb.getMimeType()); .add("mimetype", fileDb.getMimeType())
file.put("document_id", fileDb.getDocumentId()); .add("document_id", JsonUtil.nullable(fileDb.getDocumentId()))
file.put("create_date", fileDb.getCreateDate().getTime()); .add("create_date", fileDb.getCreateDate().getTime()));
files.add(file);
} }
response.put("files", files); JsonObjectBuilder response = Json.createObjectBuilder()
return Response.ok().entity(response).build(); .add("files", files);
return Response.ok().entity(response.build()).build();
} }
/** /**
@ -327,13 +318,11 @@ public class FileResource extends BaseResource {
* *
* @param id File ID * @param id File ID
* @return Response * @return Response
* @throws JSONException
*/ */
@DELETE @DELETE
@Path("{id: [a-z0-9\\-]+}") @Path("{id: [a-z0-9\\-]+}")
@Produces(MediaType.APPLICATION_JSON)
public Response delete( public Response delete(
@PathParam("id") String id) throws JSONException { @PathParam("id") String id) {
if (!authenticate()) { if (!authenticate()) {
throw new ForbiddenClientException(); throw new ForbiddenClientException();
} }
@ -365,10 +354,10 @@ public class FileResource extends BaseResource {
fileDeletedAsyncEvent.setFile(file); fileDeletedAsyncEvent.setFile(file);
AppContext.getInstance().getAsyncEventBus().post(fileDeletedAsyncEvent); AppContext.getInstance().getAsyncEventBus().post(fileDeletedAsyncEvent);
// Always return ok // Always return OK
JSONObject response = new JSONObject(); JsonObjectBuilder response = Json.createObjectBuilder()
response.put("status", "ok"); .add("status", "ok");
return Response.ok().entity(response).build(); return Response.ok().entity(response.build()).build();
} }
/** /**
@ -376,15 +365,13 @@ public class FileResource extends BaseResource {
* *
* @param fileId File ID * @param fileId File ID
* @return Response * @return Response
* @throws JSONException
*/ */
@GET @GET
@Path("{id: [a-z0-9\\-]+}/data") @Path("{id: [a-z0-9\\-]+}/data")
@Produces(MediaType.APPLICATION_OCTET_STREAM)
public Response data( public Response data(
@PathParam("id") final String fileId, @PathParam("id") final String fileId,
@QueryParam("share") String shareId, @QueryParam("share") String shareId,
@QueryParam("size") String size) throws JSONException { @QueryParam("size") String size) {
authenticate(); authenticate();
if (size != null) { if (size != null) {
@ -472,14 +459,13 @@ public class FileResource extends BaseResource {
* *
* @param documentId Document ID * @param documentId Document ID
* @return Response * @return Response
* @throws JSONException
*/ */
@GET @GET
@Path("zip") @Path("zip")
@Produces(MediaType.APPLICATION_OCTET_STREAM) @Produces(MediaType.APPLICATION_OCTET_STREAM)
public Response zip( public Response zip(
@QueryParam("id") String documentId, @QueryParam("id") String documentId,
@QueryParam("share") String shareId) throws JSONException { @QueryParam("share") String shareId) {
authenticate(); authenticate();
// Get the document // Get the document

View File

@ -1,44 +0,0 @@
package com.sismics.docs.rest.resource;
import com.sismics.docs.core.dao.jpa.LocaleDao;
import com.sismics.docs.core.model.jpa.Locale;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.ArrayList;
import java.util.List;
/**
* Locale REST resources.
*
* @author jtremeaux
*/
@Path("/locale")
public class LocaleResource extends BaseResource {
/**
* Returns the list of all locales.
*
* @return Response
* @throws JSONException
*/
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response list() throws JSONException {
LocaleDao localeDao = new LocaleDao();
List<Locale> localeList = localeDao.findAll();
JSONObject response = new JSONObject();
List<JSONObject> items = new ArrayList<>();
for (Locale locale : localeList) {
JSONObject item = new JSONObject();
item.put("id", locale.getId());
items.add(item);
}
response.put("locales", items);
return Response.ok().entity(response).build();
}
}

View File

@ -4,19 +4,16 @@ package com.sismics.docs.rest.resource;
import java.text.MessageFormat; import java.text.MessageFormat;
import java.util.List; import java.util.List;
import javax.json.Json;
import javax.json.JsonObjectBuilder;
import javax.persistence.NoResultException; import javax.persistence.NoResultException;
import javax.ws.rs.DELETE; import javax.ws.rs.DELETE;
import javax.ws.rs.FormParam; import javax.ws.rs.FormParam;
import javax.ws.rs.PUT; import javax.ws.rs.PUT;
import javax.ws.rs.Path; import javax.ws.rs.Path;
import javax.ws.rs.PathParam; import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
import com.sismics.docs.core.constant.AclTargetType; import com.sismics.docs.core.constant.AclTargetType;
import com.sismics.docs.core.constant.PermType; import com.sismics.docs.core.constant.PermType;
import com.sismics.docs.core.dao.jpa.AclDao; import com.sismics.docs.core.dao.jpa.AclDao;
@ -26,6 +23,7 @@ import com.sismics.docs.core.model.jpa.Acl;
import com.sismics.docs.core.model.jpa.Share; import com.sismics.docs.core.model.jpa.Share;
import com.sismics.rest.exception.ClientException; import com.sismics.rest.exception.ClientException;
import com.sismics.rest.exception.ForbiddenClientException; import com.sismics.rest.exception.ForbiddenClientException;
import com.sismics.rest.util.JsonUtil;
import com.sismics.rest.util.ValidationUtil; import com.sismics.rest.util.ValidationUtil;
/** /**
@ -40,13 +38,11 @@ public class ShareResource extends BaseResource {
* *
* @param documentId Document ID * @param documentId Document ID
* @return Response * @return Response
* @throws JSONException
*/ */
@PUT @PUT
@Produces(MediaType.APPLICATION_JSON)
public Response add( public Response add(
@FormParam("id") String documentId, @FormParam("id") String documentId,
@FormParam("name") String name) throws JSONException { @FormParam("name") String name) {
if (!authenticate()) { if (!authenticate()) {
throw new ForbiddenClientException(); throw new ForbiddenClientException();
} }
@ -78,12 +74,12 @@ public class ShareResource extends BaseResource {
aclDao.create(acl); aclDao.create(acl);
// Returns the created ACL // Returns the created ACL
JSONObject response = new JSONObject(); JsonObjectBuilder response = Json.createObjectBuilder()
response.put("perm", acl.getPerm().name()); .add("perm", acl.getPerm().name())
response.put("id", acl.getTargetId()); .add("id", acl.getTargetId())
response.put("name", name); .add("name", JsonUtil.nullable(name))
response.put("type", AclTargetType.SHARE); .add("type", AclTargetType.SHARE.toString());
return Response.ok().entity(response).build(); return Response.ok().entity(response.build()).build();
} }
/** /**
@ -91,13 +87,11 @@ public class ShareResource extends BaseResource {
* *
* @param id Share ID * @param id Share ID
* @return Response * @return Response
* @throws JSONException
*/ */
@DELETE @DELETE
@Path("{id: [a-z0-9\\-]+}") @Path("{id: [a-z0-9\\-]+}")
@Produces(MediaType.APPLICATION_JSON)
public Response delete( public Response delete(
@PathParam("id") String id) throws JSONException { @PathParam("id") String id) {
if (!authenticate()) { if (!authenticate()) {
throw new ForbiddenClientException(); throw new ForbiddenClientException();
} }
@ -118,9 +112,9 @@ public class ShareResource extends BaseResource {
ShareDao shareDao = new ShareDao(); ShareDao shareDao = new ShareDao();
shareDao.delete(id); shareDao.delete(id);
// Always return ok // Always return OK
JSONObject response = new JSONObject(); JsonObjectBuilder response = Json.createObjectBuilder()
response.put("status", "ok"); .add("status", "ok");
return Response.ok().entity(response).build(); return Response.ok().entity(response.build()).build();
} }
} }

View File

@ -1,21 +1,28 @@
package com.sismics.docs.rest.resource; package com.sismics.docs.rest.resource;
import java.text.MessageFormat;
import java.util.List;
import javax.json.Json;
import javax.json.JsonArrayBuilder;
import javax.json.JsonObjectBuilder;
import javax.ws.rs.DELETE;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.Response;
import org.apache.commons.lang.StringUtils;
import com.sismics.docs.core.dao.jpa.TagDao; import com.sismics.docs.core.dao.jpa.TagDao;
import com.sismics.docs.core.dao.jpa.dto.TagStatDto; import com.sismics.docs.core.dao.jpa.dto.TagStatDto;
import com.sismics.docs.core.model.jpa.Tag; import com.sismics.docs.core.model.jpa.Tag;
import com.sismics.rest.exception.ClientException; import com.sismics.rest.exception.ClientException;
import com.sismics.rest.exception.ForbiddenClientException; import com.sismics.rest.exception.ForbiddenClientException;
import com.sismics.rest.util.ValidationUtil; import com.sismics.rest.util.ValidationUtil;
import org.apache.commons.lang.StringUtils;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
/** /**
* Tag REST resources. * Tag REST resources.
@ -28,29 +35,27 @@ public class TagResource extends BaseResource {
* Returns the list of all tags. * Returns the list of all tags.
* *
* @return Response * @return Response
* @throws JSONException
*/ */
@GET @GET
@Path("/list") @Path("/list")
@Produces(MediaType.APPLICATION_JSON) public Response list() {
public Response list() throws JSONException {
if (!authenticate()) { if (!authenticate()) {
throw new ForbiddenClientException(); throw new ForbiddenClientException();
} }
TagDao tagDao = new TagDao(); TagDao tagDao = new TagDao();
List<Tag> tagList = tagDao.getByUserId(principal.getId()); List<Tag> tagList = tagDao.getByUserId(principal.getId());
JSONObject response = new JSONObject(); JsonArrayBuilder items = Json.createArrayBuilder();
List<JSONObject> items = new ArrayList<>();
for (Tag tag : tagList) { for (Tag tag : tagList) {
JSONObject item = new JSONObject(); items.add(Json.createObjectBuilder()
item.put("id", tag.getId()); .add("id", tag.getId())
item.put("name", tag.getName()); .add("name", tag.getName())
item.put("color", tag.getColor()); .add("color", tag.getColor()));
items.add(item);
} }
response.put("tags", items);
return Response.ok().entity(response).build(); JsonObjectBuilder response = Json.createObjectBuilder()
.add("tags", items);
return Response.ok().entity(response.build()).build();
} }
/** /**
@ -61,26 +66,25 @@ public class TagResource extends BaseResource {
*/ */
@GET @GET
@Path("/stats") @Path("/stats")
@Produces(MediaType.APPLICATION_JSON) public Response stats() {
public Response stats() throws JSONException {
if (!authenticate()) { if (!authenticate()) {
throw new ForbiddenClientException(); throw new ForbiddenClientException();
} }
TagDao tagDao = new TagDao(); TagDao tagDao = new TagDao();
List<TagStatDto> tagStatDtoList = tagDao.getStats(principal.getId()); List<TagStatDto> tagStatDtoList = tagDao.getStats(principal.getId());
JSONObject response = new JSONObject(); JsonArrayBuilder items = Json.createArrayBuilder();
List<JSONObject> items = new ArrayList<>();
for (TagStatDto tagStatDto : tagStatDtoList) { for (TagStatDto tagStatDto : tagStatDtoList) {
JSONObject item = new JSONObject(); items.add(Json.createObjectBuilder()
item.put("id", tagStatDto.getId()); .add("id", tagStatDto.getId())
item.put("name", tagStatDto.getName()); .add("name", tagStatDto.getName())
item.put("color", tagStatDto.getColor()); .add("color", tagStatDto.getColor())
item.put("count", tagStatDto.getCount()); .add("count", tagStatDto.getCount()));
items.add(item);
} }
response.put("stats", items);
return Response.ok().entity(response).build(); JsonObjectBuilder response = Json.createObjectBuilder()
.add("stats", items);
return Response.ok().entity(response.build()).build();
} }
/** /**
@ -88,13 +92,11 @@ public class TagResource extends BaseResource {
* *
* @param name Name * @param name Name
* @return Response * @return Response
* @throws JSONException
*/ */
@PUT @PUT
@Produces(MediaType.APPLICATION_JSON)
public Response add( public Response add(
@FormParam("name") String name, @FormParam("name") String name,
@FormParam("color") String color) throws JSONException { @FormParam("color") String color) {
if (!authenticate()) { if (!authenticate()) {
throw new ForbiddenClientException(); throw new ForbiddenClientException();
} }
@ -120,11 +122,11 @@ public class TagResource extends BaseResource {
tag.setName(name); tag.setName(name);
tag.setColor(color); tag.setColor(color);
tag.setUserId(principal.getId()); tag.setUserId(principal.getId());
String tagId = tagDao.create(tag); String id = tagDao.create(tag);
JSONObject response = new JSONObject(); JsonObjectBuilder response = Json.createObjectBuilder()
response.put("id", tagId); .add("id", id);
return Response.ok().entity(response).build(); return Response.ok().entity(response.build()).build();
} }
/** /**
@ -132,15 +134,13 @@ public class TagResource extends BaseResource {
* *
* @param name Name * @param name Name
* @return Response * @return Response
* @throws JSONException
*/ */
@POST @POST
@Path("{id: [a-z0-9\\-]+}") @Path("{id: [a-z0-9\\-]+}")
@Produces(MediaType.APPLICATION_JSON)
public Response update( public Response update(
@PathParam("id") String id, @PathParam("id") String id,
@FormParam("name") String name, @FormParam("name") String name,
@FormParam("color") String color) throws JSONException { @FormParam("color") String color) {
if (!authenticate()) { if (!authenticate()) {
throw new ForbiddenClientException(); throw new ForbiddenClientException();
} }
@ -177,9 +177,9 @@ public class TagResource extends BaseResource {
tagDao.update(tag); tagDao.update(tag);
JSONObject response = new JSONObject(); JsonObjectBuilder response = Json.createObjectBuilder()
response.put("id", id); .add("id", id);
return Response.ok().entity(response).build(); return Response.ok().entity(response.build()).build();
} }
/** /**
@ -187,13 +187,11 @@ public class TagResource extends BaseResource {
* *
* @param tagId Tag ID * @param tagId Tag ID
* @return Response * @return Response
* @throws JSONException
*/ */
@DELETE @DELETE
@Path("{id: [a-z0-9\\-]+}") @Path("{id: [a-z0-9\\-]+}")
@Produces(MediaType.APPLICATION_JSON)
public Response delete( public Response delete(
@PathParam("id") String tagId) throws JSONException { @PathParam("id") String tagId) {
if (!authenticate()) { if (!authenticate()) {
throw new ForbiddenClientException(); throw new ForbiddenClientException();
} }
@ -208,8 +206,9 @@ public class TagResource extends BaseResource {
// Delete the tag // Delete the tag
tagDao.delete(tagId); tagDao.delete(tagId);
JSONObject response = new JSONObject(); // Always return OK
response.put("status", "ok"); JsonObjectBuilder response = Json.createObjectBuilder()
return Response.ok().entity(response).build(); .add("status", "ok");
return Response.ok().entity(response.build()).build();
} }
} }

View File

@ -1,55 +0,0 @@
package com.sismics.docs.rest.resource;
import com.sun.jersey.core.util.ReaderWriter;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.ext.MessageBodyWriter;
import javax.ws.rs.ext.Provider;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
/**
* MessageBodyWriter personalized to write JSON despite the text/plain MIME type.
* Used in particuler in return of a posted form, since IE doesn't knw how to read the application/json MIME type.
*
* @author bgamard
*/
@Provider
@Produces(MediaType.TEXT_PLAIN)
public class TextPlainMessageBodyWriter implements
MessageBodyWriter<JSONObject> {
@Override
public boolean isWriteable(Class<?> type, Type genericType,
Annotation[] annotations, MediaType mediaType) {
return true;
}
@Override
public long getSize(JSONObject array, Class<?> type, Type genericType,
Annotation[] annotations, MediaType mediaType) {
return -1;
}
@Override
public void writeTo(JSONObject jsonObject, Class<?> type, Type genericType,
Annotation[] annotations, MediaType mediaType,
MultivaluedMap<String, Object> httpHeaders,
OutputStream entityStream) throws IOException,
WebApplicationException {
try {
OutputStreamWriter writer = new OutputStreamWriter(entityStream, ReaderWriter.getCharset(mediaType));
jsonObject.write(writer);
writer.flush();
} catch (JSONException e) {
throw new WebApplicationException(e);
}
}
}

View File

@ -1,43 +0,0 @@
package com.sismics.docs.rest.resource;
import com.sismics.docs.core.dao.file.theme.ThemeDao;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.ArrayList;
import java.util.List;
/**
* Theme REST resources.
*
* @author jtremeaux
*/
@Path("/theme")
public class ThemeResource extends BaseResource {
/**
* Returns the list of all themes.
*
* @return Response
* @throws JSONException
*/
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response list() throws JSONException {
ThemeDao themeDao = new ThemeDao();
List<String> themeList = themeDao.findAll();
JSONObject response = new JSONObject();
List<JSONObject> items = new ArrayList<>();
for (String theme : themeList) {
JSONObject item = new JSONObject();
item.put("id", theme);
items.add(item);
}
response.put("themes", items);
return Response.ok().entity(response).build();
}
}

View File

@ -1,5 +1,28 @@
package com.sismics.docs.rest.resource; package com.sismics.docs.rest.resource;
import java.security.NoSuchAlgorithmException;
import java.util.Date;
import java.util.Set;
import javax.json.Json;
import javax.json.JsonArrayBuilder;
import javax.json.JsonObjectBuilder;
import javax.servlet.http.Cookie;
import javax.ws.rs.DELETE;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.NewCookie;
import javax.ws.rs.core.Response;
import org.apache.commons.lang.StringUtils;
import com.google.common.base.Strings; import com.google.common.base.Strings;
import com.sismics.docs.core.constant.Constants; import com.sismics.docs.core.constant.Constants;
import com.sismics.docs.core.dao.jpa.AuthenticationTokenDao; import com.sismics.docs.core.dao.jpa.AuthenticationTokenDao;
@ -19,26 +42,8 @@ import com.sismics.rest.exception.ForbiddenClientException;
import com.sismics.rest.exception.ServerException; import com.sismics.rest.exception.ServerException;
import com.sismics.rest.util.ValidationUtil; import com.sismics.rest.util.ValidationUtil;
import com.sismics.security.UserPrincipal; import com.sismics.security.UserPrincipal;
import com.sismics.util.LocaleUtil;
import com.sismics.util.filter.TokenBasedSecurityFilter; import com.sismics.util.filter.TokenBasedSecurityFilter;
import org.apache.commons.lang.StringUtils;
import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
import javax.servlet.http.Cookie;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.NewCookie;
import javax.ws.rs.core.Response;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
/** /**
* User REST resources. * User REST resources.
* *
@ -52,17 +57,13 @@ public class UserResource extends BaseResource {
* @param username User's username * @param username User's username
* @param password Password * @param password Password
* @param email E-Mail * @param email E-Mail
* @param localeId Locale ID
* @return Response * @return Response
* @throws JSONException
*/ */
@PUT @PUT
@Produces(MediaType.APPLICATION_JSON)
public Response register( public Response register(
@FormParam("username") String username, @FormParam("username") String username,
@FormParam("password") String password, @FormParam("password") String password,
@FormParam("locale") String localeId, @FormParam("email") String email) {
@FormParam("email") String email) throws JSONException {
if (!authenticate()) { if (!authenticate()) {
throw new ForbiddenClientException(); throw new ForbiddenClientException();
@ -88,12 +89,6 @@ public class UserResource extends BaseResource {
throw new ServerException("PrivateKeyError", "Error while generating a private key", e); throw new ServerException("PrivateKeyError", "Error while generating a private key", e);
} }
user.setCreateDate(new Date()); user.setCreateDate(new Date());
if (localeId == null) {
// Set the locale from the HTTP headers
localeId = LocaleUtil.getLocaleIdFromAcceptLanguage(request.getHeader("Accept-Language"));
}
user.setLocaleId(localeId);
// Create the user // Create the user
UserDao userDao = new UserDao(); UserDao userDao = new UserDao();
@ -108,9 +103,9 @@ public class UserResource extends BaseResource {
} }
// Always return OK // Always return OK
JSONObject response = new JSONObject(); JsonObjectBuilder response = Json.createObjectBuilder()
response.put("status", "ok"); .add("status", "ok");
return Response.ok().entity(response).build(); return Response.ok().entity(response.build()).build();
} }
/** /**
@ -118,20 +113,12 @@ public class UserResource extends BaseResource {
* *
* @param password Password * @param password Password
* @param email E-Mail * @param email E-Mail
* @param themeId Theme
* @param localeId Locale ID
* @param firstConnection True if the user hasn't acknowledged the first connection wizard yet.
* @return Response * @return Response
* @throws JSONException
*/ */
@POST @POST
@Produces(MediaType.APPLICATION_JSON)
public Response update( public Response update(
@FormParam("password") String password, @FormParam("password") String password,
@FormParam("email") String email, @FormParam("email") String email) {
@FormParam("theme") String themeId,
@FormParam("locale") String localeId,
@FormParam("first_connection") Boolean firstConnection) throws JSONException {
if (!authenticate()) { if (!authenticate()) {
throw new ForbiddenClientException(); throw new ForbiddenClientException();
@ -140,8 +127,6 @@ public class UserResource extends BaseResource {
// Validate the input data // Validate the input data
password = ValidationUtil.validateLength(password, "password", 8, 50, true); password = ValidationUtil.validateLength(password, "password", 8, 50, true);
email = ValidationUtil.validateLength(email, "email", null, 100, true); email = ValidationUtil.validateLength(email, "email", null, 100, true);
localeId = ValidationUtil.validateLocale(localeId, "locale", true);
themeId = ValidationUtil.validateTheme(themeId, "theme", true);
// Update the user // Update the user
UserDao userDao = new UserDao(); UserDao userDao = new UserDao();
@ -149,16 +134,7 @@ public class UserResource extends BaseResource {
if (email != null) { if (email != null) {
user.setEmail(email); user.setEmail(email);
} }
if (themeId != null) {
user.setTheme(themeId);
}
if (localeId != null) {
user.setLocaleId(localeId);
}
if (firstConnection != null && hasBaseFunction(BaseFunction.ADMIN)) {
user.setFirstConnection(firstConnection);
}
user = userDao.update(user); user = userDao.update(user);
if (StringUtils.isNotBlank(password)) { if (StringUtils.isNotBlank(password)) {
@ -166,10 +142,10 @@ public class UserResource extends BaseResource {
userDao.updatePassword(user); userDao.updatePassword(user);
} }
// Always return "ok" // Always return OK
JSONObject response = new JSONObject(); JsonObjectBuilder response = Json.createObjectBuilder()
response.put("status", "ok"); .add("status", "ok");
return Response.ok().entity(response).build(); return Response.ok().entity(response.build()).build();
} }
/** /**
@ -178,20 +154,14 @@ public class UserResource extends BaseResource {
* @param username Username * @param username Username
* @param password Password * @param password Password
* @param email E-Mail * @param email E-Mail
* @param themeId Theme
* @param localeId Locale ID
* @return Response * @return Response
* @throws JSONException
*/ */
@POST @POST
@Path("{username: [a-zA-Z0-9_]+}") @Path("{username: [a-zA-Z0-9_]+}")
@Produces(MediaType.APPLICATION_JSON)
public Response update( public Response update(
@PathParam("username") String username, @PathParam("username") String username,
@FormParam("password") String password, @FormParam("password") String password,
@FormParam("email") String email, @FormParam("email") String email) {
@FormParam("theme") String themeId,
@FormParam("locale") String localeId) throws JSONException {
if (!authenticate()) { if (!authenticate()) {
throw new ForbiddenClientException(); throw new ForbiddenClientException();
@ -201,8 +171,6 @@ public class UserResource extends BaseResource {
// Validate the input data // Validate the input data
password = ValidationUtil.validateLength(password, "password", 8, 50, true); password = ValidationUtil.validateLength(password, "password", 8, 50, true);
email = ValidationUtil.validateLength(email, "email", null, 100, true); email = ValidationUtil.validateLength(email, "email", null, 100, true);
localeId = ValidationUtil.validateLocale(localeId, "locale", true);
themeId = ValidationUtil.validateTheme(themeId, "theme", true);
// Check if the user exists // Check if the user exists
UserDao userDao = new UserDao(); UserDao userDao = new UserDao();
@ -215,12 +183,6 @@ public class UserResource extends BaseResource {
if (email != null) { if (email != null) {
user.setEmail(email); user.setEmail(email);
} }
if (themeId != null) {
user.setTheme(themeId);
}
if (localeId != null) {
user.setLocaleId(localeId);
}
user = userDao.update(user); user = userDao.update(user);
@ -230,10 +192,10 @@ public class UserResource extends BaseResource {
userDao.updatePassword(user); userDao.updatePassword(user);
} }
// Always return "ok" // Always return OK
JSONObject response = new JSONObject(); JsonObjectBuilder response = Json.createObjectBuilder()
response.put("status", "ok"); .add("status", "ok");
return Response.ok().entity(response).build(); return Response.ok().entity(response.build()).build();
} }
/** /**
@ -244,26 +206,25 @@ public class UserResource extends BaseResource {
*/ */
@GET @GET
@Path("check_username") @Path("check_username")
@Produces(MediaType.APPLICATION_JSON)
public Response checkUsername( public Response checkUsername(
@QueryParam("username") String username) throws JSONException { @QueryParam("username") String username) {
UserDao userDao = new UserDao(); UserDao userDao = new UserDao();
User user = userDao.getActiveByUsername(username); User user = userDao.getActiveByUsername(username);
JSONObject response = new JSONObject(); JsonObjectBuilder response = Json.createObjectBuilder();
if (user != null) { if (user != null) {
response.put("status", "ko"); response.add("status", "ko")
response.put("message", "Username already registered"); .add("message", "Username already registered");
} else { } else {
response.put("status", "ok"); response.add("status", "ok");
} }
return Response.ok().entity(response).build(); return Response.ok().entity(response.build()).build();
} }
/** /**
* This resource is used to authenticate the user and create a user ession. * This resource is used to authenticate the user and create a user session.
* The "session" is only used to identify the user, no other data is stored in the session. * The "session" is only used to identify the user, no other data is stored in the session.
* *
* @param username Username * @param username Username
@ -273,11 +234,10 @@ public class UserResource extends BaseResource {
*/ */
@POST @POST
@Path("login") @Path("login")
@Produces(MediaType.APPLICATION_JSON)
public Response login( public Response login(
@FormParam("username") String username, @FormParam("username") String username,
@FormParam("password") String password, @FormParam("password") String password,
@FormParam("remember") boolean longLasted) throws JSONException { @FormParam("remember") boolean longLasted) {
// Validate the input data // Validate the input data
username = StringUtils.strip(username); username = StringUtils.strip(username);
@ -308,10 +268,10 @@ public class UserResource extends BaseResource {
// Cleanup old session tokens // Cleanup old session tokens
authenticationTokenDao.deleteOldSessionToken(userId); authenticationTokenDao.deleteOldSessionToken(userId);
JSONObject response = new JSONObject(); JsonObjectBuilder response = Json.createObjectBuilder();
int maxAge = longLasted ? TokenBasedSecurityFilter.TOKEN_LONG_LIFETIME : -1; int maxAge = longLasted ? TokenBasedSecurityFilter.TOKEN_LONG_LIFETIME : -1;
NewCookie cookie = new NewCookie(TokenBasedSecurityFilter.COOKIE_NAME, token, "/", null, null, maxAge, false); NewCookie cookie = new NewCookie(TokenBasedSecurityFilter.COOKIE_NAME, token, "/", null, null, maxAge, false);
return Response.ok().entity(response).cookie(cookie).build(); return Response.ok().entity(response.build()).cookie(cookie).build();
} }
/** /**
@ -321,8 +281,7 @@ public class UserResource extends BaseResource {
*/ */
@POST @POST
@Path("logout") @Path("logout")
@Produces(MediaType.APPLICATION_JSON) public Response logout() {
public Response logout() throws JSONException {
if (!authenticate()) { if (!authenticate()) {
throw new ForbiddenClientException(); throw new ForbiddenClientException();
} }
@ -356,9 +315,9 @@ public class UserResource extends BaseResource {
} }
// Deletes the client token in the HTTP response // Deletes the client token in the HTTP response
JSONObject response = new JSONObject(); JsonObjectBuilder response = Json.createObjectBuilder();
NewCookie cookie = new NewCookie(TokenBasedSecurityFilter.COOKIE_NAME, null); NewCookie cookie = new NewCookie(TokenBasedSecurityFilter.COOKIE_NAME, null);
return Response.ok().entity(response).cookie(cookie).build(); return Response.ok().entity(response.build()).cookie(cookie).build();
} }
/** /**
@ -367,8 +326,7 @@ public class UserResource extends BaseResource {
* @return Response * @return Response
*/ */
@DELETE @DELETE
@Produces(MediaType.APPLICATION_JSON) public Response delete() {
public Response delete() throws JSONException {
if (!authenticate()) { if (!authenticate()) {
throw new ForbiddenClientException(); throw new ForbiddenClientException();
} }
@ -382,10 +340,10 @@ public class UserResource extends BaseResource {
UserDao userDao = new UserDao(); UserDao userDao = new UserDao();
userDao.delete(principal.getName()); userDao.delete(principal.getName());
// Always return ok // Always return OK
JSONObject response = new JSONObject(); JsonObjectBuilder response = Json.createObjectBuilder()
response.put("status", "ok"); .add("status", "ok");
return Response.ok().entity(response).build(); return Response.ok().entity(response.build()).build();
} }
/** /**
@ -393,12 +351,10 @@ public class UserResource extends BaseResource {
* *
* @param username Username * @param username Username
* @return Response * @return Response
* @throws JSONException
*/ */
@DELETE @DELETE
@Path("{username: [a-zA-Z0-9_]+}") @Path("{username: [a-zA-Z0-9_]+}")
@Produces(MediaType.APPLICATION_JSON) public Response delete(@PathParam("username") String username) {
public Response delete(@PathParam("username") String username) throws JSONException {
if (!authenticate()) { if (!authenticate()) {
throw new ForbiddenClientException(); throw new ForbiddenClientException();
} }
@ -421,49 +377,44 @@ public class UserResource extends BaseResource {
// Delete the user // Delete the user
userDao.delete(user.getUsername()); userDao.delete(user.getUsername());
// Always return ok // Always return OK
JSONObject response = new JSONObject(); JsonObjectBuilder response = Json.createObjectBuilder()
response.put("status", "ok"); .add("status", "ok");
return Response.ok().entity(response).build(); return Response.ok().entity(response.build()).build();
} }
/** /**
* Returns the information about the connected user. * Returns the information about the connected user.
* *
* @return Response * @return Response
* @throws JSONException
*/ */
@GET @GET
@Produces(MediaType.APPLICATION_JSON) public Response info() {
public Response info() throws JSONException { JsonObjectBuilder response = Json.createObjectBuilder();
JSONObject response = new JSONObject();
if (!authenticate()) { if (!authenticate()) {
response.put("anonymous", true); response.add("anonymous", true);
String localeId = LocaleUtil.getLocaleIdFromAcceptLanguage(request.getHeader("Accept-Language"));
response.put("locale", localeId);
// Check if admin has the default password // Check if admin has the default password
UserDao userDao = new UserDao(); UserDao userDao = new UserDao();
User adminUser = userDao.getById("admin"); User adminUser = userDao.getById("admin");
if (adminUser != null && adminUser.getDeleteDate() == null) { if (adminUser != null && adminUser.getDeleteDate() == null) {
response.put("is_default_password", Constants.DEFAULT_ADMIN_PASSWORD.equals(adminUser.getPassword())); response.add("is_default_password", Constants.DEFAULT_ADMIN_PASSWORD.equals(adminUser.getPassword()));
} }
} else { } else {
response.put("anonymous", false); response.add("anonymous", false);
UserDao userDao = new UserDao(); UserDao userDao = new UserDao();
User user = userDao.getById(principal.getId()); User user = userDao.getById(principal.getId());
response.put("username", user.getUsername()); response.add("username", user.getUsername())
response.put("email", user.getEmail()); .add("email", user.getEmail());
response.put("theme", user.getTheme()); JsonArrayBuilder baseFunctions = Json.createArrayBuilder();
response.put("locale", user.getLocaleId()); for (String baseFunction : ((UserPrincipal) principal).getBaseFunctionSet()) {
response.put("first_connection", user.isFirstConnection()); baseFunctions.add(baseFunction);
JSONArray baseFunctions = new JSONArray(((UserPrincipal) principal).getBaseFunctionSet()); }
response.put("base_functions", baseFunctions); response.add("base_functions", baseFunctions)
response.put("is_default_password", hasBaseFunction(BaseFunction.ADMIN) && Constants.DEFAULT_ADMIN_PASSWORD.equals(user.getPassword())); .add("is_default_password", hasBaseFunction(BaseFunction.ADMIN) && Constants.DEFAULT_ADMIN_PASSWORD.equals(user.getPassword()));
} }
return Response.ok().entity(response).build(); return Response.ok().entity(response.build()).build();
} }
/** /**
@ -471,31 +422,26 @@ public class UserResource extends BaseResource {
* *
* @param username Username * @param username Username
* @return Response * @return Response
* @throws JSONException
*/ */
@GET @GET
@Path("{username: [a-zA-Z0-9_]+}") @Path("{username: [a-zA-Z0-9_]+}")
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
public Response view(@PathParam("username") String username) throws JSONException { public Response view(@PathParam("username") String username) {
if (!authenticate()) { if (!authenticate()) {
throw new ForbiddenClientException(); throw new ForbiddenClientException();
} }
checkBaseFunction(BaseFunction.ADMIN); checkBaseFunction(BaseFunction.ADMIN);
JSONObject response = new JSONObject();
UserDao userDao = new UserDao(); UserDao userDao = new UserDao();
User user = userDao.getActiveByUsername(username); User user = userDao.getActiveByUsername(username);
if (user == null) { if (user == null) {
throw new ClientException("UserNotFound", "The user doesn't exist"); throw new ClientException("UserNotFound", "The user doesn't exist");
} }
response.put("username", user.getUsername()); JsonObjectBuilder response = Json.createObjectBuilder()
response.put("email", user.getEmail()); .add("username", user.getUsername())
response.put("theme", user.getTheme()); .add("email", user.getEmail());
response.put("locale", user.getLocaleId()); return Response.ok().entity(response.build()).build();
return Response.ok().entity(response).build();
} }
/** /**
@ -506,53 +452,47 @@ public class UserResource extends BaseResource {
* @param sortColumn Sort index * @param sortColumn Sort index
* @param asc If true, ascending sorting, else descending * @param asc If true, ascending sorting, else descending
* @return Response * @return Response
* @throws JSONException
*/ */
@GET @GET
@Path("list") @Path("list")
@Produces(MediaType.APPLICATION_JSON)
public Response list( public Response list(
@QueryParam("limit") Integer limit, @QueryParam("limit") Integer limit,
@QueryParam("offset") Integer offset, @QueryParam("offset") Integer offset,
@QueryParam("sort_column") Integer sortColumn, @QueryParam("sort_column") Integer sortColumn,
@QueryParam("asc") Boolean asc) throws JSONException { @QueryParam("asc") Boolean asc) {
if (!authenticate()) { if (!authenticate()) {
throw new ForbiddenClientException(); throw new ForbiddenClientException();
} }
checkBaseFunction(BaseFunction.ADMIN); checkBaseFunction(BaseFunction.ADMIN);
JSONObject response = new JSONObject(); JsonArrayBuilder users = Json.createArrayBuilder();
List<JSONObject> users = new ArrayList<>();
PaginatedList<UserDto> paginatedList = PaginatedLists.create(limit, offset); PaginatedList<UserDto> paginatedList = PaginatedLists.create(limit, offset);
SortCriteria sortCriteria = new SortCriteria(sortColumn, asc); SortCriteria sortCriteria = new SortCriteria(sortColumn, asc);
UserDao userDao = new UserDao(); UserDao userDao = new UserDao();
userDao.findByCriteria(paginatedList, new UserCriteria(), sortCriteria); userDao.findByCriteria(paginatedList, new UserCriteria(), sortCriteria);
for (UserDto userDto : paginatedList.getResultList()) { for (UserDto userDto : paginatedList.getResultList()) {
JSONObject user = new JSONObject(); users.add(Json.createObjectBuilder()
user.put("id", userDto.getId()); .add("id", userDto.getId())
user.put("username", userDto.getUsername()); .add("username", userDto.getUsername())
user.put("email", userDto.getEmail()); .add("email", userDto.getEmail())
user.put("create_date", userDto.getCreateTimestamp()); .add("create_date", userDto.getCreateTimestamp()));
users.add(user);
} }
response.put("total", paginatedList.getResultCount());
response.put("users", users);
return Response.ok().entity(response).build(); JsonObjectBuilder response = Json.createObjectBuilder()
.add("total", paginatedList.getResultCount())
.add("users", users);
return Response.ok().entity(response.build()).build();
} }
/** /**
* Returns all active sessions. * Returns all active sessions.
* *
* @return Response * @return Response
* @throws JSONException
*/ */
@GET @GET
@Path("session") @Path("session")
@Produces(MediaType.APPLICATION_JSON) public Response session() {
public Response session() throws JSONException {
if (!authenticate()) { if (!authenticate()) {
throw new ForbiddenClientException(); throw new ForbiddenClientException();
} }
@ -567,37 +507,34 @@ public class UserResource extends BaseResource {
} }
} }
JSONObject response = new JSONObject(); JsonArrayBuilder sessions = Json.createArrayBuilder();
List<JSONObject> sessions = new ArrayList<>();
AuthenticationTokenDao authenticationTokenDao = new AuthenticationTokenDao(); AuthenticationTokenDao authenticationTokenDao = new AuthenticationTokenDao();
for (AuthenticationToken authenticationToken : authenticationTokenDao.getByUserId(principal.getId())) { for (AuthenticationToken authenticationToken : authenticationTokenDao.getByUserId(principal.getId())) {
JSONObject session = new JSONObject(); JsonObjectBuilder session = Json.createObjectBuilder()
session.put("create_date", authenticationToken.getCreationDate().getTime()); .add("create_date", authenticationToken.getCreationDate().getTime())
session.put("ip", authenticationToken.getIp()); .add("ip", authenticationToken.getIp())
session.put("user_agent", authenticationToken.getUserAgent()); .add("user_agent", authenticationToken.getUserAgent());
if (authenticationToken.getLastConnectionDate() != null) { if (authenticationToken.getLastConnectionDate() != null) {
session.put("last_connection_date", authenticationToken.getLastConnectionDate().getTime()); session.add("last_connection_date", authenticationToken.getLastConnectionDate().getTime());
} }
session.put("current", authenticationToken.getId().equals(authToken)); session.add("current", authenticationToken.getId().equals(authToken));
sessions.add(session); sessions.add(session);
} }
response.put("sessions", sessions);
return Response.ok().entity(response).build(); JsonObjectBuilder response = Json.createObjectBuilder()
.add("sessions", sessions);
return Response.ok().entity(response.build()).build();
} }
/** /**
* Deletes all active sessions except the one used for this request. * Deletes all active sessions except the one used for this request.
* *
* @return Response * @return Response
* @throws JSONException
*/ */
@DELETE @DELETE
@Path("session") @Path("session")
@Produces(MediaType.APPLICATION_JSON) public Response deleteSession() {
public Response deleteSession() throws JSONException {
if (!authenticate()) { if (!authenticate()) {
throw new ForbiddenClientException(); throw new ForbiddenClientException();
} }
@ -616,9 +553,9 @@ public class UserResource extends BaseResource {
AuthenticationTokenDao authenticationTokenDao = new AuthenticationTokenDao(); AuthenticationTokenDao authenticationTokenDao = new AuthenticationTokenDao();
authenticationTokenDao.deleteByUserId(principal.getId(), authToken); authenticationTokenDao.deleteByUserId(principal.getId(), authToken);
// Always return ok // Always return OK
JSONObject response = new JSONObject(); JsonObjectBuilder response = Json.createObjectBuilder()
response.put("status", "ok"); .add("status", "ok");
return Response.ok().entity(response).build(); return Response.ok().entity(response.build()).build();
} }
} }

View File

@ -6,10 +6,11 @@
version="3.0"> version="3.0">
<display-name>Docs</display-name> <display-name>Docs</display-name>
<!-- This filter is used to secure URLs --> <!-- This filter is used to process a couple things in the request context -->
<filter> <filter>
<filter-name>requestContextFilter</filter-name> <filter-name>requestContextFilter</filter-name>
<filter-class>com.sismics.util.filter.RequestContextFilter</filter-class> <filter-class>com.sismics.util.filter.RequestContextFilter</filter-class>
<async-supported>true</async-supported>
</filter> </filter>
<filter-mapping> <filter-mapping>
@ -22,6 +23,7 @@
<filter> <filter>
<filter-name>tokenBasedSecurityFilter</filter-name> <filter-name>tokenBasedSecurityFilter</filter-name>
<filter-class>com.sismics.util.filter.TokenBasedSecurityFilter</filter-class> <filter-class>com.sismics.util.filter.TokenBasedSecurityFilter</filter-class>
<async-supported>true</async-supported>
</filter> </filter>
<filter-mapping> <filter-mapping>
@ -29,23 +31,28 @@
<url-pattern>/api/*</url-pattern> <url-pattern>/api/*</url-pattern>
</filter-mapping> </filter-mapping>
<!-- Welcome files -->
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
<!-- Jersey --> <!-- Jersey -->
<servlet> <servlet>
<servlet-name>Jersey REST Service</servlet-name> <servlet-name>JerseyServlet</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class> <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param> <init-param>
<param-name>com.sun.jersey.config.property.packages</param-name> <param-name>jersey.config.server.provider.packages</param-name>
<param-value>com.sismics.docs.rest.resource</param-value> <param-value>com.sismics.docs.rest.resource</param-value>
</init-param> </init-param>
<init-param>
<param-name>jersey.config.server.provider.classnames</param-name>
<param-value>org.glassfish.jersey.media.multipart.MultiPartFeature</param-value>
</init-param>
<init-param>
<param-name>jersey.config.server.response.setStatusOverSendError</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>1</load-on-startup> <load-on-startup>1</load-on-startup>
<async-supported>true</async-supported>
</servlet> </servlet>
<servlet-mapping> <servlet-mapping>
<servlet-name>Jersey REST Service</servlet-name> <servlet-name>JerseyServlet</servlet-name>
<url-pattern>/api/*</url-pattern> <url-pattern>/api/*</url-pattern>
</servlet-mapping> </servlet-mapping>
</web-app> </web-app>

View File

@ -1,3 +1,3 @@
api.current_version=${project.version} api.current_version=${project.version}
api.min_version=1.0 api.min_version=1.0
db.version=0 db.version=1

View File

@ -1,3 +1,3 @@
api.current_version=${project.version} api.current_version=${project.version}
api.min_version=1.0 api.min_version=1.0
db.version=0 db.version=1

View File

@ -2,18 +2,18 @@ package com.sismics.docs.rest;
import java.util.Date; import java.util.Date;
import junit.framework.Assert; import javax.json.JsonArray;
import javax.json.JsonObject;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.Form;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import org.codehaus.jettison.json.JSONArray; import org.junit.Assert;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
import org.junit.Test; import org.junit.Test;
import com.sismics.docs.rest.filter.CookieAuthenticationFilter; import com.sismics.util.filter.TokenBasedSecurityFilter;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.ClientResponse.Status;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.core.util.MultivaluedMapImpl;
/** /**
* Test the ACL resource. * Test the ACL resource.
@ -27,7 +27,7 @@ public class TestAclResource extends BaseJerseyTest {
* @throws JSONException * @throws JSONException
*/ */
@Test @Test
public void testAclResource() throws JSONException { public void testAclResource() {
// Login acl1 // Login acl1
clientUtil.createUser("acl1"); clientUtil.createUser("acl1");
String acl1Token = clientUtil.login("acl1"); String acl1Token = clientUtil.login("acl1");
@ -37,141 +37,118 @@ public class TestAclResource extends BaseJerseyTest {
String acl2Token = clientUtil.login("acl2"); String acl2Token = clientUtil.login("acl2");
// Create a document // Create a document
WebResource documentResource = resource().path("/document"); JsonObject json = target().path("/document").request()
documentResource.addFilter(new CookieAuthenticationFilter(acl1Token)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, acl1Token)
MultivaluedMapImpl postParams = new MultivaluedMapImpl(); .put(Entity.form(new Form()
postParams.add("title", "My super title document 1"); .param("title", "My super title document 1")
postParams.add("language", "eng"); .param("language", "eng")
postParams.add("create_date", new Date().getTime()); .param("create_date", Long.toString(new Date().getTime()))), JsonObject.class);
ClientResponse response = documentResource.put(ClientResponse.class, postParams); String document1Id = json.getString("id");
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
JSONObject json = response.getEntity(JSONObject.class);
String document1Id = json.optString("id");
// Get the document as acl1 // Get the document as acl1
documentResource = resource().path("/document/" + document1Id); json = target().path("/document/" + document1Id).request()
documentResource.addFilter(new CookieAuthenticationFilter(acl1Token)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, acl1Token)
response = documentResource.get(ClientResponse.class); .get(JsonObject.class);
json = response.getEntity(JSONObject.class);
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
Assert.assertEquals(document1Id, json.getString("id")); Assert.assertEquals(document1Id, json.getString("id"));
JSONArray acls = json.getJSONArray("acls"); JsonArray acls = json.getJsonArray("acls");
Assert.assertEquals(2, acls.length()); Assert.assertEquals(2, acls.size());
// Get the document as acl2 // Get the document as acl2
documentResource = resource().path("/document/" + document1Id); Response response = target().path("/document/" + document1Id).request()
documentResource.addFilter(new CookieAuthenticationFilter(acl2Token)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, acl2Token)
response = documentResource.get(ClientResponse.class); .get();
json = response.getEntity(JSONObject.class);
Assert.assertEquals(Status.FORBIDDEN, Status.fromStatusCode(response.getStatus())); Assert.assertEquals(Status.FORBIDDEN, Status.fromStatusCode(response.getStatus()));
// Add an ACL READ for acl2 with acl1 // Add an ACL READ for acl2 with acl1
WebResource aclResource = resource().path("/acl"); json = target().path("/acl").request()
aclResource.addFilter(new CookieAuthenticationFilter(acl1Token)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, acl1Token)
postParams = new MultivaluedMapImpl(); .put(Entity.form(new Form()
postParams.add("source", document1Id); .param("source", document1Id)
postParams.add("perm", "READ"); .param("perm", "READ")
postParams.add("username", "acl2"); .param("username", "acl2")), JsonObject.class);
response = aclResource.put(ClientResponse.class, postParams);
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
json = response.getEntity(JSONObject.class);
String acl2Id = json.getString("id"); String acl2Id = json.getString("id");
// Add an ACL WRITE for acl2 with acl1 // Add an ACL WRITE for acl2 with acl1
aclResource = resource().path("/acl"); json = target().path("/acl").request()
aclResource.addFilter(new CookieAuthenticationFilter(acl1Token)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, acl1Token)
postParams = new MultivaluedMapImpl(); .put(Entity.form(new Form()
postParams.add("source", document1Id); .param("source", document1Id)
postParams.add("perm", "WRITE"); .param("perm", "WRITE")
postParams.add("username", "acl2"); .param("username", "acl2")), JsonObject.class);
response = aclResource.put(ClientResponse.class, postParams);
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
// Add an ACL WRITE for acl2 with acl1 (again) // Add an ACL WRITE for acl2 with acl1 (again)
aclResource = resource().path("/acl"); json = target().path("/acl").request()
aclResource.addFilter(new CookieAuthenticationFilter(acl1Token)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, acl1Token)
postParams = new MultivaluedMapImpl(); .put(Entity.form(new Form()
postParams.add("source", document1Id); .param("source", document1Id)
postParams.add("perm", "WRITE"); .param("perm", "WRITE")
postParams.add("username", "acl2"); .param("username", "acl2")), JsonObject.class);
response = aclResource.put(ClientResponse.class, postParams);
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
// Get the document as acl1 // Get the document as acl1
documentResource = resource().path("/document/" + document1Id); json = target().path("/document/" + document1Id).request()
documentResource.addFilter(new CookieAuthenticationFilter(acl1Token)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, acl1Token)
response = documentResource.get(ClientResponse.class); .get(JsonObject.class);
json = response.getEntity(JSONObject.class);
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
Assert.assertEquals(document1Id, json.getString("id")); Assert.assertEquals(document1Id, json.getString("id"));
acls = json.getJSONArray("acls"); acls = json.getJsonArray("acls");
Assert.assertEquals(4, acls.length()); Assert.assertEquals(4, acls.size());
// Get the document as acl2 // Get the document as acl2
documentResource = resource().path("/document/" + document1Id); json = target().path("/document/" + document1Id).request()
documentResource.addFilter(new CookieAuthenticationFilter(acl2Token)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, acl2Token)
response = documentResource.get(ClientResponse.class); .get(JsonObject.class);
json = response.getEntity(JSONObject.class);
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
Assert.assertEquals(document1Id, json.getString("id")); Assert.assertEquals(document1Id, json.getString("id"));
acls = json.getJSONArray("acls"); acls = json.getJsonArray("acls");
Assert.assertEquals(4, acls.length()); Assert.assertEquals(4, acls.size());
// Delete the ACL WRITE for acl2 with acl2 // Delete the ACL WRITE for acl2 with acl2
aclResource = resource().path("/acl/" + document1Id + "/WRITE/" + acl2Id); target().path("/acl/" + document1Id + "/WRITE/" + acl2Id).request()
aclResource.addFilter(new CookieAuthenticationFilter(acl2Token)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, acl2Token)
response = aclResource.delete(ClientResponse.class); .delete();
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
// Delete the ACL READ for acl2 with acl2 // Delete the ACL READ for acl2 with acl2
aclResource = resource().path("/acl/" + document1Id + "/READ/" + acl2Id); target().path("/acl/" + document1Id + "/READ/" + acl2Id).request()
aclResource.addFilter(new CookieAuthenticationFilter(acl2Token)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, acl2Token)
response = aclResource.delete(ClientResponse.class); .delete();
Assert.assertEquals(Status.FORBIDDEN, Status.fromStatusCode(response.getStatus()));
// Delete the ACL READ for acl2 with acl1 // Delete the ACL READ for acl2 with acl1
aclResource = resource().path("/acl/" + document1Id + "/READ/" + acl2Id); target().path("/acl/" + document1Id + "/READ/" + acl2Id).request()
aclResource.addFilter(new CookieAuthenticationFilter(acl1Token)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, acl1Token)
response = aclResource.delete(ClientResponse.class); .delete();
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
// Get the document as acl1 // Get the document as acl1
documentResource = resource().path("/document/" + document1Id); json = target().path("/document/" + document1Id).request()
documentResource.addFilter(new CookieAuthenticationFilter(acl1Token)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, acl1Token)
response = documentResource.get(ClientResponse.class); .get(JsonObject.class);
json = response.getEntity(JSONObject.class);
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
Assert.assertEquals(document1Id, json.getString("id")); Assert.assertEquals(document1Id, json.getString("id"));
acls = json.getJSONArray("acls"); acls = json.getJsonArray("acls");
Assert.assertEquals(2, acls.length()); Assert.assertEquals(2, acls.size());
String acl1Id = acls.getJSONObject(0).getString("id"); String acl1Id = acls.getJsonObject(0).getString("id");
// Get the document as acl2 // Get the document as acl2
documentResource = resource().path("/document/" + document1Id); response = target().path("/document/" + document1Id).request()
documentResource.addFilter(new CookieAuthenticationFilter(acl2Token)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, acl2Token)
response = documentResource.get(ClientResponse.class); .get();
json = response.getEntity(JSONObject.class);
Assert.assertEquals(Status.FORBIDDEN, Status.fromStatusCode(response.getStatus())); Assert.assertEquals(Status.FORBIDDEN, Status.fromStatusCode(response.getStatus()));
// Delete the ACL READ for acl1 with acl1 // Delete the ACL READ for acl1 with acl1
aclResource = resource().path("/acl/" + document1Id + "/READ/" + acl1Id); response = target().path("/acl/" + document1Id + "/READ/" + acl1Id).request()
aclResource.addFilter(new CookieAuthenticationFilter(acl1Token)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, acl1Token)
response = aclResource.delete(ClientResponse.class); .delete();
Assert.assertEquals(Status.BAD_REQUEST, Status.fromStatusCode(response.getStatus())); Assert.assertEquals(Status.BAD_REQUEST, Status.fromStatusCode(response.getStatus()));
// Delete the ACL WRITE for acl1 with acl1 // Delete the ACL WRITE for acl1 with acl1
aclResource = resource().path("/acl/" + document1Id + "/WRITE/" + acl1Id); response = target().path("/acl/" + document1Id + "/WRITE/" + acl1Id).request()
aclResource.addFilter(new CookieAuthenticationFilter(acl1Token)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, acl1Token)
response = aclResource.delete(ClientResponse.class); .delete();
Assert.assertEquals(Status.BAD_REQUEST, Status.fromStatusCode(response.getStatus())); Assert.assertEquals(Status.BAD_REQUEST, Status.fromStatusCode(response.getStatus()));
// Search target list // Search target list
aclResource = resource().path("/acl/target/search"); json = target().path("/acl/target/search")
aclResource.addFilter(new CookieAuthenticationFilter(acl1Token)); .queryParam("search", "acl")
response = aclResource.queryParam("search", "acl").get(ClientResponse.class); .request()
json = response.getEntity(JSONObject.class); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, acl1Token)
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); .get(JsonObject.class);
JSONArray users = json.getJSONArray("users"); JsonArray users = json.getJsonArray("users");
Assert.assertEquals(2, users.length()); Assert.assertEquals(2, users.size());
} }
} }

View File

@ -1,15 +1,18 @@
package com.sismics.docs.rest; package com.sismics.docs.rest;
import com.sismics.docs.rest.filter.CookieAuthenticationFilter; import javax.json.JsonArray;
import com.sun.jersey.api.client.ClientResponse; import javax.json.JsonObject;
import com.sun.jersey.api.client.ClientResponse.Status; import javax.ws.rs.client.Entity;
import com.sun.jersey.api.client.WebResource; import javax.ws.rs.core.Form;
import junit.framework.Assert; import javax.ws.rs.core.Response;
import org.codehaus.jettison.json.JSONArray; import javax.ws.rs.core.Response.Status;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import com.sismics.util.filter.TokenBasedSecurityFilter;
/** /**
* Test the app resource. * Test the app resource.
* *
@ -22,36 +25,33 @@ public class TestAppResource extends BaseJerseyTest {
* @throws JSONException * @throws JSONException
*/ */
@Test @Test
public void testAppResource() throws JSONException { public void testAppResource() {
// Login admin // Login admin
String adminAuthenticationToken = clientUtil.login("admin", "admin", false); String adminAuthenticationToken = clientUtil.login("admin", "admin", false);
// Check the application info // Check the application info
WebResource appResource = resource().path("/app"); JsonObject json = target().path("/app").request()
appResource.addFilter(new CookieAuthenticationFilter(adminAuthenticationToken)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminAuthenticationToken)
ClientResponse response = appResource.get(ClientResponse.class); .get(JsonObject.class);
response = appResource.get(ClientResponse.class);
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
JSONObject json = response.getEntity(JSONObject.class);
String currentVersion = json.getString("current_version"); String currentVersion = json.getString("current_version");
Assert.assertNotNull(currentVersion); Assert.assertNotNull(currentVersion);
String minVersion = json.getString("min_version"); String minVersion = json.getString("min_version");
Assert.assertNotNull(minVersion); Assert.assertNotNull(minVersion);
Long freeMemory = json.getLong("free_memory"); Long freeMemory = json.getJsonNumber("free_memory").longValue();
Assert.assertTrue(freeMemory > 0); Assert.assertTrue(freeMemory > 0);
Long totalMemory = json.getLong("total_memory"); Long totalMemory = json.getJsonNumber("total_memory").longValue();
Assert.assertTrue(totalMemory > 0 && totalMemory > freeMemory); Assert.assertTrue(totalMemory > 0 && totalMemory > freeMemory);
// Rebuild Lucene index // Rebuild Lucene index
appResource = resource().path("/app/batch/reindex"); Response response = target().path("/app/batch/reindex").request()
appResource.addFilter(new CookieAuthenticationFilter(adminAuthenticationToken)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminAuthenticationToken)
response = appResource.post(ClientResponse.class); .post(Entity.form(new Form()));
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
// Clean storage // Clean storage
appResource = resource().path("/app/batch/clean_storage"); response = target().path("/app/batch/clean_storage").request()
appResource.addFilter(new CookieAuthenticationFilter(adminAuthenticationToken)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminAuthenticationToken)
response = appResource.post(ClientResponse.class); .post(Entity.form(new Form()));
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
} }
@ -61,39 +61,33 @@ public class TestAppResource extends BaseJerseyTest {
* @throws JSONException * @throws JSONException
*/ */
@Test @Test
public void testLogResource() throws JSONException { public void testLogResource() {
// Login admin // Login admin
String adminAuthenticationToken = clientUtil.login("admin", "admin", false); String adminAuthenticationToken = clientUtil.login("admin", "admin", false);
// Check the logs (page 1) // Check the logs (page 1)
WebResource appResource = resource() JsonObject json = target().path("/app/log")
.path("/app/log") .queryParam("level", "DEBUG")
.queryParam("level", "DEBUG"); .request()
ClientResponse response = appResource.get(ClientResponse.class); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminAuthenticationToken)
appResource.addFilter(new CookieAuthenticationFilter(adminAuthenticationToken)); .get(JsonObject.class);
response = appResource.get(ClientResponse.class); JsonArray logs = json.getJsonArray("logs");
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); Assert.assertTrue(logs.size() > 0);
JSONObject json = response.getEntity(JSONObject.class); Long date1 = logs.getJsonObject(0).getJsonNumber("date").longValue();
JSONArray logs = json.getJSONArray("logs"); Long date2 = logs.getJsonObject(9).getJsonNumber("date").longValue();
Assert.assertTrue(logs.length() > 0); Assert.assertTrue(date1 >= date2);
Long date1 = logs.optJSONObject(0).optLong("date");
Long date2 = logs.optJSONObject(9).optLong("date");
Assert.assertTrue(date1 > date2);
// Check the logs (page 2) // Check the logs (page 2)
appResource = resource() json = target().path("/app/log")
.path("/app/log")
.queryParam("offset", "10") .queryParam("offset", "10")
.queryParam("level", "DEBUG"); .queryParam("level", "DEBUG")
response = appResource.get(ClientResponse.class); .request()
appResource.addFilter(new CookieAuthenticationFilter(adminAuthenticationToken)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminAuthenticationToken)
response = appResource.get(ClientResponse.class); .get(JsonObject.class);
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); logs = json.getJsonArray("logs");
json = response.getEntity(JSONObject.class); Assert.assertTrue(logs.size() > 0);
logs = json.getJSONArray("logs"); Long date3 = logs.getJsonObject(0).getJsonNumber("date").longValue();
Assert.assertTrue(logs.length() > 0); Long date4 = logs.getJsonObject(9).getJsonNumber("date").longValue();
Long date3 = logs.optJSONObject(0).optLong("date"); Assert.assertTrue(date3 >= date4);
Long date4 = logs.optJSONObject(9).optLong("date");
Assert.assertTrue(date3 > date4);
} }
} }

View File

@ -2,19 +2,17 @@ package com.sismics.docs.rest;
import java.util.Date; import java.util.Date;
import com.sismics.docs.rest.filter.CookieAuthenticationFilter; import javax.json.JsonArray;
import com.sun.jersey.api.client.ClientResponse; import javax.json.JsonObject;
import com.sun.jersey.api.client.ClientResponse.Status; import javax.ws.rs.client.Entity;
import com.sun.jersey.api.client.WebResource; import javax.ws.rs.core.Form;
import com.sun.jersey.core.util.MultivaluedMapImpl;
import junit.framework.Assert; import org.junit.Assert;
import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
import org.junit.Test; import org.junit.Test;
import com.sismics.util.filter.TokenBasedSecurityFilter;
/** /**
* Test the audit log resource. * Test the audit log resource.
* *
@ -27,72 +25,60 @@ public class TestAuditLogResource extends BaseJerseyTest {
* @throws JSONException * @throws JSONException
*/ */
@Test @Test
public void testAuditLogResource() throws JSONException { public void testAuditLogResource() {
// Login auditlog1 // Login auditlog1
clientUtil.createUser("auditlog1"); clientUtil.createUser("auditlog1");
String auditlog1Token = clientUtil.login("auditlog1"); String auditlog1Token = clientUtil.login("auditlog1");
// Create a tag // Create a tag
WebResource tagResource = resource().path("/tag"); JsonObject json = target().path("/tag").request()
tagResource.addFilter(new CookieAuthenticationFilter(auditlog1Token)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, auditlog1Token)
MultivaluedMapImpl postParams = new MultivaluedMapImpl(); .put(Entity.form(new Form()
postParams.add("name", "SuperTag"); .param("name", "SuperTag")
postParams.add("color", "#ffff00"); .param("color", "#ffff00")), JsonObject.class);
ClientResponse response = tagResource.put(ClientResponse.class, postParams); String tag1Id = json.getString("id");
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
JSONObject json = response.getEntity(JSONObject.class);
String tag1Id = json.optString("id");
Assert.assertNotNull(tag1Id); Assert.assertNotNull(tag1Id);
// Create a document // Create a document
WebResource documentResource = resource().path("/document");
documentResource.addFilter(new CookieAuthenticationFilter(auditlog1Token));
postParams = new MultivaluedMapImpl();
postParams.add("title", "My super title document 1");
postParams.add("description", "My super description for document 1");
postParams.add("tags", tag1Id);
postParams.add("language", "eng");
long create1Date = new Date().getTime(); long create1Date = new Date().getTime();
postParams.add("create_date", create1Date); json = target().path("/document").request()
response = documentResource.put(ClientResponse.class, postParams); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, auditlog1Token)
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); .put(Entity.form(new Form()
json = response.getEntity(JSONObject.class); .param("title", "My super title document 1")
String document1Id = json.optString("id"); .param("description", "My super description for document 1")
.param("tags", tag1Id)
.param("language", "eng")
.param("create_date", Long.toString(create1Date))), JsonObject.class);
String document1Id = json.getString("id");
Assert.assertNotNull(document1Id); Assert.assertNotNull(document1Id);
// Get all logs for the document // Get all logs for the document
WebResource auditLogResource = resource().path("/auditlog"); json = target().path("/auditlog")
auditLogResource.addFilter(new CookieAuthenticationFilter(auditlog1Token)); .queryParam("document", document1Id)
response = auditLogResource.queryParam("document", document1Id).get(ClientResponse.class); .request()
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, auditlog1Token)
json = response.getEntity(JSONObject.class); .get(JsonObject.class);
JSONArray logs = json.getJSONArray("logs"); JsonArray logs = json.getJsonArray("logs");
Assert.assertTrue(logs.length() == 3); Assert.assertTrue(logs.size() == 3);
// Get all logs for the current user // Get all logs for the current user
auditLogResource = resource().path("/auditlog"); json = target().path("/auditlog").request()
auditLogResource.addFilter(new CookieAuthenticationFilter(auditlog1Token)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, auditlog1Token)
response = auditLogResource.get(ClientResponse.class); .get(JsonObject.class);
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); logs = json.getJsonArray("logs");
json = response.getEntity(JSONObject.class); Assert.assertTrue(logs.size() == 3);
logs = json.getJSONArray("logs");
Assert.assertTrue(logs.length() == 3);
// Deletes a tag // Deletes a tag
tagResource = resource().path("/tag/" + tag1Id); json = target().path("/tag/" + tag1Id).request()
tagResource.addFilter(new CookieAuthenticationFilter(auditlog1Token)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, auditlog1Token)
response = tagResource.delete(ClientResponse.class); .delete(JsonObject.class);
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
json = response.getEntity(JSONObject.class);
Assert.assertEquals("ok", json.getString("status")); Assert.assertEquals("ok", json.getString("status"));
// Get all logs for the current user // Get all logs for the current user
auditLogResource = resource().path("/auditlog"); json = target().path("/auditlog").request()
auditLogResource.addFilter(new CookieAuthenticationFilter(auditlog1Token)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, auditlog1Token)
response = auditLogResource.get(ClientResponse.class); .get(JsonObject.class);
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); logs = json.getJsonArray("logs");
json = response.getEntity(JSONObject.class); Assert.assertTrue(logs.size() == 4);
logs = json.getJSONArray("logs");
Assert.assertTrue(logs.length() == 4);
} }
} }

View File

@ -1,31 +1,32 @@
package com.sismics.docs.rest; package com.sismics.docs.rest;
import java.io.BufferedInputStream;
import java.io.InputStream; import java.io.InputStream;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.Date; import java.util.Date;
import javax.json.JsonArray;
import javax.json.JsonObject;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.Form;
import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import junit.framework.Assert; import org.glassfish.jersey.media.multipart.FormDataMultiPart;
import org.glassfish.jersey.media.multipart.MultiPartFeature;
import org.codehaus.jettison.json.JSONArray; import org.glassfish.jersey.media.multipart.file.StreamDataBodyPart;
import org.codehaus.jettison.json.JSONObject;
import org.joda.time.format.DateTimeFormat; import org.joda.time.format.DateTimeFormat;
import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import com.google.common.io.ByteStreams; import com.google.common.io.ByteStreams;
import com.google.common.io.Resources;
import com.sismics.docs.core.util.DirectoryUtil; import com.sismics.docs.core.util.DirectoryUtil;
import com.sismics.docs.rest.filter.CookieAuthenticationFilter; import com.sismics.util.filter.TokenBasedSecurityFilter;
import com.sismics.util.mime.MimeType; import com.sismics.util.mime.MimeType;
import com.sismics.util.mime.MimeTypeUtil; import com.sismics.util.mime.MimeTypeUtil;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.ClientResponse.Status;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.core.util.MultivaluedMapImpl;
import com.sun.jersey.multipart.FormDataBodyPart;
import com.sun.jersey.multipart.FormDataMultiPart;
/** /**
* Exhaustive test of the document resource. * Exhaustive test of the document resource.
@ -35,6 +36,7 @@ import com.sun.jersey.multipart.FormDataMultiPart;
public class TestDocumentResource extends BaseJerseyTest { public class TestDocumentResource extends BaseJerseyTest {
/** /**
* Test the document resource. * Test the document resource.
*
* @throws Exception * @throws Exception
*/ */
@Test @Test
@ -48,131 +50,113 @@ public class TestDocumentResource extends BaseJerseyTest {
String document3Token = clientUtil.login("document3"); String document3Token = clientUtil.login("document3");
// Create a tag // Create a tag
WebResource tagResource = resource().path("/tag"); JsonObject json = target().path("/tag").request()
tagResource.addFilter(new CookieAuthenticationFilter(document1Token)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, document1Token)
MultivaluedMapImpl postParams = new MultivaluedMapImpl(); .put(Entity.form(new Form()
postParams.add("name", "SuperTag"); .param("name", "SuperTag")
postParams.add("color", "#ffff00"); .param("color", "#ffff00")), JsonObject.class);
ClientResponse response = tagResource.put(ClientResponse.class, postParams); String tag1Id = json.getString("id");
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
JSONObject json = response.getEntity(JSONObject.class);
String tag1Id = json.optString("id");
Assert.assertNotNull(tag1Id); Assert.assertNotNull(tag1Id);
// Create a document // Create a document
WebResource documentResource = resource().path("/document");
documentResource.addFilter(new CookieAuthenticationFilter(document1Token));
postParams = new MultivaluedMapImpl();
postParams.add("title", "My super title document 1");
postParams.add("description", "My super description for document 1");
postParams.add("tags", tag1Id);
postParams.add("language", "eng");
long create1Date = new Date().getTime(); long create1Date = new Date().getTime();
postParams.add("create_date", create1Date); json = target().path("/document").request()
response = documentResource.put(ClientResponse.class, postParams); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, document1Token)
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); .put(Entity.form(new Form()
json = response.getEntity(JSONObject.class); .param("title", "My super title document 1")
String document1Id = json.optString("id"); .param("description", "My super description for document 1")
.param("tags", tag1Id)
.param("language", "eng")
.param("create_date", Long.toString(create1Date))), JsonObject.class);
String document1Id = json.getString("id");
Assert.assertNotNull(document1Id); Assert.assertNotNull(document1Id);
// Add a file // Add a file
WebResource fileResource = resource().path("/file"); String file1Id = null;
fileResource.addFilter(new CookieAuthenticationFilter(document1Token)); try (InputStream is = Resources.getResource("file/Einstein-Roosevelt-letter.png").openStream()) {
FormDataMultiPart form = new FormDataMultiPart(); StreamDataBodyPart streamDataBodyPart = new StreamDataBodyPart("file", is, "Einstein-Roosevelt-letter.png");
InputStream file = this.getClass().getResourceAsStream("/file/Einstein-Roosevelt-letter.png"); try (FormDataMultiPart multiPart = new FormDataMultiPart()) {
FormDataBodyPart fdp = new FormDataBodyPart("file", json = target()
new BufferedInputStream(file), .register(MultiPartFeature.class)
MediaType.APPLICATION_OCTET_STREAM_TYPE); .path("/file").request()
form.bodyPart(fdp); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, document1Token)
form.field("id", document1Id); .put(Entity.entity(multiPart.field("id", document1Id).bodyPart(streamDataBodyPart),
response = fileResource.type(MediaType.MULTIPART_FORM_DATA).put(ClientResponse.class, form); MediaType.MULTIPART_FORM_DATA_TYPE), JsonObject.class);
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); file1Id = json.getString("id");
json = response.getEntity(JSONObject.class); Assert.assertNotNull(file1Id);
String file1Id = json.getString("id"); }
}
// Share this document // Share this document
WebResource fileShareResource = resource().path("/share"); json = target().path("/share").request()
fileShareResource.addFilter(new CookieAuthenticationFilter(document1Token)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, document1Token)
postParams = new MultivaluedMapImpl(); .put(Entity.form(new Form().param("id", document1Id)), JsonObject.class);
postParams.add("id", document1Id);
response = fileShareResource.put(ClientResponse.class, postParams);
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
json = response.getEntity(JSONObject.class);
// List all documents // List all documents
documentResource = resource().path("/document/list"); json = target().path("/document/list")
documentResource.addFilter(new CookieAuthenticationFilter(document1Token)); .queryParam("sort_column", 3)
MultivaluedMapImpl getParams = new MultivaluedMapImpl(); .queryParam("asc", false)
getParams.putSingle("sort_column", 3); .request()
getParams.putSingle("asc", false); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, document1Token)
response = documentResource.queryParams(getParams).get(ClientResponse.class); .get(JsonObject.class);
json = response.getEntity(JSONObject.class); JsonArray documents = json.getJsonArray("documents");
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); JsonArray tags = documents.getJsonObject(0).getJsonArray("tags");
JSONArray documents = json.getJSONArray("documents"); Assert.assertTrue(documents.size() == 1);
JSONArray tags = documents.getJSONObject(0).getJSONArray("tags"); Assert.assertEquals(document1Id, documents.getJsonObject(0).getString("id"));
Assert.assertTrue(documents.length() == 1); Assert.assertEquals("eng", documents.getJsonObject(0).getString("language"));
Assert.assertEquals(document1Id, documents.getJSONObject(0).getString("id")); Assert.assertEquals(1, documents.getJsonObject(0).getInt("file_count"));
Assert.assertEquals("eng", documents.getJSONObject(0).getString("language")); Assert.assertEquals(1, tags.size());
Assert.assertEquals(1, documents.getJSONObject(0).getInt("file_count")); Assert.assertEquals(tag1Id, tags.getJsonObject(0).getString("id"));
Assert.assertEquals(1, tags.length()); Assert.assertEquals("SuperTag", tags.getJsonObject(0).getString("name"));
Assert.assertEquals(tag1Id, tags.getJSONObject(0).getString("id")); Assert.assertEquals("#ffff00", tags.getJsonObject(0).getString("color"));
Assert.assertEquals("SuperTag", tags.getJSONObject(0).getString("name"));
Assert.assertEquals("#ffff00", tags.getJSONObject(0).getString("color"));
// List all documents from document3 // List all documents from document3
documentResource = resource().path("/document/list"); json = target().path("/document/list")
documentResource.addFilter(new CookieAuthenticationFilter(document3Token)); .queryParam("sort_column", 3)
getParams = new MultivaluedMapImpl(); .queryParam("asc", false)
getParams.putSingle("sort_column", 3); .request()
getParams.putSingle("asc", false); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, document3Token)
response = documentResource.queryParams(getParams).get(ClientResponse.class); .get(JsonObject.class);
json = response.getEntity(JSONObject.class); documents = json.getJsonArray("documents");
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); Assert.assertTrue(documents.size() == 0);
documents = json.getJSONArray("documents");
Assert.assertTrue(documents.length() == 0);
// Create a document with document3 // Create a document with document3
documentResource = resource().path("/document");
documentResource.addFilter(new CookieAuthenticationFilter(document3Token));
postParams = new MultivaluedMapImpl();
postParams.add("title", "My super title document 1");
postParams.add("description", "My super description for document 1");
postParams.add("language", "eng");
long create3Date = new Date().getTime(); long create3Date = new Date().getTime();
postParams.add("create_date", create3Date); json = target().path("/document").request()
response = documentResource.put(ClientResponse.class, postParams); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, document3Token)
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); .put(Entity.form(new Form()
json = response.getEntity(JSONObject.class); .param("title", "My super title document 1")
String document3Id = json.optString("id"); .param("description", "My super description for document 1")
.param("language", "eng")
.param("create_date", Long.toString(create3Date))), JsonObject.class);
String document3Id = json.getString("id");
Assert.assertNotNull(document3Id); Assert.assertNotNull(document3Id);
// Add a file // Add a file
fileResource = resource().path("/file"); String file3Id = null;
fileResource.addFilter(new CookieAuthenticationFilter(document3Token)); try (InputStream is = Resources.getResource("file/Einstein-Roosevelt-letter.png").openStream()) {
form = new FormDataMultiPart(); StreamDataBodyPart streamDataBodyPart = new StreamDataBodyPart("file", is, "Einstein-Roosevelt-letter.png");
file = this.getClass().getResourceAsStream("/file/Einstein-Roosevelt-letter.png"); try (FormDataMultiPart multiPart = new FormDataMultiPart()) {
fdp = new FormDataBodyPart("file", json = target()
new BufferedInputStream(file), .register(MultiPartFeature.class)
MediaType.APPLICATION_OCTET_STREAM_TYPE); .path("/file").request()
form.bodyPart(fdp); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, document3Token)
form.field("id", document3Id); .put(Entity.entity(multiPart.field("id", document3Id).bodyPart(streamDataBodyPart),
response = fileResource.type(MediaType.MULTIPART_FORM_DATA).put(ClientResponse.class, form); MediaType.MULTIPART_FORM_DATA_TYPE), JsonObject.class);
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); file3Id = json.getString("id");
json = response.getEntity(JSONObject.class); Assert.assertNotNull(file3Id);
String file3Id = json.getString("id"); }
Assert.assertNotNull(file3Id); }
// List all documents from document3 // List all documents from document3
documentResource = resource().path("/document/list"); json = target().path("/document/list")
documentResource.addFilter(new CookieAuthenticationFilter(document3Token)); .queryParam("sort_column", 3)
getParams = new MultivaluedMapImpl(); .queryParam("asc", false)
getParams.putSingle("sort_column", 3); .request()
getParams.putSingle("asc", false); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, document3Token)
response = documentResource.queryParams(getParams).get(ClientResponse.class); .get(JsonObject.class);
json = response.getEntity(JSONObject.class); documents = json.getJsonArray("documents");
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); Assert.assertTrue(documents.size() == 1);
documents = json.getJSONArray("documents");
Assert.assertTrue(documents.length() == 1);
// Search documents // Search documents
Assert.assertEquals(1, searchDocuments("full:uranium full:einstein", document1Token)); Assert.assertEquals(1, searchDocuments("full:uranium full:einstein", document1Token));
@ -200,11 +184,9 @@ public class TestDocumentResource extends BaseJerseyTest {
Assert.assertEquals(0, searchDocuments("lang:fra", document1Token)); Assert.assertEquals(0, searchDocuments("lang:fra", document1Token));
// Get a document // Get a document
documentResource = resource().path("/document/" + document1Id); json = target().path("/document/" + document1Id).request()
documentResource.addFilter(new CookieAuthenticationFilter(document1Token)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, document1Token)
response = documentResource.get(ClientResponse.class); .get(JsonObject.class);
json = response.getEntity(JSONObject.class);
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
Assert.assertEquals(document1Id, json.getString("id")); Assert.assertEquals(document1Id, json.getString("id"));
Assert.assertEquals("document1", json.getString("creator")); Assert.assertEquals("document1", json.getString("creator"));
Assert.assertEquals(1, json.getInt("file_count")); Assert.assertEquals(1, json.getInt("file_count"));
@ -212,62 +194,48 @@ public class TestDocumentResource extends BaseJerseyTest {
Assert.assertEquals("My super title document 1", json.getString("title")); Assert.assertEquals("My super title document 1", json.getString("title"));
Assert.assertEquals("My super description for document 1", json.getString("description")); Assert.assertEquals("My super description for document 1", json.getString("description"));
Assert.assertEquals("eng", json.getString("language")); Assert.assertEquals("eng", json.getString("language"));
Assert.assertEquals(create1Date, json.getLong("create_date")); Assert.assertEquals(create1Date, json.getJsonNumber("create_date").longValue());
tags = json.getJSONArray("tags"); tags = json.getJsonArray("tags");
Assert.assertEquals(1, tags.length()); Assert.assertEquals(1, tags.size());
Assert.assertEquals(tag1Id, tags.getJSONObject(0).getString("id")); Assert.assertEquals(tag1Id, tags.getJsonObject(0).getString("id"));
// Create a tag // Create a tag
tagResource = resource().path("/tag"); json = target().path("/tag").request()
tagResource.addFilter(new CookieAuthenticationFilter(document1Token)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, document1Token)
postParams = new MultivaluedMapImpl(); .put(Entity.form(new Form().param("name", "SuperTag2").param("color", "#00ffff")), JsonObject.class);
postParams.add("name", "SuperTag2"); String tag2Id = json.getString("id");
postParams.add("color", "#00ffff");
response = tagResource.put(ClientResponse.class, postParams);
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
json = response.getEntity(JSONObject.class);
String tag2Id = json.optString("id");
Assert.assertNotNull(tag1Id); Assert.assertNotNull(tag1Id);
// Update a document // Update a document
documentResource = resource().path("/document/" + document1Id); json = target().path("/document/" + document1Id).request()
documentResource.addFilter(new CookieAuthenticationFilter(document1Token)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, document1Token)
postParams = new MultivaluedMapImpl(); .post(Entity.form(new Form()
postParams.add("title", "My new super document 1"); .param("title", "My new super document 1")
postParams.add("description", "My new super description for document 1"); .param("description", "My new super description for document 1")
postParams.add("tags", tag2Id); .param("tags", tag2Id)), JsonObject.class);
response = documentResource.post(ClientResponse.class, postParams);
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
json = response.getEntity(JSONObject.class);
Assert.assertEquals(document1Id, json.getString("id")); Assert.assertEquals(document1Id, json.getString("id"));
// Search documents by query // Search documents by query
documentResource = resource().path("/document/list"); json = target().path("/document/list")
documentResource.addFilter(new CookieAuthenticationFilter(document1Token)); .queryParam("search", "super")
getParams = new MultivaluedMapImpl(); .request()
getParams.putSingle("search", "super"); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, document1Token)
response = documentResource.queryParams(getParams).get(ClientResponse.class); .get(JsonObject.class);
json = response.getEntity(JSONObject.class);
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
// Get a document // Get a document
documentResource = resource().path("/document/" + document1Id); json = target().path("/document/" + document1Id).request()
documentResource.addFilter(new CookieAuthenticationFilter(document1Token)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, document1Token)
response = documentResource.get(ClientResponse.class); .get(JsonObject.class);
json = response.getEntity(JSONObject.class);
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
Assert.assertTrue(json.getString("title").contains("new")); Assert.assertTrue(json.getString("title").contains("new"));
Assert.assertTrue(json.getString("description").contains("new")); Assert.assertTrue(json.getString("description").contains("new"));
tags = json.getJSONArray("tags"); tags = json.getJsonArray("tags");
Assert.assertEquals(1, tags.length()); Assert.assertEquals(1, tags.size());
Assert.assertEquals(tag2Id, tags.getJSONObject(0).getString("id")); Assert.assertEquals(tag2Id, tags.getJsonObject(0).getString("id"));
// Deletes a document // Deletes a document
documentResource = resource().path("/document/" + document1Id); json = target().path("/document/" + document1Id).request()
documentResource.addFilter(new CookieAuthenticationFilter(document1Token)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, document1Token)
response = documentResource.delete(ClientResponse.class); .delete(JsonObject.class);
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
json = response.getEntity(JSONObject.class);
Assert.assertEquals("ok", json.getString("status")); Assert.assertEquals("ok", json.getString("status"));
// Check that the associated files are deleted from FS // Check that the associated files are deleted from FS
@ -279,9 +247,9 @@ public class TestDocumentResource extends BaseJerseyTest {
Assert.assertFalse(thumbnailFile.exists()); Assert.assertFalse(thumbnailFile.exists());
// Get a document (KO) // Get a document (KO)
documentResource = resource().path("/document/" + document1Id); Response response = target().path("/document/" + document1Id).request()
documentResource.addFilter(new CookieAuthenticationFilter(document1Token)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, document1Token)
response = documentResource.get(ClientResponse.class); .get();
Assert.assertEquals(Status.NOT_FOUND, Status.fromStatusCode(response.getStatus())); Assert.assertEquals(Status.NOT_FOUND, Status.fromStatusCode(response.getStatus()));
} }
@ -294,14 +262,12 @@ public class TestDocumentResource extends BaseJerseyTest {
* @throws Exception * @throws Exception
*/ */
private int searchDocuments(String query, String token) throws Exception { private int searchDocuments(String query, String token) throws Exception {
WebResource documentResource = resource().path("/document/list"); JsonObject json = target().path("/document/list")
documentResource.addFilter(new CookieAuthenticationFilter(token)); .queryParam("search", query)
MultivaluedMapImpl getParams = new MultivaluedMapImpl(); .request()
getParams.putSingle("search", query); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, token)
ClientResponse response = documentResource.queryParams(getParams).get(ClientResponse.class); .get(JsonObject.class);
JSONObject json = response.getEntity(JSONObject.class); return json.getJsonArray("documents").size();
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
return json.getJSONArray("documents").length();
} }
/** /**
@ -316,53 +282,48 @@ public class TestDocumentResource extends BaseJerseyTest {
String document2Token = clientUtil.login("document2"); String document2Token = clientUtil.login("document2");
// Create a document // Create a document
WebResource documentResource = resource().path("/document");
documentResource.addFilter(new CookieAuthenticationFilter(document2Token));
MultivaluedMapImpl postParams = new MultivaluedMapImpl();
postParams.add("title", "My super title document 1");
postParams.add("description", "My super description for document 1");
postParams.add("language", "eng");
long create1Date = new Date().getTime(); long create1Date = new Date().getTime();
postParams.add("create_date", create1Date); JsonObject json = target().path("/document").request()
ClientResponse response = documentResource.put(ClientResponse.class, postParams); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, document2Token)
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); .put(Entity.form(new Form()
JSONObject json = response.getEntity(JSONObject.class); .param("title", "My super title document 1")
String document1Id = json.optString("id"); .param("description", "My super description for document 1")
.param("language", "eng")
.param("create_date", Long.toString(create1Date))), JsonObject.class);
String document1Id = json.getString("id");
Assert.assertNotNull(document1Id); Assert.assertNotNull(document1Id);
// Add a PDF file // Add a PDF file
WebResource fileResource = resource().path("/file"); String file1Id = null;
fileResource.addFilter(new CookieAuthenticationFilter(document2Token)); try (InputStream is = Resources.getResource("file/wikipedia.pdf").openStream()) {
FormDataMultiPart form = new FormDataMultiPart(); StreamDataBodyPart streamDataBodyPart = new StreamDataBodyPart("file", is, "wikipedia.pdf");
InputStream file = this.getClass().getResourceAsStream("/file/wikipedia.pdf"); try (FormDataMultiPart multiPart = new FormDataMultiPart()) {
FormDataBodyPart fdp = new FormDataBodyPart("file", json = target()
new BufferedInputStream(file), .register(MultiPartFeature.class)
MediaType.APPLICATION_OCTET_STREAM_TYPE); .path("/file").request()
form.bodyPart(fdp); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, document2Token)
form.field("id", document1Id); .put(Entity.entity(multiPart.field("id", document1Id).bodyPart(streamDataBodyPart),
response = fileResource.type(MediaType.MULTIPART_FORM_DATA).put(ClientResponse.class, form); MediaType.MULTIPART_FORM_DATA_TYPE), JsonObject.class);
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); file1Id = json.getString("id");
json = response.getEntity(JSONObject.class); Assert.assertNotNull(file1Id);
String file1Id = json.getString("id"); }
}
// Search documents by query in full content // Search documents by query in full content
documentResource = resource().path("/document/list"); json = target().path("/document/list")
documentResource.addFilter(new CookieAuthenticationFilter(document2Token)); .queryParam("search", "full:vrandecic")
MultivaluedMapImpl getParams = new MultivaluedMapImpl(); .request()
getParams.putSingle("search", "full:vrandecic"); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, document2Token)
response = documentResource.queryParams(getParams).get(ClientResponse.class); .get(JsonObject.class);
json = response.getEntity(JSONObject.class); Assert.assertTrue(json.getJsonArray("documents").size() == 1);
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
Assert.assertTrue(json.getJSONArray("documents").length() == 1);
// Get the file thumbnail data // Get the file thumbnail data
fileResource = resource().path("/file/" + file1Id + "/data"); Response response = target().path("/file/" + file1Id + "/data")
fileResource.addFilter(new CookieAuthenticationFilter(document2Token)); .queryParam("size", "thumb")
getParams = new MultivaluedMapImpl(); .request()
getParams.putSingle("size", "thumb"); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, document2Token)
response = fileResource.queryParams(getParams).get(ClientResponse.class); .get();
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); InputStream is = (InputStream) response.getEntity();
InputStream is = response.getEntityInputStream();
byte[] fileBytes = ByteStreams.toByteArray(is); byte[] fileBytes = ByteStreams.toByteArray(is);
Assert.assertTrue(fileBytes.length > 0); // Images rendered from PDF differ in size from OS to OS due to font issues Assert.assertTrue(fileBytes.length > 0); // Images rendered from PDF differ in size from OS to OS due to font issues
Assert.assertEquals(MimeType.IMAGE_JPEG, MimeTypeUtil.guessMimeType(fileBytes)); Assert.assertEquals(MimeType.IMAGE_JPEG, MimeTypeUtil.guessMimeType(fileBytes));

View File

@ -4,26 +4,29 @@ import java.io.BufferedInputStream;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.InputStream; import java.io.InputStream;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.Date;
import javax.json.JsonArray;
import javax.json.JsonObject;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.Form;
import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import junit.framework.Assert; import org.glassfish.jersey.media.multipart.FormDataMultiPart;
import org.glassfish.jersey.media.multipart.MultiPartFeature;
import org.codehaus.jettison.json.JSONArray; import org.glassfish.jersey.media.multipart.file.StreamDataBodyPart;
import org.codehaus.jettison.json.JSONObject; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import com.google.common.io.ByteStreams; import com.google.common.io.ByteStreams;
import com.google.common.io.Resources;
import com.sismics.docs.core.util.DirectoryUtil; import com.sismics.docs.core.util.DirectoryUtil;
import com.sismics.docs.rest.filter.CookieAuthenticationFilter; import com.sismics.util.filter.TokenBasedSecurityFilter;
import com.sismics.util.mime.MimeType; import com.sismics.util.mime.MimeType;
import com.sismics.util.mime.MimeTypeUtil; import com.sismics.util.mime.MimeTypeUtil;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.ClientResponse.Status;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.core.util.MultivaluedMapImpl;
import com.sun.jersey.multipart.FormDataBodyPart;
import com.sun.jersey.multipart.FormDataMultiPart;
/** /**
* Exhaustive test of the file resource. * Exhaustive test of the file resource.
@ -43,145 +46,137 @@ public class TestFileResource extends BaseJerseyTest {
String file1AuthenticationToken = clientUtil.login("file1"); String file1AuthenticationToken = clientUtil.login("file1");
// Create a document // Create a document
WebResource documentResource = resource().path("/document"); long create1Date = new Date().getTime();
documentResource.addFilter(new CookieAuthenticationFilter(file1AuthenticationToken)); JsonObject json = target().path("/document").request()
MultivaluedMapImpl postParams = new MultivaluedMapImpl(); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, file1AuthenticationToken)
postParams.add("title", "File test document 1"); .put(Entity.form(new Form()
postParams.add("language", "eng"); .param("title", "File test document 1")
ClientResponse response = documentResource.put(ClientResponse.class, postParams); .param("language", "eng")
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); .param("create_date", Long.toString(create1Date))), JsonObject.class);
JSONObject json = response.getEntity(JSONObject.class); String document1Id = json.getString("id");
String document1Id = json.optString("id");
Assert.assertNotNull(document1Id); Assert.assertNotNull(document1Id);
// Add a file // Add a file
WebResource fileResource = resource().path("/file"); String file1Id = null;
fileResource.addFilter(new CookieAuthenticationFilter(file1AuthenticationToken)); try (InputStream is = Resources.getResource("file/PIA00452.jpg").openStream()) {
FormDataMultiPart form = new FormDataMultiPart(); StreamDataBodyPart streamDataBodyPart = new StreamDataBodyPart("file", is, "PIA00452.jpg");
InputStream file = this.getClass().getResourceAsStream("/file/PIA00452.jpg"); try (FormDataMultiPart multiPart = new FormDataMultiPart()) {
FormDataBodyPart fdp = new FormDataBodyPart("file", json = target()
new BufferedInputStream(file), .register(MultiPartFeature.class)
MediaType.APPLICATION_OCTET_STREAM_TYPE); .path("/file").request()
form.bodyPart(fdp); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, file1AuthenticationToken)
form.field("id", document1Id); .put(Entity.entity(multiPart.field("id", document1Id).bodyPart(streamDataBodyPart),
response = fileResource.type(MediaType.MULTIPART_FORM_DATA).put(ClientResponse.class, form); MediaType.MULTIPART_FORM_DATA_TYPE), JsonObject.class);
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); file1Id = json.getString("id");
json = response.getEntity(JSONObject.class); Assert.assertNotNull(file1Id);
String file1Id = json.getString("id"); }
}
// Add a file // Add a file
fileResource = resource().path("/file"); String file2Id = null;
fileResource.addFilter(new CookieAuthenticationFilter(file1AuthenticationToken)); try (InputStream is = Resources.getResource("file/PIA00452.jpg").openStream()) {
form = new FormDataMultiPart(); StreamDataBodyPart streamDataBodyPart = new StreamDataBodyPart("file", is, "PIA00452.jpg");
file = this.getClass().getResourceAsStream("/file/PIA00452.jpg"); try (FormDataMultiPart multiPart = new FormDataMultiPart()) {
fdp = new FormDataBodyPart("file", json = target()
new BufferedInputStream(file), .register(MultiPartFeature.class)
MediaType.APPLICATION_OCTET_STREAM_TYPE); .path("/file").request()
form.bodyPart(fdp); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, file1AuthenticationToken)
form.field("id", document1Id); .put(Entity.entity(multiPart.field("id", document1Id).bodyPart(streamDataBodyPart),
response = fileResource.type(MediaType.MULTIPART_FORM_DATA).put(ClientResponse.class, form); MediaType.MULTIPART_FORM_DATA_TYPE), JsonObject.class);
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); file2Id = json.getString("id");
json = response.getEntity(JSONObject.class); Assert.assertNotNull(file2Id);
String file2Id = json.getString("id"); }
}
// Get the file data // Get the file data
fileResource = resource().path("/file/" + file1Id + "/data"); Response response = target().path("/file/" + file1Id + "/data").request()
fileResource.addFilter(new CookieAuthenticationFilter(file1AuthenticationToken)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, file1AuthenticationToken)
response = fileResource.get(ClientResponse.class); .get();
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); InputStream is = (InputStream) response.getEntity();
InputStream is = response.getEntityInputStream();
byte[] fileBytes = ByteStreams.toByteArray(is); byte[] fileBytes = ByteStreams.toByteArray(is);
Assert.assertEquals(MimeType.IMAGE_JPEG, MimeTypeUtil.guessMimeType(fileBytes)); Assert.assertEquals(MimeType.IMAGE_JPEG, MimeTypeUtil.guessMimeType(fileBytes));
Assert.assertTrue(fileBytes.length > 0); Assert.assertTrue(fileBytes.length > 0);
// Get the thumbnail data // Get the thumbnail data
fileResource = resource().path("/file/" + file1Id + "/data"); response = target().path("/file/" + file1Id + "/data")
fileResource.addFilter(new CookieAuthenticationFilter(file1AuthenticationToken)); .queryParam("size", "thumb")
MultivaluedMapImpl getParams = new MultivaluedMapImpl(); .request()
getParams.putSingle("size", "thumb"); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, file1AuthenticationToken)
response = fileResource.queryParams(getParams).get(ClientResponse.class); .get();
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
is = response.getEntityInputStream(); is = (InputStream) response.getEntity();
fileBytes = ByteStreams.toByteArray(is); fileBytes = ByteStreams.toByteArray(is);
Assert.assertEquals(MimeType.IMAGE_JPEG, MimeTypeUtil.guessMimeType(fileBytes)); Assert.assertEquals(MimeType.IMAGE_JPEG, MimeTypeUtil.guessMimeType(fileBytes));
Assert.assertTrue(fileBytes.length > 0); Assert.assertTrue(fileBytes.length > 0);
// Get the web data // Get the web data
fileResource = resource().path("/file/" + file1Id + "/data"); response = target().path("/file/" + file1Id + "/data")
fileResource.addFilter(new CookieAuthenticationFilter(file1AuthenticationToken)); .queryParam("size", "web")
getParams = new MultivaluedMapImpl(); .request()
getParams.putSingle("size", "web"); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, file1AuthenticationToken)
response = fileResource.queryParams(getParams).get(ClientResponse.class); .get();
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
is = response.getEntityInputStream(); is = (InputStream) response.getEntity();
fileBytes = ByteStreams.toByteArray(is); fileBytes = ByteStreams.toByteArray(is);
Assert.assertEquals(MimeType.IMAGE_JPEG, MimeTypeUtil.guessMimeType(fileBytes)); Assert.assertEquals(MimeType.IMAGE_JPEG, MimeTypeUtil.guessMimeType(fileBytes));
Assert.assertTrue(fileBytes.length > 0); Assert.assertTrue(fileBytes.length > 0);
// Check that the files are not readable directly from FS // Check that the files are not readable directly from FS
java.io.File storedFile = Paths.get(DirectoryUtil.getStorageDirectory().getPath(), file1Id).toFile(); java.io.File storedFile = Paths.get(DirectoryUtil.getStorageDirectory().getPath(), file1Id).toFile();
InputStream storedFileInputStream = new BufferedInputStream(new FileInputStream(storedFile)); try (InputStream storedFileInputStream = new BufferedInputStream(new FileInputStream(storedFile))) {
Assert.assertNull(MimeTypeUtil.guessMimeType(storedFileInputStream)); Assert.assertNull(MimeTypeUtil.guessMimeType(storedFileInputStream));
storedFileInputStream.close(); }
// Get all files from a document // Get all files from a document
fileResource = resource().path("/file/list"); json = target().path("/file/list")
fileResource.addFilter(new CookieAuthenticationFilter(file1AuthenticationToken)); .queryParam("id", document1Id)
getParams = new MultivaluedMapImpl(); .request()
getParams.putSingle("id", document1Id); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, file1AuthenticationToken)
response = fileResource.queryParams(getParams).get(ClientResponse.class); .get(JsonObject.class);
json = response.getEntity(JSONObject.class); JsonArray files = json.getJsonArray("files");
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); Assert.assertEquals(2, files.size());
JSONArray files = json.getJSONArray("files"); Assert.assertEquals(file1Id, files.getJsonObject(0).getString("id"));
Assert.assertEquals(2, files.length()); Assert.assertEquals(file2Id, files.getJsonObject(1).getString("id"));
Assert.assertEquals(file1Id, files.getJSONObject(0).getString("id"));
Assert.assertEquals(file2Id, files.getJSONObject(1).getString("id"));
// Reorder files // Reorder files
fileResource = resource().path("/file/reorder"); json = target().path("/file/reorder").request()
fileResource.addFilter(new CookieAuthenticationFilter(file1AuthenticationToken)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, file1AuthenticationToken)
postParams = new MultivaluedMapImpl(); .post(Entity.form(new Form()
postParams.add("id", document1Id); .param("id", document1Id)
postParams.add("order", file2Id); .param("order", file2Id)
postParams.add("order", file1Id); .param("order", file1Id)), JsonObject.class);
response = fileResource.post(ClientResponse.class, postParams);
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
// Get all files from a document // Get all files from a document
fileResource = resource().path("/file/list"); json = target().path("/file/list")
fileResource.addFilter(new CookieAuthenticationFilter(file1AuthenticationToken)); .queryParam("id", document1Id)
getParams = new MultivaluedMapImpl(); .request()
getParams.putSingle("id", document1Id); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, file1AuthenticationToken)
response = fileResource.queryParams(getParams).get(ClientResponse.class); .get(JsonObject.class);
json = response.getEntity(JSONObject.class); files = json.getJsonArray("files");
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); Assert.assertEquals(2, files.size());
files = json.getJSONArray("files"); Assert.assertEquals(file2Id, files.getJsonObject(0).getString("id"));
Assert.assertEquals(2, files.length()); Assert.assertEquals(file1Id, files.getJsonObject(1).getString("id"));
Assert.assertEquals(file2Id, files.getJSONObject(0).getString("id"));
Assert.assertEquals(file1Id, files.getJSONObject(1).getString("id"));
// Get a ZIP from all files // Get a ZIP from all files
fileResource = resource().path("/file/zip"); response = target().path("/file/zip")
fileResource.addFilter(new CookieAuthenticationFilter(file1AuthenticationToken)); .queryParam("id", document1Id)
getParams = new MultivaluedMapImpl(); .request()
getParams.putSingle("id", document1Id); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, file1AuthenticationToken)
response = fileResource.queryParams(getParams).get(ClientResponse.class); .get();
is = response.getEntityInputStream(); is = (InputStream) response.getEntity();
fileBytes = ByteStreams.toByteArray(is); fileBytes = ByteStreams.toByteArray(is);
Assert.assertEquals(MimeType.APPLICATION_ZIP, MimeTypeUtil.guessMimeType(fileBytes)); Assert.assertEquals(MimeType.APPLICATION_ZIP, MimeTypeUtil.guessMimeType(fileBytes));
// Deletes a file // Deletes a file
fileResource = resource().path("/file/" + file1Id); json = target().path("/file/" + file1Id).request()
fileResource.addFilter(new CookieAuthenticationFilter(file1AuthenticationToken)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, file1AuthenticationToken)
response = fileResource.delete(ClientResponse.class); .delete(JsonObject.class);
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
json = response.getEntity(JSONObject.class);
Assert.assertEquals("ok", json.getString("status")); Assert.assertEquals("ok", json.getString("status"));
// Get the file data (not found) // Get the file data (not found)
fileResource = resource().path("/file/" + file1Id + "/data"); response = target().path("/file/" + file1Id + "/data").request()
fileResource.addFilter(new CookieAuthenticationFilter(file1AuthenticationToken)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, file1AuthenticationToken)
response = fileResource.get(ClientResponse.class); .get();
Assert.assertEquals(Status.NOT_FOUND, Status.fromStatusCode(response.getStatus())); Assert.assertEquals(Status.NOT_FOUND, Status.fromStatusCode(response.getStatus()));
// Check that files are deleted from FS // Check that files are deleted from FS
@ -193,15 +188,13 @@ public class TestFileResource extends BaseJerseyTest {
Assert.assertFalse(thumbnailFile.exists()); Assert.assertFalse(thumbnailFile.exists());
// Get all files from a document // Get all files from a document
fileResource = resource().path("/file/list"); json = target().path("/file/list")
fileResource.addFilter(new CookieAuthenticationFilter(file1AuthenticationToken)); .queryParam("id", document1Id)
getParams = new MultivaluedMapImpl(); .request()
getParams.putSingle("id", document1Id); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, file1AuthenticationToken)
response = fileResource.queryParams(getParams).get(ClientResponse.class); .get(JsonObject.class);
json = response.getEntity(JSONObject.class); files = json.getJsonArray("files");
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); Assert.assertEquals(1, files.size());
files = json.getJSONArray("files");
Assert.assertEquals(1, files.length());
} }
@Test @Test
@ -211,91 +204,81 @@ public class TestFileResource extends BaseJerseyTest {
String file2AuthenticationToken = clientUtil.login("file2"); String file2AuthenticationToken = clientUtil.login("file2");
// Add a file // Add a file
WebResource fileResource = resource().path("/file"); String file1Id = null;
fileResource.addFilter(new CookieAuthenticationFilter(file2AuthenticationToken)); try (InputStream is = Resources.getResource("file/PIA00452.jpg").openStream()) {
FormDataMultiPart form = new FormDataMultiPart(); StreamDataBodyPart streamDataBodyPart = new StreamDataBodyPart("file", is, "PIA00452.jpg");
InputStream file = this.getClass().getResourceAsStream("/file/PIA00452.jpg"); try (FormDataMultiPart multiPart = new FormDataMultiPart()) {
FormDataBodyPart fdp = new FormDataBodyPart("file", JsonObject json = target()
new BufferedInputStream(file), .register(MultiPartFeature.class)
MediaType.APPLICATION_OCTET_STREAM_TYPE); .path("/file").request()
form.bodyPart(fdp); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, file2AuthenticationToken)
ClientResponse response = fileResource.type(MediaType.MULTIPART_FORM_DATA).put(ClientResponse.class, form); .put(Entity.entity(multiPart.bodyPart(streamDataBodyPart),
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); MediaType.MULTIPART_FORM_DATA_TYPE), JsonObject.class);
JSONObject json = response.getEntity(JSONObject.class); file1Id = json.getString("id");
String file1Id = json.getString("id"); Assert.assertNotNull(file1Id);
}
}
// Get all orphan files // Get all orphan files
fileResource = resource().path("/file/list"); JsonObject json = target().path("/file/list").request()
fileResource.addFilter(new CookieAuthenticationFilter(file2AuthenticationToken)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, file2AuthenticationToken)
MultivaluedMapImpl getParams = new MultivaluedMapImpl(); .get(JsonObject.class);
response = fileResource.queryParams(getParams).get(ClientResponse.class); JsonArray files = json.getJsonArray("files");
json = response.getEntity(JSONObject.class); Assert.assertEquals(1, files.size());
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
JSONArray files = json.getJSONArray("files");
Assert.assertEquals(1, files.length());
// Get the file data // Get the file data
fileResource = resource().path("/file/" + file1Id + "/data"); Response response = target().path("/file/" + file1Id + "/data").request()
fileResource.addFilter(new CookieAuthenticationFilter(file2AuthenticationToken)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, file2AuthenticationToken)
response = fileResource.get(ClientResponse.class); .get();
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); InputStream is = (InputStream) response.getEntity();
InputStream is = response.getEntityInputStream();
byte[] fileBytes = ByteStreams.toByteArray(is); byte[] fileBytes = ByteStreams.toByteArray(is);
Assert.assertEquals(MimeType.IMAGE_JPEG, MimeTypeUtil.guessMimeType(fileBytes)); Assert.assertEquals(MimeType.IMAGE_JPEG, MimeTypeUtil.guessMimeType(fileBytes));
Assert.assertEquals(163510, fileBytes.length); Assert.assertEquals(163510, fileBytes.length);
// Create a document // Create a document
WebResource documentResource = resource().path("/document"); json = target().path("/document").request()
documentResource.addFilter(new CookieAuthenticationFilter(file2AuthenticationToken)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, file2AuthenticationToken)
MultivaluedMapImpl postParams = new MultivaluedMapImpl(); .put(Entity.form(new Form()
postParams.add("title", "File test document 1"); .param("title", "File test document 1")
postParams.add("language", "eng"); .param("language", "eng")), JsonObject.class);
response = documentResource.put(ClientResponse.class, postParams); String document1Id = json.getString("id");
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
json = response.getEntity(JSONObject.class);
String document1Id = json.optString("id");
Assert.assertNotNull(document1Id); Assert.assertNotNull(document1Id);
// Attach a file to a document // Attach a file to a document
documentResource = resource().path("/file/" + file1Id); json = target().path("/file/" + file1Id).request()
documentResource.addFilter(new CookieAuthenticationFilter(file2AuthenticationToken)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, file2AuthenticationToken)
postParams = new MultivaluedMapImpl(); .post(Entity.form(new Form()
postParams.add("id", document1Id); .param("id", document1Id)), JsonObject.class);
response = documentResource.post(ClientResponse.class, postParams);
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
json = response.getEntity(JSONObject.class);
// Get all files from a document // Get all files from a document
fileResource = resource().path("/file/list"); json = target().path("/file/list")
fileResource.addFilter(new CookieAuthenticationFilter(file2AuthenticationToken)); .queryParam("id", document1Id)
getParams = new MultivaluedMapImpl(); .request()
getParams.putSingle("id", document1Id); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, file2AuthenticationToken)
response = fileResource.queryParams(getParams).get(ClientResponse.class); .get(JsonObject.class);
json = response.getEntity(JSONObject.class); files = json.getJsonArray("files");
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); Assert.assertEquals(1, files.size());
files = json.getJSONArray("files");
Assert.assertEquals(1, files.length());
// Add a file // Add a file
fileResource = resource().path("/file"); String file2Id = null;
fileResource.addFilter(new CookieAuthenticationFilter(file2AuthenticationToken)); try (InputStream is0 = Resources.getResource("file/PIA00452.jpg").openStream()) {
form = new FormDataMultiPart(); StreamDataBodyPart streamDataBodyPart = new StreamDataBodyPart("file", is0, "PIA00452.jpg");
file = this.getClass().getResourceAsStream("/file/PIA00452.jpg"); try (FormDataMultiPart multiPart = new FormDataMultiPart()) {
fdp = new FormDataBodyPart("file", json = target()
new BufferedInputStream(file), .register(MultiPartFeature.class)
MediaType.APPLICATION_OCTET_STREAM_TYPE); .path("/file").request()
form.bodyPart(fdp); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, file2AuthenticationToken)
response = fileResource.type(MediaType.MULTIPART_FORM_DATA).put(ClientResponse.class, form); .put(Entity.entity(multiPart.bodyPart(streamDataBodyPart),
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); MediaType.MULTIPART_FORM_DATA_TYPE), JsonObject.class);
json = response.getEntity(JSONObject.class); file2Id = json.getString("id");
String file2Id = json.getString("id"); Assert.assertNotNull(file2Id);
}
}
// Deletes a file // Deletes a file
fileResource = resource().path("/file/" + file2Id); json = target().path("/file/" + file2Id).request()
fileResource.addFilter(new CookieAuthenticationFilter(file2AuthenticationToken)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, file2AuthenticationToken)
response = fileResource.delete(ClientResponse.class); .delete(JsonObject.class);
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
json = response.getEntity(JSONObject.class);
Assert.assertEquals("ok", json.getString("status")); Assert.assertEquals("ok", json.getString("status"));
} }
} }

View File

@ -1,32 +0,0 @@
package com.sismics.docs.rest;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.ClientResponse.Status;
import com.sun.jersey.api.client.WebResource;
import junit.framework.Assert;
import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
import org.junit.Test;
/**
* Test the locale resource.
*
* @author jtremeaux
*/
public class TestLocaleResource extends BaseJerseyTest {
/**
* Test the locale resource.
*
* @throws JSONException
*/
@Test
public void testLocaleResource() throws JSONException {
WebResource localeResource = resource().path("/locale");
ClientResponse response = localeResource.get(ClientResponse.class);
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
JSONObject json = response.getEntity(JSONObject.class);
JSONArray locale = json.getJSONArray("locales");
Assert.assertTrue(locale.length() > 0);
}
}

View File

@ -1,16 +1,18 @@
package com.sismics.docs.rest; package com.sismics.docs.rest;
import com.sismics.docs.rest.filter.CookieAuthenticationFilter; import javax.json.JsonObject;
import com.sun.jersey.api.client.ClientResponse; import javax.ws.rs.client.Entity;
import com.sun.jersey.api.client.ClientResponse.Status; import javax.ws.rs.core.Form;
import com.sun.jersey.api.client.WebResource; import javax.ws.rs.core.Response;
import com.sun.jersey.core.util.MultivaluedMapImpl; import javax.ws.rs.core.Response.Status;
import junit.framework.Assert; import junit.framework.Assert;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
import org.junit.Test; import org.junit.Test;
import com.sismics.util.filter.TokenBasedSecurityFilter;
/** /**
* Test of the security layer. * Test of the security layer.
* *
@ -23,50 +25,48 @@ public class TestSecurity extends BaseJerseyTest {
* @throws JSONException * @throws JSONException
*/ */
@Test @Test
public void testSecurity() throws JSONException { public void testSecurity() {
// Create a user // Create a user
clientUtil.createUser("testsecurity"); clientUtil.createUser("testsecurity");
// Changes a user's email KO : the user is not connected // Changes a user's email KO : the user is not connected
WebResource userResource = resource().path("/user/update"); Response response = target().path("/user/update").request()
MultivaluedMapImpl postParams = new MultivaluedMapImpl(); .post(Entity.form(new Form().param("email", "testsecurity2@docs.com")));
postParams.add("email", "testsecurity2@docs.com");
ClientResponse response = userResource.post(ClientResponse.class, postParams);
Assert.assertEquals(Status.FORBIDDEN, Status.fromStatusCode(response.getStatus())); Assert.assertEquals(Status.FORBIDDEN, Status.fromStatusCode(response.getStatus()));
JSONObject json = response.getEntity(JSONObject.class); JsonObject json = response.readEntity(JsonObject.class);
Assert.assertEquals("ForbiddenError", json.getString("type")); Assert.assertEquals("ForbiddenError", json.getString("type"));
Assert.assertEquals("You don't have access to this resource", json.getString("message")); Assert.assertEquals("You don't have access to this resource", json.getString("message"));
// User testsecurity logs in // User testsecurity logs in
String testSecurityAuthenticationToken = clientUtil.login("testsecurity"); String testSecurityAuthenticationToken = clientUtil.login("testsecurity");
// User testsecurity creates a new user KO : no permission
response = target().path("/user").request()
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, testSecurityAuthenticationToken)
.put(Entity.form(new Form()));
Assert.assertEquals(Status.FORBIDDEN, Status.fromStatusCode(response.getStatus()));
Assert.assertEquals("ForbiddenError", json.getString("type"));
Assert.assertEquals("You don't have access to this resource", json.getString("message"));
// User testsecurity changes his email OK // User testsecurity changes his email OK
userResource = resource().path("/user"); json = target().path("/user").request()
userResource.addFilter(new CookieAuthenticationFilter(testSecurityAuthenticationToken)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, testSecurityAuthenticationToken)
postParams = new MultivaluedMapImpl(); .post(Entity.form(new Form()
postParams.add("email", "testsecurity2@docs.com"); .param("email", "testsecurity2@docs.com")), JsonObject.class);
postParams.add("locale", "en");
response = userResource.post(ClientResponse.class, postParams);
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
json = response.getEntity(JSONObject.class);
Assert.assertEquals("ok", json.getString("status")); Assert.assertEquals("ok", json.getString("status"));
// User testsecurity logs out // User testsecurity logs out
userResource = resource().path("/user/logout"); response = target().path("/user/logout").request()
userResource.addFilter(new CookieAuthenticationFilter(testSecurityAuthenticationToken)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, testSecurityAuthenticationToken)
postParams = new MultivaluedMapImpl(); .post(Entity.form(new Form()));
response = userResource.post(ClientResponse.class, postParams);
json = response.getEntity(JSONObject.class);
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
testSecurityAuthenticationToken = clientUtil.getAuthenticationCookie(response); testSecurityAuthenticationToken = clientUtil.getAuthenticationCookie(response);
Assert.assertTrue(StringUtils.isEmpty(testSecurityAuthenticationToken)); Assert.assertTrue(StringUtils.isEmpty(testSecurityAuthenticationToken));
// User testsecurity logs out KO : he is not connected anymore // User testsecurity logs out KO : he is not connected anymore
userResource = resource().path("/user/logout"); response = target().path("/user/logout").request()
userResource.addFilter(new CookieAuthenticationFilter(testSecurityAuthenticationToken)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, testSecurityAuthenticationToken)
postParams = new MultivaluedMapImpl(); .post(Entity.form(new Form()));
response = userResource.post(ClientResponse.class, postParams);
json = response.getEntity(JSONObject.class);
Assert.assertEquals(Status.FORBIDDEN, Status.fromStatusCode(response.getStatus())); Assert.assertEquals(Status.FORBIDDEN, Status.fromStatusCode(response.getStatus()));
// User testsecurity logs in with a long lived session // User testsecurity logs in with a long lived session

View File

@ -1,24 +1,25 @@
package com.sismics.docs.rest; package com.sismics.docs.rest;
import java.io.BufferedInputStream;
import java.io.InputStream; import java.io.InputStream;
import javax.json.JsonArray;
import javax.json.JsonObject;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.Form;
import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import junit.framework.Assert; import org.glassfish.jersey.media.multipart.FormDataMultiPart;
import org.glassfish.jersey.media.multipart.MultiPartFeature;
import org.codehaus.jettison.json.JSONArray; import org.glassfish.jersey.media.multipart.file.StreamDataBodyPart;
import org.codehaus.jettison.json.JSONObject; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import com.google.common.io.ByteStreams; import com.google.common.io.ByteStreams;
import com.sismics.docs.rest.filter.CookieAuthenticationFilter; import com.google.common.io.Resources;
import com.sun.jersey.api.client.ClientResponse; import com.sismics.util.filter.TokenBasedSecurityFilter;
import com.sun.jersey.api.client.ClientResponse.Status;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.core.util.MultivaluedMapImpl;
import com.sun.jersey.multipart.FormDataBodyPart;
import com.sun.jersey.multipart.FormDataMultiPart;
/** /**
* Exhaustive test of the share resource. * Exhaustive test of the share resource.
@ -28,6 +29,7 @@ import com.sun.jersey.multipart.FormDataMultiPart;
public class TestShareResource extends BaseJerseyTest { public class TestShareResource extends BaseJerseyTest {
/** /**
* Test the share resource. * Test the share resource.
* @throws Exception
* *
* @throws Exception * @throws Exception
*/ */
@ -38,99 +40,86 @@ public class TestShareResource extends BaseJerseyTest {
String share1AuthenticationToken = clientUtil.login("share1"); String share1AuthenticationToken = clientUtil.login("share1");
// Create a document // Create a document
WebResource documentResource = resource().path("/document"); JsonObject json = target().path("/document").request()
documentResource.addFilter(new CookieAuthenticationFilter(share1AuthenticationToken)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, share1AuthenticationToken)
MultivaluedMapImpl postParams = new MultivaluedMapImpl(); .put(Entity.form(new Form()
postParams.add("title", "File test document 1"); .param("title", "File test document 1")
postParams.add("language", "eng"); .param("language", "eng")), JsonObject.class);
ClientResponse response = documentResource.put(ClientResponse.class, postParams); String document1Id = json.getString("id");
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
JSONObject json = response.getEntity(JSONObject.class);
String document1Id = json.optString("id");
Assert.assertNotNull(document1Id); Assert.assertNotNull(document1Id);
// Add a file // Add a file
WebResource fileResource = resource().path("/file"); String file1Id = null;
fileResource.addFilter(new CookieAuthenticationFilter(share1AuthenticationToken)); try (InputStream is = Resources.getResource("file/PIA00452.jpg").openStream()) {
FormDataMultiPart form = new FormDataMultiPart(); StreamDataBodyPart streamDataBodyPart = new StreamDataBodyPart("file", is, "PIA00452.jpg");
InputStream file = this.getClass().getResourceAsStream("/file/PIA00452.jpg"); try (FormDataMultiPart multiPart = new FormDataMultiPart()) {
FormDataBodyPart fdp = new FormDataBodyPart("file", json = target()
new BufferedInputStream(file), .register(MultiPartFeature.class)
MediaType.APPLICATION_OCTET_STREAM_TYPE); .path("/file").request()
form.bodyPart(fdp); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, share1AuthenticationToken)
form.field("id", document1Id); .put(Entity.entity(multiPart.field("id", document1Id).bodyPart(streamDataBodyPart),
response = fileResource.type(MediaType.MULTIPART_FORM_DATA).put(ClientResponse.class, form); MediaType.MULTIPART_FORM_DATA_TYPE), JsonObject.class);
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); file1Id = json.getString("id");
json = response.getEntity(JSONObject.class); }
String file1Id = json.getString("id"); }
// Share this document // Share this document
WebResource shareResource = resource().path("/share"); json = target().path("/share").request()
shareResource.addFilter(new CookieAuthenticationFilter(share1AuthenticationToken)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, share1AuthenticationToken)
postParams = new MultivaluedMapImpl(); .put(Entity.form(new Form()
postParams.add("id", document1Id); .param("id", document1Id)
postParams.add("name", "4 All"); .param("name", "4 All")), JsonObject.class);
response = shareResource.put(ClientResponse.class, postParams);
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
json = response.getEntity(JSONObject.class);
String share1Id = json.getString("id"); String share1Id = json.getString("id");
// Get the document anonymously // Get the document anonymously
documentResource = resource().path("/document/" + document1Id); json = target().path("/document/" + document1Id)
MultivaluedMapImpl getParams = new MultivaluedMapImpl(); .queryParam("share", share1Id)
getParams.putSingle("share", share1Id); .request()
response = documentResource.queryParams(getParams).get(ClientResponse.class); .get(JsonObject.class);
json = response.getEntity(JSONObject.class);
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
Assert.assertEquals(document1Id, json.getString("id")); Assert.assertEquals(document1Id, json.getString("id"));
Assert.assertEquals(3, json.getJSONArray("acls").length()); // 2 for the creator, 1 for the share Assert.assertEquals(3, json.getJsonArray("acls").size()); // 2 for the creator, 1 for the share
// Get all files from this document anonymously // Get all files from this document anonymously
fileResource = resource().path("/file/list"); json = target().path("/file/list")
getParams = new MultivaluedMapImpl(); .queryParam("id", document1Id)
getParams.putSingle("id", document1Id); .queryParam("share", share1Id)
getParams.putSingle("share", share1Id); .request()
response = fileResource.queryParams(getParams).get(ClientResponse.class); .get(JsonObject.class);
json = response.getEntity(JSONObject.class); JsonArray files = json.getJsonArray("files");
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); Assert.assertEquals(1, files.size());
JSONArray files = json.getJSONArray("files");
Assert.assertEquals(1, files.length());
// Get the file data anonymously // Get the file data anonymously
fileResource = resource().path("/file/" + file1Id + "/data"); Response response = target().path("/file/" + file1Id + "/data")
getParams = new MultivaluedMapImpl(); .queryParam("thumbnail", false)
getParams.putSingle("thumbnail", false); .queryParam("share", share1Id)
getParams.putSingle("share", share1Id); .request()
response = fileResource.queryParams(getParams).get(ClientResponse.class); .get();
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); InputStream is = (InputStream) response.getEntity();
InputStream is = response.getEntityInputStream();
byte[] fileBytes = ByteStreams.toByteArray(is); byte[] fileBytes = ByteStreams.toByteArray(is);
Assert.assertEquals(163510, fileBytes.length); Assert.assertEquals(163510, fileBytes.length);
// Deletes the share (not allowed) // Deletes the share (not allowed)
clientUtil.createUser("share2"); clientUtil.createUser("share2");
String share2AuthenticationToken = clientUtil.login("share2"); String share2AuthenticationToken = clientUtil.login("share2");
shareResource = resource().path("/share/" + share1Id); response = target().path("/share/" + share1Id).request()
shareResource.addFilter(new CookieAuthenticationFilter(share2AuthenticationToken)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, share2AuthenticationToken)
response = shareResource.delete(ClientResponse.class); .delete();
Assert.assertEquals(Status.BAD_REQUEST, Status.fromStatusCode(response.getStatus())); Assert.assertEquals(Status.BAD_REQUEST, Status.fromStatusCode(response.getStatus()));
json = response.getEntity(JSONObject.class); json = response.readEntity(JsonObject.class);
Assert.assertEquals("DocumentNotFound", json.getString("type")); Assert.assertEquals("DocumentNotFound", json.getString("type"));
// Deletes the share // Deletes the share
shareResource = resource().path("/share/" + share1Id); json = target().path("/share/" + share1Id).request()
shareResource.addFilter(new CookieAuthenticationFilter(share1AuthenticationToken)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, share1AuthenticationToken)
response = shareResource.delete(ClientResponse.class); .delete(JsonObject.class);
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
json = response.getEntity(JSONObject.class);
Assert.assertEquals("ok", json.getString("status")); Assert.assertEquals("ok", json.getString("status"));
// Deletes the share again // Deletes the share again
shareResource = resource().path("/share/" + share1Id); response = target().path("/share/" + share1Id).request()
shareResource.addFilter(new CookieAuthenticationFilter(share1AuthenticationToken)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, share1AuthenticationToken)
response = shareResource.delete(ClientResponse.class); .delete();
Assert.assertEquals(Status.BAD_REQUEST, Status.fromStatusCode(response.getStatus())); Assert.assertEquals(Status.BAD_REQUEST, Status.fromStatusCode(response.getStatus()));
json = response.getEntity(JSONObject.class); json = response.readEntity(JsonObject.class);
Assert.assertEquals("ShareNotFound", json.getString("type")); Assert.assertEquals("ShareNotFound", json.getString("type"));
} }
} }

View File

@ -1,16 +1,18 @@
package com.sismics.docs.rest; package com.sismics.docs.rest;
import com.sismics.docs.rest.filter.CookieAuthenticationFilter; import javax.json.JsonArray;
import com.sun.jersey.api.client.ClientResponse; import javax.json.JsonObject;
import com.sun.jersey.api.client.ClientResponse.Status; import javax.ws.rs.client.Entity;
import com.sun.jersey.api.client.WebResource; import javax.ws.rs.core.Form;
import com.sun.jersey.core.util.MultivaluedMapImpl; import javax.ws.rs.core.Response;
import junit.framework.Assert; import javax.ws.rs.core.Response.Status;
import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONException; import org.junit.Assert;
import org.codehaus.jettison.json.JSONObject;
import org.junit.Test; import org.junit.Test;
import com.sismics.util.filter.TokenBasedSecurityFilter;
/** /**
* Test the tag resource. * Test the tag resource.
* *
@ -23,173 +25,138 @@ public class TestTagResource extends BaseJerseyTest {
* @throws JSONException * @throws JSONException
*/ */
@Test @Test
public void testTagResource() throws JSONException { public void testTagResource() {
// Login tag1 // Login tag1
clientUtil.createUser("tag1"); clientUtil.createUser("tag1");
String tag1Token = clientUtil.login("tag1"); String tag1Token = clientUtil.login("tag1");
// Create a tag // Create a tag
WebResource tagResource = resource().path("/tag"); JsonObject json = target().path("/tag").request()
tagResource.addFilter(new CookieAuthenticationFilter(tag1Token)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, tag1Token)
MultivaluedMapImpl postParams = new MultivaluedMapImpl(); .put(Entity.form(new Form()
postParams.add("name", "Tag3"); .param("name", "Tag3")
postParams.add("color", "#ff0000"); .param("color", "#ff0000")), JsonObject.class);
ClientResponse response = tagResource.put(ClientResponse.class, postParams); String tag3Id = json.getString("id");
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
JSONObject json = response.getEntity(JSONObject.class);
String tag3Id = json.optString("id");
Assert.assertNotNull(tag3Id); Assert.assertNotNull(tag3Id);
// Create a tag // Create a tag
tagResource = resource().path("/tag"); json = target().path("/tag").request()
tagResource.addFilter(new CookieAuthenticationFilter(tag1Token)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, tag1Token)
postParams = new MultivaluedMapImpl(); .put(Entity.form(new Form()
postParams.add("name", "Tag4"); .param("name", "Tag4")
postParams.add("color", "#00ff00"); .param("color", "#00ff00")), JsonObject.class);
response = tagResource.put(ClientResponse.class, postParams); String tag4Id = json.getString("id");
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
json = response.getEntity(JSONObject.class);
String tag4Id = json.optString("id");
Assert.assertNotNull(tag4Id); Assert.assertNotNull(tag4Id);
// Create a tag with space (not allowed) // Create a tag with space (not allowed)
tagResource = resource().path("/tag"); Response response = target().path("/tag").request()
tagResource.addFilter(new CookieAuthenticationFilter(tag1Token)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, tag1Token)
postParams = new MultivaluedMapImpl(); .put(Entity.form(new Form()
postParams.add("name", "Tag 4"); .param("name", "Tag 4")));
response = tagResource.put(ClientResponse.class, postParams);
Assert.assertEquals(Status.BAD_REQUEST, Status.fromStatusCode(response.getStatus())); Assert.assertEquals(Status.BAD_REQUEST, Status.fromStatusCode(response.getStatus()));
// Create a document // Create a document
WebResource documentResource = resource().path("/document"); json = target().path("/document").request()
documentResource.addFilter(new CookieAuthenticationFilter(tag1Token)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, tag1Token)
postParams = new MultivaluedMapImpl(); .put(Entity.form(new Form()
postParams.add("title", "My super document 1"); .param("title", "My super document 1")
postParams.add("tags", tag3Id); .param("tags", tag3Id)
postParams.add("language", "eng"); .param("language", "eng")), JsonObject.class);
response = documentResource.put(ClientResponse.class, postParams);
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
json = response.getEntity(JSONObject.class);
// Create a document // Create a document
documentResource = resource().path("/document"); json = target().path("/document").request()
documentResource.addFilter(new CookieAuthenticationFilter(tag1Token)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, tag1Token)
postParams = new MultivaluedMapImpl(); .put(Entity.form(new Form()
postParams.add("title", "My super document 2"); .param("title", "My super document 2")
postParams.add("tags", tag4Id); .param("tags", tag4Id)
postParams.add("language", "eng"); .param("language", "eng")), JsonObject.class);
response = documentResource.put(ClientResponse.class, postParams);
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
json = response.getEntity(JSONObject.class);
String document2Id = json.getString("id"); String document2Id = json.getString("id");
// Check tags on a document // Check tags on a document
documentResource = resource().path("/document/" + document2Id); json = target().path("/document/" + document2Id).request()
documentResource.addFilter(new CookieAuthenticationFilter(tag1Token)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, tag1Token)
response = documentResource.get(ClientResponse.class); .get(JsonObject.class);
json = response.getEntity(JSONObject.class); JsonArray tags = json.getJsonArray("tags");
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); Assert.assertEquals(1, tags.size());
JSONArray tags = json.getJSONArray("tags"); Assert.assertEquals(tag4Id, tags.getJsonObject(0).getString("id"));
Assert.assertEquals(1, tags.length());
Assert.assertEquals(tag4Id, tags.getJSONObject(0).getString("id"));
// Update tags on a document // Update tags on a document
documentResource = resource().path("/document/" + document2Id); response = target().path("/document/" + document2Id).request()
documentResource.addFilter(new CookieAuthenticationFilter(tag1Token)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, tag1Token)
postParams = new MultivaluedMapImpl(); .post(Entity.form(new Form()
postParams.add("tags", tag3Id); .param("tags", tag3Id)
postParams.add("tags", tag4Id); .param("tags", tag4Id)));
response = documentResource.post(ClientResponse.class, postParams);
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
// Check tags on a document // Check tags on a document
documentResource = resource().path("/document/" + document2Id); json = target().path("/document/" + document2Id).request()
documentResource.addFilter(new CookieAuthenticationFilter(tag1Token)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, tag1Token)
response = documentResource.get(ClientResponse.class); .get(JsonObject.class);
json = response.getEntity(JSONObject.class); tags = json.getJsonArray("tags");
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); Assert.assertEquals(2, tags.size());
tags = json.getJSONArray("tags"); Assert.assertEquals(tag3Id, tags.getJsonObject(0).getString("id"));
Assert.assertEquals(2, tags.length()); Assert.assertEquals(tag4Id, tags.getJsonObject(1).getString("id"));
Assert.assertEquals(tag3Id, tags.getJSONObject(0).getString("id"));
Assert.assertEquals(tag4Id, tags.getJSONObject(1).getString("id"));
// Update tags on a document // Update tags on a document
documentResource = resource().path("/document/" + document2Id); response = target().path("/document/" + document2Id).request()
documentResource.addFilter(new CookieAuthenticationFilter(tag1Token)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, tag1Token)
postParams = new MultivaluedMapImpl(); .post(Entity.form(new Form()
postParams.add("tags", tag4Id); .param("tags", tag4Id)));
response = documentResource.post(ClientResponse.class, postParams);
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
// Check tags on a document // Check tags on a document
documentResource = resource().path("/document/" + document2Id); json = target().path("/document/" + document2Id).request()
documentResource.addFilter(new CookieAuthenticationFilter(tag1Token)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, tag1Token)
response = documentResource.get(ClientResponse.class); .get(JsonObject.class);
json = response.getEntity(JSONObject.class); tags = json.getJsonArray("tags");
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); Assert.assertEquals(1, tags.size());
tags = json.getJSONArray("tags"); Assert.assertEquals(tag4Id, tags.getJsonObject(0).getString("id"));
Assert.assertEquals(1, tags.length());
Assert.assertEquals(tag4Id, tags.getJSONObject(0).getString("id"));
// Get tag stats // Get tag stats
tagResource = resource().path("/tag/stats"); json = target().path("/tag/stats").request()
tagResource.addFilter(new CookieAuthenticationFilter(tag1Token)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, tag1Token)
response = tagResource.get(ClientResponse.class); .get(JsonObject.class);
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); JsonArray stats = json.getJsonArray("stats");
json = response.getEntity(JSONObject.class); Assert.assertTrue(stats.size() == 2);
JSONArray stats = json.getJSONArray("stats"); Assert.assertEquals(1, stats.getJsonObject(0).getInt("count"));
Assert.assertTrue(stats.length() == 2); Assert.assertEquals(1, stats.getJsonObject(1).getInt("count"));
Assert.assertEquals(1, stats.getJSONObject(0).getInt("count"));
Assert.assertEquals(1, stats.getJSONObject(1).getInt("count"));
// Get all tags // Get all tags
tagResource = resource().path("/tag/list"); json = target().path("/tag/list").request()
tagResource.addFilter(new CookieAuthenticationFilter(tag1Token)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, tag1Token)
response = tagResource.get(ClientResponse.class); .get(JsonObject.class);
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); tags = json.getJsonArray("tags");
json = response.getEntity(JSONObject.class); Assert.assertTrue(tags.size() > 0);
tags = json.getJSONArray("tags"); Assert.assertEquals("Tag4", tags.getJsonObject(1).getString("name"));
Assert.assertTrue(tags.length() > 0); Assert.assertEquals("#00ff00", tags.getJsonObject(1).getString("color"));
Assert.assertEquals("Tag4", tags.getJSONObject(1).getString("name"));
Assert.assertEquals("#00ff00", tags.getJSONObject(1).getString("color"));
// Update a tag // Update a tag
tagResource = resource().path("/tag/" + tag4Id); json = target().path("/tag/" + tag4Id).request()
tagResource.addFilter(new CookieAuthenticationFilter(tag1Token)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, tag1Token)
postParams = new MultivaluedMapImpl(); .post(Entity.form(new Form()
postParams.add("name", "UpdatedName"); .param("name", "UpdatedName")
postParams.add("color", "#0000ff"); .param("color", "#0000ff")), JsonObject.class);
response = tagResource.post(ClientResponse.class, postParams);
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
json = response.getEntity(JSONObject.class);
Assert.assertEquals(tag4Id, json.getString("id")); Assert.assertEquals(tag4Id, json.getString("id"));
// Get all tags // Get all tags
tagResource = resource().path("/tag/list"); json = target().path("/tag/list").request()
tagResource.addFilter(new CookieAuthenticationFilter(tag1Token)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, tag1Token)
response = tagResource.get(ClientResponse.class); .get(JsonObject.class);
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); tags = json.getJsonArray("tags");
json = response.getEntity(JSONObject.class); Assert.assertTrue(tags.size() > 0);
tags = json.getJSONArray("tags"); Assert.assertEquals("UpdatedName", tags.getJsonObject(1).getString("name"));
Assert.assertTrue(tags.length() > 0); Assert.assertEquals("#0000ff", tags.getJsonObject(1).getString("color"));
Assert.assertEquals("UpdatedName", tags.getJSONObject(1).getString("name"));
Assert.assertEquals("#0000ff", tags.getJSONObject(1).getString("color"));
// Deletes a tag // Deletes a tag
tagResource = resource().path("/tag/" + tag4Id); target().path("/tag/" + tag4Id).request()
tagResource.addFilter(new CookieAuthenticationFilter(tag1Token)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, tag1Token)
response = tagResource.delete(ClientResponse.class); .delete();
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
json = response.getEntity(JSONObject.class);
Assert.assertEquals("ok", json.getString("status"));
// Get all tags // Get all tags
tagResource = resource().path("/tag/list"); json = target().path("/tag/list").request()
tagResource.addFilter(new CookieAuthenticationFilter(tag1Token)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, tag1Token)
response = tagResource.get(ClientResponse.class); .get(JsonObject.class);
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); tags = json.getJsonArray("tags");
json = response.getEntity(JSONObject.class); Assert.assertTrue(tags.size() == 1);
tags = json.getJSONArray("tags");
Assert.assertTrue(tags.length() == 1);
} }
} }

View File

@ -1,33 +0,0 @@
package com.sismics.docs.rest;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.ClientResponse.Status;
import com.sun.jersey.api.client.WebResource;
import junit.framework.Assert;
import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
import org.junit.Test;
/**
* Test the theme resource.
*
* @author jtremeaux
*/
public class TestThemeResource extends BaseJerseyTest {
/**
* Test the theme resource.
*
* @throws JSONException
*/
@Test
public void testThemeResource() throws JSONException {
WebResource themeResource = resource().path("/theme");
ClientResponse response = themeResource.get(ClientResponse.class);
response = themeResource.get(ClientResponse.class);
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
JSONObject json = response.getEntity(JSONObject.class);
JSONArray theme = json.getJSONArray("themes");
Assert.assertTrue(theme.length() > 0);
}
}

View File

@ -1,18 +1,19 @@
package com.sismics.docs.rest; package com.sismics.docs.rest;
import com.sismics.docs.rest.filter.CookieAuthenticationFilter; import java.util.Locale;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.ClientResponse.Status; import javax.json.JsonArray;
import com.sun.jersey.api.client.WebResource; import javax.json.JsonObject;
import com.sun.jersey.core.util.MultivaluedMapImpl; import javax.ws.rs.client.Entity;
import junit.framework.Assert; import javax.ws.rs.core.Form;
import org.codehaus.jettison.json.JSONArray; import javax.ws.rs.core.Response;
import org.codehaus.jettison.json.JSONException; import javax.ws.rs.core.Response.Status;
import org.codehaus.jettison.json.JSONObject;
import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import javax.ws.rs.core.MultivaluedMap; import com.sismics.util.filter.TokenBasedSecurityFilter;
import java.util.Locale;
/** /**
* Exhaustive test of the user resource. * Exhaustive test of the user resource.
@ -26,12 +27,11 @@ public class TestUserResource extends BaseJerseyTest {
* @throws JSONException * @throws JSONException
*/ */
@Test @Test
public void testUserResource() throws JSONException { public void testUserResource() {
// Check anonymous user information // Check anonymous user information
WebResource userResource = resource().path("/user"); JsonObject json = target().path("/user").request()
ClientResponse response = userResource.acceptLanguage(Locale.US).get(ClientResponse.class); .acceptLanguage(Locale.US)
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); .get(JsonObject.class);
JSONObject json = response.getEntity(JSONObject.class);
Assert.assertTrue(json.getBoolean("is_default_password")); Assert.assertTrue(json.getBoolean("is_default_password"));
// Create alice user // Create alice user
@ -41,95 +41,82 @@ public class TestUserResource extends BaseJerseyTest {
String adminAuthenticationToken = clientUtil.login("admin", "admin", false); String adminAuthenticationToken = clientUtil.login("admin", "admin", false);
// List all users // List all users
userResource = resource().path("/user/list"); json = target().path("/user/list")
userResource.addFilter(new CookieAuthenticationFilter(adminAuthenticationToken)); .queryParam("sort_column", 2)
MultivaluedMapImpl getParams = new MultivaluedMapImpl(); .queryParam("asc", false)
getParams.putSingle("sort_column", 2); .request()
getParams.putSingle("asc", false); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminAuthenticationToken)
response = userResource.queryParams(getParams).get(ClientResponse.class); .get(JsonObject.class);
json = response.getEntity(JSONObject.class); JsonArray users = json.getJsonArray("users");
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); Assert.assertTrue(users.size() > 0);
JSONArray users = json.getJSONArray("users");
Assert.assertTrue(users.length() > 0);
// Create a user KO (login length validation) // Create a user KO (login length validation)
userResource = resource().path("/user"); Response response = target().path("/user").request()
userResource.addFilter(new CookieAuthenticationFilter(adminAuthenticationToken)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminAuthenticationToken)
MultivaluedMapImpl postParams = new MultivaluedMapImpl(); .put(Entity.form(new Form()
postParams.putSingle("username", " bb "); .param("username", " bb ")
postParams.putSingle("email", "bob@docs.com"); .param("email", "bob@docs.com")
postParams.putSingle("password", "12345678"); .param("password", "12345678")));
response = userResource.put(ClientResponse.class, postParams);
Assert.assertEquals(Status.BAD_REQUEST, Status.fromStatusCode(response.getStatus())); Assert.assertEquals(Status.BAD_REQUEST, Status.fromStatusCode(response.getStatus()));
json = response.getEntity(JSONObject.class); json = response.readEntity(JsonObject.class);
Assert.assertEquals("ValidationError", json.getString("type")); Assert.assertEquals("ValidationError", json.getString("type"));
Assert.assertTrue(json.getString("message"), json.getString("message").contains("more than 3")); Assert.assertTrue(json.getString("message"), json.getString("message").contains("more than 3"));
// Create a user KO (login format validation) // Create a user KO (login format validation)
userResource = resource().path("/user"); response = target().path("/user").request()
userResource.addFilter(new CookieAuthenticationFilter(adminAuthenticationToken)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminAuthenticationToken)
postParams = new MultivaluedMapImpl(); .put(Entity.form(new Form()
postParams.putSingle("username", "bob-"); .param("username", "bob-")
postParams.putSingle("email", " bob@docs.com "); .param("email", "bob@docs.com")
postParams.putSingle("password", "12345678"); .param("password", "12345678")));
response = userResource.put(ClientResponse.class, postParams);
Assert.assertEquals(Status.BAD_REQUEST, Status.fromStatusCode(response.getStatus())); Assert.assertEquals(Status.BAD_REQUEST, Status.fromStatusCode(response.getStatus()));
json = response.getEntity(JSONObject.class); json = response.readEntity(JsonObject.class);
Assert.assertEquals("ValidationError", json.getString("type")); Assert.assertEquals("ValidationError", json.getString("type"));
Assert.assertTrue(json.getString("message"), json.getString("message").contains("alphanumeric")); Assert.assertTrue(json.getString("message"), json.getString("message").contains("alphanumeric"));
// Create a user KO (email format validation) // Create a user KO (email format validation)
userResource = resource().path("/user"); response = target().path("/user").request()
userResource.addFilter(new CookieAuthenticationFilter(adminAuthenticationToken)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminAuthenticationToken)
postParams = new MultivaluedMapImpl(); .put(Entity.form(new Form()
postParams.putSingle("username", "bob"); .param("username", "bob")
postParams.putSingle("email", " bobdocs.com "); .param("email", "bobdocs.com")
postParams.putSingle("password", "12345678"); .param("password", "12345678")));
response = userResource.put(ClientResponse.class, postParams);
Assert.assertEquals(Status.BAD_REQUEST, Status.fromStatusCode(response.getStatus())); Assert.assertEquals(Status.BAD_REQUEST, Status.fromStatusCode(response.getStatus()));
json = response.getEntity(JSONObject.class); json = response.readEntity(JsonObject.class);
Assert.assertEquals("ValidationError", json.getString("type")); Assert.assertEquals("ValidationError", json.getString("type"));
Assert.assertTrue(json.getString("message"), json.getString("message").contains("must be an email")); Assert.assertTrue(json.getString("message"), json.getString("message").contains("must be an email"));
// Create a user bob OK // Create a user bob OK
userResource = resource().path("/user"); Form form = new Form()
userResource.addFilter(new CookieAuthenticationFilter(adminAuthenticationToken)); .param("username", " bob ")
postParams = new MultivaluedMapImpl(); .param("email", " bob@docs.com ")
postParams.putSingle("username", " bob "); .param("password", " 12345678 ");
postParams.putSingle("email", " bob@docs.com "); json = target().path("/user").request()
postParams.putSingle("password", " 12345678 "); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminAuthenticationToken)
postParams.putSingle("locale", "fr"); .put(Entity.form(form), JsonObject.class);
response = userResource.put(ClientResponse.class, postParams);
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
// Create a user bob KO : duplicate username // Create a user bob KO : duplicate username
response = userResource.put(ClientResponse.class, postParams); response = target().path("/user").request()
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminAuthenticationToken)
.put(Entity.form(form));
Assert.assertNotSame(Status.OK, Status.fromStatusCode(response.getStatus())); Assert.assertNotSame(Status.OK, Status.fromStatusCode(response.getStatus()));
json = response.getEntity(JSONObject.class); json = response.readEntity(JsonObject.class);
Assert.assertEquals("AlreadyExistingUsername", json.getString("type")); Assert.assertEquals("AlreadyExistingUsername", json.getString("type"));
// Check if a username is free : OK // Check if a username is free : OK
userResource = resource().path("/user/check_username"); target().path("/user/check_username").queryParam("username", "carol").request().get(JsonObject.class);
MultivaluedMap<String, String> queryParams = new MultivaluedMapImpl();
queryParams.add("username", "carol");
response = userResource.queryParams(queryParams).get(ClientResponse.class);
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
// Check if a username is free : KO // Check if a username is free : KO
userResource = resource().path("/user/check_username"); response = target().path("/user/check_username").queryParam("username", "alice").request().get();
queryParams = new MultivaluedMapImpl();
queryParams.add("username", "alice");
response = userResource.queryParams(queryParams).get(ClientResponse.class);
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
json = response.getEntity(JSONObject.class); json = response.readEntity(JsonObject.class);
Assert.assertEquals("ko", json.getString("status")); Assert.assertEquals("ko", json.getString("status"));
// Login alice with extra whitespaces // Login alice with extra whitespaces
userResource = resource().path("/user/login"); response = target().path("/user/login").request()
postParams = new MultivaluedMapImpl(); .post(Entity.form(new Form()
postParams.putSingle("username", " alice "); .param("username", " alice ")
postParams.putSingle("password", " 12345678 "); .param("password", " 12345678 ")));
response = userResource.post(ClientResponse.class, postParams);
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
String aliceAuthToken = clientUtil.getAuthenticationCookie(response); String aliceAuthToken = clientUtil.getAuthenticationCookie(response);
@ -138,95 +125,80 @@ public class TestUserResource extends BaseJerseyTest {
String bobAuthToken2 = clientUtil.login("bob"); String bobAuthToken2 = clientUtil.login("bob");
// List sessions // List sessions
userResource = resource().path("/user/session"); response = target().path("/user/session").request()
userResource.addFilter(new CookieAuthenticationFilter(bobAuthToken)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, bobAuthToken)
response = userResource.get(ClientResponse.class); .get();
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
json = response.getEntity(JSONObject.class); json = response.readEntity(JsonObject.class);
Assert.assertTrue(json.getJSONArray("sessions").length() > 0); Assert.assertTrue(json.getJsonArray("sessions").size() > 0);
JSONObject session = json.getJSONArray("sessions").getJSONObject(0); JsonObject session = json.getJsonArray("sessions").getJsonObject(0);
Assert.assertEquals("127.0.0.1", session.getString("ip")); Assert.assertEquals("127.0.0.1", session.getString("ip"));
Assert.assertTrue(session.getString("user_agent").startsWith("Java")); Assert.assertTrue(session.getString("user_agent").startsWith("Jersey"));
// Delete all sessions // Delete all sessions
userResource = resource().path("/user/session"); response = target().path("/user/session").request()
userResource.addFilter(new CookieAuthenticationFilter(bobAuthToken)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, bobAuthToken)
response = userResource.delete(ClientResponse.class); .delete();
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
// Check bob user information with token 2 (just deleted) // Check bob user information with token 2 (just deleted)
userResource = resource().path("/user"); response = target().path("/user").request()
userResource.addFilter(new CookieAuthenticationFilter(bobAuthToken2)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, bobAuthToken2)
response = userResource.get(ClientResponse.class); .get();
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
json = response.getEntity(JSONObject.class); json = response.readEntity(JsonObject.class);
Assert.assertEquals(true, json.getBoolean("anonymous")); Assert.assertEquals(true, json.getBoolean("anonymous"));
// Check alice user information // Check alice user information
userResource = resource().path("/user"); json = target().path("/user").request()
userResource.addFilter(new CookieAuthenticationFilter(aliceAuthToken)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, aliceAuthToken)
response = userResource.get(ClientResponse.class); .get(JsonObject.class);
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
json = response.getEntity(JSONObject.class);
Assert.assertEquals("alice@docs.com", json.getString("email")); Assert.assertEquals("alice@docs.com", json.getString("email"));
Assert.assertEquals("default.less", json.getString("theme"));
Assert.assertFalse(json.getBoolean("first_connection"));
Assert.assertFalse(json.getBoolean("is_default_password")); Assert.assertFalse(json.getBoolean("is_default_password"));
// Check bob user information // Check bob user information
userResource = resource().path("/user"); json = target().path("/user").request()
userResource.addFilter(new CookieAuthenticationFilter(bobAuthToken)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, bobAuthToken)
response = userResource.get(ClientResponse.class); .get(JsonObject.class);
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
json = response.getEntity(JSONObject.class);
Assert.assertEquals("bob@docs.com", json.getString("email")); Assert.assertEquals("bob@docs.com", json.getString("email"));
Assert.assertEquals("fr", json.getString("locale"));
// Test login KO (user not found) // Test login KO (user not found)
userResource = resource().path("/user/login"); response = target().path("/user/login").request()
postParams.putSingle("username", "intruder"); .post(Entity.form(new Form()
postParams.putSingle("password", "12345678"); .param("username", "intruder")
response = userResource.post(ClientResponse.class, postParams); .param("password", "12345678")));
Assert.assertEquals(Status.FORBIDDEN, Status.fromStatusCode(response.getStatus())); Assert.assertEquals(Status.FORBIDDEN, Status.fromStatusCode(response.getStatus()));
// Test login KO (wrong password) // Test login KO (wrong password)
userResource = resource().path("/user/login"); response = target().path("/user/login").request()
postParams.putSingle("username", "alice"); .post(Entity.form(new Form()
postParams.putSingle("password", "error"); .param("username", "alice")
response = userResource.post(ClientResponse.class, postParams); .param("password", "error")));
Assert.assertEquals(Status.FORBIDDEN, Status.fromStatusCode(response.getStatus())); Assert.assertEquals(Status.FORBIDDEN, Status.fromStatusCode(response.getStatus()));
// User alice updates her information + changes her email // User alice updates her information + changes her email
userResource = resource().path("/user"); json = target().path("/user").request()
userResource.addFilter(new CookieAuthenticationFilter(aliceAuthToken)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, aliceAuthToken)
postParams = new MultivaluedMapImpl(); .post(Entity.form(new Form()
postParams.add("email", " alice2@docs.com "); .param("email", " alice2@docs.com ")), JsonObject.class);
postParams.add("theme", " default.less ");
postParams.add("locale", " en ");
response = userResource.post(ClientResponse.class, postParams);
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
json = response.getEntity(JSONObject.class);
Assert.assertEquals("ok", json.getString("status")); Assert.assertEquals("ok", json.getString("status"));
// Check the update // Check the update
userResource = resource().path("/user"); json = target().path("/user").request()
userResource.addFilter(new CookieAuthenticationFilter(aliceAuthToken)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, aliceAuthToken)
response = userResource.get(ClientResponse.class); .get(JsonObject.class);
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
json = response.getEntity(JSONObject.class);
Assert.assertEquals("alice2@docs.com", json.getString("email")); Assert.assertEquals("alice2@docs.com", json.getString("email"));
// Delete user alice // Delete user alice
userResource = resource().path("/user"); target().path("/user").request()
userResource.addFilter(new CookieAuthenticationFilter(aliceAuthToken)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, aliceAuthToken)
response = userResource.delete(ClientResponse.class); .delete();
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
// Check the deletion // Check the deletion
userResource = resource().path("/user/login"); response = target().path("/user/login").request()
postParams.putSingle("username", "alice"); .post(Entity.form(new Form()
postParams.putSingle("password", "12345678"); .param("username", "alice")
response = userResource.post(ClientResponse.class, postParams); .param("password", "12345678")));
Assert.assertEquals(Status.FORBIDDEN, Status.fromStatusCode(response.getStatus())); Assert.assertEquals(Status.FORBIDDEN, Status.fromStatusCode(response.getStatus()));
} }
@ -236,86 +208,59 @@ public class TestUserResource extends BaseJerseyTest {
* @throws JSONException * @throws JSONException
*/ */
@Test @Test
public void testUserResourceAdmin() throws JSONException { public void testUserResourceAdmin() {
// Create admin_user1 user // Create admin_user1 user
clientUtil.createUser("admin_user1"); clientUtil.createUser("admin_user1");
// Login admin // Login admin
String adminAuthenticationToken = clientUtil.login("admin", "admin", false); String adminAuthenticationToken = clientUtil.login("admin", "admin", false);
// Check admin information // Check admin information
WebResource userResource = resource().path("/user"); JsonObject json = target().path("/user").request()
userResource.addFilter(new CookieAuthenticationFilter(adminAuthenticationToken)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminAuthenticationToken)
ClientResponse response = userResource.get(ClientResponse.class); .get(JsonObject.class);
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
JSONObject json = response.getEntity(JSONObject.class);
Assert.assertTrue(json.getBoolean("first_connection"));
Assert.assertTrue(json.getBoolean("is_default_password")); Assert.assertTrue(json.getBoolean("is_default_password"));
// User admin updates his information // User admin updates his information
userResource = resource().path("/user"); json = target().path("/user").request()
userResource.addFilter(new CookieAuthenticationFilter(adminAuthenticationToken)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminAuthenticationToken)
MultivaluedMapImpl postParams = new MultivaluedMapImpl(); .post(Entity.form(new Form()
postParams.add("first_connection", false); .param("email", "newadminemail@docs.com")), JsonObject.class);
response = userResource.post(ClientResponse.class, postParams);
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
json = response.getEntity(JSONObject.class);
Assert.assertEquals("ok", json.getString("status")); Assert.assertEquals("ok", json.getString("status"));
// Check admin information update // Check admin information update
userResource = resource().path("/user"); json = target().path("/user").request()
userResource.addFilter(new CookieAuthenticationFilter(adminAuthenticationToken)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminAuthenticationToken)
response = userResource.get(ClientResponse.class); .get(JsonObject.class);
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); Assert.assertEquals("newadminemail@docs.com", json.getString("email"));
json = response.getEntity(JSONObject.class);
Assert.assertFalse(json.getBoolean("first_connection"));
// User admin update admin_user1 information // User admin update admin_user1 information
userResource = resource().path("/user"); json = target().path("/user").request()
userResource.addFilter(new CookieAuthenticationFilter(adminAuthenticationToken)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminAuthenticationToken)
postParams = new MultivaluedMapImpl(); .post(Entity.form(new Form()
postParams.add("email", " alice2@reader.com "); .param("email", " alice2@docs.com ")), JsonObject.class);
postParams.add("theme", " default.less");
postParams.add("locale", " en ");
postParams.add("display_title_web", true);
postParams.add("display_title_mobile", false);
postParams.add("display_unread_web", false);
postParams.add("display_unread_mobile", false);
response = userResource.post(ClientResponse.class, postParams);
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
json = response.getEntity(JSONObject.class);
Assert.assertEquals("ok", json.getString("status")); Assert.assertEquals("ok", json.getString("status"));
// User admin deletes himself: forbidden // User admin deletes himself: forbidden
userResource = resource().path("/user"); Response response = target().path("/user").request()
userResource.addFilter(new CookieAuthenticationFilter(adminAuthenticationToken)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminAuthenticationToken)
response = userResource.delete(ClientResponse.class); .delete();
Assert.assertEquals(Status.BAD_REQUEST, Status.fromStatusCode(response.getStatus())); Assert.assertEquals(Status.BAD_REQUEST, Status.fromStatusCode(response.getStatus()));
json = response.getEntity(JSONObject.class); json = response.readEntity(JsonObject.class);
Assert.assertEquals("ForbiddenError", json.getString("type"));
// User admin deletes himself: forbidden
userResource = resource().path("/user/admin");
userResource.addFilter(new CookieAuthenticationFilter(adminAuthenticationToken));
response = userResource.delete(ClientResponse.class);
Assert.assertEquals(Status.BAD_REQUEST, Status.fromStatusCode(response.getStatus()));
json = response.getEntity(JSONObject.class);
Assert.assertEquals("ForbiddenError", json.getString("type")); Assert.assertEquals("ForbiddenError", json.getString("type"));
// User admin deletes user admin_user1 // User admin deletes user admin_user1
userResource = resource().path("/user/admin_user1"); json = target().path("/user/admin_user1").request()
userResource.addFilter(new CookieAuthenticationFilter(adminAuthenticationToken)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminAuthenticationToken)
response = userResource.delete(ClientResponse.class); .delete(JsonObject.class);
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
json = response.getEntity(JSONObject.class);
Assert.assertEquals("ok", json.getString("status")); Assert.assertEquals("ok", json.getString("status"));
// User admin deletes user admin_user1 : KO (user doesn't exist) // User admin deletes user admin_user1 : KO (user doesn't exist)
userResource = resource().path("/user/admin_user1"); response = target().path("/user/admin_user1").request()
userResource.addFilter(new CookieAuthenticationFilter(adminAuthenticationToken)); .cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminAuthenticationToken)
response = userResource.delete(ClientResponse.class); .delete();
Assert.assertEquals(Status.BAD_REQUEST, Status.fromStatusCode(response.getStatus())); Assert.assertEquals(Status.BAD_REQUEST, Status.fromStatusCode(response.getStatus()));
json = response.getEntity(JSONObject.class); json = response.readEntity(JsonObject.class);
Assert.assertEquals("UserNotFound", json.getString("type")); Assert.assertEquals("UserNotFound", json.getString("type"));
} }
} }