mirror of
https://github.com/sismics/docs.git
synced 2024-11-14 18:27:58 +01:00
#79: POST /theme/color to change the main color
This commit is contained in:
parent
55cdca0c7d
commit
4e768e9103
@ -10,4 +10,8 @@ public enum ConfigType {
|
|||||||
* Lucene directory storage type.
|
* Lucene directory storage type.
|
||||||
*/
|
*/
|
||||||
LUCENE_DIRECTORY_STORAGE,
|
LUCENE_DIRECTORY_STORAGE,
|
||||||
|
/**
|
||||||
|
* Theme configuration.
|
||||||
|
*/
|
||||||
|
THEME
|
||||||
}
|
}
|
||||||
|
@ -33,4 +33,23 @@ public class ConfigDao {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates a configuration parameter.
|
||||||
|
*
|
||||||
|
* @param id Configuration parameter ID
|
||||||
|
* @param value Configuration parameter value
|
||||||
|
*/
|
||||||
|
public void update(ConfigType id, String value) {
|
||||||
|
EntityManager em = ThreadLocalContext.get().getEntityManager();
|
||||||
|
Config config = getById(id);
|
||||||
|
if (config == null) {
|
||||||
|
config = new Config();
|
||||||
|
config.setId(id);
|
||||||
|
config.setValue(value);
|
||||||
|
em.persist(config);
|
||||||
|
} else {
|
||||||
|
config.setValue(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,9 +21,7 @@ public class ContributorDao {
|
|||||||
* Creates a new contributor.
|
* Creates a new contributor.
|
||||||
*
|
*
|
||||||
* @param contributor Contributor
|
* @param contributor Contributor
|
||||||
* @param userId User ID
|
|
||||||
* @return New ID
|
* @return New ID
|
||||||
* @throws Exception
|
|
||||||
*/
|
*/
|
||||||
public String create(Contributor contributor) {
|
public String create(Contributor contributor) {
|
||||||
// Create the UUID
|
// Create the UUID
|
||||||
@ -72,7 +70,7 @@ public class ContributorDao {
|
|||||||
int i = 0;
|
int i = 0;
|
||||||
ContributorDto contributorDto = new ContributorDto();
|
ContributorDto contributorDto = new ContributorDto();
|
||||||
contributorDto.setUsername((String) o[i++]);
|
contributorDto.setUsername((String) o[i++]);
|
||||||
contributorDto.setEmail((String) o[i++]);
|
contributorDto.setEmail((String) o[i]);
|
||||||
contributorDtoList.add(contributorDto);
|
contributorDtoList.add(contributorDto);
|
||||||
}
|
}
|
||||||
return contributorDtoList;
|
return contributorDtoList;
|
||||||
|
@ -25,7 +25,6 @@ public class FileDao {
|
|||||||
* @param file File
|
* @param file File
|
||||||
* @param userId User ID
|
* @param userId User ID
|
||||||
* @return New ID
|
* @return New ID
|
||||||
* @throws Exception
|
|
||||||
*/
|
*/
|
||||||
public String create(File file, String userId) {
|
public String create(File file, String userId) {
|
||||||
// Create the UUID
|
// Create the UUID
|
||||||
@ -169,7 +168,7 @@ public class FileDao {
|
|||||||
/**
|
/**
|
||||||
* Get files by document ID or all orphan files of an user.
|
* Get files by document ID or all orphan files of an user.
|
||||||
*
|
*
|
||||||
* @parma userId User ID
|
* @param userId User ID
|
||||||
* @param documentId Document ID
|
* @param documentId Document ID
|
||||||
* @return List of files
|
* @return List of files
|
||||||
*/
|
*/
|
||||||
|
@ -108,7 +108,7 @@ public class TagDao {
|
|||||||
sb.append(" where dt.DOT_IDDOCUMENT_C = :documentId and t.TAG_DELETEDATE_D is null ");
|
sb.append(" where dt.DOT_IDDOCUMENT_C = :documentId and t.TAG_DELETEDATE_D is null ");
|
||||||
sb.append(" and t.TAG_IDUSER_C = :userId and dt.DOT_DELETEDATE_D is null ");
|
sb.append(" and t.TAG_IDUSER_C = :userId and dt.DOT_DELETEDATE_D is null ");
|
||||||
sb.append(" order by t.TAG_NAME_C ");
|
sb.append(" order by t.TAG_NAME_C ");
|
||||||
|
|
||||||
// Perform the query
|
// Perform the query
|
||||||
Query q = em.createNativeQuery(sb.toString());
|
Query q = em.createNativeQuery(sb.toString());
|
||||||
q.setParameter("documentId", documentId);
|
q.setParameter("documentId", documentId);
|
||||||
@ -116,14 +116,14 @@ public class TagDao {
|
|||||||
List<Object[]> l = q.getResultList();
|
List<Object[]> l = q.getResultList();
|
||||||
|
|
||||||
// Assemble results
|
// Assemble results
|
||||||
List<TagDto> tagDtoList = new ArrayList<TagDto>();
|
List<TagDto> tagDtoList = new ArrayList<>();
|
||||||
for (Object[] o : l) {
|
for (Object[] o : l) {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
TagDto tagDto = new TagDto();
|
TagDto tagDto = new TagDto();
|
||||||
tagDto.setId((String) o[i++]);
|
tagDto.setId((String) o[i++]);
|
||||||
tagDto.setName((String) o[i++]);
|
tagDto.setName((String) o[i++]);
|
||||||
tagDto.setColor((String) o[i++]);
|
tagDto.setColor((String) o[i++]);
|
||||||
tagDto.setParentId((String) o[i++]);
|
tagDto.setParentId((String) o[i]);
|
||||||
tagDtoList.add(tagDto);
|
tagDtoList.add(tagDto);
|
||||||
}
|
}
|
||||||
return tagDtoList;
|
return tagDtoList;
|
||||||
@ -132,7 +132,7 @@ public class TagDao {
|
|||||||
/**
|
/**
|
||||||
* Returns stats on tags.
|
* Returns stats on tags.
|
||||||
*
|
*
|
||||||
* @param documentId Document ID
|
* @param userId User ID
|
||||||
* @return Stats by tag
|
* @return Stats by tag
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@ -145,14 +145,14 @@ public class TagDao {
|
|||||||
sb.append(" where t.TAG_IDUSER_C = :userId and t.TAG_DELETEDATE_D is null ");
|
sb.append(" where t.TAG_IDUSER_C = :userId and t.TAG_DELETEDATE_D is null ");
|
||||||
sb.append(" group by t.TAG_ID_C ");
|
sb.append(" group by t.TAG_ID_C ");
|
||||||
sb.append(" order by t.TAG_NAME_C ");
|
sb.append(" order by t.TAG_NAME_C ");
|
||||||
|
|
||||||
// Perform the query
|
// Perform the query
|
||||||
Query q = em.createNativeQuery(sb.toString());
|
Query q = em.createNativeQuery(sb.toString());
|
||||||
q.setParameter("userId", userId);
|
q.setParameter("userId", userId);
|
||||||
List<Object[]> l = q.getResultList();
|
List<Object[]> l = q.getResultList();
|
||||||
|
|
||||||
// Assemble results
|
// Assemble results
|
||||||
List<TagStatDto> tagStatDtoList = new ArrayList<TagStatDto>();
|
List<TagStatDto> tagStatDtoList = new ArrayList<>();
|
||||||
for (Object[] o : l) {
|
for (Object[] o : l) {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
TagStatDto tagDto = new TagStatDto();
|
TagStatDto tagDto = new TagStatDto();
|
||||||
@ -160,7 +160,7 @@ public class TagDao {
|
|||||||
tagDto.setName((String) o[i++]);
|
tagDto.setName((String) o[i++]);
|
||||||
tagDto.setColor((String) o[i++]);
|
tagDto.setColor((String) o[i++]);
|
||||||
tagDto.setParentId((String) o[i++]);
|
tagDto.setParentId((String) o[i++]);
|
||||||
tagDto.setCount(((Number) o[i++]).intValue());
|
tagDto.setCount(((Number) o[i]).intValue());
|
||||||
tagStatDtoList.add(tagDto);
|
tagStatDtoList.add(tagDto);
|
||||||
}
|
}
|
||||||
return tagStatDtoList;
|
return tagStatDtoList;
|
||||||
@ -172,7 +172,6 @@ public class TagDao {
|
|||||||
* @param tag Tag
|
* @param tag Tag
|
||||||
* @param userId User ID
|
* @param userId User ID
|
||||||
* @return New ID
|
* @return New ID
|
||||||
* @throws Exception
|
|
||||||
*/
|
*/
|
||||||
public String create(Tag tag, String userId) {
|
public String create(Tag tag, String userId) {
|
||||||
// Create the UUID
|
// Create the UUID
|
||||||
|
@ -11,7 +11,7 @@ public class ThreadLocalContext {
|
|||||||
/**
|
/**
|
||||||
* ThreadLocal to store the context.
|
* ThreadLocal to store the context.
|
||||||
*/
|
*/
|
||||||
public static final ThreadLocal<ThreadLocalContext> threadLocalContext = new ThreadLocal<ThreadLocalContext>();
|
private static final ThreadLocal<ThreadLocalContext> threadLocalContext = new ThreadLocal<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Entity manager.
|
* Entity manager.
|
||||||
@ -46,15 +46,6 @@ public class ThreadLocalContext {
|
|||||||
threadLocalContext.set(null);
|
threadLocalContext.set(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true only if the entity manager is defined.
|
|
||||||
*
|
|
||||||
* @return Condition
|
|
||||||
*/
|
|
||||||
public boolean isInTransactionalContext() {
|
|
||||||
return entityManager != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Getter of entityManager.
|
* Getter of entityManager.
|
||||||
*
|
*
|
||||||
|
@ -108,10 +108,9 @@ 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
|
||||||
* @param nullable True if the string can be empty or null
|
* @param nullable True if the string can be empty or null
|
||||||
* @throws JSONException
|
|
||||||
*/
|
*/
|
||||||
public static void validateHexColor(String s, String name, boolean nullable) throws ClientException {
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -57,9 +57,8 @@ public abstract class BaseResource {
|
|||||||
* Checks if the user has a base function. Throw an exception if the check fails.
|
* Checks if the user has a base function. Throw an exception if the check fails.
|
||||||
*
|
*
|
||||||
* @param baseFunction Base function to check
|
* @param baseFunction Base function to check
|
||||||
* @throws JSONException
|
|
||||||
*/
|
*/
|
||||||
protected void checkBaseFunction(BaseFunction baseFunction) {
|
void checkBaseFunction(BaseFunction baseFunction) {
|
||||||
if (!hasBaseFunction(baseFunction)) {
|
if (!hasBaseFunction(baseFunction)) {
|
||||||
throw new ForbiddenClientException();
|
throw new ForbiddenClientException();
|
||||||
}
|
}
|
||||||
@ -70,9 +69,8 @@ public abstract class BaseResource {
|
|||||||
*
|
*
|
||||||
* @param baseFunction Base function to check
|
* @param baseFunction Base function to check
|
||||||
* @return True if the user has the base function
|
* @return True if the user has the base function
|
||||||
* @throws JSONException
|
|
||||||
*/
|
*/
|
||||||
protected boolean hasBaseFunction(BaseFunction baseFunction) {
|
boolean hasBaseFunction(BaseFunction baseFunction) {
|
||||||
if (principal == null || !(principal instanceof UserPrincipal)) {
|
if (principal == null || !(principal instanceof UserPrincipal)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -86,7 +84,7 @@ public abstract class BaseResource {
|
|||||||
* @param shareId Share ID (optional)
|
* @param shareId Share ID (optional)
|
||||||
* @return List of ACL target ID
|
* @return List of ACL target ID
|
||||||
*/
|
*/
|
||||||
protected List<String> getTargetIdList(String shareId) {
|
List<String> getTargetIdList(String shareId) {
|
||||||
List<String> targetIdList = Lists.newArrayList(principal.getGroupIdSet());
|
List<String> targetIdList = Lists.newArrayList(principal.getGroupIdSet());
|
||||||
if (principal.getId() != null) {
|
if (principal.getId() != null) {
|
||||||
targetIdList.add(principal.getId());
|
targetIdList.add(principal.getId());
|
||||||
|
@ -64,7 +64,6 @@ public class TagResource extends BaseResource {
|
|||||||
* Returns stats on tags.
|
* Returns stats on tags.
|
||||||
*
|
*
|
||||||
* @return Response
|
* @return Response
|
||||||
* @throws JSONException
|
|
||||||
*/
|
*/
|
||||||
@GET
|
@GET
|
||||||
@Path("/stats")
|
@Path("/stats")
|
||||||
|
@ -1,12 +1,21 @@
|
|||||||
package com.sismics.docs.rest.resource;
|
package com.sismics.docs.rest.resource;
|
||||||
|
|
||||||
import javax.ws.rs.GET;
|
import javax.json.*;
|
||||||
import javax.ws.rs.Path;
|
import javax.ws.rs.*;
|
||||||
import javax.ws.rs.Produces;
|
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
|
|
||||||
|
import com.google.common.base.Strings;
|
||||||
|
import com.sismics.docs.core.constant.ConfigType;
|
||||||
|
import com.sismics.docs.core.dao.jpa.ConfigDao;
|
||||||
|
import com.sismics.docs.core.model.jpa.Config;
|
||||||
|
import com.sismics.docs.rest.constant.BaseFunction;
|
||||||
|
import com.sismics.rest.exception.ForbiddenClientException;
|
||||||
|
import com.sismics.rest.util.ValidationUtil;
|
||||||
import com.sismics.util.css.Selector;
|
import com.sismics.util.css.Selector;
|
||||||
|
|
||||||
|
import java.io.StringReader;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Theme REST resources.
|
* Theme REST resources.
|
||||||
*
|
*
|
||||||
@ -23,8 +32,75 @@ public class ThemeResource extends BaseResource {
|
|||||||
@Path("/stylesheet")
|
@Path("/stylesheet")
|
||||||
@Produces("text/css")
|
@Produces("text/css")
|
||||||
public Response stylesheet() {
|
public Response stylesheet() {
|
||||||
|
JsonObject themeConfig = getThemeConfig();
|
||||||
|
|
||||||
|
// Build the stylesheet
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
sb.append(new Selector("body"));
|
sb.append(new Selector(".navbar")
|
||||||
|
.rule("background-color", themeConfig.getString("color", "inherit")));
|
||||||
|
|
||||||
return Response.ok().entity(sb.toString()).build();
|
return Response.ok().entity(sb.toString()).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@POST
|
||||||
|
@Path("/color")
|
||||||
|
public Response color(@FormParam("color") String color) {
|
||||||
|
if (!authenticate()) {
|
||||||
|
throw new ForbiddenClientException();
|
||||||
|
}
|
||||||
|
checkBaseFunction(BaseFunction.ADMIN);
|
||||||
|
|
||||||
|
// Validate input data
|
||||||
|
ValidationUtil.validateHexColor(color, "color", true);
|
||||||
|
|
||||||
|
// Update the JSON
|
||||||
|
JsonObjectBuilder json = getMutableThemeConfig();
|
||||||
|
if (Strings.isNullOrEmpty(color)) {
|
||||||
|
json.add("color", JsonValue.NULL);
|
||||||
|
} else {
|
||||||
|
json.add("color", color);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Persist the new configuration
|
||||||
|
ConfigDao configDao = new ConfigDao();
|
||||||
|
configDao.update(ConfigType.THEME, json.build().toString());
|
||||||
|
|
||||||
|
// Always return OK
|
||||||
|
JsonObjectBuilder response = Json.createObjectBuilder()
|
||||||
|
.add("status", "ok");
|
||||||
|
return Response.ok().entity(response.build()).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the theme configuration object.
|
||||||
|
*
|
||||||
|
* @return Theme configuration
|
||||||
|
*/
|
||||||
|
private JsonObject getThemeConfig() {
|
||||||
|
ConfigDao configDao = new ConfigDao();
|
||||||
|
Config themeConfig = configDao.getById(ConfigType.THEME);
|
||||||
|
if (themeConfig == null) {
|
||||||
|
return Json.createObjectBuilder().build();
|
||||||
|
}
|
||||||
|
|
||||||
|
try (JsonReader reader = Json.createReader(new StringReader(themeConfig.getValue()))) {
|
||||||
|
return reader.readObject();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a mutable theme configuration.
|
||||||
|
*
|
||||||
|
* @return Json builder
|
||||||
|
*/
|
||||||
|
private JsonObjectBuilder getMutableThemeConfig() {
|
||||||
|
JsonObject themeConfig = getThemeConfig();
|
||||||
|
JsonObjectBuilder json = Json.createObjectBuilder();
|
||||||
|
|
||||||
|
for (Map.Entry<String, JsonValue> entry : themeConfig.entrySet()) {
|
||||||
|
json.add(entry.getKey(), entry.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
return json;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,13 @@
|
|||||||
package com.sismics.docs.rest;
|
package com.sismics.docs.rest;
|
||||||
|
|
||||||
|
import com.sismics.util.filter.TokenBasedSecurityFilter;
|
||||||
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import javax.json.JsonObject;
|
||||||
|
import javax.ws.rs.client.Entity;
|
||||||
|
import javax.ws.rs.core.Form;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test the theme resource.
|
* Test the theme resource.
|
||||||
*
|
*
|
||||||
@ -13,9 +19,23 @@ public class TestThemeResource extends BaseJerseyTest {
|
|||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testThemeResource() {
|
public void testThemeResource() {
|
||||||
|
// Login admin
|
||||||
|
String adminToken = clientUtil.login("admin", "admin", false);
|
||||||
|
|
||||||
// Get the stylesheet anonymously
|
// Get the stylesheet anonymously
|
||||||
String stylesheet = target().path("/theme/stylesheet").request()
|
String stylesheet = target().path("/theme/stylesheet").request()
|
||||||
.get(String.class);
|
.get(String.class);
|
||||||
System.out.println(stylesheet);
|
Assert.assertTrue(stylesheet.contains("background-color: inherit;"));
|
||||||
|
|
||||||
|
// Update the main color as admin
|
||||||
|
target().path("/theme/color").request()
|
||||||
|
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminToken)
|
||||||
|
.post(Entity.form(new Form()
|
||||||
|
.param("color", "#ff0000")), JsonObject.class);
|
||||||
|
|
||||||
|
// Get the stylesheet anonymously
|
||||||
|
stylesheet = target().path("/theme/stylesheet").request()
|
||||||
|
.get(String.class);
|
||||||
|
Assert.assertTrue(stylesheet.contains("background-color: #ff0000;"));
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user