Compare commits
7 Commits
8ec806440b
...
16471e9962
| Author | SHA1 | Date | |
|---|---|---|---|
| 16471e9962 | |||
| 6e7ae115e5 | |||
| 95af38bf72 | |||
| 5e5fbd9377 | |||
| 84b1dd6352 | |||
| 1f8a11a73c | |||
| 7f0ff8157f |
@@ -8,7 +8,6 @@ import org.springframework.context.annotation.ComponentScan;
|
|||||||
@SpringBootApplication
|
@SpringBootApplication
|
||||||
@EnableAutoConfiguration
|
@EnableAutoConfiguration
|
||||||
public class CodikiApplication {
|
public class CodikiApplication {
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
SpringApplication.run(CodikiApplication.class, args);
|
SpringApplication.run(CodikiApplication.class, args);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -101,8 +101,8 @@ public class AccountController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@PutMapping("/")
|
@PutMapping("/")
|
||||||
public void update(@RequestBody final UserDTO pUser, final HttpServletRequest pRequest,
|
public void update(@RequestBody UserDTO pUser, HttpServletResponse pResponse, Principal pPrincipal)
|
||||||
final HttpServletResponse pResponse, final Principal pPrincipal) throws IOException {
|
throws IOException {
|
||||||
accountService.updateUser(pUser, pRequest, pResponse, pPrincipal);
|
accountService.updateUser(pUser, pResponse, pPrincipal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,5 @@
|
|||||||
package org.codiki.account;
|
package org.codiki.account;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.nio.file.NoSuchFileException;
|
|
||||||
import java.security.Principal;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
|
|
||||||
import org.codiki.core.entities.dto.ImageDTO;
|
import org.codiki.core.entities.dto.ImageDTO;
|
||||||
import org.codiki.core.entities.dto.PasswordWrapperDTO;
|
import org.codiki.core.entities.dto.PasswordWrapperDTO;
|
||||||
import org.codiki.core.entities.dto.UserDTO;
|
import org.codiki.core.entities.dto.UserDTO;
|
||||||
@@ -22,38 +10,30 @@ import org.codiki.core.security.CustomAuthenticationProvider;
|
|||||||
import org.codiki.core.services.FileUploadService;
|
import org.codiki.core.services.FileUploadService;
|
||||||
import org.codiki.core.services.UserService;
|
import org.codiki.core.services.UserService;
|
||||||
import org.codiki.core.utils.StringUtils;
|
import org.codiki.core.utils.StringUtils;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.core.io.Resource;
|
import org.springframework.core.io.Resource;
|
||||||
import org.springframework.security.authentication.BadCredentialsException;
|
import org.springframework.security.authentication.BadCredentialsException;
|
||||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.security.Principal;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class AccountService {
|
public class AccountService {
|
||||||
/** Logger. */
|
private final CustomAuthenticationProvider authenticationProvider;
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(FileUploadService.class);
|
private final UserService userService;
|
||||||
|
private final UserRepository userRepository;
|
||||||
|
private final FileUploadService fileUploadService;
|
||||||
|
private final ImageRepository imageRepository;
|
||||||
|
|
||||||
private CustomAuthenticationProvider authenticationProvider;
|
/** Constructor. */
|
||||||
|
|
||||||
private UserService userService;
|
|
||||||
|
|
||||||
private UserRepository userRepository;
|
|
||||||
|
|
||||||
private FileUploadService fileUploadService;
|
|
||||||
|
|
||||||
private ImageRepository imageRepository;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor.
|
|
||||||
* @param authenticationProvider
|
|
||||||
* @param userService
|
|
||||||
* @param userRepository
|
|
||||||
* @param fileUploadService
|
|
||||||
* @param imageRepository
|
|
||||||
*/
|
|
||||||
public AccountService(CustomAuthenticationProvider authenticationProvider,
|
public AccountService(CustomAuthenticationProvider authenticationProvider,
|
||||||
UserService userService,
|
UserService userService,
|
||||||
UserRepository userRepository,
|
UserRepository userRepository,
|
||||||
@@ -93,8 +73,8 @@ public class AccountService {
|
|||||||
return resultCode;
|
return resultCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String uploadFile(final MultipartFile pFile, final HttpServletRequest pRequest,
|
public String uploadFile(MultipartFile pFile, HttpServletResponse pResponse, Principal pPrincipal)
|
||||||
final HttpServletResponse pResponse, final Principal pPrincipal) throws IOException {
|
throws IOException {
|
||||||
final String avatarFileName = fileUploadService.uploadProfileImage(pFile);
|
final String avatarFileName = fileUploadService.uploadProfileImage(pFile);
|
||||||
|
|
||||||
final Optional<User> connectedUser = userService.getUserByPrincipal(pPrincipal);
|
final Optional<User> connectedUser = userService.getUserByPrincipal(pPrincipal);
|
||||||
@@ -117,8 +97,7 @@ public class AccountService {
|
|||||||
return fileUploadService.loadAvatar(pAvatarFileName);
|
return fileUploadService.loadAvatar(pAvatarFileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<ImageDTO> getUserImages(final HttpServletRequest pRequest, final HttpServletResponse pResponse,
|
public List<ImageDTO> getUserImages(HttpServletResponse pResponse, Principal pPrincipal) throws IOException {
|
||||||
final Principal pPrincipal) throws IOException {
|
|
||||||
List<ImageDTO> result = new LinkedList<>();
|
List<ImageDTO> result = new LinkedList<>();
|
||||||
|
|
||||||
final Optional<User> connectedUser = userService.getUserByPrincipal(pPrincipal);
|
final Optional<User> connectedUser = userService.getUserByPrincipal(pPrincipal);
|
||||||
@@ -132,7 +111,7 @@ public class AccountService {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void signin(final User pUser, final HttpServletResponse pResponse) throws IOException {
|
public void signin(User pUser, HttpServletResponse pResponse) throws IOException {
|
||||||
if(pUser.getName() == null || pUser.getEmail() == null || pUser.getPassword() == null || "".equals(pUser.getPassword().trim())) {
|
if(pUser.getName() == null || pUser.getEmail() == null || pUser.getPassword() == null || "".equals(pUser.getPassword().trim())) {
|
||||||
pResponse.sendError(HttpServletResponse.SC_BAD_REQUEST);
|
pResponse.sendError(HttpServletResponse.SC_BAD_REQUEST);
|
||||||
} else if(userRepository.findByEmail(pUser.getEmail()).isPresent()) {
|
} else if(userRepository.findByEmail(pUser.getEmail()).isPresent()) {
|
||||||
@@ -148,8 +127,7 @@ public class AccountService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateUser(final UserDTO pUser, final HttpServletRequest pRequest,
|
public void updateUser(UserDTO pUser, HttpServletResponse pResponse, Principal pPrincipal) throws IOException {
|
||||||
final HttpServletResponse pResponse, final Principal pPrincipal) throws IOException {
|
|
||||||
final Optional<User> connectedUserOpt = userService.getUserByPrincipal(pPrincipal);
|
final Optional<User> connectedUserOpt = userService.getUserByPrincipal(pPrincipal);
|
||||||
if(connectedUserOpt.isPresent()) {
|
if(connectedUserOpt.isPresent()) {
|
||||||
final User connectedUser = connectedUserOpt.get();
|
final User connectedUser = connectedUserOpt.get();
|
||||||
|
|||||||
@@ -1,11 +1,7 @@
|
|||||||
package org.codiki.categories;
|
package org.codiki.categories;
|
||||||
|
|
||||||
import java.util.List;
|
import com.fasterxml.jackson.annotation.JsonView;
|
||||||
import java.util.Optional;
|
import org.codiki.core.entities.dto.View;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import java.util.stream.StreamSupport;
|
|
||||||
|
|
||||||
import org.codiki.core.entities.dto.CategoryDTO;
|
|
||||||
import org.codiki.core.entities.persistence.Category;
|
import org.codiki.core.entities.persistence.Category;
|
||||||
import org.codiki.core.repositories.CategoryRepository;
|
import org.codiki.core.repositories.CategoryRepository;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@@ -14,22 +10,33 @@ import org.springframework.web.bind.annotation.PathVariable;
|
|||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/api/categories")
|
@RequestMapping("/api/categories")
|
||||||
public class CategoryController {
|
public class CategoryController {
|
||||||
|
private final CategoryRepository categoryRepository;
|
||||||
|
|
||||||
@Autowired
|
/** Constructor. */
|
||||||
private CategoryRepository categoryRepository;
|
public CategoryController(CategoryRepository categoryRepository) {
|
||||||
|
this.categoryRepository = categoryRepository;
|
||||||
@GetMapping("/{id}")
|
|
||||||
public CategoryDTO findById(@PathVariable("id") final Long pId) {
|
|
||||||
final Optional<Category> result = categoryRepository.findById(pId);
|
|
||||||
return result.isPresent() ? new CategoryDTO(result.get()) : null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@JsonView(View.CategoryDTO.class)
|
||||||
|
@GetMapping("/{id}")
|
||||||
|
public Category findById(@PathVariable("id") final Long pId,
|
||||||
|
HttpServletResponse response) {
|
||||||
|
return categoryRepository.findByIdWithSubCategories(pId)
|
||||||
|
.orElseGet(() -> {
|
||||||
|
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonView(View.CategoryDTO.class)
|
||||||
@GetMapping("/")
|
@GetMapping("/")
|
||||||
public List<CategoryDTO> getAll() {
|
public List<Category> getAll() {
|
||||||
return StreamSupport.stream(categoryRepository.findAll().spliterator(), false)
|
return categoryRepository.findAllWithSubCategories();
|
||||||
.map(CategoryDTO::new).collect(Collectors.toList());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,58 +0,0 @@
|
|||||||
package org.codiki.core.config;
|
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.boot.web.servlet.error.ErrorAttributes;
|
|
||||||
import org.springframework.boot.web.servlet.error.ErrorController;
|
|
||||||
import org.springframework.util.Assert;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
import org.springframework.web.context.request.RequestAttributes;
|
|
||||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
|
||||||
import org.springframework.web.context.request.ServletWebRequest;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Controller that catch errors from spring rest or spring security and others, and transform them to JSON response.
|
|
||||||
*/
|
|
||||||
@RestController
|
|
||||||
@RequestMapping("/error")
|
|
||||||
public class CustomErrorController implements ErrorController {
|
|
||||||
|
|
||||||
private final ErrorAttributes errorAttributes;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
public CustomErrorController(ErrorAttributes errorAttributes) {
|
|
||||||
Assert.notNull(errorAttributes, "ErrorAttributes must not be null");
|
|
||||||
this.errorAttributes = errorAttributes;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getErrorPath() {
|
|
||||||
return "/error";
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequestMapping
|
|
||||||
public Map<String, Object> error(HttpServletRequest request){
|
|
||||||
Map<String, Object> body = getErrorAttributes(request, getTraceParameter(request));
|
|
||||||
String trace = (String) body.get("trace");
|
|
||||||
if(trace != null){
|
|
||||||
String[] lines = trace.split("\n\t");
|
|
||||||
body.put("trace", lines);
|
|
||||||
}
|
|
||||||
return body;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean getTraceParameter(HttpServletRequest request) {
|
|
||||||
String parameter = request.getParameter("trace");
|
|
||||||
if (parameter == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return !"false".equals(parameter.toLowerCase());
|
|
||||||
}
|
|
||||||
|
|
||||||
private Map<String, Object> getErrorAttributes(HttpServletRequest request, boolean includeStackTrace) {
|
|
||||||
return errorAttributes.getErrorAttributes(new ServletWebRequest(request), includeStackTrace);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -17,21 +17,11 @@ import org.springframework.transaction.annotation.EnableTransactionManagement;
|
|||||||
@EnableJpaRepositories("org.codiki.core.repositories")
|
@EnableJpaRepositories("org.codiki.core.repositories")
|
||||||
@PropertySource("classpath:application.yml")
|
@PropertySource("classpath:application.yml")
|
||||||
public class JpaConfiguration {
|
public class JpaConfiguration {
|
||||||
|
|
||||||
@Value("${spring.jpa.datasource.driverClassName}")
|
|
||||||
private String driverClassName;
|
|
||||||
|
|
||||||
@Value("${spring.jpa.datasource.url}")
|
|
||||||
private String url;
|
|
||||||
|
|
||||||
@Value("${spring.jpa.datasource.username}")
|
|
||||||
private String username;
|
|
||||||
|
|
||||||
@Value("${spring.jpa.datasource.password}")
|
|
||||||
private String password;
|
|
||||||
|
|
||||||
@Bean(name = "dataSource")
|
@Bean(name = "dataSource")
|
||||||
public DataSource getDataSource() {
|
public DataSource getDataSource(@Value("${spring.jpa.datasource.driverClassName}") String driverClassName,
|
||||||
|
@Value("${spring.jpa.datasource.url}") String url,
|
||||||
|
@Value("${spring.jpa.datasource.username}") String username,
|
||||||
|
@Value("${spring.jpa.datasource.password}") String password) {
|
||||||
return DataSourceBuilder.create()
|
return DataSourceBuilder.create()
|
||||||
.username(username)
|
.username(username)
|
||||||
.password(password)
|
.password(password)
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import java.io.IOException;
|
|||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
public class RobotsTxtController {
|
public class RobotsTxtController {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(RobotsTxtController.class);
|
private static final Logger LOG = LoggerFactory.getLogger(RobotsTxtController.class);
|
||||||
|
|
||||||
@RequestMapping(value = "/robots.txt")
|
@RequestMapping(value = "/robots.txt")
|
||||||
|
|||||||
@@ -3,4 +3,5 @@ package org.codiki.core.entities.dto;
|
|||||||
public class View {
|
public class View {
|
||||||
public interface UserDTO {}
|
public interface UserDTO {}
|
||||||
public interface PostDTO {}
|
public interface PostDTO {}
|
||||||
|
public interface CategoryDTO {}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,10 +20,12 @@ import org.codiki.core.entities.dto.CategoryDTO;
|
|||||||
import org.codiki.core.entities.dto.View;
|
import org.codiki.core.entities.dto.View;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonView;
|
import com.fasterxml.jackson.annotation.JsonView;
|
||||||
|
import org.hibernate.annotations.Proxy;
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name="category")
|
@Table(name="category")
|
||||||
@Inheritance(strategy = InheritanceType.JOINED)
|
@Inheritance(strategy = InheritanceType.JOINED)
|
||||||
|
@Proxy(lazy = false)
|
||||||
public class Category implements Serializable {
|
public class Category implements Serializable {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
@@ -32,10 +34,10 @@ public class Category implements Serializable {
|
|||||||
/* ******************* */
|
/* ******************* */
|
||||||
@Id
|
@Id
|
||||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
@JsonView(View.PostDTO.class)
|
@JsonView({View.PostDTO.class, View.CategoryDTO.class})
|
||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
@JsonView(View.PostDTO.class)
|
@JsonView({View.PostDTO.class, View.CategoryDTO.class})
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
/* ******************* */
|
/* ******************* */
|
||||||
@@ -45,6 +47,7 @@ public class Category implements Serializable {
|
|||||||
@JoinColumn(name = "creator_id")
|
@JoinColumn(name = "creator_id")
|
||||||
protected User creator;
|
protected User creator;
|
||||||
|
|
||||||
|
@JsonView({View.CategoryDTO.class})
|
||||||
@OneToMany(mappedBy = "mainCategory")
|
@OneToMany(mappedBy = "mainCategory")
|
||||||
private List<SubCategory> listSubCategories;
|
private List<SubCategory> listSubCategories;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package org.codiki.core.entities.persistence;
|
package org.codiki.core.entities.persistence;
|
||||||
|
|
||||||
|
import org.hibernate.annotations.Proxy;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -19,6 +21,7 @@ import javax.persistence.TemporalType;
|
|||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name="comment")
|
@Table(name="comment")
|
||||||
|
@Proxy(lazy = false)
|
||||||
public class Comment implements Serializable {
|
public class Comment implements Serializable {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package org.codiki.core.entities.persistence;
|
package org.codiki.core.entities.persistence;
|
||||||
|
|
||||||
|
import org.hibernate.annotations.Proxy;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
@@ -17,6 +19,7 @@ import javax.persistence.TemporalType;
|
|||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name="comment_history")
|
@Table(name="comment_history")
|
||||||
|
@Proxy(lazy = false)
|
||||||
public class CommentHistory implements Serializable {
|
public class CommentHistory implements Serializable {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package org.codiki.core.entities.persistence;
|
package org.codiki.core.entities.persistence;
|
||||||
|
|
||||||
|
import org.hibernate.annotations.Proxy;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
@@ -16,6 +18,7 @@ import javax.persistence.TemporalType;
|
|||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name="image")
|
@Table(name="image")
|
||||||
|
@Proxy(lazy = false)
|
||||||
public class Image implements Serializable {
|
public class Image implements Serializable {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
|||||||
@@ -25,9 +25,11 @@ import org.hibernate.annotations.Generated;
|
|||||||
import org.hibernate.annotations.GenerationTime;
|
import org.hibernate.annotations.GenerationTime;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonView;
|
import com.fasterxml.jackson.annotation.JsonView;
|
||||||
|
import org.hibernate.annotations.Proxy;
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name="post")
|
@Table(name="post")
|
||||||
|
@Proxy(lazy = false)
|
||||||
public class Post implements Serializable {
|
public class Post implements Serializable {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package org.codiki.core.entities.persistence;
|
package org.codiki.core.entities.persistence;
|
||||||
|
|
||||||
|
import org.hibernate.annotations.Proxy;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
@@ -17,6 +19,7 @@ import javax.persistence.TemporalType;
|
|||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name="post_history")
|
@Table(name="post_history")
|
||||||
|
@Proxy(lazy = false)
|
||||||
public class PostHistory implements Serializable {
|
public class PostHistory implements Serializable {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
|||||||
@@ -11,9 +11,11 @@ import javax.persistence.Table;
|
|||||||
import org.codiki.core.entities.dto.View;
|
import org.codiki.core.entities.dto.View;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonView;
|
import com.fasterxml.jackson.annotation.JsonView;
|
||||||
|
import org.hibernate.annotations.Proxy;
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name="role")
|
@Table(name="role")
|
||||||
|
@Proxy(lazy = false)
|
||||||
public class Role implements Serializable {
|
public class Role implements Serializable {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
package org.codiki.core.entities.persistence;
|
package org.codiki.core.entities.persistence;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonView;
|
||||||
|
import org.hibernate.annotations.Proxy;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
@@ -10,6 +13,7 @@ import javax.persistence.Table;
|
|||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "sub_category")
|
@Table(name = "sub_category")
|
||||||
|
@Proxy(lazy = false)
|
||||||
public class SubCategory extends Category {
|
public class SubCategory extends Category {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
@@ -34,4 +38,15 @@ public class SubCategory extends Category {
|
|||||||
public List<Post> getListPosts() {
|
public List<Post> getListPosts() {
|
||||||
return listPosts;
|
return listPosts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc Category#getListSubCategories}.
|
||||||
|
*
|
||||||
|
* This getter is overrided to set {@link JsonView} annotation to avoid Lazy initialization for subcategories.
|
||||||
|
*/
|
||||||
|
@JsonView()
|
||||||
|
@Override
|
||||||
|
public List<SubCategory> getListSubCategories() {
|
||||||
|
return super.getListSubCategories();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,9 +25,11 @@ import org.hibernate.annotations.Generated;
|
|||||||
import org.hibernate.annotations.GenerationTime;
|
import org.hibernate.annotations.GenerationTime;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonView;
|
import com.fasterxml.jackson.annotation.JsonView;
|
||||||
|
import org.hibernate.annotations.Proxy;
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name="`user`")
|
@Table(name="`user`")
|
||||||
|
@Proxy(lazy = false)
|
||||||
public class User implements Serializable {
|
public class User implements Serializable {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package org.codiki.core.entities.persistence;
|
package org.codiki.core.entities.persistence;
|
||||||
|
|
||||||
|
import org.hibernate.annotations.Proxy;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
@@ -16,6 +18,7 @@ import javax.persistence.Table;
|
|||||||
*/
|
*/
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name="version")
|
@Table(name="version")
|
||||||
|
@Proxy(lazy = false)
|
||||||
public class Version implements Serializable {
|
public class Version implements Serializable {
|
||||||
private static final long serialVersionUID = -8803744005903941330L;
|
private static final long serialVersionUID = -8803744005903941330L;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package org.codiki.core.entities.persistence;
|
package org.codiki.core.entities.persistence;
|
||||||
|
|
||||||
|
import org.hibernate.annotations.Proxy;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
@@ -13,6 +15,7 @@ import javax.persistence.Table;
|
|||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name="version_revision")
|
@Table(name="version_revision")
|
||||||
|
@Proxy(lazy = false)
|
||||||
public class VersionRevision implements Serializable {
|
public class VersionRevision implements Serializable {
|
||||||
private static final long serialVersionUID = 1837590467941917225L;
|
private static final long serialVersionUID = 1837590467941917225L;
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,19 @@
|
|||||||
package org.codiki.core.repositories;
|
package org.codiki.core.repositories;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
import org.codiki.core.entities.persistence.Category;
|
import org.codiki.core.entities.persistence.Category;
|
||||||
import org.springframework.data.jpa.repository.Query;
|
import org.springframework.data.jpa.repository.Query;
|
||||||
import org.springframework.data.repository.CrudRepository;
|
import org.springframework.data.repository.CrudRepository;
|
||||||
|
import org.springframework.data.repository.query.Param;
|
||||||
import org.springframework.stereotype.Repository;
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
@Repository
|
@Repository
|
||||||
public interface CategoryRepository extends CrudRepository<Category, Long> {
|
public interface CategoryRepository extends CrudRepository<Category, Long> {
|
||||||
@Query("SELECT c FROM Category c JOIN FETCH c.listSubCategories")
|
@Query("SELECT c FROM Category c LEFT JOIN FETCH c.listSubCategories WHERE c.id = :id")
|
||||||
|
Optional<Category> findByIdWithSubCategories(@Param("id") Long id);
|
||||||
|
|
||||||
|
@Query("SELECT DISTINCT(c) FROM Category c LEFT JOIN FETCH c.listSubCategories ORDER BY c.name")
|
||||||
List<Category> findAllWithSubCategories();
|
List<Category> findAllWithSubCategories();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import org.springframework.stereotype.Component;
|
|||||||
public class CorsFilter implements Filter {
|
public class CorsFilter implements Filter {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(FilterConfig filterConfig) throws ServletException {
|
public void init(FilterConfig filterConfig) {
|
||||||
// Do nothing
|
// Do nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,5 +40,4 @@ public class CorsFilter implements Filter {
|
|||||||
public void destroy() {
|
public void destroy() {
|
||||||
// Do nothing
|
// Do nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,23 +1,21 @@
|
|||||||
package org.codiki.core.security;
|
package org.codiki.core.security;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
import org.springframework.security.authentication.AuthenticationProvider;
|
import org.springframework.security.authentication.AuthenticationProvider;
|
||||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
import org.springframework.security.core.AuthenticationException;
|
import org.springframework.security.core.AuthenticationException;
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
public class CustomAuthenticationProvider implements AuthenticationProvider {
|
public class CustomAuthenticationProvider implements AuthenticationProvider {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
|
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
|
||||||
// Creation of the authentication bean with its roles
|
// Creation of the authentication bean with its roles
|
||||||
Authentication auth = new UsernamePasswordAuthenticationToken(authentication.getName(),
|
Authentication auth = new UsernamePasswordAuthenticationToken(authentication.getName(),
|
||||||
authentication.getCredentials(), new ArrayList<GrantedAuthority>());
|
authentication.getCredentials(), new ArrayList<>());
|
||||||
|
|
||||||
// Set the auth bean in spring security context
|
// Set the auth bean in spring security context
|
||||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||||
@@ -29,5 +27,4 @@ public class CustomAuthenticationProvider implements AuthenticationProvider {
|
|||||||
public boolean supports(Class<?> authentication) {
|
public boolean supports(Class<?> authentication) {
|
||||||
return authentication.equals(UsernamePasswordAuthenticationToken.class);
|
return authentication.equals(UsernamePasswordAuthenticationToken.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,13 @@
|
|||||||
package org.codiki.core.security;
|
package org.codiki.core.security;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import javax.servlet.ServletException;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
|
|
||||||
import org.springframework.security.core.AuthenticationException;
|
import org.springframework.security.core.AuthenticationException;
|
||||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Authentication entry point configured in
|
* Authentication entry point configured in
|
||||||
* {@link SecurityConfiguration#configure(org.springframework.security.config.annotation.web.builders.HttpSecurity)}
|
* {@link SecurityConfiguration#configure(org.springframework.security.config.annotation.web.builders.HttpSecurity)}
|
||||||
|
|||||||
@@ -26,11 +26,7 @@ public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
|
|||||||
private CustomAuthenticationProvider authenticationProvider;
|
private CustomAuthenticationProvider authenticationProvider;
|
||||||
private RestAuthenticationEntryPoint authenticationEntryPoint;
|
private RestAuthenticationEntryPoint authenticationEntryPoint;
|
||||||
|
|
||||||
/**
|
/** Constructor. */
|
||||||
* Constructor.
|
|
||||||
* @param authenticationProvider
|
|
||||||
* @param authenticationEntryPoint
|
|
||||||
*/
|
|
||||||
public SecurityConfiguration(CustomAuthenticationProvider authenticationProvider,
|
public SecurityConfiguration(CustomAuthenticationProvider authenticationProvider,
|
||||||
RestAuthenticationEntryPoint authenticationEntryPoint) {
|
RestAuthenticationEntryPoint authenticationEntryPoint) {
|
||||||
this.authenticationProvider = authenticationProvider;
|
this.authenticationProvider = authenticationProvider;
|
||||||
|
|||||||
@@ -1,15 +1,6 @@
|
|||||||
package org.codiki.core.services;
|
package org.codiki.core.services;
|
||||||
|
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.MalformedURLException;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.nio.file.Paths;
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
import org.apache.commons.lang.RandomStringUtils;
|
import org.apache.commons.lang.RandomStringUtils;
|
||||||
import org.codiki.core.utils.StringUtils;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
@@ -18,6 +9,12 @@ import org.springframework.core.io.UrlResource;
|
|||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class FileUploadService {
|
public class FileUploadService {
|
||||||
/** Logger. */
|
/** Logger. */
|
||||||
@@ -25,12 +22,17 @@ public class FileUploadService {
|
|||||||
/** Length of uploaded file names. */
|
/** Length of uploaded file names. */
|
||||||
private static final int DESTINATION_IMAGE_NAME_LENGTH = 30;
|
private static final int DESTINATION_IMAGE_NAME_LENGTH = 30;
|
||||||
|
|
||||||
@Value("${codiki.files.upload}")
|
private final String folderUpload;
|
||||||
private String folderUpload;
|
private final String folderProfileImages;
|
||||||
@Value("${codiki.files.profile-images}")
|
private final String folderImages;
|
||||||
private String folderProfileImages;
|
|
||||||
@Value("${codiki.files.images}")
|
public FileUploadService(@Value("${codiki.files.upload}") String folderUpload,
|
||||||
private String folderImages;
|
@Value("${codiki.files.profile-images}") String folderProfileImages,
|
||||||
|
@Value("${codiki.files.images}")String folderImages) {
|
||||||
|
this.folderUpload = folderUpload;
|
||||||
|
this.folderProfileImages = folderProfileImages;
|
||||||
|
this.folderImages = folderImages;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds the destination file name, which is a random string with 30 char
|
* Builds the destination file name, which is a random string with 30 char
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import org.springframework.stereotype.Service;
|
|||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class ParserService {
|
public class ParserService {
|
||||||
|
|
||||||
private static final String REG_CODE = "\\[code lg="([a-z]+)"\\](.*)\\[\\/code\\]\\n";
|
private static final String REG_CODE = "\\[code lg="([a-z]+)"\\](.*)\\[\\/code\\]\\n";
|
||||||
private static final String REG_CODE_REPLACE = "<pre class=\"line-numbers\"><code class=\"language-\\1\">\\2</code></pre>";
|
private static final String REG_CODE_REPLACE = "<pre class=\"line-numbers\"><code class=\"language-\\1\">\\2</code></pre>";
|
||||||
private static final String REG_IMAGES = "\\[img src="([^\"| ]+)"( alt="([^\"| ]+)")? \\/\\]";
|
private static final String REG_IMAGES = "\\[img src="([^\"| ]+)"( alt="([^\"| ]+)")? \\/\\]";
|
||||||
@@ -17,12 +16,12 @@ public class ParserService {
|
|||||||
private static final String REG_LINKS = "\\[link href="([^\"| ]+)" txt="([^\"| ]+)" \\/\\]";
|
private static final String REG_LINKS = "\\[link href="([^\"| ]+)" txt="([^\"| ]+)" \\/\\]";
|
||||||
private static final String REG_LINKS_REPLACE = "<a href=\"\\1\">\\2</a>";
|
private static final String REG_LINKS_REPLACE = "<a href=\"\\1\">\\2</a>";
|
||||||
|
|
||||||
static final Pattern PATTERN_CODE;
|
private static final Pattern PATTERN_CODE;
|
||||||
static final Pattern PATTERN_CODE_REPLACE;
|
private static final Pattern PATTERN_CODE_REPLACE;
|
||||||
static final Pattern PATTERN_IMAGES;
|
private static final Pattern PATTERN_IMAGES;
|
||||||
static final Pattern PATTERN_IMAGES_REPLACE;
|
private static final Pattern PATTERN_IMAGES_REPLACE;
|
||||||
static final Pattern PATTERN_LINKS;
|
private static final Pattern PATTERN_LINKS;
|
||||||
static final Pattern PATTERN_LINKS_REPLACE;
|
private static final Pattern PATTERN_LINKS_REPLACE;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
PATTERN_CODE = Pattern.compile(REG_CODE);
|
PATTERN_CODE = Pattern.compile(REG_CODE);
|
||||||
@@ -45,7 +44,7 @@ public class ParserService {
|
|||||||
return pSource.replace("£ø", "$");
|
return pSource.replace("£ø", "$");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String parseHeaders(final String pSource) {
|
String parseHeaders(final String pSource) {
|
||||||
String result = pSource;
|
String result = pSource;
|
||||||
for(int i = 1 ; i <= 3 ; i++) {
|
for(int i = 1 ; i <= 3 ; i++) {
|
||||||
result = parseHeadersHX(result, i);
|
result = parseHeadersHX(result, i);
|
||||||
@@ -53,7 +52,7 @@ public class ParserService {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String parseHeadersHX(final String pSource, final int pNumHeader) {
|
String parseHeadersHX(final String pSource, final int pNumHeader) {
|
||||||
String result = pSource;
|
String result = pSource;
|
||||||
|
|
||||||
// (.*)(\[hX\](.*)\[\/hX\])+(.*)
|
// (.*)(\[hX\](.*)\[\/hX\])+(.*)
|
||||||
@@ -73,11 +72,11 @@ public class ParserService {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String parseBackSpaces(final String pSource) {
|
String parseBackSpaces(final String pSource) {
|
||||||
return pSource.replaceAll("\r?\n", "<br/>").replaceAll("\\[\\/code\\]<br\\/><br\\/>", "[/code]\n");
|
return pSource.replaceAll("\r?\n", "<br/>").replaceAll("\\[\\/code\\]<br\\/><br\\/>", "[/code]\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String parseImages(final String pSource) {
|
String parseImages(final String pSource) {
|
||||||
String result = pSource;
|
String result = pSource;
|
||||||
|
|
||||||
Matcher matcher = PATTERN_IMAGES.matcher(result);
|
Matcher matcher = PATTERN_IMAGES.matcher(result);
|
||||||
@@ -96,7 +95,7 @@ public class ParserService {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String parseLinks(final String pSource) {
|
String parseLinks(final String pSource) {
|
||||||
String result = pSource;
|
String result = pSource;
|
||||||
|
|
||||||
Matcher matcher = PATTERN_LINKS.matcher(result);
|
Matcher matcher = PATTERN_LINKS.matcher(result);
|
||||||
|
|||||||
@@ -17,15 +17,18 @@ import javax.swing.text.html.Option;
|
|||||||
public class UserService {
|
public class UserService {
|
||||||
private static final String MSG_BAD_CREDENTIALS = "Adresse email ou mot de passe incorrect.";
|
private static final String MSG_BAD_CREDENTIALS = "Adresse email ou mot de passe incorrect.";
|
||||||
|
|
||||||
@Autowired
|
private final UserRepository userRepository;
|
||||||
private UserRepository userRepository;
|
|
||||||
|
public UserService(UserRepository userRepository) {
|
||||||
|
this.userRepository = userRepository;
|
||||||
|
}
|
||||||
|
|
||||||
public User checkCredentials(final String email, final String password) throws BadCredentialsException {
|
public User checkCredentials(final String email, final String password) throws BadCredentialsException {
|
||||||
final Optional<User> optUser = userRepository.findByEmail(email);
|
final Optional<User> optUser = userRepository.findByEmail(email);
|
||||||
|
|
||||||
// If no user exists with the given email of if the given password doesn't match
|
// If no user exists with the given email of if the given password doesn't match
|
||||||
// to the user password, we throw an exception.
|
// to the user password, we throw an exception.
|
||||||
if(!optUser.isPresent() || !StringUtils.compareHash(password, optUser.get().getPassword())) {
|
if(optUser.isEmpty() || !StringUtils.compareHash(password, optUser.get().getPassword())) {
|
||||||
throw new BadCredentialsException(MSG_BAD_CREDENTIALS);
|
throw new BadCredentialsException(MSG_BAD_CREDENTIALS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import java.util.Date;
|
|||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
public class DateUtils {
|
public class DateUtils {
|
||||||
public static final String FORMAT_DEFAULT = "dd/MM/yyyy HH:mm:ss";
|
private static final String FORMAT_DEFAULT = "dd/MM/yyyy HH:mm:ss";
|
||||||
|
|
||||||
public static Date parseDate(String pSource, String pPattern) throws ParseException {
|
public static Date parseDate(String pSource, String pPattern) throws ParseException {
|
||||||
Date result = null;
|
Date result = null;
|
||||||
@@ -27,7 +27,7 @@ public class DateUtils {
|
|||||||
return getSimpleDateFormat(FORMAT_DEFAULT).format(pDate);
|
return getSimpleDateFormat(FORMAT_DEFAULT).format(pDate);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SimpleDateFormat getSimpleDateFormat(String pPattern) {
|
private static SimpleDateFormat getSimpleDateFormat(String pPattern) {
|
||||||
SimpleDateFormat result = new SimpleDateFormat(pPattern, Locale.FRENCH);
|
SimpleDateFormat result = new SimpleDateFormat(pPattern, Locale.FRENCH);
|
||||||
result.setLenient(false);
|
result.setLenient(false);
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
@@ -52,9 +52,7 @@ public class ImageController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping
|
@PostMapping
|
||||||
public ResponseEntity<String> uploadImage(@RequestParam("file") MultipartFile pFile,
|
public ResponseEntity<String> uploadImage(@RequestParam("file") MultipartFile pFile, final Principal pPrincipal) {
|
||||||
final HttpServletResponse pResponse,
|
|
||||||
final Principal pPrincipal) throws IOException {
|
|
||||||
ResponseEntity<String> result;
|
ResponseEntity<String> result;
|
||||||
try {
|
try {
|
||||||
result = ResponseEntity.status(HttpStatus.OK)
|
result = ResponseEntity.status(HttpStatus.OK)
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ public class ImageService {
|
|||||||
* @param fileUploadService File upload service.
|
* @param fileUploadService File upload service.
|
||||||
* @param imageRepository Image repository.
|
* @param imageRepository Image repository.
|
||||||
*/
|
*/
|
||||||
public ImageService(UserService userService,
|
ImageService(UserService userService,
|
||||||
UserRepository userRepository,
|
UserRepository userRepository,
|
||||||
FileUploadService fileUploadService,
|
FileUploadService fileUploadService,
|
||||||
ImageRepository imageRepository) {
|
ImageRepository imageRepository) {
|
||||||
@@ -86,11 +86,11 @@ public class ImageService {
|
|||||||
return fileUploadService.loadAvatar(pAvatarFileName);
|
return fileUploadService.loadAvatar(pAvatarFileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<Resource> loadImage(final String pImageLink) {
|
Optional<Resource> loadImage(final String pImageLink) {
|
||||||
return fileUploadService.loadImage(pImageLink);
|
return fileUploadService.loadImage(pImageLink);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<ImageDTO> getUserImages(final Principal pPrincipal) {
|
List<ImageDTO> getUserImages(final Principal pPrincipal) {
|
||||||
return imageRepository.getByUserId(userService.getUserByPrincipal(pPrincipal)
|
return imageRepository.getByUserId(userService.getUserByPrincipal(pPrincipal)
|
||||||
.map(User::getId)
|
.map(User::getId)
|
||||||
.orElseThrow(NoSuchElementException::new))
|
.orElseThrow(NoSuchElementException::new))
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import java.util.Optional;
|
|||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.StreamSupport;
|
import java.util.stream.StreamSupport;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
import org.codiki.core.entities.dto.PostDTO;
|
import org.codiki.core.entities.dto.PostDTO;
|
||||||
@@ -19,7 +18,6 @@ import org.codiki.core.repositories.PostRepository;
|
|||||||
import org.codiki.core.services.ParserService;
|
import org.codiki.core.services.ParserService;
|
||||||
import org.codiki.core.services.UserService;
|
import org.codiki.core.services.UserService;
|
||||||
import org.codiki.core.utils.StringUtils;
|
import org.codiki.core.utils.StringUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.data.domain.PageRequest;
|
import org.springframework.data.domain.PageRequest;
|
||||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
@@ -35,7 +33,6 @@ import com.fasterxml.jackson.annotation.JsonView;
|
|||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/api/posts")
|
@RequestMapping("/api/posts")
|
||||||
public class PostController {
|
public class PostController {
|
||||||
|
|
||||||
private static final int LIMIT_POSTS_HOME = 20;
|
private static final int LIMIT_POSTS_HOME = 20;
|
||||||
/** Service to parse post content. */
|
/** Service to parse post content. */
|
||||||
private ParserService parserService;
|
private ParserService parserService;
|
||||||
@@ -112,14 +109,11 @@ public class PostController {
|
|||||||
|
|
||||||
@JsonView(View.PostDTO.class)
|
@JsonView(View.PostDTO.class)
|
||||||
@GetMapping("/myPosts")
|
@GetMapping("/myPosts")
|
||||||
public List<Post> getMyPosts(final HttpServletRequest pRequest, final HttpServletResponse pResponse,
|
public List<Post> getMyPosts(final HttpServletResponse pResponse, final Principal pPrincipal) throws IOException {
|
||||||
final Principal pPrincipal) throws IOException {
|
|
||||||
List<Post> result = new LinkedList<>();
|
List<Post> result = new LinkedList<>();
|
||||||
|
|
||||||
final Optional<User> connectedUser = userService.getUserByPrincipal(pPrincipal);
|
final Optional<User> connectedUser = userService.getUserByPrincipal(pPrincipal);
|
||||||
if(connectedUser.isPresent()) {
|
if(connectedUser.isPresent()) {
|
||||||
// result = postRepository.getByCreator(connectedUser.get().getId())
|
|
||||||
// .stream().map(PostDTO::new).collect(Collectors.toList());
|
|
||||||
result = postRepository.getByCreator(connectedUser.get().getId());
|
result = postRepository.getByCreator(connectedUser.get().getId());
|
||||||
} else {
|
} else {
|
||||||
pResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED);
|
pResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED);
|
||||||
@@ -142,20 +136,21 @@ public class PostController {
|
|||||||
|
|
||||||
@JsonView(View.PostDTO.class)
|
@JsonView(View.PostDTO.class)
|
||||||
@PostMapping("/")
|
@PostMapping("/")
|
||||||
public Post insert(@RequestBody final PostDTO pPost, final HttpServletRequest pRequest,
|
public Post insert(@RequestBody final Post pPost,
|
||||||
final HttpServletResponse pResponse, final Principal pPrincipal) {
|
final HttpServletResponse pResponse,
|
||||||
return postService.insert(pPost, pRequest, pResponse, pPrincipal).orElse(null);
|
final Principal pPrincipal) {
|
||||||
|
pResponse.setStatus(postService.insert(pPost, pPrincipal));
|
||||||
|
return pPost;
|
||||||
}
|
}
|
||||||
|
|
||||||
@PutMapping("/")
|
@PutMapping("/")
|
||||||
public void update(@RequestBody final Post pPost, final HttpServletRequest pRequest,
|
public void update(@RequestBody final Post pPost,
|
||||||
final HttpServletResponse pResponse, final Principal pPrincipal) throws IOException {
|
final HttpServletResponse pResponse, final Principal pPrincipal) throws IOException {
|
||||||
postService.update(pPost, pRequest, pResponse, pPrincipal);
|
postService.update(pPost, pResponse, pPrincipal);
|
||||||
}
|
}
|
||||||
|
|
||||||
@DeleteMapping("/{postKey}")
|
@DeleteMapping("/{postKey}")
|
||||||
public void delete(@PathVariable("postKey") final String pPostKey, final HttpServletRequest pRequest,
|
public void delete(@PathVariable("postKey") final String pPostKey, final Principal pPrincipal) {
|
||||||
final HttpServletResponse pResponse, final Principal pPrincipal) throws IOException {
|
postService.delete(pPostKey, pPrincipal);
|
||||||
postService.delete(pPostKey, pRequest, pResponse, pPrincipal);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,72 +1,59 @@
|
|||||||
package org.codiki.posts;
|
package org.codiki.posts;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.security.Principal;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.codiki.core.entities.business.SearchEntity;
|
import org.codiki.core.entities.business.SearchEntity;
|
||||||
import org.codiki.core.entities.dto.PostDTO;
|
|
||||||
import org.codiki.core.entities.persistence.Category;
|
import org.codiki.core.entities.persistence.Category;
|
||||||
import org.codiki.core.entities.persistence.Post;
|
import org.codiki.core.entities.persistence.Post;
|
||||||
import org.codiki.core.entities.persistence.User;
|
import org.codiki.core.entities.persistence.User;
|
||||||
import org.codiki.core.repositories.CategoryRepository;
|
import org.codiki.core.repositories.CategoryRepository;
|
||||||
import org.codiki.core.repositories.PostRepository;
|
import org.codiki.core.repositories.PostRepository;
|
||||||
|
import org.codiki.core.services.IllegalAccessException;
|
||||||
import org.codiki.core.services.UserService;
|
import org.codiki.core.services.UserService;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.security.Principal;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class PostService {
|
public class PostService {
|
||||||
static final int SCORE_TITLE = 50;
|
private static final int SCORE_TITLE = 50;
|
||||||
|
private static final int SCORE_DESCRIPTION = 5;
|
||||||
|
private static final int SCORE_TEXT = 1;
|
||||||
|
private static final int SCORE_CATEGORY = 30;
|
||||||
|
private static final int SCORE_AUTHOR_NAME = 40;
|
||||||
|
private static final int SCORE_AUTHOR_EMAIL = 40;
|
||||||
|
|
||||||
static final int SCORE_DESCRIPTION = 5;
|
private final PostRepository postRepository;
|
||||||
|
|
||||||
static final int SCORE_TEXT = 1;
|
private final CategoryRepository categoryRepository;
|
||||||
|
|
||||||
static final int SCORE_CATEGORY = 30;
|
private final UserService userService;
|
||||||
|
|
||||||
static final int SCORE_AUTHOR_NAME = 40;
|
/** Constructor. */
|
||||||
|
public PostService(PostRepository postRepository,
|
||||||
static final int SCORE_AUTHOR_EMAIL = 40;
|
CategoryRepository categoryRepository,
|
||||||
|
UserService userService) {
|
||||||
@Autowired
|
this.postRepository = postRepository;
|
||||||
private PostRepository postRepository;
|
this.categoryRepository = categoryRepository;
|
||||||
|
this.userService = userService;
|
||||||
@Autowired
|
|
||||||
private CategoryRepository categoryRepository;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private UserService userService;
|
|
||||||
|
|
||||||
public Optional<Post> insert(final PostDTO pPost, final HttpServletRequest pRequest,
|
|
||||||
final HttpServletResponse pResponse, final Principal pPrincipal) {
|
|
||||||
Optional<Post> result = Optional.empty();
|
|
||||||
|
|
||||||
final Optional<User> user = userService.getUserByPrincipal(pPrincipal);
|
|
||||||
|
|
||||||
if(user.isPresent()) {
|
|
||||||
final Post postToSave = new Post(pPost);
|
|
||||||
postToSave.setAuthor(user.get());
|
|
||||||
postRepository.save(postToSave);
|
|
||||||
result = Optional.of(postToSave);
|
|
||||||
} else {
|
|
||||||
pResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
public int insert(final Post pPost, final Principal pPrincipal) {
|
||||||
|
return userService.getUserByPrincipal(pPrincipal)
|
||||||
|
.map(user -> {
|
||||||
|
pPost.setCreationDate(new Date());
|
||||||
|
pPost.setAuthor(user);
|
||||||
|
postRepository.save(pPost);
|
||||||
|
return HttpServletResponse.SC_OK;
|
||||||
|
})
|
||||||
|
.orElse(HttpServletResponse.SC_UNAUTHORIZED);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void update(final Post pPost, final HttpServletRequest pRequest,
|
public void update(final Post pPost, final HttpServletResponse pResponse, final Principal pPrincipal)
|
||||||
final HttpServletResponse pResponse, final Principal pPrincipal) throws IOException {
|
throws IOException {
|
||||||
final Optional<User> connectedUser = userService.getUserByPrincipal(pPrincipal);
|
final Optional<User> connectedUser = userService.getUserByPrincipal(pPrincipal);
|
||||||
|
|
||||||
if(connectedUser.isPresent() && connectedUser.get().getKey().equals(pPost.getAuthor().getKey())) {
|
if(connectedUser.isPresent() && connectedUser.get().getKey().equals(pPost.getAuthor().getKey())) {
|
||||||
@@ -96,23 +83,19 @@ public class PostService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void delete(final String pPostKey, final HttpServletRequest pRequest,
|
public void delete(final String pPostKey, final Principal pPrincipal){
|
||||||
final HttpServletResponse pResponse, final Principal pPrincipal) throws IOException {
|
String userKey = userService.getUserByPrincipal(pPrincipal)
|
||||||
final Optional<Post> postToDelete = postRepository.getByKey(pPostKey);
|
.map(User::getKey)
|
||||||
if(postToDelete.isPresent()) {
|
.orElseThrow(NoSuchElementException::new);
|
||||||
final Optional<User> connectedUser = userService.getUserByPrincipal(pPrincipal);
|
|
||||||
if(connectedUser.isPresent()) {
|
Post postToDelete = postRepository.getByKey(pPostKey)
|
||||||
if(connectedUser.get().getKey().equals(postToDelete.get().getAuthor().getKey())) {
|
.orElseThrow(NoSuchElementException::new);
|
||||||
postRepository.delete(postToDelete.get());
|
|
||||||
} else {
|
if(postToDelete.getAuthor() == null || !postToDelete.getAuthor().getKey().equals(userKey)) {
|
||||||
pResponse.sendError(HttpServletResponse.SC_FORBIDDEN);
|
throw new IllegalAccessException();
|
||||||
}
|
|
||||||
} else {
|
|
||||||
pResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
pResponse.sendError(HttpServletResponse.SC_NOT_FOUND);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
postRepository.delete(postToDelete);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Post> search(String pSearchCriteria) {
|
public List<Post> search(String pSearchCriteria) {
|
||||||
@@ -123,12 +106,12 @@ public class PostService {
|
|||||||
calculateScore(e, criteriasArray);
|
calculateScore(e, criteriasArray);
|
||||||
listSearchEntities.add(e);
|
listSearchEntities.add(e);
|
||||||
});
|
});
|
||||||
Collections.sort(listSearchEntities, (e1, e2) -> e2.getScore() - e1.getScore());
|
listSearchEntities.sort((e1, e2) -> e2.getScore() - e1.getScore());
|
||||||
|
|
||||||
return listSearchEntities.stream().map(SearchEntity::getPost).collect(Collectors.toList());
|
return listSearchEntities.stream().map(SearchEntity::getPost).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
void calculateScore(final SearchEntity searchPost, final String[] pCriteriasArray) {
|
private void calculateScore(final SearchEntity searchPost, final String[] pCriteriasArray) {
|
||||||
for(final String criteria : pCriteriasArray) {
|
for(final String criteria : pCriteriasArray) {
|
||||||
String formattedCriteria = formatForComp(criteria);
|
String formattedCriteria = formatForComp(criteria);
|
||||||
|
|
||||||
@@ -141,41 +124,41 @@ public class PostService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String formatForComp(final String pElem) {
|
private String formatForComp(final String pElem) {
|
||||||
return StringUtils.stripAccents(pElem.toLowerCase());
|
return StringUtils.stripAccents(pElem.toLowerCase());
|
||||||
}
|
}
|
||||||
|
|
||||||
void calculateScoreForTitle(final SearchEntity pSearchPost, final String pCriteria) {
|
private void calculateScoreForTitle(final SearchEntity pSearchPost, final String pCriteria) {
|
||||||
if(formatForComp(pSearchPost.getPost().getTitle()).contains(pCriteria)) {
|
if(formatForComp(pSearchPost.getPost().getTitle()).contains(pCriteria)) {
|
||||||
pSearchPost.increaseScore(SCORE_TITLE);
|
pSearchPost.increaseScore(SCORE_TITLE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void calculateScoreForDescription(final SearchEntity pSearchPost, final String pCriteria) {
|
private void calculateScoreForDescription(final SearchEntity pSearchPost, final String pCriteria) {
|
||||||
final int criteriaOccurence = StringUtils.countMatches(formatForComp(pSearchPost.getPost().getDescription()),
|
final int criteriaOccurence = StringUtils.countMatches(formatForComp(pSearchPost.getPost().getDescription()),
|
||||||
pCriteria);
|
pCriteria);
|
||||||
pSearchPost.increaseScore(criteriaOccurence * SCORE_DESCRIPTION);
|
pSearchPost.increaseScore(criteriaOccurence * SCORE_DESCRIPTION);
|
||||||
}
|
}
|
||||||
|
|
||||||
void calculateScoreForText(final SearchEntity pSearchPost, final String pCriteria) {
|
private void calculateScoreForText(final SearchEntity pSearchPost, final String pCriteria) {
|
||||||
final int criteriaOccurence = StringUtils.countMatches(formatForComp(pSearchPost.getPost().getText()),
|
final int criteriaOccurence = StringUtils.countMatches(formatForComp(pSearchPost.getPost().getText()),
|
||||||
pCriteria);
|
pCriteria);
|
||||||
pSearchPost.increaseScore(criteriaOccurence * SCORE_TEXT);
|
pSearchPost.increaseScore(criteriaOccurence * SCORE_TEXT);
|
||||||
}
|
}
|
||||||
|
|
||||||
void calculateScoreForCategory(final SearchEntity pSearchPost, final String pCriteria) {
|
private void calculateScoreForCategory(final SearchEntity pSearchPost, final String pCriteria) {
|
||||||
if(formatForComp(pSearchPost.getPost().getCategory().getName()).contains(pCriteria)) {
|
if(formatForComp(pSearchPost.getPost().getCategory().getName()).contains(pCriteria)) {
|
||||||
pSearchPost.increaseScore(SCORE_CATEGORY);
|
pSearchPost.increaseScore(SCORE_CATEGORY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void calculateScoreForAuthorName(final SearchEntity pSearchPost, final String pCriteria) {
|
private void calculateScoreForAuthorName(final SearchEntity pSearchPost, final String pCriteria) {
|
||||||
if(formatForComp(pSearchPost.getPost().getAuthor().getName()).contains(pCriteria)) {
|
if(formatForComp(pSearchPost.getPost().getAuthor().getName()).contains(pCriteria)) {
|
||||||
pSearchPost.increaseScore(SCORE_AUTHOR_NAME);
|
pSearchPost.increaseScore(SCORE_AUTHOR_NAME);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void calculateScoreForAuthorEmail(final SearchEntity pSearchPost, final String pCriteria) {
|
private void calculateScoreForAuthorEmail(final SearchEntity pSearchPost, final String pCriteria) {
|
||||||
if(formatForComp(pSearchPost.getPost().getAuthor().getEmail()).contains(pCriteria)) {
|
if(formatForComp(pSearchPost.getPost().getAuthor().getEmail()).contains(pCriteria)) {
|
||||||
pSearchPost.increaseScore(SCORE_AUTHOR_EMAIL);
|
pSearchPost.increaseScore(SCORE_AUTHOR_EMAIL);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,12 +13,14 @@ import org.springframework.web.bind.annotation.RestController;
|
|||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/api/versionrevisions")
|
@RequestMapping("/api/versionrevisions")
|
||||||
public class VersionRevisionController {
|
public class VersionRevisionController {
|
||||||
|
private final VersionRevisionRepository repository;
|
||||||
|
private final VersionRepository versionRepository;
|
||||||
|
|
||||||
@Autowired
|
public VersionRevisionController(VersionRevisionRepository repository,
|
||||||
private VersionRevisionRepository repository;
|
VersionRepository versionRepository) {
|
||||||
|
this.repository = repository;
|
||||||
@Autowired
|
this.versionRepository = versionRepository;
|
||||||
private VersionRepository versionRepository;
|
}
|
||||||
|
|
||||||
@GetMapping("/versions")
|
@GetMapping("/versions")
|
||||||
public Iterable<Version> getVersions() {
|
public Iterable<Version> getVersions() {
|
||||||
|
|||||||
@@ -40,8 +40,7 @@ spring:
|
|||||||
url: jdbc:postgresql://localhost:5432/codiki
|
url: jdbc:postgresql://localhost:5432/codiki
|
||||||
username: codiki
|
username: codiki
|
||||||
password: P@ssword
|
password: P@ssword
|
||||||
# TODO: Delete all Lazy relationships and set following property to false
|
open-in-view: false
|
||||||
# open-in-view: false
|
|
||||||
# Because detection is disabled you have to set correct dialect by hand.
|
# Because detection is disabled you have to set correct dialect by hand.
|
||||||
database-platform: org.hibernate.dialect.PostgreSQL9Dialect
|
database-platform: org.hibernate.dialect.PostgreSQL9Dialect
|
||||||
# Disable feature detection by this undocumented parameter.
|
# Disable feature detection by this undocumented parameter.
|
||||||
|
|||||||
@@ -3,4 +3,5 @@ INSERT INTO version (number) VALUES ('1.2.0');
|
|||||||
INSERT INTO version_revision (version_id, text, bugfix) VALUES
|
INSERT INTO version_revision (version_id, text, bugfix) VALUES
|
||||||
(4, 'Migration vers Angular 8.2.', FALSE),
|
(4, 'Migration vers Angular 8.2.', FALSE),
|
||||||
(4, 'Migration vers Java 11.', FALSE),
|
(4, 'Migration vers Java 11.', FALSE),
|
||||||
(4, 'Corrections mineures et améliorations de code.', TRUE);
|
(4, 'Corrections mineures et améliorations de code.', TRUE),
|
||||||
|
(4, 'Ajout d''un gestionnaire de notifications pop-ups.', FALSE);
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import { catchError } from 'rxjs/operators';
|
|||||||
import { AuthService } from '../services/auth.service';
|
import { AuthService } from '../services/auth.service';
|
||||||
import { NotificationsComponent } from '../notifications/notifications.component';
|
import { NotificationsComponent } from '../notifications/notifications.component';
|
||||||
|
|
||||||
|
const REG_URL_LOGIN = /^https?:\/\/.*(:\d{1,5})?\/api\/account\/login$/;
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class UnauthorizedInterceptor implements HttpInterceptor {
|
export class UnauthorizedInterceptor implements HttpInterceptor {
|
||||||
constructor(
|
constructor(
|
||||||
@@ -18,8 +20,10 @@ export class UnauthorizedInterceptor implements HttpInterceptor {
|
|||||||
if (err.status === 401) {
|
if (err.status === 401) {
|
||||||
this.authService.setAnonymous();
|
this.authService.setAnonymous();
|
||||||
this.router.navigate(['/login']);
|
this.router.navigate(['/login']);
|
||||||
|
if (!err.url.match(REG_URL_LOGIN)) {
|
||||||
window.setTimeout(() => NotificationsComponent.error('Veuillez vous authentifier pour réaliser cette action.'), 500);
|
window.setTimeout(() => NotificationsComponent.error('Veuillez vous authentifier pour réaliser cette action.'), 500);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const error = (err.error && err.error.message) || err.statusText;
|
const error = (err.error && err.error.message) || err.statusText;
|
||||||
return throwError(error);
|
return throwError(error);
|
||||||
|
|||||||
@@ -17,8 +17,16 @@
|
|||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item dropdown" dropdown *ngIf="isAuthenticated()">
|
<li class="nav-item dropdown" dropdown *ngIf="isAuthenticated()">
|
||||||
<a dropdownToggle mdbRippleRadius type="button" class="nav-link dropdown-toggle waves-light" mdbRippleRadius>
|
<a dropdownToggle
|
||||||
<i class="fa fa-user-circle"></i> Mon Compte
|
mdbRippleRadius
|
||||||
|
type="button"
|
||||||
|
class="nav-link waves-light"
|
||||||
|
mdbTooltip="Mon compte"
|
||||||
|
placement="bottom"
|
||||||
|
mdbRippleRadius>
|
||||||
|
<img id="user-profile-img"
|
||||||
|
[src]="getConnectedUserImage()"
|
||||||
|
(error)="onUserProfileLoadingError($event)"/>
|
||||||
</a>
|
</a>
|
||||||
<div *dropdownMenu class="dropdown-menu dropdown-menu-right dropdown dropdown-primary" role="menu">
|
<div *dropdownMenu class="dropdown-menu dropdown-menu-right dropdown dropdown-primary" role="menu">
|
||||||
<a class="dropdown-item waves-light" mdbRippleRadius routerLink="/myPosts">
|
<a class="dropdown-item waves-light" mdbRippleRadius routerLink="/myPosts">
|
||||||
@@ -47,7 +55,10 @@
|
|||||||
<i class="fa fa-chevron-left"></i>
|
<i class="fa fa-chevron-left"></i>
|
||||||
</a>
|
</a>
|
||||||
<div *ngFor="let category of listCategories">
|
<div *ngFor="let category of listCategories">
|
||||||
<a [id]="'category-' + category.id" class="collapsible" *ngIf="category.listSubCategories.length" (click)="openCategoriesLinks(category)">
|
<a [id]="'category-' + category.id"
|
||||||
|
class="collapsible"
|
||||||
|
*ngIf="!!category.listSubCategories && category.listSubCategories.length"
|
||||||
|
(click)="openCategoriesLinks(category)">
|
||||||
{{category.name}} <i class="fa {{accordionOpenned[category.id] ? 'fa-chevron-down' : 'fa-chevron-right'}} float-right"></i>
|
{{category.name}} <i class="fa {{accordionOpenned[category.id] ? 'fa-chevron-down' : 'fa-chevron-right'}} float-right"></i>
|
||||||
</a>
|
</a>
|
||||||
<div class="categoriesLinks" >
|
<div class="categoriesLinks" >
|
||||||
|
|||||||
@@ -27,42 +27,48 @@
|
|||||||
overflow-x: hidden; /* Disable horizontal scroll */
|
overflow-x: hidden; /* Disable horizontal scroll */
|
||||||
padding-top: 20px; /* Place content 60px from the top */
|
padding-top: 20px; /* Place content 60px from the top */
|
||||||
transition: 0.3s; /* 0.5 second transition effect to slide in the sidenav */
|
transition: 0.3s; /* 0.5 second transition effect to slide in the sidenav */
|
||||||
}
|
|
||||||
|
|
||||||
/* The navigation menu links */
|
/* The navigation menu links */
|
||||||
.sidenav a {
|
a {
|
||||||
padding: 8px 32px 8px 32px;
|
padding: 8px 32px 8px 32px;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
color: white;
|
color: white;
|
||||||
display: block;
|
display: block;
|
||||||
transition: 0.3s;
|
transition: 0.3s;
|
||||||
}
|
|
||||||
|
|
||||||
/* When you mouse over the navigation links, change their color */
|
/* When you mouse over the navigation links, change their color */
|
||||||
.sidenav a:hover {
|
&:hover {
|
||||||
color: #ccc;
|
color: #ccc;
|
||||||
background-color: #5c6bc0;
|
background-color: #5c6bc0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.sidenav h3 {
|
h3 {
|
||||||
padding: 8px 8px 8px 32px;
|
padding: 8px 8px 8px 32px;
|
||||||
color: white;
|
color: white;
|
||||||
padding-bottom: 25px;
|
padding-bottom: 25px;
|
||||||
border-bottom: 1px solid #5c6bc0;
|
border-bottom: 1px solid #5c6bc0;
|
||||||
}
|
}
|
||||||
/* Position and style the close button (top right corner) */
|
|
||||||
.sidenav .closebtn {
|
/* Position and style the close button (top right corner) */
|
||||||
|
.closebtn {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 25px;
|
top: 25px;
|
||||||
right: 25px;
|
right: 25px;
|
||||||
margin-left: 50px;
|
margin-left: 50px;
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* On smaller screens, where height is less than 450px, change the style of the sidenav (less padding and a smaller font size) */
|
/* On smaller screens, where height is less than 450px, change the style of the sidenav (less padding and a smaller font size) */
|
||||||
@media screen and (max-height: 450px) {
|
@media screen and (max-height: 450px) {
|
||||||
.sidenav {padding-top: 15px;}
|
.sidenav {
|
||||||
.sidenav a {font-size: 18px;}
|
padding-top: 15px;
|
||||||
|
|
||||||
|
a {
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#overlay {
|
#overlay {
|
||||||
@@ -74,8 +80,8 @@
|
|||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
background-color: rgba(0,0,0,0.5); /* Black background with opacity */
|
background-color: rgba(0, 0, 0, 0.5); /* Black background with opacity */
|
||||||
z-index: 999; /* Specify a stack order in case you're using a different order for other elements */
|
z-index: 1031; /* Specify a stack order in case you're using a different order for other elements */
|
||||||
transition: 0.5s;
|
transition: 0.5s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,6 +90,10 @@
|
|||||||
max-height: 0;
|
max-height: 0;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
transition: max-height 0.2s ease-out;
|
transition: max-height 0.2s ease-out;
|
||||||
|
|
||||||
|
a {
|
||||||
|
padding-left: 50px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.dropdown-item.danger-color-dark:hover {
|
.dropdown-item.danger-color-dark:hover {
|
||||||
@@ -93,3 +103,15 @@
|
|||||||
.collapsible i.fa {
|
.collapsible i.fa {
|
||||||
padding-top: 4px;
|
padding-top: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#user-profile-img {
|
||||||
|
filter: opacity(1);
|
||||||
|
transition: filter 0.3s;
|
||||||
|
border-radius: 50%;
|
||||||
|
width: 35px;
|
||||||
|
height: 35px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
filter: opacity(0.5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { HeaderService } from './header.service';
|
|||||||
import { environment } from '../../environments/environment';
|
import { environment } from '../../environments/environment';
|
||||||
|
|
||||||
const SIDENAV_WIDTH = '300px';
|
const SIDENAV_WIDTH = '300px';
|
||||||
|
const DEFAULT_USER_ICON = '../../assets/images/default_user_icon.png';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-header',
|
selector: 'app-header',
|
||||||
@@ -80,4 +81,13 @@ export class HeaderComponent implements OnInit {
|
|||||||
this.accordionOpenned[category.id] = true;
|
this.accordionOpenned[category.id] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getConnectedUserImage() {
|
||||||
|
const userImage = this.authService.getUser().image;
|
||||||
|
return !!userImage ? `./api/images/loadAvatar/${userImage}` : DEFAULT_USER_ICON;
|
||||||
|
}
|
||||||
|
|
||||||
|
onUserProfileLoadingError(event): void {
|
||||||
|
event.target.src = DEFAULT_USER_ICON;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ export class CreateUpdatePostComponent implements OnInit {
|
|||||||
this.listCategories = [];
|
this.listCategories = [];
|
||||||
this.activatedTab = Tabs.EDITION;
|
this.activatedTab = Tabs.EDITION;
|
||||||
this.createUpdatePostService.getCategories().subscribe(listCategories => {
|
this.createUpdatePostService.getCategories().subscribe(listCategories => {
|
||||||
this.listCategories = listCategories.filter(category => !category.listSubCategories.length);
|
this.listCategories = listCategories.filter(category => !category.listSubCategories);
|
||||||
});
|
});
|
||||||
|
|
||||||
const postKey = this.activatedRoute.snapshot.paramMap.get('postKey');
|
const postKey = this.activatedRoute.snapshot.paramMap.get('postKey');
|
||||||
@@ -166,6 +166,7 @@ export class CreateUpdatePostComponent implements OnInit {
|
|||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
this.createUpdatePostService.addPost(this.model).subscribe(post => {
|
this.createUpdatePostService.addPost(this.model).subscribe(post => {
|
||||||
|
NotificationsComponent.success('Article enregistré');
|
||||||
this.router.navigate([`/posts/update/${post.key}`]);
|
this.router.navigate([`/posts/update/${post.key}`]);
|
||||||
}, error => {
|
}, error => {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
|
|||||||
@@ -7,5 +7,9 @@
|
|||||||
<span *ngIf="listPosts?.length === 0">
|
<span *ngIf="listPosts?.length === 0">
|
||||||
Aucun article.
|
Aucun article.
|
||||||
</span>
|
</span>
|
||||||
<a routerLink="/posts/new" class="fixed-action-btn green white-text">+</a>
|
<a routerLink="/posts/new"
|
||||||
|
class="fixed-action-btn green white-text"
|
||||||
|
mdbTooltip="Créer un article" placement="left">
|
||||||
|
+
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -43,9 +43,6 @@
|
|||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
<p>Êtes vous sûr de vouloir supprimer cet article ?</p>
|
<p>Êtes vous sûr de vouloir supprimer cet article ?</p>
|
||||||
<p *ngIf="postDeletionFailed" class="red-text">
|
|
||||||
Une erreur est survenue lors de la suppression de l'article.
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { NotificationsComponent } from 'src/app/core/notifications/notifications.component';
|
||||||
import { Component, OnInit, SecurityContext, ViewChild } from '@angular/core';
|
import { Component, OnInit, SecurityContext, ViewChild } from '@angular/core';
|
||||||
import { ActivatedRoute, Router } from '@angular/router';
|
import { ActivatedRoute, Router } from '@angular/router';
|
||||||
import { HttpErrorResponse } from '@angular/common/http';
|
import { HttpErrorResponse } from '@angular/common/http';
|
||||||
@@ -38,9 +39,7 @@ export class PostComponent implements OnInit {
|
|||||||
notFound: boolean;
|
notFound: boolean;
|
||||||
owned: boolean;
|
owned: boolean;
|
||||||
|
|
||||||
@ViewChild('alertDelete', {static: true}) alertDelete;
|
@ViewChild('alertDelete', {static: false}) alertDelete;
|
||||||
|
|
||||||
postDeletionFailed: boolean;
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private activatedRoute: ActivatedRoute,
|
private activatedRoute: ActivatedRoute,
|
||||||
@@ -51,7 +50,6 @@ export class PostComponent implements OnInit {
|
|||||||
) {
|
) {
|
||||||
this.loaded = false;
|
this.loaded = false;
|
||||||
this.owned = false;
|
this.owned = false;
|
||||||
this.postDeletionFailed = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
@@ -91,16 +89,13 @@ export class PostComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
deletePost(): void {
|
deletePost(): void {
|
||||||
this.postDeletionFailed = false;
|
|
||||||
|
|
||||||
this.postService.deletePost(this.post).subscribe(() => {
|
this.postService.deletePost(this.post).subscribe(() => {
|
||||||
|
NotificationsComponent.success('Article supprimé.');
|
||||||
this.alertDelete.hide();
|
this.alertDelete.hide();
|
||||||
this.router.navigate(['/myPosts']);
|
this.router.navigate(['/myPosts']);
|
||||||
}, error => {
|
}, error => {
|
||||||
this.postDeletionFailed = true;
|
console.error(error);
|
||||||
setTimeout(() => {
|
NotificationsComponent.error('Une erreur est survenue lors de la suppression de l\'article.');
|
||||||
this.postDeletionFailed = false;
|
|
||||||
}, 3500);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
BIN
src/main/ts/src/assets/images/default_user_icon.png
Normal file
BIN
src/main/ts/src/assets/images/default_user_icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.4 KiB |
BIN
src/main/ts/src/assets/images/favicon.ico
Normal file
BIN
src/main/ts/src/assets/images/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
@@ -6,7 +6,7 @@
|
|||||||
<meta name="robots" content="noindex, nofollow" />
|
<meta name="robots" content="noindex, nofollow" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<base href="/" />
|
<base href="/" />
|
||||||
<link rel="icon" type="image/x-icon" href="assets/images/favicon.png" />
|
<link rel="icon" type="image/x-icon" href="assets/images/favicon.ico" />
|
||||||
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet" />
|
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet" />
|
||||||
<link href="./assets/css/prism.css" rel="stylesheet" />
|
<link href="./assets/css/prism.css" rel="stylesheet" />
|
||||||
</head>
|
</head>
|
||||||
|
|||||||
Reference in New Issue
Block a user