commit bf502b708b8b8f0ba4a50b422eaa6d691121a1b1
Author: Jakub Smid <jaksmid@seznam.cz>
Date:   Wed May 11 10:51:41 2022 +0200

    Added sources (can add/edit bibliography page)
    
    re #9788

diff --git a/backend/src/main/java/cz/zcu/kiv/backendapi/config/DataInitiator.java b/backend/src/main/java/cz/zcu/kiv/backendapi/config/DataInitiator.java
index bef823e..0bcb5a8 100644
--- a/backend/src/main/java/cz/zcu/kiv/backendapi/config/DataInitiator.java
+++ b/backend/src/main/java/cz/zcu/kiv/backendapi/config/DataInitiator.java
@@ -3,6 +3,8 @@ package cz.zcu.kiv.backendapi.config;
 import cz.zcu.kiv.backendapi.catalog.CatalogItem;
 import cz.zcu.kiv.backendapi.catalog.CatalogItemRepository;
 import cz.zcu.kiv.backendapi.catalog.ICatalogItemService;
+import cz.zcu.kiv.backendapi.sources.ISourcesService;
+import cz.zcu.kiv.backendapi.sources.Sources;
 import cz.zcu.kiv.backendapi.titlepage.ITitlePageService;
 import cz.zcu.kiv.backendapi.titlepage.TitlePage;
 import cz.zcu.kiv.backendapi.type.ITypeService;
@@ -41,6 +43,7 @@ public class DataInitiator implements ApplicationListener<ContextRefreshedEvent>
     private final UserRepository userRepository;
 
     private final ITitlePageService titlePageService;
+    private final ISourcesService sourcesService;
 
     private final BCryptPasswordEncoder encoder;
 
@@ -54,7 +57,8 @@ public class DataInitiator implements ApplicationListener<ContextRefreshedEvent>
         List<CatalogItem> catalog = loadCatalog();
         catalogService.saveCatalog(catalog);
 
-        titlePageService.updateTitlePage(new TitlePage(1L, "", ""));
+        titlePageService.updateTitlePage(new TitlePage(1L, ""));
+        sourcesService.updateSources(new Sources(1L, ""));
 
         UserEntity user1 = new UserEntity("admin", "admin", encoder.encode("password"), (byte) 7, true);
         userRepository.save(user1);
diff --git a/backend/src/main/java/cz/zcu/kiv/backendapi/security/SecurityConfig.java b/backend/src/main/java/cz/zcu/kiv/backendapi/security/SecurityConfig.java
index b1ddf70..aa6a3c0 100644
--- a/backend/src/main/java/cz/zcu/kiv/backendapi/security/SecurityConfig.java
+++ b/backend/src/main/java/cz/zcu/kiv/backendapi/security/SecurityConfig.java
@@ -63,6 +63,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
         PERMITTED_ENDPOINTS.put("/catalog-items", HttpMethod.GET);
         PERMITTED_ENDPOINTS.put("/catalog-items/**", HttpMethod.GET);
         PERMITTED_ENDPOINTS.put("/title-page", HttpMethod.GET);
+        PERMITTED_ENDPOINTS.put("/sources", HttpMethod.GET);
     }
 
     /**
@@ -92,7 +93,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
                 .antMatchers(HttpMethod.POST, "/catalog-items").hasAuthority(Permission.WRITE.name())
                 .antMatchers(HttpMethod.PUT, "/catalog-items/*").hasAuthority(Permission.WRITE.name())
                 .antMatchers(HttpMethod.DELETE, "/catalog-items/*").hasAuthority(Permission.DELETE.name())
-                .antMatchers(HttpMethod.POST, "/title-page").hasRole(Role.ADMIN.name())
+                .antMatchers(HttpMethod.POST, "/title-page", "/sources").hasRole(Role.ADMIN.name())
                 .anyRequest()
                 .authenticated();
     }
diff --git a/backend/src/main/java/cz/zcu/kiv/backendapi/sources/ISourcesService.java b/backend/src/main/java/cz/zcu/kiv/backendapi/sources/ISourcesService.java
new file mode 100644
index 0000000..5322e40
--- /dev/null
+++ b/backend/src/main/java/cz/zcu/kiv/backendapi/sources/ISourcesService.java
@@ -0,0 +1,21 @@
+package cz.zcu.kiv.backendapi.sources;
+
+/**
+ * Sources service interface
+ */
+public interface ISourcesService {
+    /**
+     * Returns sources
+     *
+     * @return sources
+     */
+    Sources getSources();
+
+    /**
+     * Adds or updates sources
+     *
+     * @param sources sources
+     */
+    void updateSources(Sources sources);
+
+}
diff --git a/backend/src/main/java/cz/zcu/kiv/backendapi/sources/Sources.java b/backend/src/main/java/cz/zcu/kiv/backendapi/sources/Sources.java
new file mode 100644
index 0000000..7f2a493
--- /dev/null
+++ b/backend/src/main/java/cz/zcu/kiv/backendapi/sources/Sources.java
@@ -0,0 +1,36 @@
+package cz.zcu.kiv.backendapi.sources;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+/**
+ * Class representing sources
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Entity
+@Table(name = "sources")
+@Schema(name = "SourcesDto")
+public class Sources {
+    /**
+     * ID
+     */
+    @Id
+    @JsonIgnore
+    private Long id;
+
+    /**
+     * Sources
+     */
+    @Column(length = 100000)
+    private String sources;
+}
diff --git a/backend/src/main/java/cz/zcu/kiv/backendapi/sources/SourcesController.java b/backend/src/main/java/cz/zcu/kiv/backendapi/sources/SourcesController.java
new file mode 100644
index 0000000..700c846
--- /dev/null
+++ b/backend/src/main/java/cz/zcu/kiv/backendapi/sources/SourcesController.java
@@ -0,0 +1,43 @@
+package cz.zcu.kiv.backendapi.sources;
+
+import io.swagger.v3.oas.annotations.Operation;
+import lombok.RequiredArgsConstructor;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+
+/**
+ * Controller for sources
+ */
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/sources")
+public class SourcesController {
+    /**
+     * Sources service
+     */
+    private final ISourcesService sourcesService;
+
+    /**
+     * Returns sources
+     *
+     * @return sources
+     */
+    @GetMapping("")
+    @Operation(summary = "returns sources")
+    public ResponseEntity<Sources> getTitlePage() {
+        return new ResponseEntity<>(sourcesService.getSources(), HttpStatus.OK);
+    }
+
+    /**
+     * Updates sources
+     *
+     * @param sources sources
+     */
+    @PostMapping("")
+    @Operation(summary = "updates/creates sources")
+    public void updateTitlePage(@RequestBody Sources sources) {
+        sourcesService.updateSources(sources);
+    }
+
+}
diff --git a/backend/src/main/java/cz/zcu/kiv/backendapi/sources/SourcesRepository.java b/backend/src/main/java/cz/zcu/kiv/backendapi/sources/SourcesRepository.java
new file mode 100644
index 0000000..2cdb192
--- /dev/null
+++ b/backend/src/main/java/cz/zcu/kiv/backendapi/sources/SourcesRepository.java
@@ -0,0 +1,11 @@
+package cz.zcu.kiv.backendapi.sources;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+/**
+ * Sources repository
+ */
+@Repository
+public interface SourcesRepository extends JpaRepository<Sources, Long> {
+}
diff --git a/backend/src/main/java/cz/zcu/kiv/backendapi/sources/SourcesServiceImplementation.java b/backend/src/main/java/cz/zcu/kiv/backendapi/sources/SourcesServiceImplementation.java
new file mode 100644
index 0000000..bff7e8b
--- /dev/null
+++ b/backend/src/main/java/cz/zcu/kiv/backendapi/sources/SourcesServiceImplementation.java
@@ -0,0 +1,43 @@
+package cz.zcu.kiv.backendapi.sources;
+
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.Optional;
+
+/**
+ * Sources service implementation
+ */
+@Service
+@Transactional
+@RequiredArgsConstructor
+@Slf4j
+public class SourcesServiceImplementation implements ISourcesService {
+    /**
+     * ID of the sources
+     */
+    private static final long SOURCES_ID = 1;
+
+    /**
+     * Sources repository
+     */
+    private final SourcesRepository sourcesRepository;
+
+    @Override
+    public Sources getSources() {
+        Optional<Sources> optionalSources = sourcesRepository.findById(SOURCES_ID);
+        if (optionalSources.isEmpty()) {
+            Sources sources = new Sources(SOURCES_ID, "");
+            return sourcesRepository.save(sources);
+        }
+        return optionalSources.get();
+    }
+
+    @Override
+    public void updateSources(Sources sources) {
+        sources.setId(SOURCES_ID);
+        sourcesRepository.save(sources);
+    }
+}
diff --git a/backend/src/main/java/cz/zcu/kiv/backendapi/titlepage/ITitlePageService.java b/backend/src/main/java/cz/zcu/kiv/backendapi/titlepage/ITitlePageService.java
index 5539794..88795f0 100644
--- a/backend/src/main/java/cz/zcu/kiv/backendapi/titlepage/ITitlePageService.java
+++ b/backend/src/main/java/cz/zcu/kiv/backendapi/titlepage/ITitlePageService.java
@@ -12,7 +12,7 @@ public interface ITitlePageService {
     TitlePage getTitlePage();
 
     /**
-     * Adds or updates title page with given ID
+     * Adds or updates title page
      *
      * @param titlePage title page
      */
diff --git a/backend/src/main/java/cz/zcu/kiv/backendapi/titlepage/TitlePage.java b/backend/src/main/java/cz/zcu/kiv/backendapi/titlepage/TitlePage.java
index 0c6e685..9ee2138 100644
--- a/backend/src/main/java/cz/zcu/kiv/backendapi/titlepage/TitlePage.java
+++ b/backend/src/main/java/cz/zcu/kiv/backendapi/titlepage/TitlePage.java
@@ -28,11 +28,6 @@ public class TitlePage {
     @JsonIgnore
     private Long id;
 
-    /**
-     * Title
-     */
-    private String title;
-
     /**
      * Content of the title page
      */
diff --git a/backend/src/main/java/cz/zcu/kiv/backendapi/titlepage/TitlePageServiceImplementation.java b/backend/src/main/java/cz/zcu/kiv/backendapi/titlepage/TitlePageServiceImplementation.java
index 3c86c0a..13a5115 100644
--- a/backend/src/main/java/cz/zcu/kiv/backendapi/titlepage/TitlePageServiceImplementation.java
+++ b/backend/src/main/java/cz/zcu/kiv/backendapi/titlepage/TitlePageServiceImplementation.java
@@ -29,7 +29,7 @@ public class TitlePageServiceImplementation implements ITitlePageService {
     public TitlePage getTitlePage() {
         Optional<TitlePage> optionalTitlePage = titlePageRepository.findById(TITLE_PAGE_ID);
         if (optionalTitlePage.isEmpty()) {
-            TitlePage titlePage = new TitlePage(TITLE_PAGE_ID, "", "");
+            TitlePage titlePage = new TitlePage(TITLE_PAGE_ID, "");
             return titlePageRepository.save(titlePage);
         }
         return optionalTitlePage.get();
diff --git a/backend/src/test/java/cz/zcu/kiv/backendapi/sources/SourcesServiceImplementationTest.java b/backend/src/test/java/cz/zcu/kiv/backendapi/sources/SourcesServiceImplementationTest.java
new file mode 100644
index 0000000..1030eb7
--- /dev/null
+++ b/backend/src/test/java/cz/zcu/kiv/backendapi/sources/SourcesServiceImplementationTest.java
@@ -0,0 +1,96 @@
+package cz.zcu.kiv.backendapi.sources;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import java.util.Optional;
+
+import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.BDDMockito.given;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+
+@ExtendWith(MockitoExtension.class)
+class SourcesServiceImplementationTest {
+
+    @Mock
+    private SourcesRepository sourcesRepository;
+
+    private SourcesServiceImplementation underTest;
+
+    @BeforeEach
+    void setUp() {
+        underTest = new SourcesServiceImplementation(sourcesRepository);
+    }
+
+    @Test
+    void testAddSources() {
+        // given
+        long id = 1;
+        Sources sources = new Sources();
+        sources.setSources("sources");
+
+        // when
+        underTest.updateSources(sources);
+
+        // then
+        ArgumentCaptor<Sources> argumentCaptor = ArgumentCaptor.forClass(Sources.class);
+
+        verify(sourcesRepository).save(argumentCaptor.capture());
+
+        Sources capturedSources = argumentCaptor.getValue();
+
+        assertThat(capturedSources.getId()).isEqualTo(id);
+
+        assertThat(capturedSources).isEqualTo(sources);
+
+    }
+
+    @Test
+    void testGetSourcesWhenExists() {
+        // given
+        long id = 1;
+        Sources sources = new Sources(id, "sources");
+
+        given(sourcesRepository.findById(id)).willReturn(Optional.of(sources));
+
+        // when
+        Sources result = underTest.getSources();
+
+        // then
+        verify(sourcesRepository).findById(id);
+        verify(sourcesRepository, never()).save(any());
+
+        assertThat(result).isEqualTo(sources);
+
+    }
+
+    @Test
+    void testGetTitlePageWhenNotExists() {
+        // given
+        long id = 1;
+        Sources sources = new Sources(id, "");
+
+        given(sourcesRepository.findById(id)).willReturn(Optional.empty());
+
+        // when
+        underTest.getSources();
+
+        // then
+        verify(sourcesRepository).findById(id);
+
+        ArgumentCaptor<Sources> argumentCaptor = ArgumentCaptor.forClass(Sources.class);
+
+        verify(sourcesRepository).save(argumentCaptor.capture());
+
+        Sources capturedSources = argumentCaptor.getValue();
+
+        assertThat(capturedSources).isEqualTo(sources);
+
+    }
+}
\ No newline at end of file
diff --git a/backend/src/test/java/cz/zcu/kiv/backendapi/titlepage/TitlePageServiceImplementationTest.java b/backend/src/test/java/cz/zcu/kiv/backendapi/titlepage/TitlePageServiceImplementationTest.java
index 61a333a..893f675 100644
--- a/backend/src/test/java/cz/zcu/kiv/backendapi/titlepage/TitlePageServiceImplementationTest.java
+++ b/backend/src/test/java/cz/zcu/kiv/backendapi/titlepage/TitlePageServiceImplementationTest.java
@@ -33,7 +33,6 @@ class TitlePageServiceImplementationTest {
         // given
         long id = 1;
         TitlePage titlePage = new TitlePage();
-        titlePage.setTitle("title");
         titlePage.setContent("content");
 
         // when
@@ -56,7 +55,7 @@ class TitlePageServiceImplementationTest {
     void testGetTitlePageWhenExists() {
         // given
         long id = 1;
-        TitlePage titlePage = new TitlePage(id, "title", "content");
+        TitlePage titlePage = new TitlePage(id, "content");
 
         given(titlePageRepository.findById(id)).willReturn(Optional.of(titlePage));
 
@@ -75,7 +74,7 @@ class TitlePageServiceImplementationTest {
     void testGetTitlePageWhenNotExists() {
         // given
         long id = 1;
-        TitlePage titlePage = new TitlePage(id, "", "");
+        TitlePage titlePage = new TitlePage(id, "");
 
         given(titlePageRepository.findById(id)).willReturn(Optional.empty());
 
