Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
62cdbef
some config
dmkofgl Apr 11, 2019
d442655
Main entities
dmkofgl Apr 11, 2019
ead0196
Create dto for entities
dmkofgl Apr 11, 2019
e799f71
Add config to db in properties
dmkofgl Apr 11, 2019
dd61e47
Add repositories
dmkofgl Apr 11, 2019
0472757
Add config for tests
dmkofgl Apr 11, 2019
2e4c135
Create abstract services
dmkofgl Apr 11, 2019
39d68b0
Create tests for services
dmkofgl Apr 11, 2019
4ead6e5
Implements services
dmkofgl Apr 11, 2019
c654335
Create responses for entities
dmkofgl Apr 11, 2019
8cccb07
Create rest controllers
dmkofgl Apr 11, 2019
8ed06e4
Create react client
dmkofgl Apr 11, 2019
fa10578
Add text editor in react client
dmkofgl Apr 12, 2019
eba2e1e
allow users to login
dmkofgl Apr 22, 2019
1ab2986
change db to postgreSQL in docker
dmkofgl Apr 24, 2019
173325d
Add public folder.
dmkofgl Apr 24, 2019
e735029
Allow download and upload files.
dmkofgl Apr 24, 2019
37dd2a0
Add token-based security
dmkofgl Apr 24, 2019
dc3d5fa
Set book author by audit
dmkofgl Apr 24, 2019
34508c2
Calculate count of pages in article
dmkofgl Apr 24, 2019
1298987
commit files
dmkofgl Apr 24, 2019
9198585
some refactoring
dmkofgl Apr 29, 2019
ca0e006
Extract web client
dmkofgl May 21, 2019
cfe326b
some refactoring.Change Oauth2 from authconfigure to custom
dmkofgl May 22, 2019
8b75f19
Some refactoring
dmkofgl May 28, 2019
24329d3
Add validation annotations and tests for it for dto
dmkofgl Jun 17, 2019
e1e3092
fix bug.Write tests for entity validation.
dmkofgl Jun 19, 2019
7ad9eef
Add controller advice for validation exceptions
dmkofgl Jun 19, 2019
def086f
Add equals impl in profile.
dmkofgl Jun 21, 2019
34edcb0
Add formatting entity
dmkofgl Jun 21, 2019
cd6ff63
Add formatting
dmkofgl Jun 24, 2019
85afd23
Rename enum for format kind
dmkofgl Jun 24, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:2.1.3.RELEASE")
}
}

apply plugin: 'java'
apply plugin: 'idea'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'

bootJar {
baseName = 'writer-fic'
version = '0.1.0'
}

repositories {
mavenCentral()
}

sourceCompatibility = 1.8
targetCompatibility = 1.8
compileJava.options.encoding = 'UTF-8'

tasks.withType(JavaCompile) {
options.encoding = 'UTF-8'
}
dependencies {
compile("org.springframework.boot:spring-boot-starter-data-jpa")
compile("org.springframework.boot:spring-boot-starter-web")
compile("org.springframework.boot:spring-boot-starter-test")
compile("org.springframework.boot:spring-boot-starter-hateoas")
compile("org.springframework.boot:spring-boot-starter-security")
compile("org.springframework.security:spring-security-test")
compile("org.springframework.security:spring-security-oauth2-client")

compile("org.apache.poi:poi:4.1.0")
compile("io.jsonwebtoken:jjwt:0.5.1")
compile("fr.opensagres.xdocreport:org.apache.poi.xwpf.converter.xhtml:1.0.4")
compile("org.apache.poi:poi-ooxml:4.1.0")
compile("es.nitaur.markdown:txtmark:0.16")
compile("org.projectlombok:lombok")
compile("mysql:mysql-connector-java")
compile("org.postgresql:postgresql")
compile("com.h2database:h2")

testCompile("junit:junit")
}
14 changes: 14 additions & 0 deletions src/main/java/fic/writer/Application.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package fic.writer;

import fic.writer.web.config.properties.AppProperties;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;

@SpringBootApplication
@EnableConfigurationProperties(AppProperties.class)
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package fic.writer.domain.aspect;

import fic.writer.domain.entity.Book;
import fic.writer.domain.entity.Profile;
import fic.writer.domain.service.BookService;
import fic.writer.exception.DoesNotHavePermissionException;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.AuditorAware;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Component;

import java.util.Optional;

@Aspect
@Component
public class DenyAccessToNotAuthorAspect {
@Autowired
private BookService bookService;
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private AuditorAware<Profile> profileAuditorAware;


@Pointcut("execution(* fic.writer.domain.service.BookService.deleteById(..)) && args(bookId,..))")
public void deleteBook(Long bookId) {
}

@Pointcut("execution(* fic.writer.domain.service.BookService.addArticle(..)) && args(bookId,..)) ")
public void addArticle(Long bookId) {
}

@Pointcut("execution(* fic.writer.domain.service.BookService.removeArticle(..)) && args(bookId,..))")
public void removedArticle(Long bookId) {
}

@Before("deleteBook(bookId) || addArticle(bookId) || removedArticle(bookId)")
public void denyModifyBookForNoneAuthors(Long bookId) {
Optional<Profile> optionalProfile = profileAuditorAware.getCurrentAuditor();
Book book = bookService.findById(bookId).get();

optionalProfile.ifPresent(p -> {
if (checkForPermissions(book, p)) {
throw new DoesNotHavePermissionException();
}
});
}

private boolean checkForPermissions(Book book, Profile profile) {
return !(isAuthor(book, profile) || isCoauthor(book, profile));
}

private boolean isAuthor(Book book, Profile profile) {
return book.getAuthor().getId().equals(profile.getId());
}

private boolean isCoauthor(Book book, Profile profile) {
return book.getCoauthors().contains(profile);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package fic.writer.domain.audit;

import fic.writer.domain.entity.Profile;
import fic.writer.web.config.security.authorization.UserPrincipal;
import org.springframework.data.domain.AuditorAware;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;

import java.util.Optional;

public class SpringSecurityAuditorAware implements AuditorAware<Profile> {
@Override
public Optional<Profile> getCurrentAuditor() {
Optional<Profile> user = Optional.empty();
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication != null) {
UserPrincipal userPrincipal = (UserPrincipal) authentication.getPrincipal();
user = Optional.ofNullable(userPrincipal.getProfileDetails().getProfile());
}
return user;
}
}
25 changes: 25 additions & 0 deletions src/main/java/fic/writer/domain/entity/Actor.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package fic.writer.domain.entity;

import lombok.*;

import javax.persistence.*;
import javax.validation.constraints.NotBlank;
import java.util.Set;

@Entity
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class Actor {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(updatable = false)
private Long id;
@NotBlank
private String name;
private String description;
@ManyToMany(fetch = FetchType.LAZY, mappedBy = "actors")
private Set<Book> books;
}
44 changes: 44 additions & 0 deletions src/main/java/fic/writer/domain/entity/Article.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package fic.writer.domain.entity;

import lombok.*;
import org.hibernate.annotations.Formula;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import javax.persistence.*;
import javax.validation.constraints.NotBlank;
import java.util.Date;
import java.util.Set;

@Entity
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
@EntityListeners(AuditingEntityListener.class)
public class Article {
private static final int CHARS_IN_PAGE = 1800;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@NotBlank
private String title;
@CreatedDate
private Date created;
@LastModifiedDate
private Date lastModify;
@Column(columnDefinition = "TEXT")
@NotBlank
private String content;
private String annotation;
@ManyToOne(fetch = FetchType.LAZY)
private Book book;
@Formula("ceil( CHAR_LENGTH(content)/" + CHARS_IN_PAGE + ")")
private long pageCount;
@Singular("formatters")
@OneToMany(fetch = FetchType.LAZY)
Set<Formatting> formattings;

}
83 changes: 83 additions & 0 deletions src/main/java/fic/writer/domain/entity/Book.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package fic.writer.domain.entity;

import fic.writer.domain.entity.enums.Size;
import fic.writer.domain.entity.enums.State;
import lombok.*;
import org.springframework.data.annotation.CreatedBy;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import javax.persistence.*;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.util.Set;

@Entity
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
@EntityListeners(AuditingEntityListener.class)
public class Book {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@NotBlank
private String title;
@ManyToOne
@CreatedBy
@NotNull
private Profile author;

@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "book_subauthors",
joinColumns = {@JoinColumn(name = "book_id")},
inverseJoinColumns = {@JoinColumn(name = "user_id")}
)
@Singular("coauthors")
private Set<Profile> coauthors;

@OneToMany(fetch = FetchType.EAGER)
@Singular("source")
private Set<Book> source;

@Column(columnDefinition = "text")
private String description;

@Enumerated
private Size size;

@Enumerated
private State state;

@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@Singular("articles")
private Set<Article> articles;

@Transient
private Long pageCount;

@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "book_genres",
joinColumns = {@JoinColumn(name = "book_id")},
inverseJoinColumns = {@JoinColumn(name = "genre_id")}
)
private Set<Genre> genres;

@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "book_actors",
joinColumns = {@JoinColumn(name = "book_id")},
inverseJoinColumns = {@JoinColumn(name = "actor_id")}
)
@Singular("actors")
private Set<Actor> actors;

@PostLoad
private void calculatePageCount() {
this.pageCount = 0L;
if (articles != null) {
pageCount = articles.stream().mapToLong(Article::getPageCount).sum();
}
}

}
27 changes: 27 additions & 0 deletions src/main/java/fic/writer/domain/entity/Formatting.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package fic.writer.domain.entity;

import fic.writer.domain.entity.enums.FormattingType;
import lombok.*;

import javax.persistence.*;
import javax.validation.constraints.NotNull;

@Entity
@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Formatting {
@Id
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
private Article article;
@NotNull
private Long startIndex;
@NotNull
private Long endIndex;
@NotNull
@Enumerated(value = EnumType.ORDINAL)
private FormattingType type;
}
23 changes: 23 additions & 0 deletions src/main/java/fic/writer/domain/entity/Genre.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package fic.writer.domain.entity;

import lombok.*;

import javax.persistence.*;
import javax.validation.constraints.NotBlank;
import java.util.Set;

@Entity
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class Genre {
@Id
private Long id;
@NotBlank
@Column(unique = true)
private String name;
@ManyToMany(mappedBy = "genres", fetch = FetchType.LAZY)
private Set<Book> book;
}
Loading