diff --git a/.github/workflows/new-pr.yml b/.github/workflows/new-pr.yml
index 00f4fd8..84c3aa8 100644
--- a/.github/workflows/new-pr.yml
+++ b/.github/workflows/new-pr.yml
@@ -15,6 +15,6 @@ jobs:
uses: Ilshidur/action-discord@0.3.0
with:
args: |
- Nova contribuição recebida. \(>_<)/
+ Nova contribuição recebida. \\(>_<)/
${{ github.event.pull_request.title }}
${{ github.event.pull_request.html_url}}
diff --git a/README.md b/README.md
index 2ef7edb..80d4d06 100644
--- a/README.md
+++ b/README.md
@@ -26,6 +26,14 @@ Add in VMArguments to run in an IDE
-Dspring.profiles.active=local
+### Development data
+
+You can use the file [data.sql](src/test/resources/db/data/data.sql) to insert data to your local db.
+
+### Cleaning DB
+
+All data volume is mapped to directory `tmp`. You can delete this folder to get rid of development data.
+
## How to run
You can run with maven
@@ -44,7 +52,7 @@ tip: --rm parameter will exclude container image after execution and it cause da
### Writing Tests
-If you wanna use db connection on your test you must extend the class `AbstractIntegrationTest`. This class will run the docker container and configure the spring datasource.
+If you want to use db connection on your test you must extend the class `AbstractIntegrationTest`. This class will run the docker container and configure the spring datasource.
## How to contribute
diff --git a/openapi.yaml b/openapi.yaml
index 9b846d0..5c66ed0 100644
--- a/openapi.yaml
+++ b/openapi.yaml
@@ -42,9 +42,9 @@ paths:
- bearerAuth: []
tags:
- Author
- /cordels:
+ /cordels/summaries:
get:
- summary: "Retrieve all cordels by pages"
+ summary: "Retrieve all summaries by pages"
parameters:
- name: page
in: query
@@ -79,6 +79,7 @@ paths:
$ref: '#/components/schemas/ReponsePage'
tags:
- Cordel
+ /cordels:
post:
summary: "Create a new cordel"
requestBody:
@@ -94,7 +95,7 @@ paths:
- Cordel
/cordels/{id}:
get:
- summary: "Get a specific cordel with all content"
+ summary: "Get a cordel with full content"
parameters:
- name: "id"
in: "path"
@@ -108,7 +109,7 @@ paths:
content:
application/json:
schema:
- $ref: '#/components/schemas/FullCordel'
+ $ref: '#/components/schemas/Cordel'
404:
description: "Not found"
tags:
@@ -240,6 +241,8 @@ components:
content:
type: string
description: cordel text
+ xilogravuraUrl:
+ type: string
published:
type: boolean
tags:
@@ -261,30 +264,6 @@ components:
xilogravuraUrl:
type: string
description: image url
- FullCordel:
- type: object
- description: Cordel data with content. For operations like POST and PUT the inner objects only need the id
- properties:
- id:
- type: integer
- description: cordel id
- author:
- $ref: '#/components/schemas/Author'
- title:
- type: string
- description: cordel title
- description:
- type: string
- description: cordel's description
- content:
- type: string
- description: cordel text
- xilogravura:
- $ref: '#/components/schemas/Xilogravura'
- tags:
- type: array
- items:
- type: string
Page:
type: object
properties:
@@ -333,16 +312,6 @@ components:
type: string
expiresAt:
type: integer
- Xilogravura:
- type: object
- properties:
- id:
- type: integer
- description:
- type: string
- url:
- type: string
-
securitySchemes:
bearerAuth:
type: http
diff --git a/pom.xml b/pom.xml
index a750040..01c3345 100644
--- a/pom.xml
+++ b/pom.xml
@@ -7,13 +7,13 @@
org.springframework.boot
spring-boot-starter-parent
- 2.5.1
+ 2.5.5
br.com.itsmemario
ecordel
- 0.6.0-SNAPSHOT
+ 1.0.0-SNAPSHOT
e-cordel
e-reader for cordels
@@ -180,7 +180,10 @@
org.owasp
dependency-check-maven
- 6.2.0
+ 6.3.2
+
+ 6
+
diff --git a/src/main/java/br/com/itsmemario/ecordel/author/AuthorDto.java b/src/main/java/br/com/itsmemario/ecordel/author/AuthorDto.java
index 7ae340e..149d2d9 100644
--- a/src/main/java/br/com/itsmemario/ecordel/author/AuthorDto.java
+++ b/src/main/java/br/com/itsmemario/ecordel/author/AuthorDto.java
@@ -30,6 +30,15 @@ public class AuthorDto {
private String name;
private String email;
+ public static AuthorDto of(Author author) {
+ var dto = new AuthorDto();
+ dto.setName(author.getName());
+ dto.setAbout(author.getAbout());
+ dto.setEmail(author.getEmail());
+ dto.setId(author.getId());
+ return dto;
+ }
+
public Author toEntity() {
var author = new Author();
author.setId(id);
diff --git a/src/main/java/br/com/itsmemario/ecordel/cordel/Cordel.java b/src/main/java/br/com/itsmemario/ecordel/cordel/Cordel.java
index c0b5596..a9ef3b7 100644
--- a/src/main/java/br/com/itsmemario/ecordel/cordel/Cordel.java
+++ b/src/main/java/br/com/itsmemario/ecordel/cordel/Cordel.java
@@ -18,15 +18,15 @@
package br.com.itsmemario.ecordel.cordel;
import br.com.itsmemario.ecordel.author.Author;
-import br.com.itsmemario.ecordel.xilogravura.Xilogravura;
import javax.persistence.*;
import javax.validation.constraints.NotBlank;
+import java.util.Collections;
import java.util.Objects;
import java.util.Set;
@Entity
-public class Cordel implements CordelView {
+public class Cordel {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@@ -38,9 +38,7 @@ public class Cordel implements CordelView {
private String title;
@NotBlank
private String content;
- @OneToOne
- @JoinColumn(name = "xilogravura_id")
- private Xilogravura xilogravura;
+ private String xilogravuraUrl;
private String description;
@ElementCollection
@CollectionTable(name = "cordel_tags")
@@ -87,12 +85,12 @@ public void setContent(String content) {
this.content = content;
}
- public Xilogravura getXilogravura() {
- return xilogravura;
+ public String getXilogravuraUrl() {
+ return xilogravuraUrl;
}
- public void setXilogravura(Xilogravura xilogravura) {
- this.xilogravura = xilogravura;
+ public void setXilogravuraUrl(String xilogravuraUrl) {
+ this.xilogravuraUrl = xilogravuraUrl;
}
public String getDescription() {
@@ -104,7 +102,7 @@ public void setDescription(String description) {
}
public Set getTags() {
- return tags;
+ return Collections.unmodifiableSet(tags);
}
public void setTags(Set tags) {
diff --git a/src/main/java/br/com/itsmemario/ecordel/cordel/CordelController.java b/src/main/java/br/com/itsmemario/ecordel/cordel/CordelController.java
index cb0218d..574a94c 100644
--- a/src/main/java/br/com/itsmemario/ecordel/cordel/CordelController.java
+++ b/src/main/java/br/com/itsmemario/ecordel/cordel/CordelController.java
@@ -17,7 +17,6 @@
package br.com.itsmemario.ecordel.cordel;
-import br.com.itsmemario.ecordel.xilogravura.Xilogravura;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -45,19 +44,20 @@ public class CordelController {
}
@GetMapping("{id}")
- public ResponseEntity getCordel(@PathVariable Long id) {
+ public ResponseEntity getCordel(@PathVariable Long id) {
logger.info("request received get cordel by id: {}", id);
Optional cordel = service.findById(id);
if (cordel.isPresent()) {
- return ResponseEntity.ok(cordel.get());
+ CordelDto body = CordelDto.of(cordel.get());
+ return ResponseEntity.ok(body);
} else {
logger.info("cordel with id {} not fond", id);
return ResponseEntity.notFound().build();
}
}
- @GetMapping
+ @GetMapping("summaries")
public Page getCordels(@RequestParam(required = false) String title,
@RequestParam(defaultValue = "true") boolean published,
Pageable pageable) {
@@ -76,14 +76,14 @@ public ResponseEntity create(@RequestBody @Valid CordelDto dto, UriCompo
}
@PutMapping("{id}/xilogravura")
- public ResponseEntity putXilogravura(@PathVariable Long id, Xilogravura xilogravura, @RequestParam("file") MultipartFile file) {
+ public ResponseEntity putXilogravura(@PathVariable Long id, @RequestParam("file") MultipartFile file) {
logger.info("request received, update xilogravura for cordel: {}", id);
- Cordel cordel = service.updateXilogravura(id, xilogravura, file);
- return ResponseEntity.ok(cordel);
+ Cordel cordel = service.updateXilogravura(id, file);
+ return ResponseEntity.ok(CordelDto.of(cordel));
}
@PutMapping("{id}")
- public ResponseEntity update(@RequestBody @Valid CordelDto dto, @PathVariable Long id) {
+ public ResponseEntity update(@RequestBody @Valid CordelDto dto, @PathVariable Long id) {
logger.info("request received update cordel with id: {}", id);
Optional existingCordel = service.findById(id);
@@ -93,8 +93,8 @@ public ResponseEntity update(@RequestBody @Valid CordelDto dto, @PathVar
var cordel = dto.toEntity();
cordel.setId(id);
-
- return ResponseEntity.ok(service.save(cordel));
+ Cordel updatedCordel = service.save(cordel);
+ return ResponseEntity.ok(CordelDto.of(updatedCordel));
}
}
diff --git a/src/main/java/br/com/itsmemario/ecordel/cordel/CordelDto.java b/src/main/java/br/com/itsmemario/ecordel/cordel/CordelDto.java
index b9c0e7a..1761b5a 100644
--- a/src/main/java/br/com/itsmemario/ecordel/cordel/CordelDto.java
+++ b/src/main/java/br/com/itsmemario/ecordel/cordel/CordelDto.java
@@ -41,6 +41,21 @@ public class CordelDto {
private String content;
private boolean published;
private Set tags;
+ private String xilogravuraUrl;
+
+ public static CordelDto of( Cordel cordel ){
+ var dto = new CordelDto();
+ var authorDto = AuthorDto.of(cordel.getAuthor());
+ dto.setAuthor(authorDto);
+ dto.setTags(cordel.getTags());
+ dto.setPublished(cordel.isPublished());
+ dto.setId(cordel.getId());
+ dto.setContent(cordel.getContent());
+ dto.setDescription(cordel.getDescription());
+ dto.setTitle(cordel.getTitle());
+ dto.setXilogravuraUrl(cordel.getXilogravuraUrl());
+ return dto;
+ }
public Cordel toEntity() {
var cordel = new Cordel();
@@ -51,6 +66,7 @@ public Cordel toEntity() {
cordel.setContent( content );
cordel.setPublished( published );
cordel.setTags( tags );
+ cordel.setXilogravuraUrl( xilogravuraUrl );
return cordel;
}
diff --git a/src/main/java/br/com/itsmemario/ecordel/cordel/CordelRepository.java b/src/main/java/br/com/itsmemario/ecordel/cordel/CordelRepository.java
index 25bfc6f..01c3392 100644
--- a/src/main/java/br/com/itsmemario/ecordel/cordel/CordelRepository.java
+++ b/src/main/java/br/com/itsmemario/ecordel/cordel/CordelRepository.java
@@ -20,9 +20,16 @@
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
-interface CordelRepository extends CustomCordelRepository, JpaRepository{
+interface CordelRepository extends JpaRepository{
- Page findAllProjectedBy(Pageable pageable);
+ @Query("SELECT new br.com.itsmemario.ecordel.cordel.CordelSummary(c.id, c.title, c.xilogravuraUrl, a.name) " +
+ "FROM Cordel c JOIN c.author a WHERE c.published = :published")
+ Page findAllByPublished(boolean published, Pageable pageable);
+
+ @Query("SELECT new br.com.itsmemario.ecordel.cordel.CordelSummary(c.id, c.title, c.xilogravuraUrl, a.name) " +
+ "FROM Cordel c JOIN c.author a WHERE c.published = :published and lower(c.title) LIKE lower( :title ) ")
+ Page findAllByPublishedAndTitleLike(boolean published, String title, Pageable pageable);
}
diff --git a/src/main/java/br/com/itsmemario/ecordel/cordel/CordelService.java b/src/main/java/br/com/itsmemario/ecordel/cordel/CordelService.java
index 9f17d62..ebdae6c 100644
--- a/src/main/java/br/com/itsmemario/ecordel/cordel/CordelService.java
+++ b/src/main/java/br/com/itsmemario/ecordel/cordel/CordelService.java
@@ -17,7 +17,6 @@
package br.com.itsmemario.ecordel.cordel;
-import br.com.itsmemario.ecordel.xilogravura.Xilogravura;
import br.com.itsmemario.ecordel.xilogravura.XilogravuraService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
@@ -25,12 +24,13 @@
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
-import java.util.List;
import java.util.Optional;
@Service
public class CordelService {
+ private static final int MINIMUM_SIZE = 3;
+
private CordelRepository repository;
private XilogravuraService xilogravuraService;
@@ -41,36 +41,36 @@ public CordelService(CordelRepository repository, XilogravuraService xilogravura
this.xilogravuraService = xilogravuraService;
}
- public Page getCordels(Pageable pageable) {
- return repository.findAllProjectedBy(pageable);
- }
-
public Cordel save(Cordel cordel) {
return repository.save(cordel);
}
- public Page findByTags(List tags, Pageable pageable){
- return repository.findByTags(tags, pageable);
- }
-
public Optional findById(Long id) {
return repository.findById(id);
}
public Page findPublishedByTitle(boolean published, String title, Pageable pageable) {
- return repository.findPublishedByTitleLike(published, title, pageable);
+ if (isAValidString(title)) {
+ return repository.findAllByPublishedAndTitleLike(published, String.format("%%%s%%", title), pageable);
+ }
+
+ return repository.findAllByPublished(published, pageable);
}
- public Cordel updateXilogravura(Long cordelId, Xilogravura xilogravura, MultipartFile file) {
+ public Cordel updateXilogravura(Long cordelId, MultipartFile file) {
Optional byId = findById(cordelId);
if(byId.isPresent()) {
Cordel cordel = byId.get();
- Xilogravura xilogravuraWithFile = xilogravuraService.createXilogravuraWithFile(xilogravura, file);
- cordel.setXilogravura(xilogravuraWithFile);
+ String xilogravuraUrl = xilogravuraService.createXilogravuraWithFile(file);
+ cordel.setXilogravuraUrl( xilogravuraUrl );
return save(cordel);
}else{
throw new CordelNotFoundException();
}
}
+
+ private boolean isAValidString(String title) {
+ return title != null && title.length() >= MINIMUM_SIZE;
+ }
}
diff --git a/src/main/java/br/com/itsmemario/ecordel/cordel/CordelView.java b/src/main/java/br/com/itsmemario/ecordel/cordel/CordelView.java
deleted file mode 100644
index 42ee317..0000000
--- a/src/main/java/br/com/itsmemario/ecordel/cordel/CordelView.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2020 Projeto e-cordel (http://ecordel.com.br)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package br.com.itsmemario.ecordel.cordel;
-
-import br.com.itsmemario.ecordel.author.AuthorView;
-import br.com.itsmemario.ecordel.xilogravura.Xilogravura;
-
-import java.util.Set;
-
-
-public interface CordelView {
-
- Long getId();
- AuthorView getAuthor();
- String getTitle();
- Xilogravura getXilogravura();
- String getDescription();
- Set getTags();
-
-}
diff --git a/src/main/java/br/com/itsmemario/ecordel/cordel/CustomCordelRepository.java b/src/main/java/br/com/itsmemario/ecordel/cordel/CustomCordelRepository.java
deleted file mode 100644
index 64c23dc..0000000
--- a/src/main/java/br/com/itsmemario/ecordel/cordel/CustomCordelRepository.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 2020-2021 Projeto e-cordel (http://ecordel.com.br)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package br.com.itsmemario.ecordel.cordel;
-
-import org.springframework.data.domain.Page;
-import org.springframework.data.domain.Pageable;
-
-import java.util.List;
-
-interface CustomCordelRepository {
-
- Page findByTags(List tags, Pageable pageable);
-
- Page findPublishedByTitleLike(boolean published, String title, Pageable pageable);
-}
diff --git a/src/main/java/br/com/itsmemario/ecordel/cordel/CustomCordelRepositoryImpl.java b/src/main/java/br/com/itsmemario/ecordel/cordel/CustomCordelRepositoryImpl.java
deleted file mode 100644
index 7d95605..0000000
--- a/src/main/java/br/com/itsmemario/ecordel/cordel/CustomCordelRepositoryImpl.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Copyright 2020-2021 Projeto e-cordel (http://ecordel.com.br)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package br.com.itsmemario.ecordel.cordel;
-
-import br.com.itsmemario.ecordel.author.Author;
-import org.springframework.data.domain.Page;
-import org.springframework.data.domain.PageImpl;
-import org.springframework.data.domain.Pageable;
-import org.springframework.stereotype.Repository;
-import org.springframework.transaction.annotation.Transactional;
-
-import javax.persistence.EntityManager;
-import javax.persistence.PersistenceContext;
-import javax.persistence.TypedQuery;
-import java.math.BigInteger;
-import java.util.List;
-import java.util.stream.Collectors;
-
-
-@Repository
-@Transactional(readOnly = true)
-class CustomCordelRepositoryImpl implements CustomCordelRepository {
-
- private static final int MINIMUM_SIZE = 3;
- private static final String TAGS = "tags";
- private static final String LIMIT = "limit";
- private static final String OFFSET = "offset";
-
- private static final String LIMIT_SQL = " limit :limit offset :offset ";
-
- private static final String FIND_BY_TAGS_SQL_FROM = " from cordel_tags ct \n" +
- "join cordel c on c.id = ct.cordel_id \n" +
- "join author a on a.id = c.author_id \n" +
- "where ct.tags in (:tags) \n";
-
- private static final String FIND_BY_TAGS_SQL = "select distinct(c.id) as id, c.title, c.description, a.name, a.email " + FIND_BY_TAGS_SQL_FROM + LIMIT_SQL;
-
- private static final String FIND_BY_TAGS_SQL_COUNT = "select COUNT(distinct(c.id)) " + FIND_BY_TAGS_SQL_FROM ;
-
- private static final String CORDEL_SUMMARY = " SELECT new br.com.itsmemario.ecordel.cordel.CordelSummary(c.id, c.title, x.url, a.name) " +
- " FROM Cordel c JOIN c.author a LEFT JOIN c.xilogravura x WHERE c.published = :published ";
-
- private static final String COUNT_CORDEL_SUMMARY = "SELECT COUNT(c.id) FROM Cordel c JOIN c.author a " +
- " LEFT JOIN c.xilogravura x WHERE c.published = :published ";
-
- private static final String TITLE = "title";
- public static final String PUBLISHED = "published";
-
- @PersistenceContext
- private EntityManager entityManager;
-
- @Override
- public Page findByTags(List tags, Pageable pageable) {
- long count = countResults(tags);
- if(count == 0) return Page.empty(pageable);
-
- var query = entityManager.createNativeQuery(FIND_BY_TAGS_SQL);
- query.setParameter(TAGS, tags);
- query.setParameter(LIMIT, pageable.getPageSize());
- query.setParameter(OFFSET, pageable.getOffset());
- List