Revize e111342b
Přidáno uživatelem Jakub Šmíd před asi 3 roky(ů)
backend/pom.xml | ||
---|---|---|
66 | 66 |
<artifactId>commons-csv</artifactId> |
67 | 67 |
<version>1.9.0</version> |
68 | 68 |
</dependency> |
69 |
|
|
70 |
<dependency> |
|
71 |
<groupId>com.auth0</groupId> |
|
72 |
<artifactId>java-jwt</artifactId> |
|
73 |
<version>3.19.0</version> |
|
74 |
</dependency> |
|
75 |
|
|
76 |
<dependency> |
|
77 |
<groupId>com.google.guava</groupId> |
|
78 |
<artifactId>guava</artifactId> |
|
79 |
<version>31.1-jre</version> |
|
80 |
</dependency> |
|
81 |
|
|
82 |
<dependency> |
|
83 |
<groupId>org.springframework.boot</groupId> |
|
84 |
<artifactId>spring-boot-configuration-processor</artifactId> |
|
85 |
<version>2.4.2</version> |
|
86 |
<optional>true</optional> |
|
87 |
</dependency> |
|
69 | 88 |
</dependencies> |
70 | 89 |
|
71 | 90 |
<build> |
backend/src/main/java/cz/zcu/kiv/backendapi/alternativename/AlternativeNameEntity.java | ||
---|---|---|
1 |
package cz.zcu.kiv.backendapi.alternativename; |
|
2 |
|
|
3 |
import cz.zcu.kiv.backendapi.catalog.CatalogEntity; |
|
4 |
import lombok.AllArgsConstructor; |
|
5 |
import lombok.Data; |
|
6 |
import lombok.NoArgsConstructor; |
|
7 |
|
|
8 |
import javax.persistence.*; |
|
9 |
import java.io.Serializable; |
|
10 |
|
|
11 |
/** |
|
12 |
* Alternative name entity representing alternative name of geographic entry |
|
13 |
*/ |
|
14 |
@Data |
|
15 |
@NoArgsConstructor |
|
16 |
@AllArgsConstructor |
|
17 |
@Entity |
|
18 |
@Table(name = "alternative_names") |
|
19 |
@IdClass(AlternativeNameEntity.class) |
|
20 |
public class AlternativeNameEntity implements Serializable { |
|
21 |
/** |
|
22 |
* Name, serves as ID |
|
23 |
*/ |
|
24 |
@Id |
|
25 |
private String name; |
|
26 |
|
|
27 |
/** |
|
28 |
* Catalog entity |
|
29 |
*/ |
|
30 |
@ManyToOne |
|
31 |
@JoinColumn(name = "catalog_id") |
|
32 |
@Id |
|
33 |
private CatalogEntity catalog; |
|
34 |
} |
backend/src/main/java/cz/zcu/kiv/backendapi/alternativename/AlternativeNameRepository.java | ||
---|---|---|
1 |
package cz.zcu.kiv.backendapi.alternativename; |
|
2 |
|
|
3 |
import org.springframework.data.jpa.repository.JpaRepository; |
|
4 |
import org.springframework.stereotype.Repository; |
|
5 |
import org.springframework.transaction.annotation.Transactional; |
|
6 |
|
|
7 |
/** |
|
8 |
* Alternative name repository |
|
9 |
*/ |
|
10 |
@Repository |
|
11 |
@Transactional(readOnly = true) |
|
12 |
public interface AlternativeNameRepository extends JpaRepository<AlternativeNameEntity, AlternativeNameEntity> { |
|
13 |
} |
backend/src/main/java/cz/zcu/kiv/backendapi/alternativename/AlternativeNameServiceImpl.java | ||
---|---|---|
1 |
package cz.zcu.kiv.backendapi.alternativename; |
|
2 |
|
|
3 |
import lombok.RequiredArgsConstructor; |
|
4 |
import org.springframework.stereotype.Service; |
|
5 |
import org.springframework.transaction.annotation.Transactional; |
|
6 |
|
|
7 |
/** |
|
8 |
* Alternative name service implementation |
|
9 |
*/ |
|
10 |
@Service |
|
11 |
@Transactional |
|
12 |
@RequiredArgsConstructor |
|
13 |
public class AlternativeNameServiceImpl implements IAlternativeNameService { |
|
14 |
|
|
15 |
/** |
|
16 |
* Alternative name repository |
|
17 |
*/ |
|
18 |
private final AlternativeNameRepository alternativeNameRepository; |
|
19 |
} |
backend/src/main/java/cz/zcu/kiv/backendapi/alternativename/IAlternativeNameService.java | ||
---|---|---|
1 |
package cz.zcu.kiv.backendapi.alternativename; |
|
2 |
|
|
3 |
/** |
|
4 |
* Alternative name service interface |
|
5 |
*/ |
|
6 |
public interface IAlternativeNameService { |
|
7 |
} |
backend/src/main/java/cz/zcu/kiv/backendapi/bibliography/BibliographyEntity.java | ||
---|---|---|
1 |
package cz.zcu.kiv.backendapi.bibliography; |
|
2 |
|
|
3 |
import cz.zcu.kiv.backendapi.catalog.CatalogEntity; |
|
4 |
import lombok.AllArgsConstructor; |
|
5 |
import lombok.Data; |
|
6 |
import lombok.NoArgsConstructor; |
|
7 |
|
|
8 |
import javax.persistence.*; |
|
9 |
import java.io.Serializable; |
|
10 |
|
|
11 |
/** |
|
12 |
* Bibliography entity representing bibliography |
|
13 |
*/ |
|
14 |
@Data |
|
15 |
@NoArgsConstructor |
|
16 |
@AllArgsConstructor |
|
17 |
@Entity |
|
18 |
@Table(name = "bibliography") |
|
19 |
@IdClass(BibliographyEntity.class) |
|
20 |
public class BibliographyEntity implements Serializable { |
|
21 |
/** |
|
22 |
* Source, serves as ID |
|
23 |
*/ |
|
24 |
@Id |
|
25 |
private String source; |
|
26 |
|
|
27 |
@ManyToOne |
|
28 |
@JoinColumn(name = "catalog_id") |
|
29 |
private CatalogEntity catalog; |
|
30 |
} |
backend/src/main/java/cz/zcu/kiv/backendapi/bibliography/BibliographyRepository.java | ||
---|---|---|
1 |
package cz.zcu.kiv.backendapi.bibliography; |
|
2 |
|
|
3 |
import org.springframework.data.jpa.repository.JpaRepository; |
|
4 |
import org.springframework.stereotype.Repository; |
|
5 |
import org.springframework.transaction.annotation.Transactional; |
|
6 |
|
|
7 |
/** |
|
8 |
* Bibliography repository |
|
9 |
*/ |
|
10 |
@Repository |
|
11 |
@Transactional(readOnly = true) |
|
12 |
public interface BibliographyRepository extends JpaRepository<BibliographyEntity, BibliographyEntity> { |
|
13 |
} |
backend/src/main/java/cz/zcu/kiv/backendapi/bibliography/BibliographyServiceImpl.java | ||
---|---|---|
1 |
package cz.zcu.kiv.backendapi.bibliography; |
|
2 |
|
|
3 |
import lombok.RequiredArgsConstructor; |
|
4 |
import org.springframework.stereotype.Service; |
|
5 |
import org.springframework.transaction.annotation.Transactional; |
|
6 |
|
|
7 |
/** |
|
8 |
* Bibliography service implementation |
|
9 |
*/ |
|
10 |
@Service |
|
11 |
@Transactional |
|
12 |
@RequiredArgsConstructor |
|
13 |
public class BibliographyServiceImpl implements IBibliographyService { |
|
14 |
/** |
|
15 |
* Bibliography repository |
|
16 |
*/ |
|
17 |
private final BibliographyRepository bibliographyRepository; |
|
18 |
} |
backend/src/main/java/cz/zcu/kiv/backendapi/bibliography/IBibliographyService.java | ||
---|---|---|
1 |
package cz.zcu.kiv.backendapi.bibliography; |
|
2 |
|
|
3 |
/** |
|
4 |
* Bibliography service interface |
|
5 |
*/ |
|
6 |
public interface IBibliographyService { |
|
7 |
} |
backend/src/main/java/cz/zcu/kiv/backendapi/catalog/CatalogEntity.java | ||
---|---|---|
1 |
package cz.zcu.kiv.backendapi.catalog; |
|
2 |
|
|
3 |
import cz.zcu.kiv.backendapi.alternativename.AlternativeNameEntity; |
|
4 |
import cz.zcu.kiv.backendapi.bibliography.BibliographyEntity; |
|
5 |
import cz.zcu.kiv.backendapi.country.CountryEntity; |
|
6 |
import cz.zcu.kiv.backendapi.type.TypeEntity; |
|
7 |
import cz.zcu.kiv.backendapi.writtenform.WrittenFormEntity; |
|
8 |
import lombok.Getter; |
|
9 |
import lombok.NoArgsConstructor; |
|
10 |
import lombok.Setter; |
|
11 |
import org.hibernate.annotations.LazyCollection; |
|
12 |
import org.hibernate.annotations.LazyCollectionOption; |
|
13 |
|
|
14 |
import javax.persistence.*; |
|
15 |
import java.util.*; |
|
16 |
import java.util.regex.Matcher; |
|
17 |
import java.util.regex.Pattern; |
|
18 |
import java.util.stream.Collectors; |
|
19 |
|
|
20 |
/** |
|
21 |
* Catalog entity representing catalog |
|
22 |
*/ |
|
23 |
//@Data |
|
24 |
@Getter |
|
25 |
@Setter |
|
26 |
@NoArgsConstructor |
|
27 |
@Entity |
|
28 |
@Table(name = "catalog") |
|
29 |
public class CatalogEntity { |
|
30 |
private static final String INTEGER_PATTERN = "\\d+"; |
|
31 |
private static final String DOUBLE_PATTERN = "(\\d+[.]\\d+)|(\\d+)"; |
|
32 |
private static final String EMPTY_ENTRY = "–"; |
|
33 |
/** |
|
34 |
* Catalog entry id |
|
35 |
*/ |
|
36 |
@Id |
|
37 |
@GeneratedValue |
|
38 |
private UUID id; |
|
39 |
|
|
40 |
/** |
|
41 |
* Name of geographic entry |
|
42 |
*/ |
|
43 |
private String name; |
|
44 |
|
|
45 |
/** |
|
46 |
* Certainty |
|
47 |
*/ |
|
48 |
private int certainty; |
|
49 |
|
|
50 |
/** |
|
51 |
* Longitude |
|
52 |
*/ |
|
53 |
private double longitude; |
|
54 |
|
|
55 |
/** |
|
56 |
* Latitude |
|
57 |
*/ |
|
58 |
private double latitude; |
|
59 |
|
|
60 |
/** |
|
61 |
* Bibliography |
|
62 |
*/ |
|
63 |
@OneToMany(mappedBy = "catalog", cascade = CascadeType.ALL) |
|
64 |
@LazyCollection(LazyCollectionOption.FALSE) |
|
65 |
private Set<BibliographyEntity> bibliography; |
|
66 |
|
|
67 |
/** |
|
68 |
* Countries |
|
69 |
*/ |
|
70 |
@OneToMany(mappedBy = "catalog", cascade = CascadeType.ALL) |
|
71 |
@LazyCollection(LazyCollectionOption.FALSE) |
|
72 |
private Set<CountryEntity> countries; |
|
73 |
|
|
74 |
/** |
|
75 |
* Written forms |
|
76 |
*/ |
|
77 |
@OneToMany(mappedBy = "catalog", cascade = CascadeType.ALL) |
|
78 |
@LazyCollection(LazyCollectionOption.FALSE) |
|
79 |
private Set<WrittenFormEntity> writtenForms; |
|
80 |
|
|
81 |
/** |
|
82 |
* Alternative name |
|
83 |
*/ |
|
84 |
@OneToMany(mappedBy = "catalog", cascade = CascadeType.ALL) |
|
85 |
@LazyCollection(LazyCollectionOption.FALSE) |
|
86 |
private Set<AlternativeNameEntity> alternativeNames; |
|
87 |
|
|
88 |
/** |
|
89 |
* Set of user roles - many-to-many relationship |
|
90 |
*/ |
|
91 |
@ManyToMany(fetch = FetchType.EAGER) |
|
92 |
@JoinTable( |
|
93 |
name = "catalog_type", |
|
94 |
joinColumns = { |
|
95 |
@JoinColumn(name = "catalog_id", referencedColumnName = "id") |
|
96 |
}, |
|
97 |
inverseJoinColumns = { |
|
98 |
@JoinColumn(name = "type", referencedColumnName = "type") |
|
99 |
} |
|
100 |
) |
|
101 |
private Set<TypeEntity> types = Collections.emptySet(); |
|
102 |
|
|
103 |
public CatalogEntity(final List<String> csvFields) { |
|
104 |
|
|
105 |
this.name = csvFields.get(1); |
|
106 |
List<String> stringList = processListField(csvFields.get(2)); |
|
107 |
this.alternativeNames = new HashSet<>(stringList.size()); |
|
108 |
for (String s : stringList) { |
|
109 |
this.alternativeNames.add(new AlternativeNameEntity(s, this)); |
|
110 |
} |
|
111 |
this.certainty = processIntField(csvFields.get(3)); |
|
112 |
this.latitude = processDoubleField(csvFields.get(4)); |
|
113 |
this.longitude = processDoubleField(csvFields.get(5)); |
|
114 |
stringList = processListField(csvFields.get(6)); |
|
115 |
this.writtenForms = new HashSet<>(stringList.size()); |
|
116 |
for (String s : stringList) { |
|
117 |
this.writtenForms.add(new WrittenFormEntity(s, this)); |
|
118 |
} |
|
119 |
stringList = processListField(csvFields.get(7)); |
|
120 |
this.types = new HashSet<>(stringList.size()); |
|
121 |
for (String s : stringList) { |
|
122 |
this.types.add(new TypeEntity(s)); |
|
123 |
} |
|
124 |
stringList = processListField(csvFields.get(8)); |
|
125 |
this.countries = new HashSet<>(stringList.size()); |
|
126 |
for (String s : stringList) { |
|
127 |
this.countries.add(new CountryEntity(s, this)); |
|
128 |
} |
|
129 |
stringList = processListField(csvFields.get(10)); |
|
130 |
this.bibliography = new HashSet<>(stringList.size()); |
|
131 |
for (String s : stringList) { |
|
132 |
this.bibliography.add(new BibliographyEntity(s, this)); |
|
133 |
} |
|
134 |
} |
|
135 |
|
|
136 |
private int processIntField(String field) { |
|
137 |
Matcher matcher = Pattern.compile(INTEGER_PATTERN).matcher(field); |
|
138 |
if (matcher.find()) { |
|
139 |
return Integer.parseInt(matcher.group()); |
|
140 |
} else { |
|
141 |
return 0; |
|
142 |
} |
|
143 |
} |
|
144 |
|
|
145 |
private double processDoubleField(String field) { |
|
146 |
Matcher matcher = Pattern.compile(DOUBLE_PATTERN).matcher(field); |
|
147 |
if (matcher.find()) { |
|
148 |
return Double.parseDouble(matcher.group()); |
|
149 |
} else { |
|
150 |
return 0.0; |
|
151 |
} |
|
152 |
} |
|
153 |
|
|
154 |
private List<String> processListField(String field) { |
|
155 |
if (field.isEmpty() || field.equals(EMPTY_ENTRY)) { |
|
156 |
return new ArrayList<>(); |
|
157 |
} |
|
158 |
return Arrays.stream(field.split(",")).map(String::trim).filter(item -> !item.isEmpty()).collect(Collectors.toList()); |
|
159 |
} |
|
160 |
} |
backend/src/main/java/cz/zcu/kiv/backendapi/catalog/CatalogRepository.java | ||
---|---|---|
1 |
package cz.zcu.kiv.backendapi.catalog; |
|
2 |
|
|
3 |
import org.springframework.data.jpa.repository.JpaRepository; |
|
4 |
import org.springframework.data.jpa.repository.Query; |
|
5 |
import org.springframework.stereotype.Repository; |
|
6 |
import org.springframework.transaction.annotation.Transactional; |
|
7 |
|
|
8 |
import java.util.List; |
|
9 |
import java.util.UUID; |
|
10 |
|
|
11 |
/** |
|
12 |
* Catalog repository |
|
13 |
*/ |
|
14 |
@Repository |
|
15 |
@Transactional(readOnly = true) |
|
16 |
public interface CatalogRepository extends JpaRepository<CatalogEntity, UUID> { |
|
17 |
|
|
18 |
/** |
|
19 |
* Selects all catalog entries with given name or where given name appears in alternative names |
|
20 |
* @param name name |
|
21 |
* @return list of catalog entries with given name / alternative name |
|
22 |
*/ |
|
23 |
@Query("SELECT DISTINCT c FROM CatalogEntity c LEFT JOIN AlternativeNameEntity a ON c = a.catalog WHERE (?1 = c.name OR ?1 = a.name)") |
|
24 |
List<CatalogEntity> getCatalogEntitiesByName(String name); |
|
25 |
} |
backend/src/main/java/cz/zcu/kiv/backendapi/catalog/CatalogServiceImpl.java | ||
---|---|---|
1 |
package cz.zcu.kiv.backendapi.catalog; |
|
2 |
|
|
3 |
import cz.zcu.kiv.backendapi.type.TypeEntity; |
|
4 |
import cz.zcu.kiv.backendapi.type.ITypeService; |
|
5 |
import lombok.RequiredArgsConstructor; |
|
6 |
import org.springframework.stereotype.Service; |
|
7 |
import org.springframework.transaction.annotation.Transactional; |
|
8 |
|
|
9 |
import java.util.List; |
|
10 |
|
|
11 |
/** |
|
12 |
* Catalog service implementation |
|
13 |
*/ |
|
14 |
@Service |
|
15 |
@Transactional |
|
16 |
@RequiredArgsConstructor |
|
17 |
public class CatalogServiceImpl implements ICatalogService { |
|
18 |
/** |
|
19 |
* Catalog repository |
|
20 |
*/ |
|
21 |
private final CatalogRepository catalogRepository; |
|
22 |
|
|
23 |
private final ITypeService typeService; |
|
24 |
|
|
25 |
@Override |
|
26 |
public void saveCatalog(List<CatalogEntity> catalogEntities) { |
|
27 |
for (CatalogEntity catalogEntity : catalogEntities) { |
|
28 |
for (TypeEntity type: catalogEntity.getTypes() ) { |
|
29 |
|
|
30 |
if (typeService.getTypeByName(type.getType()).isEmpty()){ |
|
31 |
typeService.saveType(type); |
|
32 |
} |
|
33 |
} |
|
34 |
} |
|
35 |
catalogRepository.saveAll(catalogEntities); |
|
36 |
} |
|
37 |
} |
backend/src/main/java/cz/zcu/kiv/backendapi/catalog/ICatalogService.java | ||
---|---|---|
1 |
package cz.zcu.kiv.backendapi.catalog; |
|
2 |
|
|
3 |
import java.util.List; |
|
4 |
|
|
5 |
/** |
|
6 |
* Catalog service interface |
|
7 |
*/ |
|
8 |
public interface ICatalogService { |
|
9 |
void saveCatalog(List<CatalogEntity> catalogEntities); |
|
10 |
} |
backend/src/main/java/cz/zcu/kiv/backendapi/config/DataInitiator.java | ||
---|---|---|
1 | 1 |
package cz.zcu.kiv.backendapi.config; |
2 | 2 |
|
3 |
import cz.zcu.kiv.backendapi.model.CatalogEntity; |
|
4 |
import cz.zcu.kiv.backendapi.service.catalog.ICatalogService; |
|
3 |
import cz.zcu.kiv.backendapi.catalog.CatalogEntity; |
|
4 |
import cz.zcu.kiv.backendapi.type.TypeEntity; |
|
5 |
import cz.zcu.kiv.backendapi.catalog.CatalogRepository; |
|
6 |
import cz.zcu.kiv.backendapi.catalog.ICatalogService; |
|
7 |
import cz.zcu.kiv.backendapi.type.ITypeService; |
|
8 |
import cz.zcu.kiv.backendapi.user.UserEntity; |
|
9 |
import cz.zcu.kiv.backendapi.user.UserRepository; |
|
5 | 10 |
import lombok.RequiredArgsConstructor; |
6 | 11 |
import org.apache.commons.csv.CSVFormat; |
7 | 12 |
import org.apache.commons.csv.CSVParser; |
8 | 13 |
import org.apache.commons.csv.CSVRecord; |
9 | 14 |
import org.springframework.context.ApplicationListener; |
10 | 15 |
import org.springframework.context.event.ContextRefreshedEvent; |
16 |
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; |
|
11 | 17 |
import org.springframework.stereotype.Component; |
12 | 18 |
import org.springframework.transaction.annotation.Transactional; |
13 | 19 |
|
14 | 20 |
import java.io.File; |
15 | 21 |
import java.io.IOException; |
22 |
import java.nio.charset.Charset; |
|
16 | 23 |
import java.nio.charset.StandardCharsets; |
17 | 24 |
import java.util.ArrayList; |
18 | 25 |
import java.util.List; |
... | ... | |
24 | 31 |
|
25 | 32 |
private final ICatalogService catalogService; |
26 | 33 |
|
34 |
private final ITypeService typeService; |
|
35 |
|
|
36 |
private final CatalogRepository catalogRepository; |
|
37 |
|
|
38 |
private final UserRepository userRepository; |
|
39 |
|
|
40 |
private final BCryptPasswordEncoder encoder; |
|
41 |
|
|
27 | 42 |
@Override |
28 | 43 |
@Transactional |
29 | 44 |
public void onApplicationEvent(ContextRefreshedEvent event) { |
45 |
List<TypeEntity> types = loadTypes(); |
|
46 |
typeService.saveTypes(types); |
|
30 | 47 |
List<CatalogEntity> catalog = loadCatalog(); |
31 | 48 |
catalogService.saveCatalog(catalog); |
32 | 49 |
|
50 |
UserEntity user1 = new UserEntity("admin", "admin", encoder.encode("password"), (byte) 7, true); |
|
51 |
userRepository.save(user1); |
|
52 |
|
|
53 |
UserEntity user2 = new UserEntity("normal", "normal", encoder.encode("password"), (byte) 1, false); |
|
54 |
userRepository.save(user2); |
|
55 |
|
|
33 | 56 |
} |
34 | 57 |
|
35 | 58 |
private List<CatalogEntity> loadCatalog() { |
... | ... | |
50 | 73 |
return catalogEntities; |
51 | 74 |
|
52 | 75 |
} |
76 |
|
|
77 |
private List<TypeEntity> loadTypes() { |
|
78 |
List<TypeEntity> types = new ArrayList<>(); |
|
79 |
CSVParser parser; |
|
80 |
File csvData = new File("AssyrianProject-All.csv"); |
|
81 |
try { |
|
82 |
parser = CSVParser.parse(csvData, Charset.defaultCharset(), CSVFormat.DEFAULT.builder().setSkipHeaderRecord(true).build()); |
|
83 |
for (CSVRecord csvRecord : parser) { |
|
84 |
if (csvRecord.get(0).equals("10000")) { |
|
85 |
types.add(new TypeEntity(csvRecord.get(2))); |
|
86 |
} |
|
87 |
} |
|
88 |
} catch (IOException e) { |
|
89 |
e.printStackTrace(); |
|
90 |
} |
|
91 |
return types; |
|
92 |
} |
|
53 | 93 |
} |
backend/src/main/java/cz/zcu/kiv/backendapi/country/CountryEntity.java | ||
---|---|---|
1 |
package cz.zcu.kiv.backendapi.country; |
|
2 |
|
|
3 |
import cz.zcu.kiv.backendapi.catalog.CatalogEntity; |
|
4 |
import lombok.AllArgsConstructor; |
|
5 |
import lombok.Data; |
|
6 |
import lombok.NoArgsConstructor; |
|
7 |
|
|
8 |
import javax.persistence.*; |
|
9 |
import java.io.Serializable; |
|
10 |
|
|
11 |
/** |
|
12 |
* Country entity representing country of geographic entry |
|
13 |
*/ |
|
14 |
@Data |
|
15 |
@NoArgsConstructor |
|
16 |
@AllArgsConstructor |
|
17 |
@Entity |
|
18 |
@Table(name = "countries") |
|
19 |
@IdClass(CountryEntity.class) |
|
20 |
public class CountryEntity implements Serializable { |
|
21 |
/** |
|
22 |
* Name of country, serves as ID |
|
23 |
*/ |
|
24 |
@Id |
|
25 |
private String name; |
|
26 |
|
|
27 |
@ManyToOne |
|
28 |
@JoinColumn(name = "catalog_id") |
|
29 |
@Id |
|
30 |
private CatalogEntity catalog; |
|
31 |
} |
backend/src/main/java/cz/zcu/kiv/backendapi/country/CountryRepository.java | ||
---|---|---|
1 |
package cz.zcu.kiv.backendapi.country; |
|
2 |
|
|
3 |
import org.springframework.data.jpa.repository.JpaRepository; |
|
4 |
import org.springframework.stereotype.Repository; |
|
5 |
import org.springframework.transaction.annotation.Transactional; |
|
6 |
|
|
7 |
/** |
|
8 |
* Country repository |
|
9 |
*/ |
|
10 |
@Repository |
|
11 |
@Transactional(readOnly = true) |
|
12 |
public interface CountryRepository extends JpaRepository<CountryEntity, CountryEntity> { |
|
13 |
} |
backend/src/main/java/cz/zcu/kiv/backendapi/country/CountryServiceImpl.java | ||
---|---|---|
1 |
package cz.zcu.kiv.backendapi.country; |
|
2 |
|
|
3 |
import lombok.RequiredArgsConstructor; |
|
4 |
import org.springframework.stereotype.Service; |
|
5 |
import org.springframework.transaction.annotation.Transactional; |
|
6 |
|
|
7 |
/** |
|
8 |
* Country service implementation |
|
9 |
*/ |
|
10 |
@Service |
|
11 |
@Transactional |
|
12 |
@RequiredArgsConstructor |
|
13 |
public class CountryServiceImpl implements ICountryService { |
|
14 |
|
|
15 |
/** |
|
16 |
* Country repository |
|
17 |
*/ |
|
18 |
private final CountryRepository countryRepository; |
|
19 |
} |
backend/src/main/java/cz/zcu/kiv/backendapi/country/ICountryService.java | ||
---|---|---|
1 |
package cz.zcu.kiv.backendapi.country; |
|
2 |
|
|
3 |
/** |
|
4 |
* Country service interface |
|
5 |
*/ |
|
6 |
public interface ICountryService { |
|
7 |
} |
backend/src/main/java/cz/zcu/kiv/backendapi/exception/ApiExceptionHandler.java | ||
---|---|---|
1 |
package cz.zcu.kiv.backendapi.exception; |
|
2 |
|
|
3 |
|
|
4 |
import org.springframework.http.ResponseEntity; |
|
5 |
import org.springframework.web.bind.annotation.ControllerAdvice; |
|
6 |
import org.springframework.web.bind.annotation.ExceptionHandler; |
|
7 |
|
|
8 |
@ControllerAdvice |
|
9 |
public class ApiExceptionHandler { |
|
10 |
|
|
11 |
@ExceptionHandler(value = {ApiRequestException.class}) |
|
12 |
public ResponseEntity<Object> handleApiRequestException(ApiRequestException exception) { |
|
13 |
return new ResponseEntity<>(exception, exception.getHttpStatus()); |
|
14 |
} |
|
15 |
} |
backend/src/main/java/cz/zcu/kiv/backendapi/exception/ApiRequestException.java | ||
---|---|---|
1 |
package cz.zcu.kiv.backendapi.exception; |
|
2 |
|
|
3 |
import lombok.Getter; |
|
4 |
import org.springframework.http.HttpStatus; |
|
5 |
|
|
6 |
@Getter |
|
7 |
public class ApiRequestException extends RuntimeException { |
|
8 |
private final HttpStatus httpStatus; |
|
9 |
|
|
10 |
public ApiRequestException(String message, HttpStatus httpStatus) { |
|
11 |
super(message); |
|
12 |
this.httpStatus = httpStatus; |
|
13 |
} |
|
14 |
|
|
15 |
public ApiRequestException(String message, Throwable cause, HttpStatus httpStatus) { |
|
16 |
super(message, cause); |
|
17 |
this.httpStatus = httpStatus; |
|
18 |
} |
|
19 |
} |
backend/src/main/java/cz/zcu/kiv/backendapi/model/AlternativeNameEntity.java | ||
---|---|---|
1 |
package cz.zcu.kiv.backendapi.model; |
|
2 |
|
|
3 |
import lombok.AllArgsConstructor; |
|
4 |
import lombok.Data; |
|
5 |
import lombok.NoArgsConstructor; |
|
6 |
|
|
7 |
import javax.persistence.*; |
|
8 |
import java.io.Serializable; |
|
9 |
import java.util.UUID; |
|
10 |
|
|
11 |
/** |
|
12 |
* Alternative name entity representing alternative name of geographic entry |
|
13 |
*/ |
|
14 |
@Data |
|
15 |
@NoArgsConstructor |
|
16 |
@AllArgsConstructor |
|
17 |
@Entity |
|
18 |
@Table(name = "alternative_names") |
|
19 |
@IdClass(AlternativeNameEntity.class) |
|
20 |
public class AlternativeNameEntity implements Serializable { |
|
21 |
/** |
|
22 |
* Name, serves as ID |
|
23 |
*/ |
|
24 |
@Id |
|
25 |
private String name; |
|
26 |
|
|
27 |
/** |
|
28 |
* Catalog entity |
|
29 |
*/ |
|
30 |
@ManyToOne |
|
31 |
@JoinColumn(name = "catalog_id") |
|
32 |
@Id |
|
33 |
private CatalogEntity catalog; |
|
34 |
} |
backend/src/main/java/cz/zcu/kiv/backendapi/model/BibliographyEntity.java | ||
---|---|---|
1 |
package cz.zcu.kiv.backendapi.model; |
|
2 |
|
|
3 |
import lombok.AllArgsConstructor; |
|
4 |
import lombok.Data; |
|
5 |
import lombok.NoArgsConstructor; |
|
6 |
|
|
7 |
import javax.persistence.*; |
|
8 |
import java.io.Serializable; |
|
9 |
|
|
10 |
/** |
|
11 |
* Bibliography entity representing bibliography |
|
12 |
*/ |
|
13 |
@Data |
|
14 |
@NoArgsConstructor |
|
15 |
@AllArgsConstructor |
|
16 |
@Entity |
|
17 |
@Table(name = "bibliography") |
|
18 |
@IdClass(BibliographyEntity.class) |
|
19 |
public class BibliographyEntity implements Serializable { |
|
20 |
/** |
|
21 |
* Source, serves as ID |
|
22 |
*/ |
|
23 |
@Id |
|
24 |
private String source; |
|
25 |
|
|
26 |
@ManyToOne |
|
27 |
@JoinColumn(name = "catalog_id") |
|
28 |
private CatalogEntity catalog; |
|
29 |
} |
backend/src/main/java/cz/zcu/kiv/backendapi/model/CatalogEntity.java | ||
---|---|---|
1 |
package cz.zcu.kiv.backendapi.model; |
|
2 |
|
|
3 |
import lombok.Data; |
|
4 |
import lombok.Getter; |
|
5 |
import lombok.NoArgsConstructor; |
|
6 |
import lombok.Setter; |
|
7 |
import org.hibernate.annotations.LazyCollection; |
|
8 |
import org.hibernate.annotations.LazyCollectionOption; |
|
9 |
|
|
10 |
import javax.persistence.*; |
|
11 |
import java.util.*; |
|
12 |
import java.util.regex.Matcher; |
|
13 |
import java.util.regex.Pattern; |
|
14 |
import java.util.stream.Collectors; |
|
15 |
|
|
16 |
/** |
|
17 |
* Catalog entity representing catalog |
|
18 |
*/ |
|
19 |
//@Data |
|
20 |
@Getter |
|
21 |
@Setter |
|
22 |
@NoArgsConstructor |
|
23 |
@Entity |
|
24 |
@Table(name = "catalog") |
|
25 |
public class CatalogEntity { |
|
26 |
private static final String INTEGER_PATTERN = "\\d+"; |
|
27 |
private static final String DOUBLE_PATTERN = "(\\d+[.]\\d+)|(\\d+)"; |
|
28 |
private static final String EMPTY_ENTRY = "–"; |
|
29 |
/** |
|
30 |
* Catalog entry id |
|
31 |
*/ |
|
32 |
@Id |
|
33 |
@GeneratedValue |
|
34 |
private UUID id; |
|
35 |
|
|
36 |
/** |
|
37 |
* Name of geographic entry |
|
38 |
*/ |
|
39 |
private String name; |
|
40 |
|
|
41 |
/** |
|
42 |
* Certainty |
|
43 |
*/ |
|
44 |
private int certainty; |
|
45 |
|
|
46 |
/** |
|
47 |
* Longitude |
|
48 |
*/ |
|
49 |
private double longitude; |
|
50 |
|
|
51 |
/** |
|
52 |
* Latitude |
|
53 |
*/ |
|
54 |
private double latitude; |
|
55 |
|
|
56 |
/** |
|
57 |
* Bibliography |
|
58 |
*/ |
|
59 |
@OneToMany(mappedBy = "catalog", cascade = CascadeType.ALL) |
|
60 |
@LazyCollection(LazyCollectionOption.FALSE) |
|
61 |
private Set<BibliographyEntity> bibliography; |
|
62 |
|
|
63 |
/** |
|
64 |
* Countries |
|
65 |
*/ |
|
66 |
@OneToMany(mappedBy = "catalog", cascade = CascadeType.ALL) |
|
67 |
@LazyCollection(LazyCollectionOption.FALSE) |
|
68 |
private Set<CountryEntity> countries; |
|
69 |
|
|
70 |
/** |
|
71 |
* Written forms |
|
72 |
*/ |
|
73 |
@OneToMany(mappedBy = "catalog", cascade = CascadeType.ALL) |
|
74 |
@LazyCollection(LazyCollectionOption.FALSE) |
|
75 |
private Set<WrittenFormEntity> writtenForms; |
|
76 |
|
|
77 |
/** |
|
78 |
* Alternative name |
|
79 |
*/ |
|
80 |
@OneToMany(mappedBy = "catalog", cascade = CascadeType.ALL) |
|
81 |
@LazyCollection(LazyCollectionOption.FALSE) |
|
82 |
private Set<AlternativeNameEntity> alternativeNames; |
|
83 |
|
|
84 |
/** |
|
85 |
* Set of user roles - many-to-many relationship |
|
86 |
*/ |
|
87 |
@ManyToMany(fetch = FetchType.EAGER) |
|
88 |
@JoinTable( |
|
89 |
name = "catalog_type", |
|
90 |
joinColumns = { |
|
91 |
@JoinColumn(name = "catalog_id", referencedColumnName = "id") |
|
92 |
}, |
|
93 |
inverseJoinColumns = { |
|
94 |
@JoinColumn(name = "type", referencedColumnName = "type") |
|
95 |
} |
|
96 |
) |
|
97 |
private Set<TypeEntity> types = Collections.emptySet(); |
|
98 |
|
|
99 |
public CatalogEntity(final List<String> csvFields) { |
|
100 |
|
|
101 |
this.name = csvFields.get(1); |
|
102 |
List<String> stringList = processListField(csvFields.get(2)); |
|
103 |
this.alternativeNames = new HashSet<>(stringList.size()); |
|
104 |
for (String s : stringList) { |
|
105 |
this.alternativeNames.add(new AlternativeNameEntity(s, this)); |
|
106 |
} |
|
107 |
this.certainty = processIntField(csvFields.get(3)); |
|
108 |
this.latitude = processDoubleField(csvFields.get(4)); |
|
109 |
this.longitude = processDoubleField(csvFields.get(5)); |
|
110 |
stringList = processListField(csvFields.get(6)); |
|
111 |
this.writtenForms = new HashSet<>(stringList.size()); |
|
112 |
for (String s : stringList) { |
|
113 |
this.writtenForms.add(new WrittenFormEntity(s, this)); |
|
114 |
} |
|
115 |
stringList = processListField(csvFields.get(7)); |
|
116 |
this.types = new HashSet<>(stringList.size()); |
|
117 |
for (String s : stringList) { |
|
118 |
this.types.add(new TypeEntity(s)); |
|
119 |
} |
|
120 |
stringList = processListField(csvFields.get(8)); |
|
121 |
this.countries = new HashSet<>(stringList.size()); |
|
122 |
for (String s : stringList) { |
|
123 |
this.countries.add(new CountryEntity(s, this)); |
|
124 |
} |
|
125 |
stringList = processListField(csvFields.get(10)); |
|
126 |
this.bibliography = new HashSet<>(stringList.size()); |
|
127 |
for (String s : stringList) { |
|
128 |
this.bibliography.add(new BibliographyEntity(s, this)); |
|
129 |
} |
|
130 |
} |
|
131 |
|
|
132 |
private int processIntField(String field) { |
|
133 |
Matcher matcher = Pattern.compile(INTEGER_PATTERN).matcher(field); |
|
134 |
if (matcher.find()) { |
|
135 |
return Integer.parseInt(matcher.group()); |
|
136 |
} else { |
|
137 |
return 0; |
|
138 |
} |
|
139 |
} |
|
140 |
|
|
141 |
private double processDoubleField(String field) { |
|
142 |
Matcher matcher = Pattern.compile(DOUBLE_PATTERN).matcher(field); |
|
143 |
if (matcher.find()) { |
|
144 |
return Double.parseDouble(matcher.group()); |
|
145 |
} else { |
|
146 |
return 0.0; |
|
147 |
} |
|
148 |
} |
|
149 |
|
|
150 |
private List<String> processListField(String field) { |
|
151 |
if (field.isEmpty() || field.equals(EMPTY_ENTRY)) { |
|
152 |
return new ArrayList<>(); |
|
153 |
} |
|
154 |
return Arrays.stream(field.split(",")).map(String::trim).collect(Collectors.toList()); |
|
155 |
} |
|
156 |
} |
backend/src/main/java/cz/zcu/kiv/backendapi/model/CountryEntity.java | ||
---|---|---|
1 |
package cz.zcu.kiv.backendapi.model; |
|
2 |
|
|
3 |
import lombok.AllArgsConstructor; |
|
4 |
import lombok.Data; |
|
5 |
import lombok.NoArgsConstructor; |
|
6 |
|
|
7 |
import javax.persistence.*; |
|
8 |
import java.io.Serializable; |
|
9 |
|
|
10 |
/** |
|
11 |
* Country entity representing country of geographic entry |
|
12 |
*/ |
|
13 |
@Data |
|
14 |
@NoArgsConstructor |
|
15 |
@AllArgsConstructor |
|
16 |
@Entity |
|
17 |
@Table(name = "countries") |
|
18 |
@IdClass(CountryEntity.class) |
|
19 |
public class CountryEntity implements Serializable { |
|
20 |
/** |
|
21 |
* Name of country, serves as ID |
|
22 |
*/ |
|
23 |
@Id |
|
24 |
private String name; |
|
25 |
|
|
26 |
@ManyToOne |
|
27 |
@JoinColumn(name = "catalog_id") |
|
28 |
@Id |
|
29 |
private CatalogEntity catalog; |
|
30 |
} |
backend/src/main/java/cz/zcu/kiv/backendapi/model/Role.java | ||
---|---|---|
1 |
package cz.zcu.kiv.backendapi.model; |
|
2 |
|
|
3 |
import lombok.Getter; |
|
4 |
|
|
5 |
/** |
|
6 |
* Enum for user roles |
|
7 |
*/ |
|
8 |
@Getter |
|
9 |
public enum Role { |
|
10 |
ADMIN("ROLE_ADMIN"), |
|
11 |
USER("ROLE_USER"); |
|
12 |
|
|
13 |
/** |
|
14 |
* Role |
|
15 |
*/ |
|
16 |
private final String role; |
|
17 |
|
|
18 |
/** |
|
19 |
* Creates role |
|
20 |
* |
|
21 |
* @param role role |
|
22 |
*/ |
|
23 |
Role(final String role) { |
|
24 |
this.role = role; |
|
25 |
} |
|
26 |
} |
backend/src/main/java/cz/zcu/kiv/backendapi/model/TypeEntity.java | ||
---|---|---|
1 |
package cz.zcu.kiv.backendapi.model; |
|
2 |
|
|
3 |
import lombok.AllArgsConstructor; |
|
4 |
import lombok.Data; |
|
5 |
import lombok.NoArgsConstructor; |
|
6 |
|
|
7 |
import javax.persistence.Entity; |
|
8 |
import javax.persistence.Id; |
|
9 |
import javax.persistence.Table; |
|
10 |
|
|
11 |
/** |
|
12 |
* Type entity representing type of geographic entry |
|
13 |
*/ |
|
14 |
@Data |
|
15 |
@NoArgsConstructor |
|
16 |
@AllArgsConstructor |
|
17 |
@Entity |
|
18 |
@Table(name = "types") |
|
19 |
public class TypeEntity { |
|
20 |
/** |
|
21 |
* Type (e.g. river), serves as ID |
|
22 |
*/ |
|
23 |
@Id |
|
24 |
private String type; |
|
25 |
} |
backend/src/main/java/cz/zcu/kiv/backendapi/model/UserEntity.java | ||
---|---|---|
1 |
package cz.zcu.kiv.backendapi.model; |
|
2 |
|
|
3 |
import lombok.Data; |
|
4 |
import lombok.NoArgsConstructor; |
|
5 |
import org.hibernate.annotations.Type; |
|
6 |
import org.springframework.security.core.GrantedAuthority; |
|
7 |
import org.springframework.security.core.authority.SimpleGrantedAuthority; |
|
8 |
import org.springframework.security.core.userdetails.UserDetails; |
|
9 |
|
|
10 |
import javax.persistence.*; |
|
11 |
import java.util.ArrayList; |
|
12 |
import java.util.Collection; |
|
13 |
import java.util.List; |
|
14 |
import java.util.UUID; |
|
15 |
|
|
16 |
/** |
|
17 |
* User entity representing application user |
|
18 |
*/ |
|
19 |
@Data |
|
20 |
@NoArgsConstructor |
|
21 |
@Entity |
|
22 |
@Table(name = "users") |
|
23 |
public class UserEntity implements UserDetails { |
|
24 |
/** |
|
25 |
* Name |
|
26 |
*/ |
|
27 |
private String name; |
|
28 |
|
|
29 |
/** |
|
30 |
* Email - serves as username and must be unique - serves as Id |
|
31 |
*/ |
|
32 |
@Id |
|
33 |
private String email; |
|
34 |
|
|
35 |
/** |
|
36 |
* Password |
|
37 |
*/ |
|
38 |
private String password; |
|
39 |
|
|
40 |
/** |
|
41 |
* Whether the user is admin or not |
|
42 |
*/ |
|
43 |
@Column(name = "is_admin") |
|
44 |
@Type(type = "numeric_boolean") |
|
45 |
private boolean isAdmin; |
|
46 |
|
|
47 |
@Override |
|
48 |
public Collection<? extends GrantedAuthority> getAuthorities() { |
|
49 |
final List<GrantedAuthority> authorities = new ArrayList<>(); |
|
50 |
if (isAdmin) { |
|
51 |
authorities.add(new SimpleGrantedAuthority(Role.ADMIN.getRole())); |
|
52 |
} else { |
|
53 |
authorities.add(new SimpleGrantedAuthority(Role.USER.getRole())); |
|
54 |
} |
|
55 |
|
|
56 |
return authorities; |
|
57 |
} |
|
58 |
|
|
59 |
public String getPassword() { |
|
60 |
return password; |
|
61 |
} |
|
62 |
|
|
63 |
@Override |
|
64 |
public String getUsername() { |
|
65 |
return email; |
|
66 |
} |
|
67 |
|
|
68 |
@Override |
|
69 |
public boolean isAccountNonExpired() { |
|
70 |
return true; |
|
71 |
} |
|
72 |
|
|
73 |
@Override |
|
74 |
public boolean isAccountNonLocked() { |
|
75 |
return true; |
|
76 |
} |
|
77 |
|
|
78 |
@Override |
|
79 |
public boolean isCredentialsNonExpired() { |
|
80 |
return true; |
|
81 |
} |
|
82 |
|
|
83 |
@Override |
|
84 |
public boolean isEnabled() { |
|
85 |
return true; |
|
86 |
} |
|
87 |
} |
backend/src/main/java/cz/zcu/kiv/backendapi/model/WrittenFormEntity.java | ||
---|---|---|
1 |
package cz.zcu.kiv.backendapi.model; |
|
2 |
|
|
3 |
import lombok.AllArgsConstructor; |
|
4 |
import lombok.Data; |
|
5 |
import lombok.NoArgsConstructor; |
|
6 |
|
|
7 |
import javax.persistence.*; |
|
8 |
import java.io.Serializable; |
|
9 |
|
|
10 |
/** |
|
11 |
* Written form entity representing written form of geographic entry |
|
12 |
*/ |
|
13 |
@Data |
|
14 |
@NoArgsConstructor |
|
15 |
@AllArgsConstructor |
|
16 |
@Entity |
|
17 |
@Table(name = "written_forms") |
|
18 |
@IdClass(WrittenFormEntity.class) |
|
19 |
public class WrittenFormEntity implements Serializable { |
|
20 |
/** |
|
21 |
* Written form, serves as ID |
|
22 |
*/ |
|
23 |
@Id |
|
24 |
private String form; |
|
25 |
|
|
26 |
@ManyToOne |
|
27 |
@JoinColumn(name = "catalog_id") |
|
28 |
@Id |
|
29 |
private CatalogEntity catalog; |
|
30 |
} |
backend/src/main/java/cz/zcu/kiv/backendapi/repo/AlternativeNameRepository.java | ||
---|---|---|
1 |
package cz.zcu.kiv.backendapi.repo; |
|
2 |
|
|
3 |
import cz.zcu.kiv.backendapi.model.AlternativeNameEntity; |
|
4 |
import org.springframework.data.jpa.repository.JpaRepository; |
|
5 |
import org.springframework.stereotype.Repository; |
|
6 |
import org.springframework.transaction.annotation.Transactional; |
|
7 |
|
|
8 |
/** |
|
9 |
* Alternative name repository |
|
10 |
*/ |
|
11 |
@Repository |
|
12 |
@Transactional(readOnly = true) |
|
13 |
public interface AlternativeNameRepository extends JpaRepository<AlternativeNameEntity, AlternativeNameEntity> { |
|
14 |
} |
backend/src/main/java/cz/zcu/kiv/backendapi/repo/BibliographyRepository.java | ||
---|---|---|
1 |
package cz.zcu.kiv.backendapi.repo; |
|
2 |
|
|
3 |
import cz.zcu.kiv.backendapi.model.BibliographyEntity; |
|
4 |
import org.springframework.data.jpa.repository.JpaRepository; |
|
5 |
import org.springframework.stereotype.Repository; |
|
6 |
import org.springframework.transaction.annotation.Transactional; |
|
7 |
|
|
8 |
/** |
|
9 |
* Bibliography repository |
|
10 |
*/ |
|
11 |
@Repository |
|
12 |
@Transactional(readOnly = true) |
|
13 |
public interface BibliographyRepository extends JpaRepository<BibliographyEntity, BibliographyEntity> { |
|
14 |
} |
backend/src/main/java/cz/zcu/kiv/backendapi/repo/CatalogRepository.java | ||
---|---|---|
1 |
package cz.zcu.kiv.backendapi.repo; |
|
2 |
|
|
3 |
import cz.zcu.kiv.backendapi.model.CatalogEntity; |
|
4 |
import org.springframework.data.jpa.repository.JpaRepository; |
|
5 |
import org.springframework.stereotype.Repository; |
|
6 |
import org.springframework.transaction.annotation.Transactional; |
|
7 |
|
|
8 |
import java.util.UUID; |
|
9 |
|
|
10 |
/** |
|
11 |
* Catalog repository |
|
12 |
*/ |
|
13 |
@Repository |
|
14 |
@Transactional(readOnly = true) |
|
15 |
public interface CatalogRepository extends JpaRepository<CatalogEntity, UUID> { |
|
16 |
} |
backend/src/main/java/cz/zcu/kiv/backendapi/repo/CountryRepository.java | ||
---|---|---|
1 |
package cz.zcu.kiv.backendapi.repo; |
|
2 |
|
|
3 |
import cz.zcu.kiv.backendapi.model.CountryEntity; |
|
4 |
import org.springframework.data.jpa.repository.JpaRepository; |
|
5 |
import org.springframework.stereotype.Repository; |
|
6 |
import org.springframework.transaction.annotation.Transactional; |
|
7 |
|
|
8 |
/** |
|
9 |
* Country repository |
|
10 |
*/ |
|
11 |
@Repository |
|
12 |
@Transactional(readOnly = true) |
|
13 |
public interface CountryRepository extends JpaRepository<CountryEntity, CountryEntity> { |
|
14 |
} |
backend/src/main/java/cz/zcu/kiv/backendapi/repo/TypeRepository.java | ||
---|---|---|
1 |
package cz.zcu.kiv.backendapi.repo; |
|
2 |
|
|
3 |
import cz.zcu.kiv.backendapi.model.TypeEntity; |
|
4 |
import org.springframework.data.jpa.repository.JpaRepository; |
|
5 |
import org.springframework.stereotype.Repository; |
|
6 |
import org.springframework.transaction.annotation.Transactional; |
|
7 |
|
|
8 |
|
|
9 |
/** |
|
10 |
* Type repository |
|
11 |
*/ |
|
12 |
@Repository |
|
13 |
@Transactional(readOnly = true) |
|
14 |
public interface TypeRepository extends JpaRepository<TypeEntity, String> { |
|
15 |
} |
backend/src/main/java/cz/zcu/kiv/backendapi/repo/UserRepository.java | ||
---|---|---|
1 |
package cz.zcu.kiv.backendapi.repo; |
|
2 |
|
|
3 |
import cz.zcu.kiv.backendapi.model.UserEntity; |
|
4 |
import org.springframework.data.jpa.repository.JpaRepository; |
|
5 |
import org.springframework.stereotype.Repository; |
|
6 |
import org.springframework.transaction.annotation.Transactional; |
|
7 |
|
|
8 |
|
|
9 |
/** |
|
10 |
* User repository |
|
11 |
*/ |
|
12 |
@Repository |
|
13 |
@Transactional(readOnly = true) |
|
14 |
public interface UserRepository extends JpaRepository<UserEntity, String> { |
|
15 |
} |
backend/src/main/java/cz/zcu/kiv/backendapi/repo/WrittenFormRepository.java | ||
---|---|---|
1 |
package cz.zcu.kiv.backendapi.repo; |
|
2 |
|
|
3 |
import cz.zcu.kiv.backendapi.model.WrittenFormEntity; |
|
4 |
import org.springframework.data.jpa.repository.JpaRepository; |
|
5 |
import org.springframework.stereotype.Repository; |
|
6 |
import org.springframework.transaction.annotation.Transactional; |
|
7 |
|
|
8 |
/** |
|
9 |
* Written form repository |
|
10 |
*/ |
|
11 |
@Repository |
|
12 |
@Transactional(readOnly = true) |
|
13 |
public interface WrittenFormRepository extends JpaRepository<WrittenFormEntity, WrittenFormEntity> { |
|
14 |
} |
backend/src/main/java/cz/zcu/kiv/backendapi/security/PasswordEncoder.java | ||
---|---|---|
1 |
package cz.zcu.kiv.backendapi.security; |
|
2 |
|
|
3 |
import org.springframework.context.annotation.Bean; |
|
4 |
import org.springframework.context.annotation.Configuration; |
|
5 |
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; |
|
6 |
|
|
7 |
/** |
|
8 |
* Class representing password encoder |
|
9 |
*/ |
|
10 |
@Configuration |
|
11 |
public class PasswordEncoder { |
|
12 |
|
|
13 |
/** |
|
14 |
* Returns password encoder |
|
15 |
* |
|
16 |
* @return password encoder |
|
17 |
*/ |
|
18 |
@Bean |
|
19 |
public BCryptPasswordEncoder bCryptPasswordEncoder() { |
|
20 |
return new BCryptPasswordEncoder(); |
|
21 |
} |
|
22 |
|
|
23 |
} |
backend/src/main/java/cz/zcu/kiv/backendapi/security/SecurityConfig.java | ||
---|---|---|
1 |
package cz.zcu.kiv.backendapi.security; |
|
2 |
|
|
3 |
import cz.zcu.kiv.backendapi.security.jwt.JwtUtils; |
|
4 |
import cz.zcu.kiv.backendapi.security.jwt.JwtTokenVerifier; |
|
5 |
import cz.zcu.kiv.backendapi.security.jwt.JwtUsernameAndPasswordAuthenticationFilter; |
|
6 |
import cz.zcu.kiv.backendapi.user.Permission; |
|
7 |
import cz.zcu.kiv.backendapi.user.Role; |
|
8 |
import lombok.RequiredArgsConstructor; |
|
9 |
import org.springframework.context.annotation.Bean; |
|
10 |
import org.springframework.context.annotation.Configuration; |
|
11 |
import org.springframework.security.authentication.dao.DaoAuthenticationProvider; |
|
12 |
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; |
|
13 |
import org.springframework.security.config.annotation.web.builders.HttpSecurity; |
|
14 |
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; |
|
15 |
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; |
|
16 |
import org.springframework.security.config.http.SessionCreationPolicy; |
|
17 |
import org.springframework.security.core.userdetails.UserDetailsService; |
|
18 |
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; |
|
19 |
|
|
20 |
/** |
|
21 |
* Security config class |
|
22 |
*/ |
|
23 |
@Configuration |
|
24 |
@EnableWebSecurity |
|
25 |
@RequiredArgsConstructor |
|
26 |
public class SecurityConfig extends WebSecurityConfigurerAdapter { |
|
27 |
/** |
|
28 |
* User detail service |
|
29 |
*/ |
|
30 |
private final UserDetailsService userDetailsService; |
|
31 |
|
|
32 |
/** |
|
33 |
* Password encoder |
|
34 |
*/ |
|
35 |
private final BCryptPasswordEncoder bCryptPasswordEncoder; |
|
36 |
|
|
37 |
/** |
|
38 |
* JWT utils |
|
39 |
*/ |
|
40 |
private final JwtUtils jwtUtils; |
|
41 |
|
|
42 |
/** |
|
43 |
* List of permitted pages without login |
|
44 |
*/ |
|
45 |
private final String[] permittedUrls = new String[]{"/login", "/token/refresh"}; |
|
46 |
|
|
47 |
/** |
|
48 |
* Security configuration |
|
49 |
* |
|
50 |
* @param http http security |
|
51 |
* @throws Exception exception |
|
52 |
*/ |
|
53 |
@Override |
|
54 |
protected void configure(HttpSecurity http) throws Exception { |
|
55 |
http. |
|
56 |
csrf().disable() |
|
57 |
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) |
|
58 |
.and() |
|
59 |
.authorizeRequests() |
|
60 |
.antMatchers("/login").permitAll() |
|
61 |
.antMatchers(permittedUrls).permitAll() |
|
62 |
.antMatchers("/admin/**").hasRole(Role.ADMIN.name()) |
|
63 |
.antMatchers("/write/**").hasAuthority(Permission.WRITE.name()) |
|
64 |
.antMatchers("/read/**").hasAuthority(Permission.READ.name()) |
|
65 |
.antMatchers("/delete/**").hasAuthority(Permission.DELETE.name()) |
|
66 |
.anyRequest() |
|
67 |
.authenticated() |
|
68 |
.and() |
|
69 |
.addFilter(new JwtUsernameAndPasswordAuthenticationFilter(authenticationManager(), jwtUtils)) |
|
70 |
.addFilterAfter(new JwtTokenVerifier(jwtUtils, permittedUrls), JwtUsernameAndPasswordAuthenticationFilter.class); |
|
71 |
} |
|
72 |
|
|
73 |
/** |
|
74 |
* Sets authentication provider to authentication manager |
|
75 |
* |
|
76 |
* @param auth authentication manager builder |
|
77 |
*/ |
|
78 |
@Override |
|
79 |
protected void configure(final AuthenticationManagerBuilder auth) { |
|
80 |
auth.authenticationProvider(authenticationProvider()); |
|
81 |
} |
|
82 |
|
|
83 |
|
|
84 |
/** |
|
85 |
* Returns authentication provider |
|
86 |
* |
|
87 |
* @return authentication provider |
|
88 |
*/ |
|
89 |
@Bean |
|
90 |
public DaoAuthenticationProvider authenticationProvider() { |
|
91 |
final DaoAuthenticationProvider provider = new DaoAuthenticationProvider(); |
|
92 |
provider.setUserDetailsService(userDetailsService); |
|
93 |
provider.setPasswordEncoder(bCryptPasswordEncoder); |
|
94 |
return provider; |
|
95 |
} |
|
96 |
|
|
97 |
} |
backend/src/main/java/cz/zcu/kiv/backendapi/security/jwt/JwtTokenVerifier.java | ||
---|---|---|
1 |
package cz.zcu.kiv.backendapi.security.jwt; |
|
2 |
|
|
3 |
import com.auth0.jwt.JWT; |
|
4 |
import com.auth0.jwt.JWTVerifier; |
|
5 |
import com.auth0.jwt.algorithms.Algorithm; |
|
6 |
import com.auth0.jwt.interfaces.DecodedJWT; |
|
7 |
import com.google.common.base.Strings; |
|
8 |
import lombok.RequiredArgsConstructor; |
|
9 |
import lombok.extern.slf4j.Slf4j; |
|
10 |
import org.springframework.http.HttpHeaders; |
|
11 |
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; |
|
12 |
import org.springframework.security.core.authority.SimpleGrantedAuthority; |
|
13 |
import org.springframework.security.core.context.SecurityContextHolder; |
|
14 |
import org.springframework.security.web.util.matcher.AntPathRequestMatcher; |
|
15 |
import org.springframework.web.filter.OncePerRequestFilter; |
|
16 |
|
|
17 |
import javax.servlet.FilterChain; |
|
18 |
import javax.servlet.ServletException; |
|
19 |
import javax.servlet.http.HttpServletRequest; |
|
20 |
import javax.servlet.http.HttpServletResponse; |
|
21 |
import java.io.IOException; |
|
22 |
import java.util.*; |
|
23 |
import java.util.stream.Collectors; |
|
24 |
|
|
25 |
|
|
26 |
/** |
|
27 |
* Class that verifies JWT per request |
|
28 |
*/ |
|
29 |
@Slf4j |
|
30 |
@RequiredArgsConstructor |
|
31 |
public class JwtTokenVerifier extends OncePerRequestFilter { |
|
32 |
|
|
33 |
/** |
|
34 |
* JWT utils |
|
35 |
*/ |
|
36 |
private final JwtUtils jwtUtils; |
|
37 |
|
|
38 |
/** |
|
39 |
* Array or urls with this filter (JWT not needed for them) |
|
40 |
*/ |
|
41 |
private final String[] skipFilterUrls; |
|
42 |
|
|
43 |
/** |
|
44 |
* Filters request - checks for JWT token and validates it |
|
45 |
* |
Také k dispozici: Unified diff
Added JWT and permissions, changed project structure
- filters when authenticating - sends JWT
- filters per request - controls JWT
- added permission to user (READ, WRITE, DELETE)
- created package-by-feature from package-by-layer
re #9204