commit b2af5445ffa9fdce0aefb0ec8077920ffeaa9eff
Author: Jakub Šmíd <biba10@students.zcu.cz>
Date:   Tue Mar 29 10:53:40 2022 +0000

    Passwords and permissions update

diff --git a/backend/src/main/java/cz/zcu/kiv/backendapi/alternativename/AlternativeName.java b/backend/src/main/java/cz/zcu/kiv/backendapi/alternativename/AlternativeName.java
new file mode 100644
index 0000000..ab9664e
--- /dev/null
+++ b/backend/src/main/java/cz/zcu/kiv/backendapi/alternativename/AlternativeName.java
@@ -0,0 +1,34 @@
+package cz.zcu.kiv.backendapi.alternativename;
+
+import cz.zcu.kiv.backendapi.catalog.CatalogEntry;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.persistence.*;
+import java.io.Serializable;
+
+/**
+ * Alternative name entity representing alternative name of geographic entry
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Entity
+@Table(name = "alternative_names")
+@IdClass(AlternativeName.class)
+public class AlternativeName implements Serializable {
+    /**
+     * Name, serves as ID
+     */
+    @Id
+    private String name;
+
+    /**
+     * Catalog entity
+     */
+    @ManyToOne
+    @JoinColumn(name = "catalog_id")
+    @Id
+    private CatalogEntry catalog;
+}
diff --git a/backend/src/main/java/cz/zcu/kiv/backendapi/alternativename/AlternativeNameEntity.java b/backend/src/main/java/cz/zcu/kiv/backendapi/alternativename/AlternativeNameEntity.java
deleted file mode 100644
index d393840..0000000
--- a/backend/src/main/java/cz/zcu/kiv/backendapi/alternativename/AlternativeNameEntity.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package cz.zcu.kiv.backendapi.alternativename;
-
-import cz.zcu.kiv.backendapi.catalog.CatalogEntity;
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import javax.persistence.*;
-import java.io.Serializable;
-
-/**
- * Alternative name entity representing alternative name of geographic entry
- */
-@Data
-@NoArgsConstructor
-@AllArgsConstructor
-@Entity
-@Table(name = "alternative_names")
-@IdClass(AlternativeNameEntity.class)
-public class AlternativeNameEntity implements Serializable {
-    /**
-     * Name, serves as ID
-     */
-    @Id
-    private String name;
-
-    /**
-     * Catalog entity
-     */
-    @ManyToOne
-    @JoinColumn(name = "catalog_id")
-    @Id
-    private CatalogEntity catalog;
-}
diff --git a/backend/src/main/java/cz/zcu/kiv/backendapi/alternativename/AlternativeNameRepository.java b/backend/src/main/java/cz/zcu/kiv/backendapi/alternativename/AlternativeNameRepository.java
index f4ba8f3..fe76e29 100644
--- a/backend/src/main/java/cz/zcu/kiv/backendapi/alternativename/AlternativeNameRepository.java
+++ b/backend/src/main/java/cz/zcu/kiv/backendapi/alternativename/AlternativeNameRepository.java
@@ -9,5 +9,5 @@ import org.springframework.transaction.annotation.Transactional;
  */
 @Repository
 @Transactional(readOnly = true)
-public interface AlternativeNameRepository extends JpaRepository<AlternativeNameEntity, AlternativeNameEntity> {
+public interface AlternativeNameRepository extends JpaRepository<AlternativeName, AlternativeName> {
 }
diff --git a/backend/src/main/java/cz/zcu/kiv/backendapi/bibliography/Bibliography.java b/backend/src/main/java/cz/zcu/kiv/backendapi/bibliography/Bibliography.java
new file mode 100644
index 0000000..f261707
--- /dev/null
+++ b/backend/src/main/java/cz/zcu/kiv/backendapi/bibliography/Bibliography.java
@@ -0,0 +1,30 @@
+package cz.zcu.kiv.backendapi.bibliography;
+
+import cz.zcu.kiv.backendapi.catalog.CatalogEntry;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.persistence.*;
+import java.io.Serializable;
+
+/**
+ * Bibliography entity representing bibliography
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Entity
+@Table(name = "bibliography")
+@IdClass(Bibliography.class)
+public class Bibliography implements Serializable {
+    /**
+     * Source, serves as ID
+     */
+    @Id
+    private String source;
+
+    @ManyToOne
+    @JoinColumn(name = "catalog_id")
+    private CatalogEntry catalog;
+}
diff --git a/backend/src/main/java/cz/zcu/kiv/backendapi/bibliography/BibliographyEntity.java b/backend/src/main/java/cz/zcu/kiv/backendapi/bibliography/BibliographyEntity.java
deleted file mode 100644
index 3281b8d..0000000
--- a/backend/src/main/java/cz/zcu/kiv/backendapi/bibliography/BibliographyEntity.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package cz.zcu.kiv.backendapi.bibliography;
-
-import cz.zcu.kiv.backendapi.catalog.CatalogEntity;
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import javax.persistence.*;
-import java.io.Serializable;
-
-/**
- * Bibliography entity representing bibliography
- */
-@Data
-@NoArgsConstructor
-@AllArgsConstructor
-@Entity
-@Table(name = "bibliography")
-@IdClass(BibliographyEntity.class)
-public class BibliographyEntity implements Serializable {
-    /**
-     * Source, serves as ID
-     */
-    @Id
-    private String source;
-
-    @ManyToOne
-    @JoinColumn(name = "catalog_id")
-    private CatalogEntity catalog;
-}
diff --git a/backend/src/main/java/cz/zcu/kiv/backendapi/bibliography/BibliographyRepository.java b/backend/src/main/java/cz/zcu/kiv/backendapi/bibliography/BibliographyRepository.java
index 134bbea..5a60cd5 100644
--- a/backend/src/main/java/cz/zcu/kiv/backendapi/bibliography/BibliographyRepository.java
+++ b/backend/src/main/java/cz/zcu/kiv/backendapi/bibliography/BibliographyRepository.java
@@ -9,5 +9,5 @@ import org.springframework.transaction.annotation.Transactional;
  */
 @Repository
 @Transactional(readOnly = true)
-public interface BibliographyRepository extends JpaRepository<BibliographyEntity, BibliographyEntity> {
+public interface BibliographyRepository extends JpaRepository<Bibliography, Bibliography> {
 }
diff --git a/backend/src/main/java/cz/zcu/kiv/backendapi/catalog/CatalogController.java b/backend/src/main/java/cz/zcu/kiv/backendapi/catalog/CatalogController.java
index 69c813c..1004663 100644
--- a/backend/src/main/java/cz/zcu/kiv/backendapi/catalog/CatalogController.java
+++ b/backend/src/main/java/cz/zcu/kiv/backendapi/catalog/CatalogController.java
@@ -19,11 +19,16 @@ public class CatalogController {
     /**
      * Catalog service
      */
-    private final ICatalogService catalogService;
+    private final ICatalogEntryService catalogService;
 
+    /**
+     * Saves new catalog entry
+     *
+     * @param catalogEntryDto catalog entry DTO
+     */
     @PostMapping("")
-    public void addCatalogEntry(@RequestBody CatalogDto catalogDto) {
-        catalogService.saveCatalogEntry(catalogDto);
+    public void addCatalogEntry(@RequestBody CatalogEntryDto catalogEntryDto) {
+        catalogService.saveCatalogEntry(catalogEntryDto);
     }
 
     /**
@@ -35,19 +40,19 @@ public class CatalogController {
      * @return list of catalog entries satisfying given filter
      */
     @GetMapping("")
-    public ResponseEntity<List<CatalogDto>> getCatalog(@RequestParam(defaultValue = "") String name, @RequestParam(defaultValue = "") String country, @RequestParam(defaultValue = "") String type) {
+    public ResponseEntity<List<CatalogEntryDto>> getCatalog(@RequestParam(defaultValue = "") String name, @RequestParam(defaultValue = "") String country, @RequestParam(defaultValue = "") String type) {
         return new ResponseEntity<>(catalogService.getCatalog(name, country, type), HttpStatus.OK);
     }
 
     /**
      * Updates catalog entry with given ID
      *
-     * @param id         ID
-     * @param catalogDto catalog DTO
+     * @param id              ID
+     * @param catalogEntryDto catalog DTO
      */
     @PutMapping("/{id}")
-    public void updateCatalogEntry(@PathVariable UUID id, @RequestBody CatalogDto catalogDto) {
-        catalogService.updateCatalogEntry(id, catalogDto);
+    public void updateCatalogEntry(@PathVariable UUID id, @RequestBody CatalogEntryDto catalogEntryDto) {
+        catalogService.updateCatalogEntry(id, catalogEntryDto);
     }
 
     /**
diff --git a/backend/src/main/java/cz/zcu/kiv/backendapi/catalog/CatalogDto.java b/backend/src/main/java/cz/zcu/kiv/backendapi/catalog/CatalogDto.java
deleted file mode 100644
index 564b716..0000000
--- a/backend/src/main/java/cz/zcu/kiv/backendapi/catalog/CatalogDto.java
+++ /dev/null
@@ -1,70 +0,0 @@
-package cz.zcu.kiv.backendapi.catalog;
-
-import com.fasterxml.jackson.annotation.JsonProperty;
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import java.util.Collections;
-import java.util.Set;
-import java.util.UUID;
-
-/**
- * Class representing catalog DTO
- */
-@Data
-@AllArgsConstructor
-@NoArgsConstructor
-public class CatalogDto {
-    /**
-     * Id
-     */
-    @JsonProperty(access = JsonProperty.Access.READ_ONLY)
-    private UUID id;
-
-    /**
-     * Name of geographic entry
-     */
-    private String name;
-
-    /**
-     * Certainty
-     */
-    private int certainty;
-
-    /**
-     * Longitude
-     */
-    private double longitude;
-
-    /**
-     * Latitude
-     */
-    private double latitude;
-
-    /**
-     * Bibliography
-     */
-    private Set<String> bibliography = Collections.emptySet();
-
-    /**
-     * Countries
-     */
-    private Set<String> countries = Collections.emptySet();
-
-    /**
-     * Written forms
-     */
-    private Set<String> writtenForms = Collections.emptySet();
-
-    /**
-     * Alternative names
-     */
-    private Set<String> alternativeNames = Collections.emptySet();
-
-    /**
-     * Types
-     */
-    private Set<String> types = Collections.emptySet();
-
-}
diff --git a/backend/src/main/java/cz/zcu/kiv/backendapi/catalog/CatalogEntity.java b/backend/src/main/java/cz/zcu/kiv/backendapi/catalog/CatalogEntity.java
deleted file mode 100644
index a60e2ca..0000000
--- a/backend/src/main/java/cz/zcu/kiv/backendapi/catalog/CatalogEntity.java
+++ /dev/null
@@ -1,150 +0,0 @@
-package cz.zcu.kiv.backendapi.catalog;
-
-import cz.zcu.kiv.backendapi.alternativename.AlternativeNameEntity;
-import cz.zcu.kiv.backendapi.bibliography.BibliographyEntity;
-import cz.zcu.kiv.backendapi.country.CountryEntity;
-import cz.zcu.kiv.backendapi.type.TypeEntity;
-import cz.zcu.kiv.backendapi.writtenform.WrittenFormEntity;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-import org.hibernate.annotations.LazyCollection;
-import org.hibernate.annotations.LazyCollectionOption;
-
-import javax.persistence.*;
-import java.util.*;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import java.util.stream.Collectors;
-
-/**
- * Catalog entity representing catalog
- */
-//@Data
-@Getter
-@Setter
-@NoArgsConstructor
-@Entity
-@Table(name = "catalog")
-public class CatalogEntity {
-    private static final String INTEGER_PATTERN = "\\d+";
-    private static final String DOUBLE_PATTERN = "(\\d+[.]\\d+)|(\\d+)";
-    private static final String EMPTY_ENTRY = "–";
-    /**
-     * Catalog entry id
-     */
-    @Id
-    @GeneratedValue
-    private UUID id;
-
-    /**
-     * Name of geographic entry
-     */
-    private String name;
-
-    /**
-     * Certainty
-     */
-    private int certainty;
-
-    /**
-     * Longitude
-     */
-    private double longitude;
-
-    /**
-     * Latitude
-     */
-    private double latitude;
-
-    /**
-     * Bibliography
-     */
-    @OneToMany(mappedBy = "catalog", cascade = CascadeType.ALL)
-    @LazyCollection(LazyCollectionOption.FALSE)
-    private Set<BibliographyEntity> bibliography = Collections.emptySet();
-
-    /**
-     * Countries
-     */
-    @OneToMany(mappedBy = "catalog", cascade = CascadeType.ALL)
-    @LazyCollection(LazyCollectionOption.FALSE)
-    private Set<CountryEntity> countries = Collections.emptySet();
-
-    /**
-     * Written forms
-     */
-    @OneToMany(mappedBy = "catalog", cascade = CascadeType.ALL)
-    @LazyCollection(LazyCollectionOption.FALSE)
-    private Set<WrittenFormEntity> writtenForms = Collections.emptySet();
-
-    /**
-     * Alternative names
-     */
-    @OneToMany(mappedBy = "catalog", cascade = CascadeType.ALL)
-    @LazyCollection(LazyCollectionOption.FALSE)
-    private Set<AlternativeNameEntity> alternativeNames = Collections.emptySet();
-
-    /**
-     * Set of user roles - many-to-many relationship
-     */
-    @ManyToMany(fetch = FetchType.EAGER)
-    @JoinTable(
-            name = "catalog_type",
-            joinColumns = {
-                    @JoinColumn(name = "catalog_id", referencedColumnName = "id")
-            },
-            inverseJoinColumns = {
-                    @JoinColumn(name = "type", referencedColumnName = "type")
-            }
-    )
-    private Set<TypeEntity> types = Collections.emptySet();
-
-    public CatalogEntity(final List<String> csvFields) {
-
-        this.name = csvFields.get(1);
-        List<String> stringList = processListField(csvFields.get(2));
-        this.alternativeNames = stringList.stream().map(s->new AlternativeNameEntity(s, this)).collect(Collectors.toSet());
-
-        this.certainty = processIntField(csvFields.get(3));
-        this.latitude = processDoubleField(csvFields.get(4));
-        this.longitude = processDoubleField(csvFields.get(5));
-
-        stringList = processListField(csvFields.get(6));
-        this.writtenForms = stringList.stream().map(s->new WrittenFormEntity(s, this)).collect(Collectors.toSet());
-
-        stringList = processListField(csvFields.get(7));
-        this.types = stringList.stream().map(TypeEntity::new).collect(Collectors.toSet());
-
-        stringList = processListField(csvFields.get(8));
-        this.countries = stringList.stream().map(s->new CountryEntity(s, this)).collect(Collectors.toSet());
-
-        stringList = processListField(csvFields.get(10));
-        this.bibliography = stringList.stream().map(s->new BibliographyEntity(s, this)).collect(Collectors.toSet());
-    }
-
-    private int processIntField(String field) {
-        Matcher matcher = Pattern.compile(INTEGER_PATTERN).matcher(field);
-        if (matcher.find()) {
-            return Integer.parseInt(matcher.group());
-        } else {
-            return 0;
-        }
-    }
-
-    private double processDoubleField(String field) {
-        Matcher matcher = Pattern.compile(DOUBLE_PATTERN).matcher(field);
-        if (matcher.find()) {
-            return Double.parseDouble(matcher.group());
-        } else {
-            return 0.0;
-        }
-    }
-
-    private List<String> processListField(String field) {
-        if (field.isEmpty() || field.equals(EMPTY_ENTRY)) {
-            return new ArrayList<>();
-        }
-        return Arrays.stream(field.split(",")).map(String::trim).filter(item -> !item.isEmpty()).collect(Collectors.toList());
-    }
-}
diff --git a/backend/src/main/java/cz/zcu/kiv/backendapi/catalog/CatalogEntry.java b/backend/src/main/java/cz/zcu/kiv/backendapi/catalog/CatalogEntry.java
new file mode 100644
index 0000000..799ff09
--- /dev/null
+++ b/backend/src/main/java/cz/zcu/kiv/backendapi/catalog/CatalogEntry.java
@@ -0,0 +1,150 @@
+package cz.zcu.kiv.backendapi.catalog;
+
+import cz.zcu.kiv.backendapi.alternativename.AlternativeName;
+import cz.zcu.kiv.backendapi.bibliography.Bibliography;
+import cz.zcu.kiv.backendapi.country.Country;
+import cz.zcu.kiv.backendapi.type.Type;
+import cz.zcu.kiv.backendapi.writtenform.WrittenForm;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import org.hibernate.annotations.LazyCollection;
+import org.hibernate.annotations.LazyCollectionOption;
+
+import javax.persistence.*;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+/**
+ * Catalog entity representing catalog entry
+ */
+//@Data
+@Getter
+@Setter
+@NoArgsConstructor
+@Entity
+@Table(name = "catalog")
+public class CatalogEntry {
+    private static final String INTEGER_PATTERN = "\\d+";
+    private static final String DOUBLE_PATTERN = "(\\d+[.]\\d+)|(\\d+)";
+    private static final String EMPTY_ENTRY = "–";
+    /**
+     * Catalog entry id
+     */
+    @Id
+    @GeneratedValue
+    private UUID id;
+
+    /**
+     * Name of geographic entry
+     */
+    private String name;
+
+    /**
+     * Certainty
+     */
+    private int certainty;
+
+    /**
+     * Longitude
+     */
+    private double longitude;
+
+    /**
+     * Latitude
+     */
+    private double latitude;
+
+    /**
+     * Bibliography
+     */
+    @OneToMany(mappedBy = "catalog", cascade = CascadeType.ALL)
+    @LazyCollection(LazyCollectionOption.FALSE)
+    private Set<Bibliography> bibliography = Collections.emptySet();
+
+    /**
+     * Countries
+     */
+    @OneToMany(mappedBy = "catalog", cascade = CascadeType.ALL)
+    @LazyCollection(LazyCollectionOption.FALSE)
+    private Set<Country> countries = Collections.emptySet();
+
+    /**
+     * Written forms
+     */
+    @OneToMany(mappedBy = "catalog", cascade = CascadeType.ALL)
+    @LazyCollection(LazyCollectionOption.FALSE)
+    private Set<WrittenForm> writtenForms = Collections.emptySet();
+
+    /**
+     * Alternative names
+     */
+    @OneToMany(mappedBy = "catalog", cascade = CascadeType.ALL)
+    @LazyCollection(LazyCollectionOption.FALSE)
+    private Set<AlternativeName> alternativeNames = Collections.emptySet();
+
+    /**
+     * Set of user roles - many-to-many relationship
+     */
+    @ManyToMany(fetch = FetchType.EAGER)
+    @JoinTable(
+            name = "catalog_type",
+            joinColumns = {
+                    @JoinColumn(name = "catalog_id", referencedColumnName = "id")
+            },
+            inverseJoinColumns = {
+                    @JoinColumn(name = "type", referencedColumnName = "type")
+            }
+    )
+    private Set<Type> types = Collections.emptySet();
+
+    public CatalogEntry(final List<String> csvFields) {
+
+        this.name = csvFields.get(1);
+        List<String> stringList = processListField(csvFields.get(2));
+        this.alternativeNames = stringList.stream().map(s->new AlternativeName(s, this)).collect(Collectors.toSet());
+
+        this.certainty = processIntField(csvFields.get(3));
+        this.latitude = processDoubleField(csvFields.get(4));
+        this.longitude = processDoubleField(csvFields.get(5));
+
+        stringList = processListField(csvFields.get(6));
+        this.writtenForms = stringList.stream().map(s->new WrittenForm(s, this)).collect(Collectors.toSet());
+
+        stringList = processListField(csvFields.get(7));
+        this.types = stringList.stream().map(Type::new).collect(Collectors.toSet());
+
+        stringList = processListField(csvFields.get(8));
+        this.countries = stringList.stream().map(s->new Country(s, this)).collect(Collectors.toSet());
+
+        stringList = processListField(csvFields.get(9));
+        this.bibliography = stringList.stream().map(s->new Bibliography(s, this)).collect(Collectors.toSet());
+    }
+
+    private int processIntField(String field) {
+        Matcher matcher = Pattern.compile(INTEGER_PATTERN).matcher(field);
+        if (matcher.find()) {
+            return Integer.parseInt(matcher.group());
+        } else {
+            return 0;
+        }
+    }
+
+    private double processDoubleField(String field) {
+        Matcher matcher = Pattern.compile(DOUBLE_PATTERN).matcher(field);
+        if (matcher.find()) {
+            return Double.parseDouble(matcher.group());
+        } else {
+            return 0.0;
+        }
+    }
+
+    private List<String> processListField(String field) {
+        if (field.isEmpty() || field.equals(EMPTY_ENTRY)) {
+            return new ArrayList<>();
+        }
+        return Arrays.stream(field.split(",")).map(String::trim).filter(item -> !item.isEmpty()).collect(Collectors.toList());
+    }
+}
diff --git a/backend/src/main/java/cz/zcu/kiv/backendapi/catalog/CatalogEntryDto.java b/backend/src/main/java/cz/zcu/kiv/backendapi/catalog/CatalogEntryDto.java
new file mode 100644
index 0000000..d8f8124
--- /dev/null
+++ b/backend/src/main/java/cz/zcu/kiv/backendapi/catalog/CatalogEntryDto.java
@@ -0,0 +1,70 @@
+package cz.zcu.kiv.backendapi.catalog;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.Collections;
+import java.util.Set;
+import java.util.UUID;
+
+/**
+ * Class representing catalog entry DTO
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class CatalogEntryDto {
+    /**
+     * Id
+     */
+    @JsonProperty(access = JsonProperty.Access.READ_ONLY)
+    private UUID id;
+
+    /**
+     * Name of geographic entry
+     */
+    private String name;
+
+    /**
+     * Certainty
+     */
+    private int certainty;
+
+    /**
+     * Longitude
+     */
+    private double longitude;
+
+    /**
+     * Latitude
+     */
+    private double latitude;
+
+    /**
+     * Bibliography
+     */
+    private Set<String> bibliography = Collections.emptySet();
+
+    /**
+     * Countries
+     */
+    private Set<String> countries = Collections.emptySet();
+
+    /**
+     * Written forms
+     */
+    private Set<String> writtenForms = Collections.emptySet();
+
+    /**
+     * Alternative names
+     */
+    private Set<String> alternativeNames = Collections.emptySet();
+
+    /**
+     * Types
+     */
+    private Set<String> types = Collections.emptySet();
+
+}
diff --git a/backend/src/main/java/cz/zcu/kiv/backendapi/catalog/CatalogEntryRepository.java b/backend/src/main/java/cz/zcu/kiv/backendapi/catalog/CatalogEntryRepository.java
new file mode 100644
index 0000000..de5d1ff
--- /dev/null
+++ b/backend/src/main/java/cz/zcu/kiv/backendapi/catalog/CatalogEntryRepository.java
@@ -0,0 +1,33 @@
+package cz.zcu.kiv.backendapi.catalog;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.stereotype.Repository;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.Set;
+import java.util.UUID;
+
+/**
+ * Catalog repository
+ */
+@Repository
+@Transactional(readOnly = true)
+public interface CatalogEntryRepository extends JpaRepository<CatalogEntry, UUID> {
+
+    /**
+     * Returns all catalog entries containing specific values
+     *
+     * @param name    name - optional
+     * @param country country - optional
+     * @param type    type - optional
+     * @return set of catalog entries satisfying filter conditions
+     */
+    @Query("SELECT DISTINCT e FROM CatalogEntry e LEFT JOIN AlternativeName a ON e = a.catalog " +
+            "LEFT JOIN Country c ON e = c.catalog " +
+            "INNER JOIN e.types t " +
+            "WHERE (?1 = '' OR e.name LIKE ?1 OR a.name LIKE ?1) " +
+            "AND (?2 = '' OR c.name LIKE ?2) " +
+            "AND (?3 = '' OR t.type LIKE ?3)")
+    Set<CatalogEntry> filterCatalog(String name, String country, String type);
+}
diff --git a/backend/src/main/java/cz/zcu/kiv/backendapi/catalog/CatalogEntryServiceImpl.java b/backend/src/main/java/cz/zcu/kiv/backendapi/catalog/CatalogEntryServiceImpl.java
new file mode 100644
index 0000000..5168f23
--- /dev/null
+++ b/backend/src/main/java/cz/zcu/kiv/backendapi/catalog/CatalogEntryServiceImpl.java
@@ -0,0 +1,148 @@
+package cz.zcu.kiv.backendapi.catalog;
+
+import cz.zcu.kiv.backendapi.alternativename.AlternativeName;
+import cz.zcu.kiv.backendapi.bibliography.Bibliography;
+import cz.zcu.kiv.backendapi.country.Country;
+import cz.zcu.kiv.backendapi.exception.ApiRequestException;
+import cz.zcu.kiv.backendapi.type.Type;
+import cz.zcu.kiv.backendapi.type.ITypeService;
+import cz.zcu.kiv.backendapi.writtenform.WrittenForm;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.HttpStatus;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+import java.util.Set;
+import java.util.UUID;
+import java.util.stream.Collectors;
+
+/**
+ * Catalog entry service implementation
+ */
+@Service
+@Transactional
+@RequiredArgsConstructor
+@Slf4j
+public class CatalogEntryServiceImpl implements ICatalogEntryService {
+    /**
+     * Message for exception when catalog entry is not found by id
+     */
+    private static final String CATALOG_ENTRY_NOT_FOUND = "Catalog entry not found";
+    /**
+     * Catalog repository
+     */
+    private final CatalogEntryRepository catalogEntryRepository;
+
+    /**
+     * Type service
+     */
+    private final ITypeService typeService;
+
+    @Override
+    public void saveCatalog(List<CatalogEntry> catalogEntities) {
+        log.info("Saving catalog");
+        catalogEntities.forEach(this::saveCatalogEntity);
+    }
+
+    @Override
+    public void saveCatalogEntry(CatalogEntryDto catalogEntryDto) {
+        log.info("Saving catalog entry");
+        CatalogEntry catalogEntry = new CatalogEntry();
+        convertDtoToEntity(catalogEntryDto, catalogEntry);
+        saveCatalogEntity(catalogEntry);
+    }
+
+    @Override
+    public void updateCatalogEntry(UUID id, CatalogEntryDto catalogEntryDto) {
+        CatalogEntry catalogEntry = catalogEntryRepository.findById(id).orElseThrow(() -> {
+            log.error(CATALOG_ENTRY_NOT_FOUND);
+            throw new ApiRequestException(CATALOG_ENTRY_NOT_FOUND, HttpStatus.NOT_FOUND);
+        });
+        convertDtoToEntity(catalogEntryDto, catalogEntry);
+        saveCatalogEntity(catalogEntry);
+        log.info("Catalog entry updated");
+    }
+
+    @Override
+    public void deleteCatalogEntry(UUID id) {
+        CatalogEntry catalogEntry = catalogEntryRepository.findById(id).orElseThrow(() -> {
+            log.error(CATALOG_ENTRY_NOT_FOUND);
+            throw new ApiRequestException(CATALOG_ENTRY_NOT_FOUND, HttpStatus.NOT_FOUND);
+        });
+        catalogEntryRepository.delete(catalogEntry);
+        log.info("Catalog entry deleted");
+    }
+
+    @Override
+    public List<CatalogEntryDto> getCatalog(String name, String country, String type) {
+        log.info("Retrieving catalog");
+        Set<CatalogEntry> entities = catalogEntryRepository.filterCatalog(name, country, type);
+        return entities.stream().map(this::convertEntityToDto).collect(Collectors.toList());
+    }
+
+    /**
+     * Saves catalog entity to database
+     *
+     * @param catalogEntry catalog entity
+     */
+    private void saveCatalogEntity(CatalogEntry catalogEntry) {
+        for (Type type : catalogEntry.getTypes()) {
+            if (typeService.getTypeByName(type.getType()).isEmpty()) {
+                typeService.saveType(type);
+            }
+        }
+        catalogEntryRepository.save(catalogEntry);
+    }
+
+    /**
+     * Converts catalog DTO to catalog entity
+     *
+     * @param catalogEntryDto    catalog DTO
+     * @param catalogEntry catalog entity
+     */
+    private void convertDtoToEntity(CatalogEntryDto catalogEntryDto, CatalogEntry catalogEntry) {
+        catalogEntry.setName(catalogEntryDto.getName());
+        catalogEntry.setCertainty(catalogEntryDto.getCertainty());
+        catalogEntry.setLatitude(catalogEntryDto.getLatitude());
+        catalogEntry.setLongitude(catalogEntryDto.getLongitude());
+        catalogEntry.setBibliography(catalogEntryDto.getBibliography()
+                .stream().map(s -> new Bibliography(s, catalogEntry)).collect(Collectors.toSet()));
+        catalogEntry.setTypes(catalogEntryDto.getTypes()
+                .stream().map(Type::new).collect(Collectors.toSet()));
+        catalogEntry.setCountries(catalogEntryDto.getCountries()
+                .stream().map(s -> new Country(s, catalogEntry)).collect(Collectors.toSet()));
+        catalogEntry.setAlternativeNames(catalogEntryDto.getAlternativeNames()
+                .stream().map(s -> new AlternativeName(s, catalogEntry)).collect(Collectors.toSet()));
+        catalogEntry.setWrittenForms(catalogEntryDto.getWrittenForms()
+                .stream().map(s -> new WrittenForm(s, catalogEntry)).collect(Collectors.toSet()));
+    }
+
+    /**
+     * Converts catalog entity to catalog DTO
+     *
+     * @param entity catalog entity
+     * @return catalog DTO
+     */
+    private CatalogEntryDto convertEntityToDto(CatalogEntry entity) {
+        CatalogEntryDto catalogEntryDto = new CatalogEntryDto();
+        catalogEntryDto.setId(entity.getId());
+        catalogEntryDto.setName(entity.getName());
+        catalogEntryDto.setLatitude(entity.getLatitude());
+        catalogEntryDto.setLongitude(entity.getLongitude());
+        catalogEntryDto.setCertainty(entity.getCertainty());
+        catalogEntryDto.setBibliography(entity.getBibliography()
+                .stream().map(Bibliography::getSource).collect(Collectors.toSet()));
+        catalogEntryDto.setTypes(entity.getTypes()
+                .stream().map(Type::getType).collect(Collectors.toSet()));
+        catalogEntryDto.setCountries(entity.getCountries()
+                .stream().map(Country::getName).collect(Collectors.toSet()));
+        catalogEntryDto.setAlternativeNames(entity.getAlternativeNames()
+                .stream().map(AlternativeName::getName).collect(Collectors.toSet()));
+        catalogEntryDto.setWrittenForms(entity.getWrittenForms()
+                .stream().map(WrittenForm::getForm).collect(Collectors.toSet()));
+        return catalogEntryDto;
+    }
+
+}
diff --git a/backend/src/main/java/cz/zcu/kiv/backendapi/catalog/CatalogRepository.java b/backend/src/main/java/cz/zcu/kiv/backendapi/catalog/CatalogRepository.java
deleted file mode 100644
index f0b4ac2..0000000
--- a/backend/src/main/java/cz/zcu/kiv/backendapi/catalog/CatalogRepository.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package cz.zcu.kiv.backendapi.catalog;
-
-import org.springframework.data.jpa.repository.JpaRepository;
-import org.springframework.data.jpa.repository.Query;
-import org.springframework.stereotype.Repository;
-import org.springframework.transaction.annotation.Transactional;
-
-import java.util.Set;
-import java.util.UUID;
-
-/**
- * Catalog repository
- */
-@Repository
-@Transactional(readOnly = true)
-public interface CatalogRepository extends JpaRepository<CatalogEntity, UUID> {
-
-    /**
-     * Returns all catalog entries containing specific values
-     *
-     * @param name    name - optional
-     * @param country country - optional
-     * @param type    type - optional
-     * @return set of catalog entries satisfying filter conditions
-     */
-    @Query("SELECT DISTINCT e FROM CatalogEntity e LEFT JOIN AlternativeNameEntity a ON e = a.catalog " +
-            "LEFT JOIN CountryEntity c ON e = c.catalog " +
-            "INNER JOIN e.types t " +
-            "WHERE (?1 = '' OR e.name LIKE ?1 OR a.name LIKE ?1) " +
-            "AND (?2 = '' OR c.name LIKE ?2) " +
-            "AND (?3 = '' OR t.type LIKE ?3)")
-    Set<CatalogEntity> filterCatalog(String name, String country, String type);
-}
diff --git a/backend/src/main/java/cz/zcu/kiv/backendapi/catalog/CatalogServiceImpl.java b/backend/src/main/java/cz/zcu/kiv/backendapi/catalog/CatalogServiceImpl.java
deleted file mode 100644
index d999041..0000000
--- a/backend/src/main/java/cz/zcu/kiv/backendapi/catalog/CatalogServiceImpl.java
+++ /dev/null
@@ -1,148 +0,0 @@
-package cz.zcu.kiv.backendapi.catalog;
-
-import cz.zcu.kiv.backendapi.alternativename.AlternativeNameEntity;
-import cz.zcu.kiv.backendapi.bibliography.BibliographyEntity;
-import cz.zcu.kiv.backendapi.country.CountryEntity;
-import cz.zcu.kiv.backendapi.exception.ApiRequestException;
-import cz.zcu.kiv.backendapi.type.TypeEntity;
-import cz.zcu.kiv.backendapi.type.ITypeService;
-import cz.zcu.kiv.backendapi.writtenform.WrittenFormEntity;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.http.HttpStatus;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-
-import java.util.List;
-import java.util.Set;
-import java.util.UUID;
-import java.util.stream.Collectors;
-
-/**
- * Catalog service implementation
- */
-@Service
-@Transactional
-@RequiredArgsConstructor
-@Slf4j
-public class CatalogServiceImpl implements ICatalogService {
-    /**
-     * Message for exception when catalog entry is not found by id
-     */
-    private static final String CATALOG_ENTRY_NOT_FOUND = "Catalog entry not found";
-    /**
-     * Catalog repository
-     */
-    private final CatalogRepository catalogRepository;
-
-    /**
-     * Type service
-     */
-    private final ITypeService typeService;
-
-    @Override
-    public void saveCatalog(List<CatalogEntity> catalogEntities) {
-        log.info("Saving catalog");
-        catalogEntities.forEach(this::saveCatalogEntity);
-    }
-
-    @Override
-    public void saveCatalogEntry(CatalogDto catalogDto) {
-        log.info("Saving catalog entry");
-        CatalogEntity catalogEntity = new CatalogEntity();
-        convertDtoToEntity(catalogDto, catalogEntity);
-        saveCatalogEntity(catalogEntity);
-    }
-
-    @Override
-    public void updateCatalogEntry(UUID id, CatalogDto catalogDto) {
-        CatalogEntity catalogEntity = catalogRepository.findById(id).orElseThrow(() -> {
-            log.error(CATALOG_ENTRY_NOT_FOUND);
-            throw new ApiRequestException(CATALOG_ENTRY_NOT_FOUND, HttpStatus.NOT_FOUND);
-        });
-        convertDtoToEntity(catalogDto, catalogEntity);
-        saveCatalogEntity(catalogEntity);
-        log.info("Catalog entry updated");
-    }
-
-    @Override
-    public void deleteCatalogEntry(UUID id) {
-        CatalogEntity catalogEntity = catalogRepository.findById(id).orElseThrow(() -> {
-            log.error(CATALOG_ENTRY_NOT_FOUND);
-            throw new ApiRequestException(CATALOG_ENTRY_NOT_FOUND, HttpStatus.NOT_FOUND);
-        });
-        catalogRepository.delete(catalogEntity);
-        log.info("Catalog entry deleted");
-    }
-
-    @Override
-    public List<CatalogDto> getCatalog(String name, String country, String type) {
-        log.info("Retrieving catalog");
-        Set<CatalogEntity> entities = catalogRepository.filterCatalog(name, country, type);
-        return entities.stream().map(this::convertEntityToDto).collect(Collectors.toList());
-    }
-
-    /**
-     * Saves catalog entity to database
-     *
-     * @param catalogEntity catalog entity
-     */
-    private void saveCatalogEntity(CatalogEntity catalogEntity) {
-        for (TypeEntity type : catalogEntity.getTypes()) {
-            if (typeService.getTypeByName(type.getType()).isEmpty()) {
-                typeService.saveType(type);
-            }
-        }
-        catalogRepository.save(catalogEntity);
-    }
-
-    /**
-     * Converts catalog DTO to catalog entity
-     *
-     * @param catalogDto    catalog DTO
-     * @param catalogEntity catalog entity
-     */
-    private void convertDtoToEntity(CatalogDto catalogDto, CatalogEntity catalogEntity) {
-        catalogEntity.setName(catalogDto.getName());
-        catalogEntity.setCertainty(catalogDto.getCertainty());
-        catalogEntity.setLatitude(catalogDto.getLatitude());
-        catalogEntity.setLongitude(catalogDto.getLongitude());
-        catalogEntity.setBibliography(catalogDto.getBibliography()
-                .stream().map(s -> new BibliographyEntity(s, catalogEntity)).collect(Collectors.toSet()));
-        catalogEntity.setTypes(catalogDto.getTypes()
-                .stream().map(TypeEntity::new).collect(Collectors.toSet()));
-        catalogEntity.setCountries(catalogDto.getCountries()
-                .stream().map(s -> new CountryEntity(s, catalogEntity)).collect(Collectors.toSet()));
-        catalogEntity.setAlternativeNames(catalogDto.getAlternativeNames()
-                .stream().map(s -> new AlternativeNameEntity(s, catalogEntity)).collect(Collectors.toSet()));
-        catalogEntity.setWrittenForms(catalogDto.getWrittenForms()
-                .stream().map(s -> new WrittenFormEntity(s, catalogEntity)).collect(Collectors.toSet()));
-    }
-
-    /**
-     * Converts catalog entity to catalog DTO
-     *
-     * @param entity catalog entity
-     * @return catalog DTO
-     */
-    private CatalogDto convertEntityToDto(CatalogEntity entity) {
-        CatalogDto catalogDto = new CatalogDto();
-        catalogDto.setId(entity.getId());
-        catalogDto.setName(entity.getName());
-        catalogDto.setLatitude(entity.getLatitude());
-        catalogDto.setLongitude(entity.getLongitude());
-        catalogDto.setCertainty(entity.getCertainty());
-        catalogDto.setBibliography(entity.getBibliography()
-                .stream().map(BibliographyEntity::getSource).collect(Collectors.toSet()));
-        catalogDto.setTypes(entity.getTypes()
-                .stream().map(TypeEntity::getType).collect(Collectors.toSet()));
-        catalogDto.setCountries(entity.getCountries()
-                .stream().map(CountryEntity::getName).collect(Collectors.toSet()));
-        catalogDto.setAlternativeNames(entity.getAlternativeNames()
-                .stream().map(AlternativeNameEntity::getName).collect(Collectors.toSet()));
-        catalogDto.setWrittenForms(entity.getWrittenForms()
-                .stream().map(WrittenFormEntity::getForm).collect(Collectors.toSet()));
-        return catalogDto;
-    }
-
-}
diff --git a/backend/src/main/java/cz/zcu/kiv/backendapi/catalog/ICatalogEntryService.java b/backend/src/main/java/cz/zcu/kiv/backendapi/catalog/ICatalogEntryService.java
new file mode 100644
index 0000000..c2bc22b
--- /dev/null
+++ b/backend/src/main/java/cz/zcu/kiv/backendapi/catalog/ICatalogEntryService.java
@@ -0,0 +1,49 @@
+package cz.zcu.kiv.backendapi.catalog;
+
+import java.util.List;
+import java.util.UUID;
+
+/**
+ * Catalog service interface
+ */
+public interface ICatalogEntryService {
+    /**
+     * Saves list of catalog entries
+     *
+     * @param catalogEntities catalog entris
+     */
+    void saveCatalog(List<CatalogEntry> catalogEntities);
+
+    /**
+     * Saves one catalog entry
+     *
+     * @param catalogEntryDto catalog DTO
+     */
+    void saveCatalogEntry(CatalogEntryDto catalogEntryDto);
+
+    /**
+     * Updates catalog entry with given ID
+     *
+     * @param id         ID
+     * @param catalogEntryDto catalog DTO
+     */
+    void updateCatalogEntry(UUID id, CatalogEntryDto catalogEntryDto);
+
+    /**
+     * Deletes catalog entry with given ID
+     *
+     * @param id ID
+     */
+    void deleteCatalogEntry(UUID id);
+
+    /**
+     * Returns catalog entries satisfying given filter
+     *
+     * @param name    name - optional
+     * @param country country - optional
+     * @param type    type - optional
+     * @return list of catalog entries satisfying given filter
+     */
+    List<CatalogEntryDto> getCatalog(String name, String country, String type);
+
+}
diff --git a/backend/src/main/java/cz/zcu/kiv/backendapi/catalog/ICatalogService.java b/backend/src/main/java/cz/zcu/kiv/backendapi/catalog/ICatalogService.java
deleted file mode 100644
index 66da0f0..0000000
--- a/backend/src/main/java/cz/zcu/kiv/backendapi/catalog/ICatalogService.java
+++ /dev/null
@@ -1,49 +0,0 @@
-package cz.zcu.kiv.backendapi.catalog;
-
-import java.util.List;
-import java.util.UUID;
-
-/**
- * Catalog service interface
- */
-public interface ICatalogService {
-    /**
-     * Saves list of catalog entries
-     *
-     * @param catalogEntities catalog entris
-     */
-    void saveCatalog(List<CatalogEntity> catalogEntities);
-
-    /**
-     * Saves one catalog entry
-     *
-     * @param catalogDto catalog DTO
-     */
-    void saveCatalogEntry(CatalogDto catalogDto);
-
-    /**
-     * Updates catalog entry with given ID
-     *
-     * @param id         ID
-     * @param catalogDto catalog DTO
-     */
-    void updateCatalogEntry(UUID id, CatalogDto catalogDto);
-
-    /**
-     * Deletes catalog entry with given ID
-     *
-     * @param id ID
-     */
-    void deleteCatalogEntry(UUID id);
-
-    /**
-     * Returns catalog entries satisfying given filter
-     *
-     * @param name    name - optional
-     * @param country country - optional
-     * @param type    type - optional
-     * @return list of catalog entries satisfying given filter
-     */
-    List<CatalogDto> getCatalog(String name, String country, String type);
-
-}
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 05dd781..b98a12c 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
@@ -1,9 +1,9 @@
 package cz.zcu.kiv.backendapi.config;
 
-import cz.zcu.kiv.backendapi.catalog.CatalogEntity;
-import cz.zcu.kiv.backendapi.type.TypeEntity;
-import cz.zcu.kiv.backendapi.catalog.CatalogRepository;
-import cz.zcu.kiv.backendapi.catalog.ICatalogService;
+import cz.zcu.kiv.backendapi.catalog.CatalogEntry;
+import cz.zcu.kiv.backendapi.type.Type;
+import cz.zcu.kiv.backendapi.catalog.CatalogEntryRepository;
+import cz.zcu.kiv.backendapi.catalog.ICatalogEntryService;
 import cz.zcu.kiv.backendapi.type.ITypeService;
 import cz.zcu.kiv.backendapi.user.UserEntity;
 import cz.zcu.kiv.backendapi.user.UserRepository;
@@ -29,11 +29,11 @@ import java.util.List;
 @RequiredArgsConstructor
 public class DataInitiator implements ApplicationListener<ContextRefreshedEvent> {
 
-    private final ICatalogService catalogService;
+    private final ICatalogEntryService catalogService;
 
     private final ITypeService typeService;
 
-    private final CatalogRepository catalogRepository;
+    private final CatalogEntryRepository catalogEntryRepository;
 
     private final UserRepository userRepository;
 
@@ -42,9 +42,9 @@ public class DataInitiator implements ApplicationListener<ContextRefreshedEvent>
     @Override
     @Transactional
     public void onApplicationEvent(ContextRefreshedEvent event) {
-        List<TypeEntity> types = loadTypes();
+        List<Type> types = loadTypes();
         typeService.saveTypes(types);
-        List<CatalogEntity> catalog = loadCatalog();
+        List<CatalogEntry> catalog = loadCatalog();
         catalogService.saveCatalog(catalog);
 
         UserEntity user1 = new UserEntity("admin", "admin", encoder.encode("password"), (byte) 7, true);
@@ -55,9 +55,9 @@ public class DataInitiator implements ApplicationListener<ContextRefreshedEvent>
 
     }
 
-    private List<CatalogEntity> loadCatalog() {
-        List<CatalogEntity> catalogEntities = new ArrayList<>();
-        File csvData = new File("AssyrianProject-AllNoDupl.csv");
+    private List<CatalogEntry> loadCatalog() {
+        List<CatalogEntry> catalogEntities = new ArrayList<>();
+        File csvData = new File("AssyrianProject-AllNoDupl-22-03-28.csv");
         CSVParser parser;
         try {
             parser = CSVParser.parse(csvData, StandardCharsets.UTF_8, CSVFormat.Builder.create(CSVFormat.DEFAULT)
@@ -65,7 +65,7 @@ public class DataInitiator implements ApplicationListener<ContextRefreshedEvent>
                     .setSkipHeaderRecord(true)
                     .build());
             for (CSVRecord csvRecord : parser) {
-                catalogEntities.add(new CatalogEntity(csvRecord.toList()));
+                catalogEntities.add(new CatalogEntry(csvRecord.toList()));
             }
         } catch (IOException e) {
             e.printStackTrace();
@@ -74,15 +74,15 @@ public class DataInitiator implements ApplicationListener<ContextRefreshedEvent>
 
     }
 
-    private List<TypeEntity> loadTypes() {
-        List<TypeEntity> types = new ArrayList<>();
+    private List<Type> loadTypes() {
+        List<Type> types = new ArrayList<>();
         CSVParser parser;
         File csvData = new File("AssyrianProject-All.csv");
         try {
             parser = CSVParser.parse(csvData, Charset.defaultCharset(), CSVFormat.DEFAULT.builder().setSkipHeaderRecord(true).build());
             for (CSVRecord csvRecord : parser) {
                 if (csvRecord.get(0).equals("10000")) {
-                    types.add(new TypeEntity(csvRecord.get(2)));
+                    types.add(new Type(csvRecord.get(2)));
                 }
             }
         } catch (IOException e) {
diff --git a/backend/src/main/java/cz/zcu/kiv/backendapi/country/Country.java b/backend/src/main/java/cz/zcu/kiv/backendapi/country/Country.java
new file mode 100644
index 0000000..26dec24
--- /dev/null
+++ b/backend/src/main/java/cz/zcu/kiv/backendapi/country/Country.java
@@ -0,0 +1,31 @@
+package cz.zcu.kiv.backendapi.country;
+
+import cz.zcu.kiv.backendapi.catalog.CatalogEntry;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.persistence.*;
+import java.io.Serializable;
+
+/**
+ * Country entity representing country of geographic entry
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Entity
+@Table(name = "countries")
+@IdClass(Country.class)
+public class Country implements Serializable {
+    /**
+     * Name of country, serves as ID
+     */
+    @Id
+    private String name;
+
+    @ManyToOne
+    @JoinColumn(name = "catalog_id")
+    @Id
+    private CatalogEntry catalog;
+}
diff --git a/backend/src/main/java/cz/zcu/kiv/backendapi/country/CountryEntity.java b/backend/src/main/java/cz/zcu/kiv/backendapi/country/CountryEntity.java
deleted file mode 100644
index 1e5eeae..0000000
--- a/backend/src/main/java/cz/zcu/kiv/backendapi/country/CountryEntity.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package cz.zcu.kiv.backendapi.country;
-
-import cz.zcu.kiv.backendapi.catalog.CatalogEntity;
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import javax.persistence.*;
-import java.io.Serializable;
-
-/**
- * Country entity representing country of geographic entry
- */
-@Data
-@NoArgsConstructor
-@AllArgsConstructor
-@Entity
-@Table(name = "countries")
-@IdClass(CountryEntity.class)
-public class CountryEntity implements Serializable {
-    /**
-     * Name of country, serves as ID
-     */
-    @Id
-    private String name;
-
-    @ManyToOne
-    @JoinColumn(name = "catalog_id")
-    @Id
-    private CatalogEntity catalog;
-}
diff --git a/backend/src/main/java/cz/zcu/kiv/backendapi/country/CountryRepository.java b/backend/src/main/java/cz/zcu/kiv/backendapi/country/CountryRepository.java
index cc881c4..1eb9eed 100644
--- a/backend/src/main/java/cz/zcu/kiv/backendapi/country/CountryRepository.java
+++ b/backend/src/main/java/cz/zcu/kiv/backendapi/country/CountryRepository.java
@@ -9,5 +9,5 @@ import org.springframework.transaction.annotation.Transactional;
  */
 @Repository
 @Transactional(readOnly = true)
-public interface CountryRepository extends JpaRepository<CountryEntity, CountryEntity> {
+public interface CountryRepository extends JpaRepository<Country, Country> {
 }
diff --git a/backend/src/main/java/cz/zcu/kiv/backendapi/exception/ApiRequestException.java b/backend/src/main/java/cz/zcu/kiv/backendapi/exception/ApiRequestException.java
index 7244082..d43df3d 100644
--- a/backend/src/main/java/cz/zcu/kiv/backendapi/exception/ApiRequestException.java
+++ b/backend/src/main/java/cz/zcu/kiv/backendapi/exception/ApiRequestException.java
@@ -12,8 +12,4 @@ public class ApiRequestException extends RuntimeException {
         this.httpStatus = httpStatus;
     }
 
-    public ApiRequestException(String message, Throwable cause, HttpStatus httpStatus) {
-        super(message, cause);
-        this.httpStatus = httpStatus;
-    }
 }
diff --git a/backend/src/main/java/cz/zcu/kiv/backendapi/password/PasswordDto.java b/backend/src/main/java/cz/zcu/kiv/backendapi/password/PasswordDto.java
new file mode 100644
index 0000000..3cfa4c3
--- /dev/null
+++ b/backend/src/main/java/cz/zcu/kiv/backendapi/password/PasswordDto.java
@@ -0,0 +1,40 @@
+package cz.zcu.kiv.backendapi.password;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import cz.zcu.kiv.backendapi.validation.PasswordMatches;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+
+/**
+ * Password data object
+ */
+@Data
+@PasswordMatches
+@NoArgsConstructor
+public class PasswordDto {
+    /**
+     * Minimal length for password
+     */
+    @JsonIgnore
+    private  static final int MIN_PASSWORD_LENGTH = 8;
+
+    /**
+     * New password - must be strong enough
+     */
+    @NotNull(message = "Password must not be null")
+    @NotEmpty(message = "Password must not be empty")
+    @Size(min = MIN_PASSWORD_LENGTH, message = "Password must be at least " + MIN_PASSWORD_LENGTH + " characters long")
+    private String password;
+
+    /**
+     * New password confirmation - must match new password
+     */
+    @NotNull(message = "Confirmation password must not be null")
+    @NotEmpty(message = "Confirmation password must not be empty")
+    private String confirmationPassword;
+
+}
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 2b70185..d688fb8 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
@@ -8,6 +8,7 @@ import cz.zcu.kiv.backendapi.user.Role;
 import lombok.RequiredArgsConstructor;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
+import org.springframework.http.HttpMethod;
 import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
 import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
 import org.springframework.security.config.annotation.web.builders.HttpSecurity;
@@ -61,7 +62,8 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
                 .and()
                 .authorizeRequests()
                 .antMatchers(permittedUrls).permitAll()
-                .antMatchers("/admin/**").hasRole(Role.ADMIN.name())
+                .antMatchers("/user/update-permissions/**", "/user/reset-password/**").hasRole(Role.ADMIN.name())
+                .antMatchers(HttpMethod.DELETE, "/user/**").hasRole(Role.ADMIN.name())
                 .antMatchers("/write/**").hasAuthority(Permission.WRITE.name())
                 .antMatchers("/read/**").hasAuthority(Permission.READ.name())
                 .antMatchers("/delete/**").hasAuthority(Permission.DELETE.name())
diff --git a/backend/src/main/java/cz/zcu/kiv/backendapi/security/jwt/JwtUtils.java b/backend/src/main/java/cz/zcu/kiv/backendapi/security/jwt/JwtUtils.java
index 2a6fc0d..43407a7 100644
--- a/backend/src/main/java/cz/zcu/kiv/backendapi/security/jwt/JwtUtils.java
+++ b/backend/src/main/java/cz/zcu/kiv/backendapi/security/jwt/JwtUtils.java
@@ -59,9 +59,7 @@ public class JwtUtils {
      * Claim authorities name
      */
     private String claimAuthoritiesName;
-
-    public JwtUtils() {
-    }
+    
 
     /**
      * Returns algorithm for JWT
diff --git a/backend/src/main/java/cz/zcu/kiv/backendapi/type/ITypeService.java b/backend/src/main/java/cz/zcu/kiv/backendapi/type/ITypeService.java
index 0a28c16..ad89f2e 100644
--- a/backend/src/main/java/cz/zcu/kiv/backendapi/type/ITypeService.java
+++ b/backend/src/main/java/cz/zcu/kiv/backendapi/type/ITypeService.java
@@ -8,9 +8,9 @@ import java.util.Optional;
  */
 public interface ITypeService {
 
-    void saveType(TypeEntity typeEntity);
+    void saveType(Type type);
 
-    void saveTypes(List<TypeEntity> typesEntities);
+    void saveTypes(List<Type> typesEntities);
 
-    Optional<TypeEntity> getTypeByName(String type);
+    Optional<Type> getTypeByName(String type);
 }
diff --git a/backend/src/main/java/cz/zcu/kiv/backendapi/type/Type.java b/backend/src/main/java/cz/zcu/kiv/backendapi/type/Type.java
new file mode 100644
index 0000000..43a4954
--- /dev/null
+++ b/backend/src/main/java/cz/zcu/kiv/backendapi/type/Type.java
@@ -0,0 +1,25 @@
+package cz.zcu.kiv.backendapi.type;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+/**
+ * Type entity representing type of geographic entry
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Entity
+@Table(name = "types")
+public class Type {
+    /**
+     * Type (e.g. river), serves as ID
+     */
+    @Id
+    private String type;
+}
diff --git a/backend/src/main/java/cz/zcu/kiv/backendapi/type/TypeEntity.java b/backend/src/main/java/cz/zcu/kiv/backendapi/type/TypeEntity.java
deleted file mode 100644
index 193793f..0000000
--- a/backend/src/main/java/cz/zcu/kiv/backendapi/type/TypeEntity.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package cz.zcu.kiv.backendapi.type;
-
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import javax.persistence.Entity;
-import javax.persistence.Id;
-import javax.persistence.Table;
-
-/**
- * Type entity representing type of geographic entry
- */
-@Data
-@NoArgsConstructor
-@AllArgsConstructor
-@Entity
-@Table(name = "types")
-public class TypeEntity {
-    /**
-     * Type (e.g. river), serves as ID
-     */
-    @Id
-    private String type;
-}
diff --git a/backend/src/main/java/cz/zcu/kiv/backendapi/type/TypeRepository.java b/backend/src/main/java/cz/zcu/kiv/backendapi/type/TypeRepository.java
index 1524edd..28405bb 100644
--- a/backend/src/main/java/cz/zcu/kiv/backendapi/type/TypeRepository.java
+++ b/backend/src/main/java/cz/zcu/kiv/backendapi/type/TypeRepository.java
@@ -10,5 +10,5 @@ import org.springframework.transaction.annotation.Transactional;
  */
 @Repository
 @Transactional(readOnly = true)
-public interface TypeRepository extends JpaRepository<TypeEntity, String> {
+public interface TypeRepository extends JpaRepository<Type, String> {
 }
diff --git a/backend/src/main/java/cz/zcu/kiv/backendapi/type/TypeServiceImpl.java b/backend/src/main/java/cz/zcu/kiv/backendapi/type/TypeServiceImpl.java
index 74863c9..bd8d4a0 100644
--- a/backend/src/main/java/cz/zcu/kiv/backendapi/type/TypeServiceImpl.java
+++ b/backend/src/main/java/cz/zcu/kiv/backendapi/type/TypeServiceImpl.java
@@ -20,17 +20,17 @@ public class TypeServiceImpl implements ITypeService {
     private final TypeRepository typeRepository;
 
     @Override
-    public void saveType(TypeEntity typeEntity) {
-        typeRepository.save(typeEntity);
+    public void saveType(Type type) {
+        typeRepository.save(type);
     }
 
     @Override
-    public void saveTypes(List<TypeEntity> typesEntities) {
+    public void saveTypes(List<Type> typesEntities) {
         typeRepository.saveAll(typesEntities);
     }
 
     @Override
-    public Optional<TypeEntity> getTypeByName(String type) {
+    public Optional<Type> getTypeByName(String type) {
         return typeRepository.findById(type);
     }
 
diff --git a/backend/src/main/java/cz/zcu/kiv/backendapi/user/IUserService.java b/backend/src/main/java/cz/zcu/kiv/backendapi/user/IUserService.java
index 0c8f245..2db84bc 100644
--- a/backend/src/main/java/cz/zcu/kiv/backendapi/user/IUserService.java
+++ b/backend/src/main/java/cz/zcu/kiv/backendapi/user/IUserService.java
@@ -1,5 +1,8 @@
 package cz.zcu.kiv.backendapi.user;
 
+import cz.zcu.kiv.backendapi.password.PasswordDto;
+import premission.PermissionDto;
+
 import java.util.List;
 
 /**
@@ -22,8 +25,11 @@ public interface IUserService {
      */
     void registerNewUser(UserDto userDto);
 
-    void updateUser(String username, UserDto userDto);
-
+    /**
+     * Deletes user with given username
+     *
+     * @param username username
+     */
     void deleteUser(String username);
 
     /**
@@ -32,4 +38,28 @@ public interface IUserService {
      * @return list of all users
      */
     List<UserDto> getAllUsers();
+
+    /**
+     * Changes password of the user
+     *
+     * @param oldPassword old poasswort
+     * @param passwordDto password DTO containing new password and confirmation password
+     */
+    void changePassword(String oldPassword, PasswordDto passwordDto);
+
+    /**
+     * Updates permissions to given user
+     *
+     * @param username      username
+     * @param permissionDto permissions
+     */
+    void updatePermissions(String username, PermissionDto permissionDto);
+
+    /**
+     * Resets password to given user
+     *
+     * @param username    username
+     * @param newPassword new password
+     */
+    void resetPassword(String username, String newPassword);
 }
diff --git a/backend/src/main/java/cz/zcu/kiv/backendapi/user/Permission.java b/backend/src/main/java/cz/zcu/kiv/backendapi/user/Permission.java
index 7813395..dc6c7a2 100644
--- a/backend/src/main/java/cz/zcu/kiv/backendapi/user/Permission.java
+++ b/backend/src/main/java/cz/zcu/kiv/backendapi/user/Permission.java
@@ -9,9 +9,7 @@ import lombok.Getter;
 public enum Permission {
     READ("READ", (byte) 0x1),
     WRITE("WRITE", (byte) 0x2),
-    DELETE("DELETE", (byte) 0x4),
-
-    ;
+    DELETE("DELETE", (byte) 0x4);
 
     /**
      * Permission name
diff --git a/backend/src/main/java/cz/zcu/kiv/backendapi/user/UserController.java b/backend/src/main/java/cz/zcu/kiv/backendapi/user/UserController.java
index dd32942..006c5ea 100644
--- a/backend/src/main/java/cz/zcu/kiv/backendapi/user/UserController.java
+++ b/backend/src/main/java/cz/zcu/kiv/backendapi/user/UserController.java
@@ -5,19 +5,24 @@ import com.auth0.jwt.JWTVerifier;
 import com.auth0.jwt.algorithms.Algorithm;
 import com.auth0.jwt.interfaces.DecodedJWT;
 import com.google.common.base.Strings;
+import cz.zcu.kiv.backendapi.password.PasswordDto;
 import cz.zcu.kiv.backendapi.security.jwt.JwtUtils;
 import cz.zcu.kiv.backendapi.exception.ApiRequestException;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.http.HttpHeaders;
 import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
 import org.springframework.http.ResponseEntity;
+import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.security.core.GrantedAuthority;
 import org.springframework.web.bind.annotation.*;
+import premission.PermissionDto;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import javax.validation.Valid;
+import javax.validation.constraints.NotNull;
 import java.io.IOException;
 import java.time.LocalDateTime;
 import java.time.ZoneId;
@@ -28,7 +33,7 @@ import java.util.stream.Collectors;
 /**
  * Controller for users
  */
-@RestController()
+@RestController
 @RequiredArgsConstructor
 @Slf4j
 public class UserController {
@@ -49,11 +54,23 @@ public class UserController {
      *
      * @param userDto user DTO
      */
-    @PostMapping("/register")
+    @PostMapping("/user/register")
     public void registerNewUser(@RequestBody @Valid UserDto userDto) {
         userService.registerNewUser(userDto);
     }
 
+
+    /**
+     * Changes password to logged-in user
+     *
+     * @param oldPassword old password
+     * @param passwordDto password DTO
+     */
+    @PatchMapping("/user/change-password")
+    public void changePassword(@Valid @NotNull(message = "Old password must not be null") @RequestParam String oldPassword, @RequestBody @Valid PasswordDto passwordDto) {
+        userService.changePassword(oldPassword, passwordDto);
+    }
+
     /**
      * Returns list of all users
      *
@@ -64,10 +81,26 @@ public class UserController {
         return new ResponseEntity<>(userService.getAllUsers(), HttpStatus.OK);
     }
 
-    //TODO check if need, if needed probably change new dto without email, comment otherwise
-    @PutMapping("/user/{username}")
-    public void updateUser(@PathVariable String username, @RequestBody @Valid UserDto userDto) {
-        userService.updateUser(username, userDto);
+    /**
+     * Updates permissions to given user
+     *
+     * @param username      username
+     * @param permissionDto permissions
+     */
+    @PatchMapping("/user/update-permissions/{username}")
+    public void updatePermissions(@PathVariable String username, @RequestBody PermissionDto permissionDto) {
+        userService.updatePermissions(username, permissionDto);
+    }
+
+    /**
+     * Resets password to given user
+     *
+     * @param username    username
+     * @param passwordDto password
+     */
+    @PatchMapping(value = "/user/reset-password/{username}")
+    public void resetPassword(@PathVariable String username, @RequestBody @Valid PasswordDto passwordDto) {
+        userService.resetPassword(username, passwordDto.getPassword());
     }
 
     //TODO check if needed, comment otherwise
diff --git a/backend/src/main/java/cz/zcu/kiv/backendapi/user/UserDto.java b/backend/src/main/java/cz/zcu/kiv/backendapi/user/UserDto.java
index 7101847..a529ca7 100644
--- a/backend/src/main/java/cz/zcu/kiv/backendapi/user/UserDto.java
+++ b/backend/src/main/java/cz/zcu/kiv/backendapi/user/UserDto.java
@@ -1,15 +1,21 @@
 package cz.zcu.kiv.backendapi.user;
 
-import com.sun.istack.NotNull;
+import cz.zcu.kiv.backendapi.password.PasswordDto;
+import cz.zcu.kiv.backendapi.validation.PasswordMatches;
 import cz.zcu.kiv.backendapi.validation.ValidEmail;
 import lombok.Data;
+import premission.PermissionDto;
 
+import javax.validation.Valid;
 import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
+
 
 /**
  * User data object
  */
 @Data
+@PasswordMatches
 public class UserDto {
     /**
      * Name
@@ -20,24 +26,24 @@ public class UserDto {
      * Email - must be valid email
      */
     @ValidEmail
-    @NotNull
+    @NotNull(message = "Email must not be null")
     @NotEmpty(message = "Email must not be empty")
     private String email;
 
     /**
-     * Whether user has 'READ' authority
+     * Permissions
      */
-    private boolean canRead;
+    @Valid
+    private PermissionDto permissions;
 
-    /**
-     * Whether user has 'WRITE' authority
-     */
-    private boolean canWrite;
 
     /**
-     * Whether user has 'DELETE' authority
+     * Password DTO containing password and confirmation password
      */
-    private boolean canDelete;
+    @Valid
+    @NotNull(message = "Passwords must not be null")
+    @NotEmpty(message = "Passwords must not be empty")
+    private PasswordDto passwords;
 
 
 }
\ No newline at end of file
diff --git a/backend/src/main/java/cz/zcu/kiv/backendapi/user/UserServiceImpl.java b/backend/src/main/java/cz/zcu/kiv/backendapi/user/UserServiceImpl.java
index 64a075c..9ce6b4d 100644
--- a/backend/src/main/java/cz/zcu/kiv/backendapi/user/UserServiceImpl.java
+++ b/backend/src/main/java/cz/zcu/kiv/backendapi/user/UserServiceImpl.java
@@ -1,6 +1,7 @@
 package cz.zcu.kiv.backendapi.user;
 
 import cz.zcu.kiv.backendapi.exception.ApiRequestException;
+import cz.zcu.kiv.backendapi.password.PasswordDto;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.http.HttpStatus;
@@ -8,8 +9,10 @@ import org.springframework.security.core.context.SecurityContextHolder;
 import org.springframework.security.core.userdetails.UserDetails;
 import org.springframework.security.core.userdetails.UserDetailsService;
 import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
+import premission.PermissionDto;
 
 import java.util.List;
 import java.util.stream.Collectors;
@@ -32,6 +35,11 @@ public class UserServiceImpl implements IUserService, UserDetailsService {
      */
     private final UserRepository userRepository;
 
+    /**
+     * Password encoder
+     */
+    private final BCryptPasswordEncoder bCryptPasswordEncoder;
+
 
     @Override
     public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
@@ -62,16 +70,26 @@ public class UserServiceImpl implements IUserService, UserDetailsService {
     }
 
     @Override
-    public void updateUser(String username, UserDto userDto) {
+    public void updatePermissions(String username, PermissionDto permissionDto) {
         UserEntity userEntity = userRepository.findByEmail(username).orElseThrow(() ->{
             log.error(String.format(USER_NOT_FOUND, username));
             throw new UsernameNotFoundException(String.format(USER_NOT_FOUND, username));
         });
-        convertDtoToEntity(userDto, userEntity);
+        userEntity.setPermissions(getPermissionsFromDto(permissionDto));
         userEntity.setEmail(username);
         userRepository.save(userEntity);
     }
 
+    @Override
+    public void resetPassword(String username, String newPassword) {
+        UserEntity userEntity = userRepository.findByEmail(username).orElseThrow(() ->{
+            log.error(String.format(USER_NOT_FOUND, username));
+            throw new UsernameNotFoundException(String.format(USER_NOT_FOUND, username));
+        });
+        userEntity.setPassword(bCryptPasswordEncoder.encode(newPassword));
+        userRepository.save(userEntity);
+    }
+
     //TODO maybe check if user is not deleting himself - or it might be ok
     @Override
     public void deleteUser(String username) {
@@ -87,6 +105,18 @@ public class UserServiceImpl implements IUserService, UserDetailsService {
         return userRepository.findAll().stream().map(this::convertEntityToDto).collect(Collectors.toList());
     }
 
+    @Override
+    public void changePassword(String oldPassword, PasswordDto passwordDto) {
+        UserEntity loggedUser = getUserByName((String) SecurityContextHolder.getContext().getAuthentication().getPrincipal());
+        if (!bCryptPasswordEncoder.matches(oldPassword, loggedUser.getPassword())) {
+            throw new ApiRequestException("Old password does not match", HttpStatus.BAD_REQUEST);
+        }
+        loggedUser.setPassword(bCryptPasswordEncoder.encode(passwordDto.getPassword()));
+        userRepository.save(loggedUser);
+    }
+
+
+
     /**
      * Converts user DTO to user entity
      *
@@ -96,7 +126,8 @@ public class UserServiceImpl implements IUserService, UserDetailsService {
     private void convertDtoToEntity(UserDto userDto, UserEntity userEntity) {
         userEntity.setName(userDto.getName());
         userEntity.setEmail(userDto.getEmail());
-        userEntity.setPermissions(getPermissionsFromDto(userDto));
+        userEntity.setPermissions(getPermissionsFromDto(userDto.getPermissions()));
+        userEntity.setPassword(bCryptPasswordEncoder.encode(userDto.getPasswords().getPassword()));
     }
 
     /**
@@ -121,32 +152,34 @@ public class UserServiceImpl implements IUserService, UserDetailsService {
      */
     private void setPermissionsToDto(UserDto userDto, UserEntity userEntity) {
         byte userPermissions = userEntity.getPermissions();
+        PermissionDto permissionDto = new PermissionDto();
         if ((userPermissions & Permission.READ.getBit()) == Permission.READ.getBit()) {
-            userDto.setCanRead(true);
+            permissionDto.setCanRead(true);
         }
         if ((userPermissions & Permission.WRITE.getBit()) == Permission.WRITE.getBit()) {
-            userDto.setCanWrite(true);
+            permissionDto.setCanWrite(true);
         }
         if ((userPermissions & Permission.DELETE.getBit()) == Permission.DELETE.getBit()) {
-            userDto.setCanDelete(true);
+            permissionDto.setCanDelete(true);
         }
+        userDto.setPermissions(permissionDto);
     }
 
     /**
-     * Returns permissions as byte from user DTO
+     * Returns permissions as byte from permission DTO
      *
-     * @param userDto user DTO
+     * @param permissionDto permission DTO
      * @return permissions as byte
      */
-    private byte getPermissionsFromDto(UserDto userDto) {
+    private byte getPermissionsFromDto(PermissionDto permissionDto) {
         byte permissions = (byte) 0;
-        if (userDto.isCanRead()) {
+        if (permissionDto.isCanRead()) {
             permissions |= Permission.READ.getBit();
         }
-        if (userDto.isCanWrite()) {
+        if (permissionDto.isCanWrite()) {
             permissions |= Permission.WRITE.getBit();
         }
-        if (userDto.isCanDelete()) {
+        if (permissionDto.isCanDelete()) {
             permissions |= Permission.DELETE.getBit();
         }
         return permissions;
diff --git a/backend/src/main/java/cz/zcu/kiv/backendapi/validation/EmailValidator.java b/backend/src/main/java/cz/zcu/kiv/backendapi/validation/EmailValidator.java
index 8d45d5b..2a20bd4 100644
--- a/backend/src/main/java/cz/zcu/kiv/backendapi/validation/EmailValidator.java
+++ b/backend/src/main/java/cz/zcu/kiv/backendapi/validation/EmailValidator.java
@@ -28,6 +28,9 @@ public class EmailValidator implements ConstraintValidator<ValidEmail, String> {
      */
     @Override
     public boolean isValid(final String email, final ConstraintValidatorContext constraintValidatorContext) {
+        if (email == null) {
+            return false;
+        }
         final Matcher matcher = PATTERN.matcher(email);
         return matcher.matches();
     }
diff --git a/backend/src/main/java/cz/zcu/kiv/backendapi/validation/PasswordMatches.java b/backend/src/main/java/cz/zcu/kiv/backendapi/validation/PasswordMatches.java
new file mode 100644
index 0000000..51930b0
--- /dev/null
+++ b/backend/src/main/java/cz/zcu/kiv/backendapi/validation/PasswordMatches.java
@@ -0,0 +1,25 @@
+package cz.zcu.kiv.backendapi.validation;
+
+import javax.validation.Constraint;
+import javax.validation.Payload;
+import java.lang.annotation.*;
+
+/**
+ * Constraint to password matches confirmation password
+ */
+@Target({ElementType.TYPE, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+@Constraint(validatedBy = PasswordMatchesValidator.class)
+@Documented
+public @interface PasswordMatches {
+    /**
+     * Error message when validation fails
+     *
+     * @return error message
+     */
+    String message() default "Passwords do not match";
+
+    Class<?>[] groups() default {};
+
+    Class<? extends Payload>[] payload() default {};
+}
diff --git a/backend/src/main/java/cz/zcu/kiv/backendapi/validation/PasswordMatchesValidator.java b/backend/src/main/java/cz/zcu/kiv/backendapi/validation/PasswordMatchesValidator.java
new file mode 100644
index 0000000..76c08e9
--- /dev/null
+++ b/backend/src/main/java/cz/zcu/kiv/backendapi/validation/PasswordMatchesValidator.java
@@ -0,0 +1,27 @@
+package cz.zcu.kiv.backendapi.validation;
+
+import cz.zcu.kiv.backendapi.password.PasswordDto;
+
+import javax.validation.ConstraintValidator;
+import javax.validation.ConstraintValidatorContext;
+
+/**
+ * Validator for password and confirmation password
+ */
+public class PasswordMatchesValidator implements ConstraintValidator<PasswordMatches, PasswordDto> {
+
+    /**
+     * Checks if password and confirmation password match
+     *
+     * @param passwordDto                password DTO
+     * @param constraintValidatorContext constraint validator context
+     * @return true if passwords matches, false otherwise
+     */
+    @Override
+    public boolean isValid(final PasswordDto passwordDto, final ConstraintValidatorContext constraintValidatorContext) {
+        if (passwordDto.getPassword() == null || passwordDto.getConfirmationPassword() == null) {
+            return false;
+        }
+        return passwordDto.getPassword().equals(passwordDto.getConfirmationPassword());
+    }
+}
diff --git a/backend/src/main/java/cz/zcu/kiv/backendapi/writtenform/WrittenForm.java b/backend/src/main/java/cz/zcu/kiv/backendapi/writtenform/WrittenForm.java
new file mode 100644
index 0000000..8d98d74
--- /dev/null
+++ b/backend/src/main/java/cz/zcu/kiv/backendapi/writtenform/WrittenForm.java
@@ -0,0 +1,31 @@
+package cz.zcu.kiv.backendapi.writtenform;
+
+import cz.zcu.kiv.backendapi.catalog.CatalogEntry;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.persistence.*;
+import java.io.Serializable;
+
+/**
+ * Written form entity representing written form of geographic entry
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Entity
+@Table(name = "written_forms")
+@IdClass(WrittenForm.class)
+public class WrittenForm implements Serializable {
+    /**
+     * Written form, serves as ID
+     */
+    @Id
+    private String form;
+
+    @ManyToOne
+    @JoinColumn(name = "catalog_id")
+    @Id
+    private CatalogEntry catalog;
+}
diff --git a/backend/src/main/java/cz/zcu/kiv/backendapi/writtenform/WrittenFormEntity.java b/backend/src/main/java/cz/zcu/kiv/backendapi/writtenform/WrittenFormEntity.java
deleted file mode 100644
index ff1a117..0000000
--- a/backend/src/main/java/cz/zcu/kiv/backendapi/writtenform/WrittenFormEntity.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package cz.zcu.kiv.backendapi.writtenform;
-
-import cz.zcu.kiv.backendapi.catalog.CatalogEntity;
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import javax.persistence.*;
-import java.io.Serializable;
-
-/**
- * Written form entity representing written form of geographic entry
- */
-@Data
-@NoArgsConstructor
-@AllArgsConstructor
-@Entity
-@Table(name = "written_forms")
-@IdClass(WrittenFormEntity.class)
-public class WrittenFormEntity implements Serializable {
-    /**
-     * Written form, serves as ID
-     */
-    @Id
-    private String form;
-
-    @ManyToOne
-    @JoinColumn(name = "catalog_id")
-    @Id
-    private CatalogEntity catalog;
-}
diff --git a/backend/src/main/java/cz/zcu/kiv/backendapi/writtenform/WrittenFormRepository.java b/backend/src/main/java/cz/zcu/kiv/backendapi/writtenform/WrittenFormRepository.java
index 5965847..63d0c46 100644
--- a/backend/src/main/java/cz/zcu/kiv/backendapi/writtenform/WrittenFormRepository.java
+++ b/backend/src/main/java/cz/zcu/kiv/backendapi/writtenform/WrittenFormRepository.java
@@ -9,5 +9,5 @@ import org.springframework.transaction.annotation.Transactional;
  */
 @Repository
 @Transactional(readOnly = true)
-public interface WrittenFormRepository extends JpaRepository<WrittenFormEntity, WrittenFormEntity> {
+public interface WrittenFormRepository extends JpaRepository<WrittenForm, WrittenForm> {
 }
diff --git a/backend/src/main/java/premission/PermissionDto.java b/backend/src/main/java/premission/PermissionDto.java
new file mode 100644
index 0000000..1b0812a
--- /dev/null
+++ b/backend/src/main/java/premission/PermissionDto.java
@@ -0,0 +1,24 @@
+package premission;
+
+import lombok.Data;
+
+/**
+ * Permission DTO
+ */
+@Data
+public class PermissionDto {
+    /**
+     * Whether user has 'READ' authority
+     */
+    private boolean canRead;
+
+    /**
+     * Whether user has 'WRITE' authority
+     */
+    private boolean canWrite;
+
+    /**
+     * Whether user has 'DELETE' authority
+     */
+    private boolean canDelete;
+}
