Revize 39c320ad
Přidáno uživatelem Jakub Šmíd před asi 3 roky(ů)
backend/src/main/java/cz/zcu/kiv/backendapi/catalog/CatalogController.java | ||
---|---|---|
1 |
package cz.zcu.kiv.backendapi.catalog; |
|
2 |
|
|
3 |
import lombok.RequiredArgsConstructor; |
|
4 |
import org.springframework.http.HttpStatus; |
|
5 |
import org.springframework.http.ResponseEntity; |
|
6 |
import org.springframework.web.bind.annotation.*; |
|
7 |
|
|
8 |
import java.util.List; |
|
9 |
import java.util.UUID; |
|
10 |
|
|
11 |
/** |
|
12 |
* Controller for catalog |
|
13 |
*/ |
|
14 |
@RestController |
|
15 |
@RequiredArgsConstructor |
|
16 |
@RequestMapping("/catalog") |
|
17 |
public class CatalogController { |
|
18 |
|
|
19 |
/** |
|
20 |
* Catalog service |
|
21 |
*/ |
|
22 |
private final ICatalogService catalogService; |
|
23 |
|
|
24 |
@PostMapping("") |
|
25 |
public void addCatalogEntry(@RequestBody CatalogDto catalogDto) { |
|
26 |
catalogService.saveCatalogEntry(catalogDto); |
|
27 |
} |
|
28 |
|
|
29 |
/** |
|
30 |
* Returns catalog |
|
31 |
* |
|
32 |
* @return catalog |
|
33 |
*/ |
|
34 |
@GetMapping("") |
|
35 |
public ResponseEntity<List<CatalogDto>> getAllUsers() { |
|
36 |
return new ResponseEntity<>(catalogService.getCatalog(), HttpStatus.OK); |
|
37 |
} |
|
38 |
|
|
39 |
/** |
|
40 |
* Updates catalog entry with given ID |
|
41 |
* |
|
42 |
* @param id ID |
|
43 |
* @param catalogDto catalog DTO |
|
44 |
*/ |
|
45 |
@PutMapping("/{id}") |
|
46 |
public void updateCatalogEntry(@PathVariable UUID id, @RequestBody CatalogDto catalogDto) { |
|
47 |
catalogService.updateCatalogEntry(id, catalogDto); |
|
48 |
} |
|
49 |
|
|
50 |
/** |
|
51 |
* Deletes catalog entry with given ID |
|
52 |
* |
|
53 |
* @param id ID |
|
54 |
*/ |
|
55 |
@DeleteMapping("/{id}") |
|
56 |
public void deleteCatalogEntry(@PathVariable UUID id) { |
|
57 |
catalogService.deleteCatalogEntry(id); |
|
58 |
} |
|
59 |
} |
backend/src/main/java/cz/zcu/kiv/backendapi/catalog/CatalogDto.java | ||
---|---|---|
1 |
package cz.zcu.kiv.backendapi.catalog; |
|
2 |
|
|
3 |
import lombok.Data; |
|
4 |
|
|
5 |
import java.util.Collections; |
|
6 |
import java.util.Set; |
|
7 |
import java.util.UUID; |
|
8 |
|
|
9 |
/** |
|
10 |
* Class representing catalog DTO |
|
11 |
*/ |
|
12 |
@Data |
|
13 |
public class CatalogDto { |
|
14 |
/** |
|
15 |
* Id |
|
16 |
*/ |
|
17 |
private UUID id; |
|
18 |
|
|
19 |
/** |
|
20 |
* Name of geographic entry |
|
21 |
*/ |
|
22 |
private String name; |
|
23 |
|
|
24 |
/** |
|
25 |
* Certainty |
|
26 |
*/ |
|
27 |
private int certainty; |
|
28 |
|
|
29 |
/** |
|
30 |
* Longitude |
|
31 |
*/ |
|
32 |
private double longitude; |
|
33 |
|
|
34 |
/** |
|
35 |
* Latitude |
|
36 |
*/ |
|
37 |
private double latitude; |
|
38 |
|
|
39 |
/** |
|
40 |
* Bibliography |
|
41 |
*/ |
|
42 |
private Set<String> bibliography = Collections.emptySet(); |
|
43 |
|
|
44 |
/** |
|
45 |
* Countries |
|
46 |
*/ |
|
47 |
private Set<String> countries = Collections.emptySet(); |
|
48 |
|
|
49 |
/** |
|
50 |
* Written forms |
|
51 |
*/ |
|
52 |
private Set<String> writtenForms = Collections.emptySet(); |
|
53 |
|
|
54 |
/** |
|
55 |
* Alternative names |
|
56 |
*/ |
|
57 |
private Set<String> alternativeNames = Collections.emptySet(); |
|
58 |
|
|
59 |
/** |
|
60 |
* Types |
|
61 |
*/ |
|
62 |
private Set<String> types = Collections.emptySet(); |
|
63 |
|
|
64 |
} |
backend/src/main/java/cz/zcu/kiv/backendapi/catalog/CatalogEntity.java | ||
---|---|---|
79 | 79 |
private Set<WrittenFormEntity> writtenForms; |
80 | 80 |
|
81 | 81 |
/** |
82 |
* Alternative name |
|
82 |
* Alternative names
|
|
83 | 83 |
*/ |
84 | 84 |
@OneToMany(mappedBy = "catalog", cascade = CascadeType.ALL) |
85 | 85 |
@LazyCollection(LazyCollectionOption.FALSE) |
... | ... | |
104 | 104 |
|
105 | 105 |
this.name = csvFields.get(1); |
106 | 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 |
} |
|
107 |
this.alternativeNames = stringList.stream().map(s->new AlternativeNameEntity(s, this)).collect(Collectors.toSet()); |
|
108 |
|
|
111 | 109 |
this.certainty = processIntField(csvFields.get(3)); |
112 | 110 |
this.latitude = processDoubleField(csvFields.get(4)); |
113 | 111 |
this.longitude = processDoubleField(csvFields.get(5)); |
112 |
|
|
114 | 113 |
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 |
} |
|
114 |
this.writtenForms = stringList.stream().map(s->new WrittenFormEntity(s, this)).collect(Collectors.toSet()); |
|
115 |
|
|
119 | 116 |
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 |
} |
|
117 |
this.types = stringList.stream().map(TypeEntity::new).collect(Collectors.toSet()); |
|
118 |
|
|
124 | 119 |
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 |
} |
|
120 |
this.countries = stringList.stream().map(s->new CountryEntity(s, this)).collect(Collectors.toSet()); |
|
121 |
|
|
129 | 122 |
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 |
} |
|
123 |
this.bibliography = stringList.stream().map(s->new BibliographyEntity(s, this)).collect(Collectors.toSet()); |
|
134 | 124 |
} |
135 | 125 |
|
136 | 126 |
private int processIntField(String field) { |
backend/src/main/java/cz/zcu/kiv/backendapi/catalog/CatalogRepository.java | ||
---|---|---|
6 | 6 |
import org.springframework.transaction.annotation.Transactional; |
7 | 7 |
|
8 | 8 |
import java.util.List; |
9 |
import java.util.Set; |
|
9 | 10 |
import java.util.UUID; |
10 | 11 |
|
11 | 12 |
/** |
... | ... | |
22 | 23 |
*/ |
23 | 24 |
@Query("SELECT DISTINCT c FROM CatalogEntity c LEFT JOIN AlternativeNameEntity a ON c = a.catalog WHERE (?1 = c.name OR ?1 = a.name)") |
24 | 25 |
List<CatalogEntity> getCatalogEntitiesByName(String name); |
26 |
|
|
27 |
// @Query("SELECT DISTINCT c FROM CatalogEntity c LEFT JOIN AlternativeNameEntity a ON c = a.catalog WHERE (?1 IS NULL OR ?1 = c.name OR ?1 = a.name)" + |
|
28 |
// "LEFT JOIN TypeEntity e on c = e.catalog WHERE (?2 IS NULL OR e.)") |
|
29 |
// Set<CatalogEntity> filterCatalog(String name, String type, String country); |
|
25 | 30 |
} |
backend/src/main/java/cz/zcu/kiv/backendapi/catalog/CatalogServiceImpl.java | ||
---|---|---|
1 | 1 |
package cz.zcu.kiv.backendapi.catalog; |
2 | 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; |
|
3 | 6 |
import cz.zcu.kiv.backendapi.type.TypeEntity; |
4 | 7 |
import cz.zcu.kiv.backendapi.type.ITypeService; |
8 |
import cz.zcu.kiv.backendapi.writtenform.WrittenFormEntity; |
|
5 | 9 |
import lombok.RequiredArgsConstructor; |
10 |
import lombok.extern.slf4j.Slf4j; |
|
11 |
import org.springframework.security.core.userdetails.UsernameNotFoundException; |
|
6 | 12 |
import org.springframework.stereotype.Service; |
7 | 13 |
import org.springframework.transaction.annotation.Transactional; |
8 | 14 |
|
9 | 15 |
import java.util.List; |
16 |
import java.util.UUID; |
|
17 |
import java.util.stream.Collectors; |
|
10 | 18 |
|
11 | 19 |
/** |
12 | 20 |
* Catalog service implementation |
... | ... | |
14 | 22 |
@Service |
15 | 23 |
@Transactional |
16 | 24 |
@RequiredArgsConstructor |
25 |
@Slf4j |
|
17 | 26 |
public class CatalogServiceImpl implements ICatalogService { |
27 |
/** |
|
28 |
* Message for exception when catalog entry is not found by id |
|
29 |
*/ |
|
30 |
private static final String CATALOG_ENTRY_NOT_FOUND = "Catalog entry not found"; |
|
18 | 31 |
/** |
19 | 32 |
* Catalog repository |
20 | 33 |
*/ |
21 | 34 |
private final CatalogRepository catalogRepository; |
22 | 35 |
|
36 |
/** |
|
37 |
* Type service |
|
38 |
*/ |
|
23 | 39 |
private final ITypeService typeService; |
24 | 40 |
|
25 | 41 |
@Override |
26 | 42 |
public void saveCatalog(List<CatalogEntity> catalogEntities) { |
27 |
for (CatalogEntity catalogEntity : catalogEntities) { |
|
28 |
for (TypeEntity type: catalogEntity.getTypes() ) { |
|
43 |
log.info("Saving catalog"); |
|
44 |
catalogEntities.forEach(this::saveCatalogEntity); |
|
45 |
} |
|
46 |
|
|
47 |
@Override |
|
48 |
public void saveCatalogEntry(CatalogDto catalogDto) { |
|
49 |
log.info("Saving catalog entry"); |
|
50 |
CatalogEntity catalogEntity = new CatalogEntity(); |
|
51 |
convertDtoToEntity(catalogDto, catalogEntity); |
|
52 |
saveCatalogEntity(catalogEntity); |
|
53 |
} |
|
54 |
|
|
55 |
@Override |
|
56 |
public void updateCatalogEntry(UUID id, CatalogDto catalogDto) { |
|
57 |
CatalogEntity catalogEntity = catalogRepository.findById(id).orElseThrow(() -> { |
|
58 |
log.error(CATALOG_ENTRY_NOT_FOUND); |
|
59 |
throw new UsernameNotFoundException(CATALOG_ENTRY_NOT_FOUND); |
|
60 |
}); |
|
61 |
convertDtoToEntity(catalogDto, catalogEntity); |
|
62 |
catalogRepository.save(catalogEntity); |
|
63 |
log.info("Catalog entry updated"); |
|
64 |
} |
|
65 |
|
|
66 |
@Override |
|
67 |
public void deleteCatalogEntry(UUID id) { |
|
68 |
CatalogEntity catalogEntity = catalogRepository.findById(id).orElseThrow(() -> { |
|
69 |
log.error(CATALOG_ENTRY_NOT_FOUND); |
|
70 |
throw new UsernameNotFoundException(CATALOG_ENTRY_NOT_FOUND); |
|
71 |
}); |
|
72 |
catalogRepository.delete(catalogEntity); |
|
73 |
log.info("Catalog entry deleted"); |
|
74 |
} |
|
29 | 75 |
|
30 |
if (typeService.getTypeByName(type.getType()).isEmpty()){ |
|
31 |
typeService.saveType(type); |
|
32 |
} |
|
76 |
@Override |
|
77 |
public List<CatalogDto> getCatalog() { |
|
78 |
log.info("Retrieving catalog"); |
|
79 |
List<CatalogEntity> entities = catalogRepository.findAll(); |
|
80 |
return entities.stream().map(this::convertEntityToDto).collect(Collectors.toList()); |
|
81 |
} |
|
82 |
|
|
83 |
/** |
|
84 |
* Saves catalog entity to database |
|
85 |
* |
|
86 |
* @param catalogEntity catalog entity |
|
87 |
*/ |
|
88 |
private void saveCatalogEntity(CatalogEntity catalogEntity) { |
|
89 |
for (TypeEntity type : catalogEntity.getTypes()) { |
|
90 |
if (typeService.getTypeByName(type.getType()).isEmpty()) { |
|
91 |
typeService.saveType(type); |
|
33 | 92 |
} |
34 | 93 |
} |
35 |
catalogRepository.saveAll(catalogEntities); |
|
94 |
catalogRepository.save(catalogEntity); |
|
95 |
} |
|
96 |
|
|
97 |
/** |
|
98 |
* Converts catalog DTO to catalog entity |
|
99 |
* |
|
100 |
* @param catalogDto catalog DTO |
|
101 |
* @param catalogEntity catalog entity |
|
102 |
*/ |
|
103 |
private void convertDtoToEntity(CatalogDto catalogDto, CatalogEntity catalogEntity) { |
|
104 |
catalogEntity.setName(catalogDto.getName()); |
|
105 |
catalogEntity.setCertainty(catalogDto.getCertainty()); |
|
106 |
catalogEntity.setLatitude(catalogDto.getLatitude()); |
|
107 |
catalogEntity.setLongitude(catalogDto.getLongitude()); |
|
108 |
catalogEntity.setBibliography(catalogDto.getBibliography() |
|
109 |
.stream().map(s -> new BibliographyEntity(s, catalogEntity)).collect(Collectors.toSet())); |
|
110 |
catalogEntity.setTypes(catalogDto.getTypes() |
|
111 |
.stream().map(TypeEntity::new).collect(Collectors.toSet())); |
|
112 |
catalogEntity.setCountries(catalogDto.getCountries() |
|
113 |
.stream().map(s -> new CountryEntity(s, catalogEntity)).collect(Collectors.toSet())); |
|
114 |
catalogEntity.setAlternativeNames(catalogDto.getAlternativeNames() |
|
115 |
.stream().map(s -> new AlternativeNameEntity(s, catalogEntity)).collect(Collectors.toSet())); |
|
116 |
catalogEntity.setWrittenForms(catalogDto.getWrittenForms() |
|
117 |
.stream().map(s -> new WrittenFormEntity(s, catalogEntity)).collect(Collectors.toSet())); |
|
36 | 118 |
} |
119 |
|
|
120 |
/** |
|
121 |
* Converts catalog entity to catalog DTO |
|
122 |
* |
|
123 |
* @param entity catalog entity |
|
124 |
* @return catalog DTO |
|
125 |
*/ |
|
126 |
private CatalogDto convertEntityToDto(CatalogEntity entity) { |
|
127 |
CatalogDto catalogDto = new CatalogDto(); |
|
128 |
catalogDto.setId(entity.getId()); |
|
129 |
catalogDto.setName(entity.getName()); |
|
130 |
catalogDto.setLatitude(entity.getLatitude()); |
|
131 |
catalogDto.setLongitude(entity.getLongitude()); |
|
132 |
catalogDto.setCertainty(entity.getCertainty()); |
|
133 |
catalogDto.setBibliography(entity.getBibliography() |
|
134 |
.stream().map(BibliographyEntity::getSource).collect(Collectors.toSet())); |
|
135 |
catalogDto.setTypes(entity.getTypes() |
|
136 |
.stream().map(TypeEntity::getType).collect(Collectors.toSet())); |
|
137 |
catalogDto.setCountries(entity.getCountries() |
|
138 |
.stream().map(CountryEntity::getName).collect(Collectors.toSet())); |
|
139 |
catalogDto.setAlternativeNames(entity.getAlternativeNames() |
|
140 |
.stream().map(AlternativeNameEntity::getName).collect(Collectors.toSet())); |
|
141 |
catalogDto.setWrittenForms(entity.getWrittenForms() |
|
142 |
.stream().map(WrittenFormEntity::getForm).collect(Collectors.toSet())); |
|
143 |
return catalogDto; |
|
144 |
} |
|
145 |
|
|
37 | 146 |
} |
backend/src/main/java/cz/zcu/kiv/backendapi/catalog/ICatalogService.java | ||
---|---|---|
1 | 1 |
package cz.zcu.kiv.backendapi.catalog; |
2 | 2 |
|
3 | 3 |
import java.util.List; |
4 |
import java.util.UUID; |
|
4 | 5 |
|
5 | 6 |
/** |
6 | 7 |
* Catalog service interface |
7 | 8 |
*/ |
8 | 9 |
public interface ICatalogService { |
10 |
/** |
|
11 |
* Saves list of catalog entries |
|
12 |
* |
|
13 |
* @param catalogEntities catalog entris |
|
14 |
*/ |
|
9 | 15 |
void saveCatalog(List<CatalogEntity> catalogEntities); |
16 |
|
|
17 |
/** |
|
18 |
* Saves one catalog entry |
|
19 |
* |
|
20 |
* @param catalogDto catalog DTO |
|
21 |
*/ |
|
22 |
void saveCatalogEntry(CatalogDto catalogDto); |
|
23 |
|
|
24 |
/** |
|
25 |
* Updates catalog entry with given ID |
|
26 |
* |
|
27 |
* @param id ID |
|
28 |
* @param catalogDto catalog DTO |
|
29 |
*/ |
|
30 |
void updateCatalogEntry(UUID id, CatalogDto catalogDto); |
|
31 |
|
|
32 |
/** |
|
33 |
* Deletes catalog entry with given ID |
|
34 |
* |
|
35 |
* @param id ID |
|
36 |
*/ |
|
37 |
void deleteCatalogEntry(UUID id); |
|
38 |
|
|
39 |
/** |
|
40 |
* Returns whole catalog |
|
41 |
* |
|
42 |
* @return catalog (as list of catalog entries) |
|
43 |
*/ |
|
44 |
List<CatalogDto> getCatalog(); |
|
45 |
|
|
10 | 46 |
} |
backend/src/main/java/cz/zcu/kiv/backendapi/exception/ApiExceptionHandler.java | ||
---|---|---|
43 | 43 |
public ResponseEntity<Object> handleApiRequestException(ApiRequestException exception) { |
44 | 44 |
return new ResponseEntity<>(exception.getMessage(), exception.getHttpStatus()); |
45 | 45 |
} |
46 |
|
|
47 |
/** |
|
48 |
* Handles illegal argument exception |
|
49 |
* |
|
50 |
* @param exception illegal argument exception |
|
51 |
* @return response entity with message and status |
|
52 |
*/ |
|
53 |
@ExceptionHandler(value = {IllegalArgumentException.class}) |
|
54 |
public ResponseEntity<Object> handleIllegalArgumentException(IllegalArgumentException exception) { |
|
55 |
return new ResponseEntity<>(exception.getMessage(), HttpStatus.BAD_REQUEST); |
|
56 |
} |
|
46 | 57 |
} |
backend/src/main/java/cz/zcu/kiv/backendapi/security/SecurityConfig.java | ||
---|---|---|
74 | 74 |
.addFilterAfter(new JwtTokenVerifier(jwtUtils, permittedUrls), JwtUsernameAndPasswordAuthenticationFilter.class); |
75 | 75 |
|
76 | 76 |
} |
77 |
// @Override |
|
78 |
// public void configure(WebSecurity web) throws Exception { |
|
79 |
// web.ignoring().antMatchers("/swagger-ui/**", "/v3/api-docs","/v3/api-docs/swagger-config", "/swagger-ui.html", "/swagger-ui-custom.html"); |
|
80 |
// } |
|
81 |
|
|
82 | 77 |
|
83 | 78 |
/** |
84 | 79 |
* Sets authentication provider to authentication manager |
backend/src/main/java/cz/zcu/kiv/backendapi/user/IUserService.java | ||
---|---|---|
15 | 15 |
*/ |
16 | 16 |
UserEntity getUserByName(String username); |
17 | 17 |
|
18 |
/** |
|
19 |
* Registers new user |
|
20 |
* |
|
21 |
* @param userDto user DTO |
|
22 |
*/ |
|
18 | 23 |
void registerNewUser(UserDto userDto); |
19 | 24 |
|
20 |
void updateUser(UserDto userDto); |
|
25 |
void updateUser(String username, UserDto userDto);
|
|
21 | 26 |
|
22 | 27 |
void deleteUser(String username); |
23 | 28 |
|
29 |
/** |
|
30 |
* Returns list of all users |
|
31 |
* |
|
32 |
* @return list of all users |
|
33 |
*/ |
|
24 | 34 |
List<UserDto> getAllUsers(); |
25 | 35 |
} |
backend/src/main/java/cz/zcu/kiv/backendapi/user/UserController.java | ||
---|---|---|
66 | 66 |
|
67 | 67 |
//TODO check if need, if needed probably change new dto without email, comment otherwise |
68 | 68 |
@PutMapping("/user/{username}") |
69 |
@ResponseStatus(value = HttpStatus.OK) |
|
70 | 69 |
public void updateUser(@PathVariable String username, @RequestBody @Valid UserDto userDto) { |
71 |
userService.updateUser(userDto); |
|
70 |
userService.updateUser(username, userDto);
|
|
72 | 71 |
} |
73 | 72 |
|
74 | 73 |
//TODO check if needed, comment otherwise |
75 | 74 |
@DeleteMapping("/user/{username}") |
76 |
@ResponseStatus(value = HttpStatus.OK) |
|
77 | 75 |
public void deleteUser(@PathVariable String username) { |
78 | 76 |
userService.deleteUser(username); |
79 | 77 |
} |
backend/src/main/java/cz/zcu/kiv/backendapi/user/UserServiceImpl.java | ||
---|---|---|
62 | 62 |
} |
63 | 63 |
|
64 | 64 |
@Override |
65 |
public void updateUser(UserDto userDto) { |
|
66 |
UserEntity userEntity = userRepository.findByEmail(userDto.getEmail()).orElseThrow(() ->{
|
|
67 |
log.error(String.format(USER_NOT_FOUND, userDto.getEmail()));
|
|
68 |
throw new UsernameNotFoundException(String.format(USER_NOT_FOUND, userDto.getEmail()));
|
|
65 |
public void updateUser(String username, UserDto userDto) {
|
|
66 |
UserEntity userEntity = userRepository.findByEmail(username).orElseThrow(() ->{
|
|
67 |
log.error(String.format(USER_NOT_FOUND, username));
|
|
68 |
throw new UsernameNotFoundException(String.format(USER_NOT_FOUND, username));
|
|
69 | 69 |
}); |
70 | 70 |
convertDtoToEntity(userDto, userEntity); |
71 |
userEntity.setEmail(username); |
|
71 | 72 |
userRepository.save(userEntity); |
72 | 73 |
} |
73 | 74 |
|
74 |
//TODO maybe chceck if user is not deleting himself - or it might be ok
|
|
75 |
//TODO maybe check if user is not deleting himself - or it might be ok |
|
75 | 76 |
@Override |
76 | 77 |
public void deleteUser(String username) { |
77 | 78 |
UserEntity userEntity = userRepository.findByEmail(username).orElseThrow(() ->{ |
Také k dispozici: Unified diff
Added Catalog function
- catalog DTO
- catalog controller
- adding, deleting, updating catalog entries
- getting all catalog entries
re #9164