Initial commit.
This commit is contained in:
14
src/main/java/org/codiki/CodikiApplication.java
Normal file
14
src/main/java/org/codiki/CodikiApplication.java
Normal file
@@ -0,0 +1,14 @@
|
||||
package org.codiki;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
@EnableAutoConfiguration
|
||||
public class CodikiApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(CodikiApplication.class, args);
|
||||
}
|
||||
}
|
||||
42
src/main/java/org/codiki/config/JpaConfiguration.java
Normal file
42
src/main/java/org/codiki/config/JpaConfiguration.java
Normal file
@@ -0,0 +1,42 @@
|
||||
package org.codiki.config;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.autoconfigure.domain.EntityScan;
|
||||
import org.springframework.boot.jdbc.DataSourceBuilder;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.PropertySource;
|
||||
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
|
||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
|
||||
@Configuration
|
||||
@EntityScan("org.codiki")
|
||||
@EnableTransactionManagement
|
||||
@EnableJpaRepositories("org.codiki")
|
||||
@PropertySource("classpath:application.properties")
|
||||
public class JpaConfiguration {
|
||||
|
||||
@Value("${spring.datasource.driverClassName}")
|
||||
private String driverClassName;
|
||||
|
||||
@Value("${spring.datasource.url}")
|
||||
private String url;
|
||||
|
||||
@Value("${spring.datasource.username}")
|
||||
private String username;
|
||||
|
||||
@Value("${spring.datasource.password}")
|
||||
private String password;
|
||||
|
||||
@Bean(name="dataSource")
|
||||
public DataSource getDataSource() {
|
||||
return DataSourceBuilder.create()
|
||||
.username(username)
|
||||
.password(password)
|
||||
.url(url)
|
||||
.driverClassName(driverClassName)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
103
src/main/java/org/codiki/core/AbstractFilter.java
Normal file
103
src/main/java/org/codiki/core/AbstractFilter.java
Normal file
@@ -0,0 +1,103 @@
|
||||
package org.codiki.core;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
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.HttpServletRequest;
|
||||
|
||||
import org.codiki.security.Route;
|
||||
import org.codiki.utils.StringUtils;
|
||||
|
||||
/**
|
||||
* Base class for all filters of the application.<br/>
|
||||
* <br/>
|
||||
* The children classes have to implements the method
|
||||
* {@link AbstractFilter#getClass()} to set the URLs filtered (with all or some
|
||||
* http methods), and the method
|
||||
* {@link AbstractFilter#filter(HttpServletRequest, ServletResponse, FilterChain)}
|
||||
* to define the filter processing.
|
||||
*
|
||||
* @author Takiguchi
|
||||
*
|
||||
*/
|
||||
public abstract class AbstractFilter implements Filter {
|
||||
|
||||
/** Regex url path prefix for method {@link this#isRequestFiltered(String)}. */
|
||||
private static final String PREFIX_URL_PATH = "https?:\\/\\/.*(:\\d{0,5})?";
|
||||
|
||||
@Override
|
||||
public void init(FilterConfig filterConfig) throws ServletException {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of routes which will be processed by the filter.
|
||||
*
|
||||
* @return The routes.
|
||||
*/
|
||||
protected abstract List<Route> getRoutes();
|
||||
|
||||
/**
|
||||
* Filter actions for its processing.
|
||||
*
|
||||
* @param request
|
||||
* The http request.
|
||||
* @param response
|
||||
* The response.
|
||||
* @param chain
|
||||
* The chain.
|
||||
*/
|
||||
protected abstract void filter(HttpServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException;
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
|
||||
throws IOException, ServletException {
|
||||
HttpServletRequest httpRequest = (HttpServletRequest) request;
|
||||
|
||||
if(isRequestFiltered(httpRequest.getRequestURL().toString(), httpRequest.getMethod())) {
|
||||
filter(httpRequest, response, chain);
|
||||
} else {
|
||||
chain.doFilter(request, response);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the url is allowed with the given method in parameters.
|
||||
*
|
||||
* @param pUrlRequest
|
||||
* The url request.
|
||||
* @param pMethodRequest
|
||||
* The http method of the request.
|
||||
* @return {@code true} if the url is allowed with the method, {@code false}
|
||||
* otherwise.
|
||||
*/
|
||||
boolean isRequestFiltered(final String pUrlRequest, final String pMethodRequest) {
|
||||
boolean result = false;
|
||||
|
||||
for(final Route route : getRoutes()) {
|
||||
/*
|
||||
* Check urls matching, and if the method of the route isn't set, all methods
|
||||
* are allowed. Otherwise, we check the methods too.
|
||||
*/
|
||||
result = Pattern.matches(StringUtils.concat(PREFIX_URL_PATH, route.getUrl()), pUrlRequest)
|
||||
&& (!route.getMethod().isPresent() || pMethodRequest.equals(route.getMethod().get().toString()));
|
||||
if(result) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
103
src/main/java/org/codiki/entities/dto/UserDAO.java
Normal file
103
src/main/java/org/codiki/entities/dto/UserDAO.java
Normal file
@@ -0,0 +1,103 @@
|
||||
package org.codiki.entities.dto;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import org.codiki.entities.persistence.Role;
|
||||
import org.codiki.entities.persistence.User;
|
||||
|
||||
public class UserDAO {
|
||||
|
||||
private String key;
|
||||
|
||||
private String name;
|
||||
|
||||
private String email;
|
||||
|
||||
private String password;
|
||||
|
||||
private String image;
|
||||
|
||||
private Date inscriptionDate;
|
||||
|
||||
private Role role;
|
||||
|
||||
private String token;
|
||||
|
||||
public UserDAO() {
|
||||
super();
|
||||
}
|
||||
|
||||
public UserDAO(final User pUser) {
|
||||
key = pUser.getKey();
|
||||
name = pUser.getName();
|
||||
email = pUser.getEmail();
|
||||
image = pUser.getImage();
|
||||
inscriptionDate = pUser.getInscriptionDate();
|
||||
role = pUser.getRole();
|
||||
token = pUser.getToken().getValue();
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public void setKey(String key) {
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
public void setEmail(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public String getImage() {
|
||||
return image;
|
||||
}
|
||||
|
||||
public void setImage(String image) {
|
||||
this.image = image;
|
||||
}
|
||||
|
||||
public Date getInscriptionDate() {
|
||||
return inscriptionDate;
|
||||
}
|
||||
|
||||
public void setInscriptionDate(Date inscriptionDate) {
|
||||
this.inscriptionDate = inscriptionDate;
|
||||
}
|
||||
|
||||
public Role getRole() {
|
||||
return role;
|
||||
}
|
||||
|
||||
public void setRole(Role role) {
|
||||
this.role = role;
|
||||
}
|
||||
|
||||
public String getToken() {
|
||||
return token;
|
||||
}
|
||||
|
||||
public void setToken(String token) {
|
||||
this.token = token;
|
||||
}
|
||||
}
|
||||
78
src/main/java/org/codiki/entities/persistence/Category.java
Normal file
78
src/main/java/org/codiki/entities/persistence/Category.java
Normal file
@@ -0,0 +1,78 @@
|
||||
package org.codiki.entities.persistence;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Inheritance;
|
||||
import javax.persistence.InheritanceType;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.Table;
|
||||
|
||||
@Entity
|
||||
@Table(name="category")
|
||||
@Inheritance(strategy = InheritanceType.JOINED)
|
||||
public class Category implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/* ******************* */
|
||||
/* Attributes */
|
||||
/* ******************* */
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
private String name;
|
||||
|
||||
/* ******************* */
|
||||
/* Relations */
|
||||
/* ******************* */
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "creator_id")
|
||||
protected User creator;
|
||||
|
||||
@OneToMany(mappedBy = "mainCategory")
|
||||
private List<SubCategory> listSubCategories;
|
||||
|
||||
@OneToMany(mappedBy = "category")
|
||||
protected List<Post> listPosts;
|
||||
|
||||
/* ******************* */
|
||||
/* Getters & Setters */
|
||||
/* ******************* */
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
if(this.id != null) {
|
||||
throw new IllegalAccessError("It's not allowed to rewrite the id entity.");
|
||||
}
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public User getCreator() {
|
||||
return creator;
|
||||
}
|
||||
|
||||
public void setCreator(User creator) {
|
||||
this.creator = creator;
|
||||
}
|
||||
|
||||
public List<SubCategory> getListSubCategories() {
|
||||
return listSubCategories;
|
||||
}
|
||||
}
|
||||
102
src/main/java/org/codiki/entities/persistence/Comment.java
Normal file
102
src/main/java/org/codiki/entities/persistence/Comment.java
Normal file
@@ -0,0 +1,102 @@
|
||||
package org.codiki.entities.persistence;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Temporal;
|
||||
import javax.persistence.TemporalType;
|
||||
|
||||
@Entity
|
||||
@Table(name="comment")
|
||||
public class Comment implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/* ******************* */
|
||||
/* Attributes */
|
||||
/* ******************* */
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
private String key;
|
||||
|
||||
private String text;
|
||||
|
||||
@Column(name = "creation_date")
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
private Date creationDate;
|
||||
|
||||
/* ******************* */
|
||||
/* Relations */
|
||||
/* ******************* */
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "author")
|
||||
private User author;
|
||||
|
||||
@OneToMany(mappedBy = "comment")
|
||||
private List<CommentHistory> history;
|
||||
|
||||
/* ******************* */
|
||||
/* Getters & Setters */
|
||||
/* ******************* */
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
if(this.id != null) {
|
||||
throw new IllegalAccessError("It's not allowed to rewrite the id entity.");
|
||||
}
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public void setKey(String key) {
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
public void setText(String text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public Date getCreationDate() {
|
||||
return creationDate;
|
||||
}
|
||||
|
||||
public void setCreationDate(Date creationDate) {
|
||||
this.creationDate = creationDate;
|
||||
}
|
||||
|
||||
public User getAuthor() {
|
||||
return author;
|
||||
}
|
||||
|
||||
public void setAuthor(User author) {
|
||||
this.author = author;
|
||||
}
|
||||
|
||||
public List<CommentHistory> getHistory() {
|
||||
return history;
|
||||
}
|
||||
|
||||
public void setHistory(List<CommentHistory> history) {
|
||||
this.history = history;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package org.codiki.entities.persistence;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Temporal;
|
||||
import javax.persistence.TemporalType;
|
||||
|
||||
@Entity
|
||||
@Table(name="comment_history")
|
||||
public class CommentHistory implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/* ******************* */
|
||||
/* Attributes */
|
||||
/* ******************* */
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
private String text;
|
||||
|
||||
/* ******************* */
|
||||
/* Relations */
|
||||
/* ******************* */
|
||||
@Column(name = "update_date")
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
private Date updateDate;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "comment_id")
|
||||
private Comment comment;
|
||||
|
||||
/* ******************* */
|
||||
/* Getters & Setters */
|
||||
/* ******************* */
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
if(this.id != null) {
|
||||
throw new IllegalAccessError("It's not allowed to rewrite the id entity.");
|
||||
}
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
public void setText(String text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public Date getUpdateDate() {
|
||||
return updateDate;
|
||||
}
|
||||
|
||||
public void setUpdateDate(Date updateDate) {
|
||||
this.updateDate = updateDate;
|
||||
}
|
||||
|
||||
public Comment getComment() {
|
||||
return comment;
|
||||
}
|
||||
|
||||
public void setComment(Comment comment) {
|
||||
this.comment = comment;
|
||||
}
|
||||
|
||||
}
|
||||
72
src/main/java/org/codiki/entities/persistence/Image.java
Normal file
72
src/main/java/org/codiki/entities/persistence/Image.java
Normal file
@@ -0,0 +1,72 @@
|
||||
package org.codiki.entities.persistence;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Temporal;
|
||||
import javax.persistence.TemporalType;
|
||||
|
||||
@Entity
|
||||
@Table(name="image")
|
||||
public class Image implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/* ******************* */
|
||||
/* Attributes */
|
||||
/* ******************* */
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
private String link;
|
||||
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
private Date date;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "user_id")
|
||||
private User user;
|
||||
|
||||
/* ******************* */
|
||||
/* Getters & Setters */
|
||||
/* ******************* */
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getLink() {
|
||||
return link;
|
||||
}
|
||||
|
||||
public void setLink(String link) {
|
||||
this.link = link;
|
||||
}
|
||||
|
||||
public Date getDate() {
|
||||
return date;
|
||||
}
|
||||
|
||||
public void setDate(Date date) {
|
||||
this.date = date;
|
||||
}
|
||||
|
||||
public User getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
public void setUser(User user) {
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
}
|
||||
177
src/main/java/org/codiki/entities/persistence/Post.java
Normal file
177
src/main/java/org/codiki/entities/persistence/Post.java
Normal file
@@ -0,0 +1,177 @@
|
||||
package org.codiki.entities.persistence;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Temporal;
|
||||
import javax.persistence.TemporalType;
|
||||
|
||||
import org.codiki.utils.DateUtils;
|
||||
|
||||
@Entity
|
||||
@Table(name="post")
|
||||
public class Post implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** Number of character that compose the text extract. */
|
||||
private static final short EXTRACT_LENGTH = 250;
|
||||
|
||||
/* ******************* */
|
||||
/* Attributes */
|
||||
/* ******************* */
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
private String key;
|
||||
|
||||
private String title;
|
||||
|
||||
private String text;
|
||||
|
||||
@Column(length = 250)
|
||||
private String description;
|
||||
|
||||
private String image;
|
||||
|
||||
@Column(name = "creation_date")
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
private Date creationDate;
|
||||
|
||||
/* ******************* */
|
||||
/* Relations */
|
||||
/* ******************* */
|
||||
@ManyToOne(fetch = FetchType.EAGER)
|
||||
@JoinColumn(name = "creator_id")
|
||||
private User author;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "category_id")
|
||||
private Category category;
|
||||
|
||||
@OneToMany(mappedBy = "post", cascade = CascadeType.REMOVE)
|
||||
private List<PostHistory> history;
|
||||
|
||||
/* ******************* */
|
||||
/* Constructors */
|
||||
/* ******************* */
|
||||
public Post() {
|
||||
super();
|
||||
}
|
||||
|
||||
/* ******************* */
|
||||
/* Getters & Setters */
|
||||
/* ******************* */
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
if(this.id != null) {
|
||||
throw new IllegalAccessError("It's not allowed to rewrite the id entity.");
|
||||
}
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public void setKey(String key) {
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
public void setText(String text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getImage() {
|
||||
return image;
|
||||
}
|
||||
|
||||
public void setImage(String image) {
|
||||
this.image = image;
|
||||
}
|
||||
|
||||
public Date getCreationDate() {
|
||||
return creationDate;
|
||||
}
|
||||
|
||||
public void setCreationDate(Date creationDate) {
|
||||
this.creationDate = creationDate;
|
||||
}
|
||||
|
||||
public String getCreationDateStr() {
|
||||
if(creationDate == null) {
|
||||
return "";
|
||||
} else {
|
||||
return DateUtils.format(creationDate);
|
||||
}
|
||||
}
|
||||
|
||||
public String getTextExtract() {
|
||||
String extract = text;
|
||||
|
||||
if(extract != null && extract.length() > EXTRACT_LENGTH) {
|
||||
extract = extract.substring(0, EXTRACT_LENGTH) + "...";
|
||||
}
|
||||
|
||||
return extract;
|
||||
}
|
||||
|
||||
public User getAuthor() {
|
||||
return author;
|
||||
}
|
||||
|
||||
public void setAuthor(User author) {
|
||||
this.author = author;
|
||||
}
|
||||
|
||||
public Category getCategory() {
|
||||
return category;
|
||||
}
|
||||
|
||||
public void setCategory(Category category) {
|
||||
this.category = category;
|
||||
}
|
||||
|
||||
public List<PostHistory> getHistory() {
|
||||
return history;
|
||||
}
|
||||
|
||||
public void setHistory(List<PostHistory> history) {
|
||||
this.history = history;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
package org.codiki.entities.persistence;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Temporal;
|
||||
import javax.persistence.TemporalType;
|
||||
|
||||
@Entity
|
||||
@Table(name="post_history")
|
||||
public class PostHistory implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
private String title;
|
||||
|
||||
private String text;
|
||||
|
||||
@Column(name = "update_date")
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
private Date updateDate;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "post_id")
|
||||
private Post post;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
if(this.id != null) {
|
||||
throw new IllegalAccessError("It's not allowed to rewrite the id entity.");
|
||||
}
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
public void setText(String text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public Date getUpdateDate() {
|
||||
return updateDate;
|
||||
}
|
||||
|
||||
public void setUpdateDate(Date updateDate) {
|
||||
this.updateDate = updateDate;
|
||||
}
|
||||
|
||||
public Post getPost() {
|
||||
return post;
|
||||
}
|
||||
|
||||
public void setPost(Post post) {
|
||||
this.post = post;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
38
src/main/java/org/codiki/entities/persistence/Role.java
Normal file
38
src/main/java/org/codiki/entities/persistence/Role.java
Normal file
@@ -0,0 +1,38 @@
|
||||
package org.codiki.entities.persistence;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
|
||||
@Entity
|
||||
@Table(name="role")
|
||||
public class Role implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
private String name;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package org.codiki.entities.persistence;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.Table;
|
||||
|
||||
@Entity
|
||||
@Table(name = "sub_category")
|
||||
public class SubCategory extends Category {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/* ******************* */
|
||||
/* Relations */
|
||||
/* ******************* */
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "main_category")
|
||||
private Category mainCategory;
|
||||
|
||||
/* ******************* */
|
||||
/* Getters & Setters */
|
||||
/* ******************* */
|
||||
public Category getMainCategory() {
|
||||
return mainCategory;
|
||||
}
|
||||
|
||||
public void setMainCategory(Category mainCategory) {
|
||||
this.mainCategory = mainCategory;
|
||||
}
|
||||
|
||||
public List<Post> getListPosts() {
|
||||
return listPosts;
|
||||
}
|
||||
}
|
||||
188
src/main/java/org/codiki/entities/persistence/User.java
Normal file
188
src/main/java/org/codiki/entities/persistence/User.java
Normal file
@@ -0,0 +1,188 @@
|
||||
package org.codiki.entities.persistence;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.SequenceGenerator;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Temporal;
|
||||
import javax.persistence.TemporalType;
|
||||
|
||||
import org.codiki.entities.security.Token;
|
||||
|
||||
@Entity
|
||||
@Table(name="`user`")
|
||||
public class User implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/* ******************* */
|
||||
/* Attributes */
|
||||
/* ******************* */
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator="user_id_seq")
|
||||
@SequenceGenerator(name="user_id_seq", sequenceName="user_id_seq", allocationSize=1)
|
||||
private Long id;
|
||||
|
||||
private String key;
|
||||
|
||||
private String name;
|
||||
|
||||
private String email;
|
||||
|
||||
private String password;
|
||||
|
||||
private String image;
|
||||
|
||||
@Column(name = "inscription_date")
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
private Date inscriptionDate;
|
||||
|
||||
/* ******************* */
|
||||
/* Relations */
|
||||
/* ******************* */
|
||||
@ManyToOne(fetch = FetchType.EAGER)
|
||||
@JoinColumn(name = "role_id")
|
||||
private Role role;
|
||||
|
||||
@OneToMany(mappedBy = "author")
|
||||
private List<Post> listPosts;
|
||||
|
||||
@OneToMany(mappedBy = "author")
|
||||
private List<Comment> listComments;
|
||||
|
||||
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
|
||||
private List<Image> listImages;
|
||||
|
||||
/** Authentication token. */
|
||||
private transient Token token;
|
||||
|
||||
/* ******************* */
|
||||
/* Constructors */
|
||||
/* ******************* */
|
||||
public User() {
|
||||
super();
|
||||
token = new Token();
|
||||
}
|
||||
|
||||
/* ******************* */
|
||||
/* Getters & Setters */
|
||||
/* ******************* */
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
if(this.id != null) {
|
||||
throw new IllegalAccessError("It's not allowed to rewrite the id entity.");
|
||||
}
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public void setKey(String key) {
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
public void setEmail(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public String getImage() {
|
||||
return image;
|
||||
}
|
||||
|
||||
public void setImage(String image) {
|
||||
this.image = image;
|
||||
}
|
||||
|
||||
public Date getInscriptionDate() {
|
||||
return inscriptionDate;
|
||||
}
|
||||
|
||||
public void setInscriptionDate(Date inscriptionDate) {
|
||||
this.inscriptionDate = inscriptionDate;
|
||||
}
|
||||
|
||||
public Role getRole() {
|
||||
return role;
|
||||
}
|
||||
|
||||
public void setRole(Role role) {
|
||||
this.role = role;
|
||||
}
|
||||
|
||||
public List<Post> getListPosts() {
|
||||
return listPosts;
|
||||
}
|
||||
|
||||
public void setListPosts(List<Post> listPosts) {
|
||||
this.listPosts = listPosts;
|
||||
}
|
||||
|
||||
public List<Comment> getListComments() {
|
||||
return listComments;
|
||||
}
|
||||
|
||||
public void setListComments(List<Comment> listComments) {
|
||||
this.listComments = listComments;
|
||||
}
|
||||
|
||||
public List<Image> getListImages() {
|
||||
return listImages;
|
||||
}
|
||||
|
||||
public void addImage(final Image pImage) {
|
||||
if(listImages == null) {
|
||||
listImages = new ArrayList<>();
|
||||
}
|
||||
listImages.add(pImage);
|
||||
|
||||
if(pImage.getUser() == null) {
|
||||
pImage.setUser(this);
|
||||
}
|
||||
}
|
||||
|
||||
public void setListImages(List<Image> listImages) {
|
||||
this.listImages = listImages;
|
||||
}
|
||||
|
||||
public Token getToken() {
|
||||
return token;
|
||||
}
|
||||
|
||||
}
|
||||
82
src/main/java/org/codiki/entities/security/Token.java
Normal file
82
src/main/java/org/codiki/entities/security/Token.java
Normal file
@@ -0,0 +1,82 @@
|
||||
package org.codiki.entities.security;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Calendar;
|
||||
|
||||
public class Token {
|
||||
/** The metric in which the validation delay is defined. */
|
||||
private static final int METRIC = Calendar.MINUTE;
|
||||
/** Number of {@link METRIC} after that the token become invalid. */
|
||||
private static final int DELAY = 30;
|
||||
|
||||
/** The Constant BITS_NUMBER. */
|
||||
private static final int BITS_NUMBER = 130;
|
||||
/** The Constant RADIX. */
|
||||
private static final int RADIX = 32;
|
||||
|
||||
/** The value. */
|
||||
private String value;
|
||||
|
||||
/**
|
||||
* Last access date. For each request to the server, this date is consulted
|
||||
* and if the valid delay is ok, this date must be updated.
|
||||
*/
|
||||
private Calendar lastAccess;
|
||||
|
||||
/**
|
||||
* Instantiates a new token.
|
||||
*/
|
||||
public Token() {
|
||||
super();
|
||||
value = new BigInteger(BITS_NUMBER, new SecureRandom()).toString(RADIX);
|
||||
lastAccess = Calendar.getInstance();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value.
|
||||
*
|
||||
* @return the value
|
||||
*/
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the last access date.
|
||||
*
|
||||
* @return the last access date
|
||||
*/
|
||||
public Calendar getLastAccess() {
|
||||
return lastAccess;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the last access date.
|
||||
*/
|
||||
public void setLastAccess() {
|
||||
lastAccess = Calendar.getInstance();
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate if the token is still valid.<br/>
|
||||
* A token is valid is its {@link Token#lastAccess} is after the current
|
||||
* date minus the {@link Token#DELAY} {@link Token#METRIC}.<br/>
|
||||
* <br/>
|
||||
* Example:<br/>
|
||||
* {@link Token#DELAY} = 30 and {@link Token#METRIC} =
|
||||
* {@link Calendar#MINUTE}.<br/>
|
||||
* A token is valid only on the 30 minutes after its
|
||||
* {@link Token#lastAccess}.<br/>
|
||||
* If the current date-time minus the 30 minutes is before the
|
||||
* {@link Token#lastAccess}, the token is still valid.
|
||||
*
|
||||
* @return {@code true} if the token is still valid, {@code false}
|
||||
* otherwise.
|
||||
*/
|
||||
public boolean isValid() {
|
||||
final Calendar lastTimeValidation = Calendar.getInstance();
|
||||
lastTimeValidation.add(METRIC, -DELAY);
|
||||
return lastAccess.getTime().after(lastTimeValidation.getTime());
|
||||
}
|
||||
}
|
||||
37
src/main/java/org/codiki/login/LoginController.java
Normal file
37
src/main/java/org/codiki/login/LoginController.java
Normal file
@@ -0,0 +1,37 @@
|
||||
package org.codiki.login;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.codiki.entities.dto.UserDAO;
|
||||
import org.codiki.security.TokenService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/account")
|
||||
public class LoginController {
|
||||
|
||||
private static final String HEADER_TOKEN = "token";
|
||||
|
||||
@Autowired
|
||||
private TokenService tokenService;
|
||||
|
||||
@Autowired
|
||||
private LoginService loginService;
|
||||
|
||||
@PostMapping("/login")
|
||||
public UserDAO login(@RequestBody UserDAO pUser, HttpServletResponse response) {
|
||||
return loginService.checkCredentials(response, pUser);
|
||||
}
|
||||
|
||||
@GetMapping("/logout")
|
||||
public void logout(HttpServletRequest pRequest) {
|
||||
tokenService.removeUser(pRequest.getHeader(HEADER_TOKEN));
|
||||
}
|
||||
|
||||
}
|
||||
50
src/main/java/org/codiki/login/LoginService.java
Normal file
50
src/main/java/org/codiki/login/LoginService.java
Normal file
@@ -0,0 +1,50 @@
|
||||
package org.codiki.login;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import javax.naming.AuthenticationException;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.codiki.entities.dto.UserDAO;
|
||||
import org.codiki.entities.persistence.User;
|
||||
import org.codiki.repositories.UserRepository;
|
||||
import org.codiki.security.TokenService;
|
||||
import org.codiki.utils.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class LoginService {
|
||||
|
||||
@Autowired
|
||||
private UserRepository userRepository;
|
||||
|
||||
@Autowired
|
||||
private TokenService tokenService;
|
||||
|
||||
/**
|
||||
* Check the user credentials and generate him a token if they are correct.
|
||||
*
|
||||
* @param pUser
|
||||
* The user sent from client.
|
||||
* @return The user populated with the generated token.
|
||||
* @throws AuthenticationException
|
||||
* If the credentials are wrong.
|
||||
*/
|
||||
public UserDAO checkCredentials(HttpServletResponse pResponse, UserDAO pUser) {
|
||||
UserDAO result = null;
|
||||
|
||||
Optional<User> user = userRepository.findByEmail(pUser.getEmail());
|
||||
|
||||
if(user.isPresent() && StringUtils.compareHash(pUser.getPassword(), user.get().getPassword())) {
|
||||
tokenService.addUser(user.get());
|
||||
result = new UserDAO(user.get());
|
||||
} else {
|
||||
pResponse.setStatus(HttpServletResponse.SC_BAD_REQUEST);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
13
src/main/java/org/codiki/repositories/UserRepository.java
Normal file
13
src/main/java/org/codiki/repositories/UserRepository.java
Normal file
@@ -0,0 +1,13 @@
|
||||
package org.codiki.repositories;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.codiki.entities.persistence.User;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface UserRepository extends CrudRepository<User, Long> {
|
||||
Optional<User> findByEmail(@Param("email") final String pEmail);
|
||||
}
|
||||
35
src/main/java/org/codiki/security/AuthenticationFilter.java
Normal file
35
src/main/java/org/codiki/security/AuthenticationFilter.java
Normal file
@@ -0,0 +1,35 @@
|
||||
package org.codiki.security;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.codiki.core.AbstractFilter;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@Order(Ordered.HIGHEST_PRECEDENCE)
|
||||
public class AuthenticationFilter extends AbstractFilter {
|
||||
|
||||
@Override
|
||||
protected List<Route> getRoutes() {
|
||||
return Arrays.asList(
|
||||
new Route("\\/api\\/account\\/.*")
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void filter(HttpServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
|
||||
System.out.println("Token : " + request.getHeader("token"));
|
||||
|
||||
chain.doFilter(request, response);
|
||||
}
|
||||
|
||||
}
|
||||
69
src/main/java/org/codiki/security/Route.java
Normal file
69
src/main/java/org/codiki/security/Route.java
Normal file
@@ -0,0 +1,69 @@
|
||||
package org.codiki.security;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.http.HttpMethod;
|
||||
|
||||
/**
|
||||
* Route for filter matching.
|
||||
*
|
||||
* @author Takiguchi
|
||||
*
|
||||
*/
|
||||
public class Route {
|
||||
/** The regex to match urls. */
|
||||
private String url;
|
||||
/** The http method to match. Use a {@link Optional#empty()} to match all methods. */
|
||||
private Optional<HttpMethod> method;
|
||||
|
||||
/**
|
||||
* Instanciate a vierge route.
|
||||
*/
|
||||
public Route() {
|
||||
super();
|
||||
url = "";
|
||||
method = Optional.empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Instanciate a route for all http methods.
|
||||
*
|
||||
* @param pUrl
|
||||
* The regex to match urls.
|
||||
*/
|
||||
public Route(final String pUrl) {
|
||||
this();
|
||||
this.url = pUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instanciate a route for methods given in parameters
|
||||
*
|
||||
* @param pUrl
|
||||
* The regex to match urls.
|
||||
* @param pMethod
|
||||
* The http method to match. Use a {@link Optional#empty()} to match
|
||||
* all methods.
|
||||
*/
|
||||
public Route(final String pUrl, final HttpMethod pMethod) {
|
||||
this(pUrl);
|
||||
this.method = Optional.of(pMethod);
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public void setUrl(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public Optional<HttpMethod> getMethod() {
|
||||
return method;
|
||||
}
|
||||
|
||||
public void setMethod(HttpMethod method) {
|
||||
this.method = Optional.of(method);
|
||||
}
|
||||
|
||||
}
|
||||
106
src/main/java/org/codiki/security/TokenService.java
Normal file
106
src/main/java/org/codiki/security/TokenService.java
Normal file
@@ -0,0 +1,106 @@
|
||||
package org.codiki.security;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import org.codiki.entities.persistence.User;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class TokenService {
|
||||
/** Map of connected users. */
|
||||
private static final Map<String, User> connectedUsers;
|
||||
|
||||
/**
|
||||
* Class constructor
|
||||
*/
|
||||
static {
|
||||
connectedUsers = new TreeMap<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the token matches to a user session, and if it is still valid.
|
||||
*
|
||||
* @param pToken
|
||||
* The token to check.
|
||||
* @return {@code true} if the token is still valid, {@code false}
|
||||
* otherwise.
|
||||
*/
|
||||
public boolean isUserConnected(final String pToken) {
|
||||
boolean result = false;
|
||||
|
||||
if (pToken != null && connectedUsers.containsKey(pToken)) {
|
||||
if (connectedUsers.get(pToken).getToken().isValid()) {
|
||||
result = true;
|
||||
} else {
|
||||
connectedUsers.remove(pToken);
|
||||
}
|
||||
}
|
||||
|
||||
// clear all the expired sessions
|
||||
clearExpiredUsers();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove from the connected users map all the elements which their token is
|
||||
* expired.
|
||||
*/
|
||||
@SuppressWarnings("unlikely-arg-type")
|
||||
private void clearExpiredUsers() {
|
||||
connectedUsers.entrySet().stream().forEach(user -> {
|
||||
if(!user.getValue().getToken().isValid()) {
|
||||
connectedUsers.remove(user).getKey();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the user to the connected users map.
|
||||
*
|
||||
* @param pUser
|
||||
* The user to add.
|
||||
*/
|
||||
public void addUser(final User pUser) {
|
||||
if(connectedUsers.get(pUser.getToken().getValue()) == null) {
|
||||
connectedUsers.put(pUser.getToken().getValue(), pUser);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh the user token last access date in the token service.
|
||||
*
|
||||
* @param pToken
|
||||
* The user token.
|
||||
*/
|
||||
public void refreshUserToken(final String pToken) {
|
||||
final User user = connectedUsers.get(pToken);
|
||||
if(user != null) {
|
||||
user.getToken().setLastAccess();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the user to the connected users map.
|
||||
*
|
||||
* @param pUser
|
||||
* The user to remove.
|
||||
*/
|
||||
public void removeUser(final User pUser) {
|
||||
removeUser(pUser.getToken().getValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the user associated to the token given in parameters, from the
|
||||
* connected users map.
|
||||
*
|
||||
* @param pToken
|
||||
* The user to delete token.
|
||||
*/
|
||||
public void removeUser(final String pToken) {
|
||||
if(pToken != null && connectedUsers.containsKey(pToken)) {
|
||||
connectedUsers.remove(pToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
35
src/main/java/org/codiki/utils/DateUtils.java
Normal file
35
src/main/java/org/codiki/utils/DateUtils.java
Normal file
@@ -0,0 +1,35 @@
|
||||
package org.codiki.utils;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
|
||||
public class DateUtils {
|
||||
public static final String FORMAT_DEFAULT = "dd/MM/yyyy HH:mm:ss";
|
||||
|
||||
public static Date parseDate(String pSource, String pPattern) throws ParseException {
|
||||
Date result = null;
|
||||
if (pSource != null && !pSource.isEmpty()) {
|
||||
DateFormat formatter = getSimpleDateFormat(pPattern);
|
||||
formatter.setLenient(false);
|
||||
result = formatter.parse(pSource);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static String format(Date pDate, String pPattern) {
|
||||
return getSimpleDateFormat(pPattern).format(pDate);
|
||||
}
|
||||
|
||||
public static String format(Date pDate) {
|
||||
return getSimpleDateFormat(FORMAT_DEFAULT).format(pDate);
|
||||
}
|
||||
|
||||
public static SimpleDateFormat getSimpleDateFormat(String pPattern) {
|
||||
SimpleDateFormat result = new SimpleDateFormat(pPattern, Locale.FRENCH);
|
||||
result.setLenient(false);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
82
src/main/java/org/codiki/utils/RegexUtils.java
Normal file
82
src/main/java/org/codiki/utils/RegexUtils.java
Normal file
@@ -0,0 +1,82 @@
|
||||
package org.codiki.utils;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public final class RegexUtils {
|
||||
|
||||
private static final String EMAIL_REGEX = "^.*@.*\\..{2,}$";
|
||||
private static final String LOWER_LETTERS_REGEX = ".*[a-z].*";
|
||||
private static final String UPPER_LETTERS_REGEX = ".*[A-Z].*";
|
||||
private static final String NUMBER_REGEX = ".*[0-9].*";
|
||||
private static final String SPECIAL_CHAR_REGEX = ".*\\W.*";
|
||||
private static final String NUMBER_ONLY_REGEX = "^[0-9]+$";
|
||||
|
||||
// La portée "package" permet à la classe StringUtils d'utiliser les patterns
|
||||
// suivants :
|
||||
static final Pattern EMAIL_PATTERN;
|
||||
static final Pattern LOWER_LETTERS_PATTERN;
|
||||
static final Pattern UPPER_LETTERS_PATTERN;
|
||||
static final Pattern NUMBER_PATTERN;
|
||||
static final Pattern SPECIAL_CHAR_PATTERN;
|
||||
static final Pattern NUMBER_ONLY_PATTERN;
|
||||
|
||||
static {
|
||||
EMAIL_PATTERN = Pattern.compile(EMAIL_REGEX);
|
||||
LOWER_LETTERS_PATTERN = Pattern.compile(LOWER_LETTERS_REGEX);
|
||||
UPPER_LETTERS_PATTERN = Pattern.compile(UPPER_LETTERS_REGEX);
|
||||
NUMBER_PATTERN = Pattern.compile(NUMBER_REGEX);
|
||||
SPECIAL_CHAR_PATTERN = Pattern.compile(SPECIAL_CHAR_REGEX);
|
||||
NUMBER_ONLY_PATTERN = Pattern.compile(NUMBER_ONLY_REGEX);
|
||||
}
|
||||
|
||||
/**
|
||||
* Chekcs if {@code pString} corresponds to an email address.
|
||||
*
|
||||
* @param pString
|
||||
* The string which should be an email address.
|
||||
* @return {@code true} if {@link pString} corresponds to an email address,
|
||||
* {@code false} otherwise.
|
||||
*/
|
||||
public static boolean isEmail(final String pString) {
|
||||
return EMAIL_PATTERN.matcher(pString).find();
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the sequences of {@code pString} matched by the {@code pRegex}
|
||||
* with the {@code pReplacingString}.
|
||||
*
|
||||
* @param pString
|
||||
* The string to update.
|
||||
* @param pRegex
|
||||
* The regex to match the sentences to replace.
|
||||
* @param pReplacingString
|
||||
* The string to replace the sentences which match with the
|
||||
* regex.
|
||||
* @return The new string.
|
||||
*/
|
||||
public static String replaceSequence(final String pString,
|
||||
final String pRegex, final String pReplacingString) {
|
||||
return Pattern.compile(pRegex).matcher(pString)
|
||||
.replaceAll(pReplacingString);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if {@code pString} corresponds to a number.
|
||||
*
|
||||
* @param pString
|
||||
* The string which should be a number.
|
||||
* @return {@code true} if {@code pString} corresponds to a number,
|
||||
* {@code false} otherwise.
|
||||
*/
|
||||
public static boolean isNumber(final String pString) {
|
||||
return NUMBER_ONLY_PATTERN.matcher(pString).find();
|
||||
}
|
||||
|
||||
public static String getGroup(final String regex, final int numeroGroupe, final String chaine) {
|
||||
final Pattern pattern = Pattern.compile(regex);
|
||||
final Matcher matcher = pattern.matcher(chaine);
|
||||
matcher.find();
|
||||
return matcher.group(numeroGroupe);
|
||||
}
|
||||
}
|
||||
93
src/main/java/org/codiki/utils/StringUtils.java
Normal file
93
src/main/java/org/codiki/utils/StringUtils.java
Normal file
@@ -0,0 +1,93 @@
|
||||
package org.codiki.utils;
|
||||
|
||||
import org.mindrot.jbcrypt.BCrypt;
|
||||
|
||||
/**
|
||||
* Generic methods about {@link String} class.
|
||||
*
|
||||
* @author takiguchi
|
||||
*
|
||||
*/
|
||||
public final class StringUtils {
|
||||
|
||||
/**
|
||||
* Indicate if {@code pString} is null or just composed of spaces.
|
||||
*
|
||||
* @param pString
|
||||
* The string to test.
|
||||
* @return {@code true} if {@code pString} is null or just composed of
|
||||
* spaces, {@code false} otherwise.
|
||||
*/
|
||||
public static boolean isNull(final String chaine) {
|
||||
return chaine == null || chaine.trim().length() == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hash the password given into parameters.
|
||||
*
|
||||
* @param pPassword The password to hash.
|
||||
* @return The password hashed.
|
||||
*/
|
||||
public static String hashPassword(final String pPassword) {
|
||||
return hashString(pPassword, 10);
|
||||
}
|
||||
|
||||
public static String hashString(final String pString, final int pSalt) {
|
||||
return BCrypt.hashpw(pString, BCrypt.gensalt(pSalt));
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare the password and the hashed string given into parameters.
|
||||
*
|
||||
* @param pPassword
|
||||
* The password to compare to the hashed string.
|
||||
* @param pHashToCompare
|
||||
* The hashed string to compare to the password.
|
||||
* @return {@code true} if the password matches to the hashed string.
|
||||
*/
|
||||
public static boolean compareHash(final String pPassword, final String pHashToCompare) {
|
||||
return BCrypt.checkpw(pPassword, pHashToCompare);
|
||||
}
|
||||
|
||||
/**
|
||||
* Concatenate the parameters to form just one single string.
|
||||
*
|
||||
* @param pArgs
|
||||
* The strings to concatenate.
|
||||
* @return The parameters concatenated.
|
||||
*/
|
||||
public static String concat(final Object... pArgs) {
|
||||
final StringBuilder result = new StringBuilder();
|
||||
for (final Object arg : pArgs) {
|
||||
result.append(arg);
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
public static String printStrings(final String... pStrings) {
|
||||
final StringBuilder result = new StringBuilder();
|
||||
for (int i = 0 ; i < pStrings.length ; i++) {
|
||||
result.append(pStrings[i]);
|
||||
if(i < pStrings.length - 1) {
|
||||
result.append(",");
|
||||
}
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
public static boolean containLowercase(final String pString) {
|
||||
return RegexUtils.LOWER_LETTERS_PATTERN.matcher(pString).find();
|
||||
}
|
||||
|
||||
public static boolean containUppercase(final String pString) {
|
||||
return RegexUtils.UPPER_LETTERS_PATTERN.matcher(pString).find();
|
||||
}
|
||||
|
||||
public static boolean containNumber(final String pString) {
|
||||
return RegexUtils.NUMBER_PATTERN.matcher(pString).find();
|
||||
}
|
||||
|
||||
public static boolean containSpecialChar(final String pString) {
|
||||
return RegexUtils.SPECIAL_CHAR_PATTERN.matcher(pString).find();
|
||||
}
|
||||
}
|
||||
15
src/main/resources/application.properties
Normal file
15
src/main/resources/application.properties
Normal file
@@ -0,0 +1,15 @@
|
||||
#server.error.whitelabel.enabled=false
|
||||
spring.datasource.driverClassName=org.postgresql.Driver
|
||||
spring.datasource.url=jdbc:postgresql://localhost:5432/codiki
|
||||
spring.datasource.username=codiki
|
||||
spring.datasource.password=P@ssword
|
||||
|
||||
# Disable feature detection by this undocumented parameter. Check the org.hibernate.engine.jdbc.internal.JdbcServiceImpl.configure method for more details.
|
||||
spring.jpa.properties.hibernate.temp.use_jdbc_metadata_defaults = false
|
||||
|
||||
# Because detection is disabled you have to set correct dialect by hand.
|
||||
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQL9Dialect
|
||||
|
||||
logging.level.org.hibernate=DEBUG
|
||||
|
||||
cors.enabled=false
|
||||
72
src/test/java/org/codiki/core/AbstractFilterTest.java
Normal file
72
src/test/java/org/codiki/core/AbstractFilterTest.java
Normal file
@@ -0,0 +1,72 @@
|
||||
package org.codiki.core;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.codiki.security.Route;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.springframework.http.HttpMethod;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class AbstractFilterTest {
|
||||
|
||||
/**
|
||||
* Class that simplify the test mocks for the method {@link AbstractFilter#getRoutes()}.
|
||||
*
|
||||
* @author Takiguchi
|
||||
*
|
||||
*/
|
||||
private class TestFilter extends AbstractFilter {
|
||||
public List<Route> routes;
|
||||
|
||||
@Override
|
||||
protected List<Route> getRoutes() {
|
||||
return routes;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void filter(HttpServletRequest request, ServletResponse response, FilterChain chain)
|
||||
throws IOException, ServletException {
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
|
||||
/** Tested class object */
|
||||
private AbstractFilter filter = new TestFilter();
|
||||
|
||||
@Test
|
||||
public void test_isRequestFiltered_true() {
|
||||
((TestFilter) filter).routes = Arrays.asList(new Route("toto", HttpMethod.GET));
|
||||
|
||||
Assert.assertTrue(filter.isRequestFiltered("http://localhost/toto", "GET"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_isRequestFiltered_true_without_httpMethod() {
|
||||
((TestFilter) filter).routes = Arrays.asList(new Route("toto"));
|
||||
|
||||
Assert.assertTrue(filter.isRequestFiltered("http://localhost/toto", "GET"));
|
||||
Assert.assertTrue(filter.isRequestFiltered("http://localhost/toto", "POST"));
|
||||
Assert.assertTrue(filter.isRequestFiltered("http://localhost/toto", "PUT"));
|
||||
Assert.assertTrue(filter.isRequestFiltered("http://localhost/toto", "DELETE"));
|
||||
Assert.assertTrue(filter.isRequestFiltered("http://localhost/toto", "DumbThing"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_isRequestFiltered_false() {
|
||||
((TestFilter) filter).routes = Arrays.asList(new Route("toto", HttpMethod.POST));
|
||||
|
||||
Assert.assertFalse(filter.isRequestFiltered("http://localhost/toto", "GET"));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user