Compare commits
1 Commits
62c13ff0b1
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fb416dff55 |
@@ -1,48 +0,0 @@
|
||||
meta {
|
||||
name: Auth App
|
||||
type: http
|
||||
seq: 1
|
||||
}
|
||||
|
||||
post {
|
||||
url: {{KEYCLOAK_BASE_URL}}/realms/{{KEYCLOAK_REALM}}/protocol/openid-connect/token
|
||||
body: formUrlEncoded
|
||||
auth: inherit
|
||||
}
|
||||
|
||||
headers {
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
}
|
||||
|
||||
body:form-urlencoded {
|
||||
grant_type: password
|
||||
client_id: {{KEYCLOAK_CLIENT_ID}}
|
||||
username: {{ADMIN_USERNAME}}
|
||||
password: {{ADMIN_PASSWORD}}
|
||||
}
|
||||
|
||||
script:post-response {
|
||||
// Parse die JSON-Antwort
|
||||
const jsonResponse = res.body;
|
||||
|
||||
|
||||
if (jsonResponse.access_token) {
|
||||
// Schreibe den access_token in eine Umgebungsvariable
|
||||
// oder in eine collection-Variable
|
||||
|
||||
// Option 1: In eine Umgebungsvariable schreiben
|
||||
// (z.B. für eine bestimmte Umgebung wie "Development")
|
||||
bru.setEnvVar("BEARER_TOKEN", jsonResponse.access_token);
|
||||
|
||||
// Option 2: In eine Collection-Variable schreiben
|
||||
// (Diese Variable ist global für alle Anfragen in deiner Collection)
|
||||
// bru.setVar("bearerToken", "Bearer " + jsonResponse.access_token);
|
||||
} else {
|
||||
// optional: Error Handling, falls der Token nicht in der Antwort ist
|
||||
console.log("Error: access_token not found in the response.");
|
||||
}
|
||||
}
|
||||
|
||||
settings {
|
||||
encodeUrl: false
|
||||
}
|
||||
@@ -33,6 +33,7 @@ script:post-response {
|
||||
// (z.B. für eine bestimmte Umgebung wie "Development")
|
||||
bru.setEnvVar("BEARER_TOKEN", jsonResponse.access_token);
|
||||
|
||||
console.log("Updated access token.");
|
||||
// Option 2: In eine Collection-Variable schreiben
|
||||
// (Diese Variable ist global für alle Anfragen in deiner Collection)
|
||||
// bru.setVar("bearerToken", "Bearer " + jsonResponse.access_token);
|
||||
@@ -1,7 +1,7 @@
|
||||
meta {
|
||||
name: Upload Organizations
|
||||
type: http
|
||||
seq: 3
|
||||
seq: 2
|
||||
}
|
||||
|
||||
post {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
meta {
|
||||
name: Upload Persons
|
||||
type: http
|
||||
seq: 2
|
||||
seq: 1
|
||||
}
|
||||
|
||||
post {
|
||||
|
||||
31
bruno/propify/Industries/Create new.bru
Normal file
31
bruno/propify/Industries/Create new.bru
Normal file
@@ -0,0 +1,31 @@
|
||||
meta {
|
||||
name: Create new
|
||||
type: http
|
||||
seq: 3
|
||||
}
|
||||
|
||||
post {
|
||||
url: {{API_BASE_URL}}/api/{{API_VERSION}}/industries
|
||||
body: json
|
||||
auth: bearer
|
||||
}
|
||||
|
||||
auth:bearer {
|
||||
token: {{BEARER_TOKEN}}
|
||||
}
|
||||
|
||||
body:json {
|
||||
{
|
||||
"name": "Bungalow",
|
||||
"street": "Hebbelstraße",
|
||||
"houseNumber": "30",
|
||||
"zipCode": "55127",
|
||||
"city": "Mainz",
|
||||
"country": "DE",
|
||||
"notes": "Lorem ipsum"
|
||||
}
|
||||
}
|
||||
|
||||
settings {
|
||||
encodeUrl: true
|
||||
}
|
||||
31
bruno/propify/Industries/Delete one by ID.bru
Normal file
31
bruno/propify/Industries/Delete one by ID.bru
Normal file
@@ -0,0 +1,31 @@
|
||||
meta {
|
||||
name: Delete one by ID
|
||||
type: http
|
||||
seq: 4
|
||||
}
|
||||
|
||||
delete {
|
||||
url: API_BASE_URL}}/api/{{API_VERSION}}/industries/e64d5e53-cd45-45fb-9237-46078077bf22
|
||||
body: json
|
||||
auth: bearer
|
||||
}
|
||||
|
||||
auth:bearer {
|
||||
token: {{BEARER_TOKEN}}
|
||||
}
|
||||
|
||||
body:json {
|
||||
{
|
||||
"name": "Mustername 1",
|
||||
"street": "Musterstraße",
|
||||
"houseNumber": "1",
|
||||
"zipCode": "55123",
|
||||
"city": "Musterstadt",
|
||||
"country": "de",
|
||||
"notes": "Lorem ipsum"
|
||||
}
|
||||
}
|
||||
|
||||
settings {
|
||||
encodeUrl: true
|
||||
}
|
||||
19
bruno/propify/Industries/Get all.bru
Normal file
19
bruno/propify/Industries/Get all.bru
Normal file
@@ -0,0 +1,19 @@
|
||||
meta {
|
||||
name: Get all
|
||||
type: http
|
||||
seq: 1
|
||||
}
|
||||
|
||||
get {
|
||||
url: {{API_BASE_URL}}/api/{{API_VERSION}}/industries
|
||||
body: none
|
||||
auth: bearer
|
||||
}
|
||||
|
||||
auth:bearer {
|
||||
token: {{BEARER_TOKEN}}
|
||||
}
|
||||
|
||||
settings {
|
||||
encodeUrl: true
|
||||
}
|
||||
19
bruno/propify/Industries/Get one by ID.bru
Normal file
19
bruno/propify/Industries/Get one by ID.bru
Normal file
@@ -0,0 +1,19 @@
|
||||
meta {
|
||||
name: Get one by ID
|
||||
type: http
|
||||
seq: 2
|
||||
}
|
||||
|
||||
get {
|
||||
url: {{API_BASE_URL}}/api/{{API_VERSION}}/industries/da002464-33e9-4bfd-9ae2-836b26955502
|
||||
body: none
|
||||
auth: bearer
|
||||
}
|
||||
|
||||
auth:bearer {
|
||||
token: {{BEARER_TOKEN}}
|
||||
}
|
||||
|
||||
settings {
|
||||
encodeUrl: true
|
||||
}
|
||||
39
bruno/propify/Industries/Upload files.bru
Normal file
39
bruno/propify/Industries/Upload files.bru
Normal file
@@ -0,0 +1,39 @@
|
||||
meta {
|
||||
name: Upload files
|
||||
type: http
|
||||
seq: 5
|
||||
}
|
||||
|
||||
post {
|
||||
url: {{API_BASE_URL}}/api/{{API_VERSION}}/industries/f4eb0c54-7c8f-4e60-b71f-1d08b8b6e2d4/upload
|
||||
body: multipartForm
|
||||
auth: bearer
|
||||
}
|
||||
|
||||
auth:bearer {
|
||||
token: {{BEARER_TOKEN}}
|
||||
}
|
||||
|
||||
body:json {
|
||||
{
|
||||
"name": "Bungalow",
|
||||
"street": "Hebbelstraße",
|
||||
"houseNumber": "30",
|
||||
"zipCode": "55127",
|
||||
"city": "Mainz",
|
||||
"country": "DE",
|
||||
"notes": "Lorem ipsum"
|
||||
}
|
||||
}
|
||||
|
||||
body:multipart-form {
|
||||
attachments: @file(/Users/murat/Pictures/IMG_0229.jpeg|/Users/murat/Pictures/schnürsenkel technik.gif)
|
||||
}
|
||||
|
||||
body:file {
|
||||
file: @file(/Users/murat/Pictures/IMG_0229.jpeg) @contentType(image/jpeg)
|
||||
}
|
||||
|
||||
settings {
|
||||
encodeUrl: true
|
||||
}
|
||||
8
bruno/propify/Industries/folder.bru
Normal file
8
bruno/propify/Industries/folder.bru
Normal file
@@ -0,0 +1,8 @@
|
||||
meta {
|
||||
name: Industries
|
||||
seq: 9
|
||||
}
|
||||
|
||||
auth {
|
||||
mode: inherit
|
||||
}
|
||||
31
bruno/propify/Organizations/Create new.bru
Normal file
31
bruno/propify/Organizations/Create new.bru
Normal file
@@ -0,0 +1,31 @@
|
||||
meta {
|
||||
name: Create new
|
||||
type: http
|
||||
seq: 3
|
||||
}
|
||||
|
||||
post {
|
||||
url: {{API_BASE_URL}}/api/{{API_VERSION}}/organizations
|
||||
body: json
|
||||
auth: bearer
|
||||
}
|
||||
|
||||
auth:bearer {
|
||||
token: {{BEARER_TOKEN}}
|
||||
}
|
||||
|
||||
body:json {
|
||||
{
|
||||
"name": "Bungalow",
|
||||
"street": "Hebbelstraße",
|
||||
"houseNumber": "30",
|
||||
"zipCode": "55127",
|
||||
"city": "Mainz",
|
||||
"country": "DE",
|
||||
"notes": "Lorem ipsum"
|
||||
}
|
||||
}
|
||||
|
||||
settings {
|
||||
encodeUrl: true
|
||||
}
|
||||
31
bruno/propify/Organizations/Delete one by ID.bru
Normal file
31
bruno/propify/Organizations/Delete one by ID.bru
Normal file
@@ -0,0 +1,31 @@
|
||||
meta {
|
||||
name: Delete one by ID
|
||||
type: http
|
||||
seq: 4
|
||||
}
|
||||
|
||||
delete {
|
||||
url: API_BASE_URL}}/api/{{API_VERSION}}/organizations/e64d5e53-cd45-45fb-9237-46078077bf22
|
||||
body: json
|
||||
auth: bearer
|
||||
}
|
||||
|
||||
auth:bearer {
|
||||
token: {{BEARER_TOKEN}}
|
||||
}
|
||||
|
||||
body:json {
|
||||
{
|
||||
"name": "Mustername 1",
|
||||
"street": "Musterstraße",
|
||||
"houseNumber": "1",
|
||||
"zipCode": "55123",
|
||||
"city": "Musterstadt",
|
||||
"country": "de",
|
||||
"notes": "Lorem ipsum"
|
||||
}
|
||||
}
|
||||
|
||||
settings {
|
||||
encodeUrl: true
|
||||
}
|
||||
19
bruno/propify/Organizations/Get all.bru
Normal file
19
bruno/propify/Organizations/Get all.bru
Normal file
@@ -0,0 +1,19 @@
|
||||
meta {
|
||||
name: Get all
|
||||
type: http
|
||||
seq: 1
|
||||
}
|
||||
|
||||
get {
|
||||
url: {{API_BASE_URL}}/api/{{API_VERSION}}/organizations
|
||||
body: none
|
||||
auth: bearer
|
||||
}
|
||||
|
||||
auth:bearer {
|
||||
token: {{BEARER_TOKEN}}
|
||||
}
|
||||
|
||||
settings {
|
||||
encodeUrl: true
|
||||
}
|
||||
19
bruno/propify/Organizations/Get one by ID.bru
Normal file
19
bruno/propify/Organizations/Get one by ID.bru
Normal file
@@ -0,0 +1,19 @@
|
||||
meta {
|
||||
name: Get one by ID
|
||||
type: http
|
||||
seq: 2
|
||||
}
|
||||
|
||||
get {
|
||||
url: {{API_BASE_URL}}/api/{{API_VERSION}}/organizations/5dba067e-d7fd-4d79-a08a-ec379834938a
|
||||
body: none
|
||||
auth: bearer
|
||||
}
|
||||
|
||||
auth:bearer {
|
||||
token: {{BEARER_TOKEN}}
|
||||
}
|
||||
|
||||
settings {
|
||||
encodeUrl: true
|
||||
}
|
||||
39
bruno/propify/Organizations/Upload files.bru
Normal file
39
bruno/propify/Organizations/Upload files.bru
Normal file
@@ -0,0 +1,39 @@
|
||||
meta {
|
||||
name: Upload files
|
||||
type: http
|
||||
seq: 5
|
||||
}
|
||||
|
||||
post {
|
||||
url: {{API_BASE_URL}}/api/{{API_VERSION}}/organizations/f4eb0c54-7c8f-4e60-b71f-1d08b8b6e2d4/upload
|
||||
body: multipartForm
|
||||
auth: bearer
|
||||
}
|
||||
|
||||
auth:bearer {
|
||||
token: {{BEARER_TOKEN}}
|
||||
}
|
||||
|
||||
body:json {
|
||||
{
|
||||
"name": "Bungalow",
|
||||
"street": "Hebbelstraße",
|
||||
"houseNumber": "30",
|
||||
"zipCode": "55127",
|
||||
"city": "Mainz",
|
||||
"country": "DE",
|
||||
"notes": "Lorem ipsum"
|
||||
}
|
||||
}
|
||||
|
||||
body:multipart-form {
|
||||
attachments: @file(/Users/murat/Pictures/IMG_0229.jpeg|/Users/murat/Pictures/schnürsenkel technik.gif)
|
||||
}
|
||||
|
||||
body:file {
|
||||
file: @file(/Users/murat/Pictures/IMG_0229.jpeg) @contentType(image/jpeg)
|
||||
}
|
||||
|
||||
settings {
|
||||
encodeUrl: true
|
||||
}
|
||||
8
bruno/propify/Organizations/folder.bru
Normal file
8
bruno/propify/Organizations/folder.bru
Normal file
@@ -0,0 +1,8 @@
|
||||
meta {
|
||||
name: Organizations
|
||||
seq: 8
|
||||
}
|
||||
|
||||
auth {
|
||||
mode: inherit
|
||||
}
|
||||
@@ -9,8 +9,8 @@ vars {
|
||||
KEYCLOAK_CLIENT_ID: skamp-app
|
||||
KEYCLOAK_REALM: skamp
|
||||
KEYCLOAK_BRUNO_CLIENT_ID: skamp-bruno
|
||||
KEYCLOAK_BRUNO_CLIENT_SECRET: sNQpCVyVckGo5AZw7FqeW0POtgWuXzJt
|
||||
}
|
||||
vars:secret [
|
||||
BEARER_TOKEN
|
||||
BEARER_TOKEN,
|
||||
KEYCLOAK_BRUNO_CLIENT_SECRET
|
||||
]
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
package de.iwomm.propify_api.controller;
|
||||
|
||||
import de.iwomm.propify_api.dto.*;
|
||||
import de.iwomm.propify_api.entity.Industry;
|
||||
import de.iwomm.propify_api.mapper.IndustryMapper;
|
||||
import de.iwomm.propify_api.service.IndustryService;
|
||||
import jakarta.persistence.EntityNotFoundException;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/v1/industries")
|
||||
public class IndustryController {
|
||||
private final IndustryService industryService;
|
||||
private final IndustryMapper industryMapper;
|
||||
|
||||
public IndustryController(IndustryService industryService, IndustryMapper industryMapper) {
|
||||
this.industryService = industryService;
|
||||
this.industryMapper = industryMapper;
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
@PreAuthorize("hasAnyRole('ROLE_ADMIN', 'ROLE_USER', 'ROLE_DEV')")
|
||||
public ResponseEntity<?> getAll() {
|
||||
List<IndustryDTO> industryDTOs = industryService.toDTOs(industryService.findAll());
|
||||
|
||||
return ResponseEntity
|
||||
.ok(industryDTOs);
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
@PreAuthorize("hasAnyRole('ROLE_ADMIN', 'ROLE_USER', 'ROLE_DEV')")
|
||||
public ResponseEntity<?> getById(@PathVariable UUID id) {
|
||||
try {
|
||||
Industry industry = industryService.findById(id).orElseThrow(EntityNotFoundException::new);
|
||||
IndustryDTO projectDTO = industryMapper.toDto(industry);
|
||||
|
||||
return ResponseEntity
|
||||
.ok(projectDTO);
|
||||
} catch (EntityNotFoundException e) {
|
||||
return ResponseEntity
|
||||
.notFound()
|
||||
.build();
|
||||
} catch (Exception e) {
|
||||
return ResponseEntity
|
||||
.internalServerError()
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
@PreAuthorize("hasAnyRole('ROLE_ADMIN', 'ROLE_USER', 'ROLE_DEV')")
|
||||
public ResponseEntity<?> create(@RequestBody IndustryDTO newIndustryDTO) {
|
||||
try {
|
||||
Industry newItem = industryService.save(newIndustryDTO);
|
||||
|
||||
URI location = ServletUriComponentsBuilder.fromCurrentRequest()
|
||||
.path("/{id}")
|
||||
.buildAndExpand(newItem.getId())
|
||||
.toUri();
|
||||
|
||||
return ResponseEntity
|
||||
.created(location)
|
||||
.body(newItem);
|
||||
} catch (Exception e) {
|
||||
return ResponseEntity
|
||||
.internalServerError()
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
@PatchMapping("/{id}")
|
||||
@PreAuthorize("hasAnyRole('ROLE_ADMIN', 'ROLE_USER', 'ROLE_DEV')")
|
||||
public ResponseEntity<?> update(@PathVariable UUID id, @RequestBody IndustryDTO industryDTO) {
|
||||
try {
|
||||
return ResponseEntity
|
||||
.ok(industryService.update(id, industryDTO));
|
||||
} catch (EntityNotFoundException e) {
|
||||
return ResponseEntity
|
||||
.notFound()
|
||||
.build();
|
||||
} catch (Exception e) {
|
||||
return ResponseEntity
|
||||
.internalServerError()
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
@DeleteMapping("/{id}")
|
||||
@PreAuthorize("hasAnyRole('ROLE_ADMIN', 'ROLE_USER', 'ROLE_DEV')")
|
||||
public ResponseEntity<?> delete(@PathVariable UUID id) {
|
||||
try {
|
||||
industryService.deleteById(id);
|
||||
|
||||
return ResponseEntity
|
||||
.noContent()
|
||||
.build();
|
||||
} catch (EntityNotFoundException e) {
|
||||
return ResponseEntity
|
||||
.notFound()
|
||||
.build();
|
||||
} catch (Exception e) {
|
||||
return ResponseEntity
|
||||
.internalServerError()
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping("/bulk-delete")
|
||||
@PreAuthorize("hasAnyRole('ROLE_ADMIN', 'ROLE_USER', 'ROLE_DEV')")
|
||||
public ResponseEntity<?> deleteMany(@RequestBody BulkDeleteIdsDTO bulkDeleteIdsDTO) {
|
||||
try {
|
||||
industryService.deleteByIds(bulkDeleteIdsDTO);
|
||||
|
||||
return ResponseEntity
|
||||
.noContent()
|
||||
.build();
|
||||
} catch (EntityNotFoundException e) {
|
||||
return ResponseEntity
|
||||
.notFound()
|
||||
.build();
|
||||
} catch (Exception e) {
|
||||
return ResponseEntity
|
||||
.internalServerError()
|
||||
.build();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
package de.iwomm.propify_api.controller;
|
||||
|
||||
import de.iwomm.propify_api.dto.OrganizationDTO;
|
||||
import de.iwomm.propify_api.dto.ProjectDetailsDTO;
|
||||
import de.iwomm.propify_api.entity.Organization;
|
||||
import de.iwomm.propify_api.entity.Project;
|
||||
import de.iwomm.propify_api.mapper.OrganizationMapper;
|
||||
import de.iwomm.propify_api.service.OrganisationService;
|
||||
import jakarta.persistence.EntityNotFoundException;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/v1/organizations")
|
||||
public class OrganizationController {
|
||||
|
||||
private final OrganizationMapper organizationMapper;
|
||||
private OrganisationService organisationService;
|
||||
|
||||
public OrganizationController(OrganisationService organisationService, OrganizationMapper organizationMapper) {
|
||||
this.organisationService = organisationService;
|
||||
this.organizationMapper = organizationMapper;
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
@PreAuthorize("hasAnyRole('ROLE_ADMIN', 'ROLE_USER')")
|
||||
public ResponseEntity<?> getAll() {
|
||||
List<OrganizationDTO> organizationDTOs = organisationService.toDTOs(organisationService.findAll());
|
||||
|
||||
return ResponseEntity
|
||||
.ok(organizationDTOs);
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
@PreAuthorize("hasAnyRole('ROLE_ADMIN', 'ROLE_USER')")
|
||||
public ResponseEntity<?> getById(@PathVariable UUID id) {
|
||||
try {
|
||||
Organization organization = organisationService.findById(id).orElseThrow(EntityNotFoundException::new);
|
||||
OrganizationDTO organizationDTO = organizationMapper.toDto(organization);
|
||||
|
||||
return ResponseEntity
|
||||
.ok(organizationDTO);
|
||||
} catch (EntityNotFoundException e) {
|
||||
return ResponseEntity
|
||||
.notFound()
|
||||
.build();
|
||||
} catch (Exception e) {
|
||||
return ResponseEntity
|
||||
.internalServerError()
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
@DeleteMapping("/{id}")
|
||||
@PreAuthorize("hasAnyRole('ROLE_ADMIN', 'ROLE_USER')")
|
||||
public ResponseEntity<?> deleteById(@PathVariable UUID id) {
|
||||
try {
|
||||
Organization organization = organisationService.findById(id).orElseThrow(EntityNotFoundException::new);
|
||||
|
||||
organisationService.delete(organization);
|
||||
|
||||
return ResponseEntity
|
||||
.ok()
|
||||
.build();
|
||||
} catch (EntityNotFoundException e) {
|
||||
return ResponseEntity
|
||||
.notFound()
|
||||
.build();
|
||||
} catch (Exception e) {
|
||||
return ResponseEntity
|
||||
.internalServerError()
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
@PreAuthorize("hasAnyRole('ROLE_ADMIN', 'ROLE_DEV')")
|
||||
public ResponseEntity<?> create(@RequestBody OrganizationDTO organizationDTO) {
|
||||
try {
|
||||
Organization newItem = organisationService.save(organizationDTO);
|
||||
|
||||
URI location = ServletUriComponentsBuilder.fromCurrentRequest()
|
||||
.path("/{id}")
|
||||
.buildAndExpand(newItem.getId())
|
||||
.toUri();
|
||||
|
||||
return ResponseEntity
|
||||
.created(location)
|
||||
.body(newItem);
|
||||
} catch (Exception e) {
|
||||
return ResponseEntity
|
||||
.internalServerError()
|
||||
.build();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package de.iwomm.propify_api.dto;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public record BulkDeleteIdsDTO(
|
||||
List<UUID> ids
|
||||
) {
|
||||
}
|
||||
9
src/main/java/de/iwomm/propify_api/dto/IndustryDTO.java
Normal file
9
src/main/java/de/iwomm/propify_api/dto/IndustryDTO.java
Normal file
@@ -0,0 +1,9 @@
|
||||
package de.iwomm.propify_api.dto;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public record IndustryDTO(
|
||||
UUID id,
|
||||
String name
|
||||
) {
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package de.iwomm.propify_api.dto;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public record NewOrganizationDTO(
|
||||
String name,
|
||||
String owner,
|
||||
UUID industryId
|
||||
) {
|
||||
}
|
||||
14
src/main/java/de/iwomm/propify_api/dto/OrganizationDTO.java
Normal file
14
src/main/java/de/iwomm/propify_api/dto/OrganizationDTO.java
Normal file
@@ -0,0 +1,14 @@
|
||||
package de.iwomm.propify_api.dto;
|
||||
|
||||
import de.iwomm.propify_api.entity.Industry;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
public record OrganizationDTO(
|
||||
UUID id,
|
||||
String name,
|
||||
IndustryDTO industry,
|
||||
String owner,
|
||||
Set<OrganizationLabelDTO> labels
|
||||
) { }
|
||||
@@ -0,0 +1,9 @@
|
||||
package de.iwomm.propify_api.dto;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public record OrganizationLabelDTO(
|
||||
UUID id,
|
||||
String name
|
||||
) {
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package de.iwomm.propify_api.entity;
|
||||
|
||||
|
||||
import de.iwomm.propify_api.entitylistener.TenantEntityListener;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.EntityListeners;
|
||||
import jakarta.persistence.MappedSuperclass;
|
||||
|
||||
@MappedSuperclass
|
||||
@EntityListeners(TenantEntityListener.class)
|
||||
public abstract class MultiTenantEntity {
|
||||
|
||||
@Column(name = "tenant_id")
|
||||
private String tenantId;
|
||||
|
||||
public String getTenantId() {
|
||||
return tenantId;
|
||||
}
|
||||
|
||||
public void setTenantId(String tenantId) {
|
||||
this.tenantId = tenantId;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,6 +2,8 @@ package de.iwomm.propify_api.entity;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
@Entity
|
||||
@@ -24,6 +26,15 @@ public class Organization {
|
||||
@Column(nullable = false)
|
||||
private LocalDateTime createdAt;
|
||||
|
||||
@ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
|
||||
@JoinTable(
|
||||
name = "organization_labels",
|
||||
joinColumns = @JoinColumn(name = "organization_id"),
|
||||
inverseJoinColumns = @JoinColumn(name = "label_id"),
|
||||
foreignKey = @ForeignKey(name = "fk_organization_labels_organization", foreignKeyDefinition = "FOREIGN KEY (organization_id) REFERENCES organization(id) ON DELETE CASCADE")
|
||||
)
|
||||
private Set<OrganizationLabel> labels = new HashSet<>();
|
||||
|
||||
@PrePersist
|
||||
protected void onCreate() {
|
||||
this.createdAt = LocalDateTime.now();
|
||||
@@ -68,4 +79,12 @@ public class Organization {
|
||||
public void setCreatedAt(LocalDateTime createdAt) {
|
||||
this.createdAt = createdAt;
|
||||
}
|
||||
|
||||
public Set<OrganizationLabel> getLabels() {
|
||||
return labels;
|
||||
}
|
||||
|
||||
public void setLabels(Set<OrganizationLabel> labels) {
|
||||
this.labels = labels;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
package de.iwomm.propify_api.entity;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import java.util.UUID;
|
||||
|
||||
@Entity
|
||||
public class OrganizationLabel {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.UUID)
|
||||
@Column(nullable = false)
|
||||
private UUID id;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String name;
|
||||
|
||||
public UUID getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(UUID id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,9 @@ package de.iwomm.propify_api.entity;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonManagedReference;
|
||||
import jakarta.persistence.*;
|
||||
import org.hibernate.annotations.Filter;
|
||||
import org.hibernate.annotations.FilterDef;
|
||||
import org.hibernate.annotations.ParamDef;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
@@ -10,7 +13,9 @@ import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@Entity
|
||||
public class Project {
|
||||
@FilterDef(name = "tenantFilter", parameters = @ParamDef(name = "tenantId", type = String.class))
|
||||
@Filter(name = "tenantFilter", condition = "tenant_id = :tenantId")
|
||||
public class Project extends MultiTenantEntity {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.UUID)
|
||||
@Column(nullable = false)
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
package de.iwomm.propify_api.entitylistener;
|
||||
|
||||
import de.iwomm.propify_api.entity.MultiTenantEntity;
|
||||
import de.iwomm.propify_api.security.TenantContext;
|
||||
import jakarta.persistence.PrePersist;
|
||||
|
||||
public class TenantEntityListener {
|
||||
|
||||
@PrePersist
|
||||
public void setTenant(Object entity) {
|
||||
if (entity instanceof MultiTenantEntity mte) {
|
||||
String tenantId = TenantContext.getTenantId();
|
||||
if (tenantId != null && mte.getTenantId() == null) {
|
||||
mte.setTenantId(tenantId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package de.iwomm.propify_api.mapper;
|
||||
|
||||
import de.iwomm.propify_api.dto.IndustryDTO;
|
||||
import de.iwomm.propify_api.entity.Industry;
|
||||
import org.mapstruct.Mapper;
|
||||
|
||||
@Mapper(componentModel = "spring")
|
||||
public interface IndustryMapper {
|
||||
IndustryDTO toDto(Industry industry);
|
||||
Industry fromDto(IndustryDTO industryDTO);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package de.iwomm.propify_api.mapper;
|
||||
|
||||
import de.iwomm.propify_api.dto.OrganizationLabelDTO;
|
||||
import de.iwomm.propify_api.entity.OrganizationLabel;
|
||||
import org.mapstruct.Mapper;
|
||||
|
||||
@Mapper(componentModel = "spring")
|
||||
public interface OrganizationLabelMapper {
|
||||
OrganizationLabelDTO toDto(OrganizationLabel organizationLabel);
|
||||
OrganizationLabel fromDto(OrganizationLabelDTO organizationLabelDTO);
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package de.iwomm.propify_api.mapper;
|
||||
|
||||
import de.iwomm.propify_api.dto.NewOrganizationDTO;
|
||||
import de.iwomm.propify_api.dto.OrganizationDTO;
|
||||
import de.iwomm.propify_api.entity.Organization;
|
||||
import org.mapstruct.Mapper;
|
||||
|
||||
@Mapper(componentModel = "spring", uses = { OrganizationLabelMapper.class, IndustryMapper.class })
|
||||
public interface OrganizationMapper {
|
||||
OrganizationDTO toDto(Organization organization);
|
||||
Organization fromDto(OrganizationDTO organizationDTO);
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package de.iwomm.propify_api.repository;
|
||||
|
||||
import de.iwomm.propify_api.entity.OrganizationLabel;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public interface OrganizationLabelRepository extends JpaRepository<OrganizationLabel, UUID> {
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package de.iwomm.propify_api.security;
|
||||
|
||||
public class TenantContext {
|
||||
private static final ThreadLocal<String> CURRENT_TENANT = new ThreadLocal<>();
|
||||
|
||||
public static void setTenantId(String tenantId) {
|
||||
CURRENT_TENANT.set(tenantId);
|
||||
}
|
||||
|
||||
public static String getTenantId() {
|
||||
return CURRENT_TENANT.get();
|
||||
}
|
||||
|
||||
public static void clear() {
|
||||
CURRENT_TENANT.remove();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package de.iwomm.propify_api.security;
|
||||
|
||||
import jakarta.persistence.EntityManager;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.hibernate.Session;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.oauth2.jwt.Jwt;
|
||||
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
@Order(1)
|
||||
public class TenantFilter extends OncePerRequestFilter {
|
||||
|
||||
private final EntityManager entityManager;
|
||||
|
||||
public TenantFilter(EntityManager entityManager) {
|
||||
this.entityManager = entityManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
FilterChain filterChain)
|
||||
throws ServletException, IOException {
|
||||
|
||||
String tenantId = null;
|
||||
|
||||
// 1️⃣ Tenant-ID aus JWT lesen
|
||||
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
|
||||
if (auth instanceof JwtAuthenticationToken jwtAuth) {
|
||||
Jwt jwt = jwtAuth.getToken();
|
||||
|
||||
// tenant_id Claim
|
||||
tenantId = jwt.getClaimAsString("tenant_id");
|
||||
|
||||
// Rollen prüfen, Superadmin darf alles sehen
|
||||
List<String> roles = jwt.getClaimAsStringList("roles");
|
||||
if (roles != null && roles.contains("ROLE_SUPERADMIN")) {
|
||||
tenantId = null; // kein Filter für Superadmin
|
||||
}
|
||||
}
|
||||
|
||||
// 2️⃣ Fallback: Header (optional, falls JWT fehlt)
|
||||
if (tenantId == null) {
|
||||
tenantId = request.getHeader("X-Tenant-ID");
|
||||
}
|
||||
|
||||
// 3️⃣ TenantContext für diesen Thread setzen
|
||||
TenantContext.setTenantId(tenantId);
|
||||
|
||||
// 4️⃣ Hibernate Filter aktivieren (falls Tenant-ID vorhanden)
|
||||
if (tenantId != null) {
|
||||
Session session = entityManager.unwrap(Session.class);
|
||||
session.enableFilter("tenantFilter")
|
||||
.setParameter("tenantId", tenantId);
|
||||
}
|
||||
|
||||
try {
|
||||
filterChain.doFilter(request, response);
|
||||
} finally {
|
||||
// 5️⃣ Aufräumen nach Request
|
||||
TenantContext.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package de.iwomm.propify_api.service;
|
||||
|
||||
import de.iwomm.propify_api.dto.*;
|
||||
import de.iwomm.propify_api.entity.Industry;
|
||||
import de.iwomm.propify_api.entity.Organization;
|
||||
import de.iwomm.propify_api.entity.Project;
|
||||
import de.iwomm.propify_api.entity.Property;
|
||||
import de.iwomm.propify_api.mapper.IndustryMapper;
|
||||
import de.iwomm.propify_api.repository.IndustryRepository;
|
||||
import jakarta.persistence.EntityNotFoundException;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
@Service
|
||||
public class IndustryService {
|
||||
private IndustryRepository industryRepository;
|
||||
private IndustryMapper industryMapper;
|
||||
|
||||
|
||||
public IndustryService(IndustryRepository industryRepository, IndustryMapper industryMapper) {
|
||||
this.industryRepository = industryRepository;
|
||||
this.industryMapper = industryMapper;
|
||||
}
|
||||
|
||||
public List<Industry> findAll() {
|
||||
return industryRepository.findAll();
|
||||
}
|
||||
|
||||
public Optional<Industry> findById(UUID id) {
|
||||
return industryRepository.findById(id);
|
||||
}
|
||||
|
||||
public Industry save(IndustryDTO dto) {
|
||||
return industryRepository.save(industryMapper.fromDto(dto));
|
||||
}
|
||||
|
||||
public void deleteByIds(BulkDeleteIdsDTO bulkDeleteIdsDTO) {
|
||||
industryRepository.deleteAllById(bulkDeleteIdsDTO.ids());
|
||||
}
|
||||
|
||||
public List<IndustryDTO> toDTOs(List<Industry> industries) {
|
||||
List<IndustryDTO> dtos = new ArrayList<>();
|
||||
|
||||
industries.forEach(industry -> {
|
||||
dtos.add(this.industryMapper.toDto(industry));
|
||||
});
|
||||
|
||||
return dtos;
|
||||
}
|
||||
|
||||
public Industry update(UUID id, IndustryDTO industryDTO) {
|
||||
Industry updated = industryRepository.findById(id).orElseThrow(EntityNotFoundException::new);
|
||||
|
||||
updated.setName(industryDTO.name());
|
||||
|
||||
industryRepository.save(updated);
|
||||
|
||||
return updated;
|
||||
}
|
||||
|
||||
public void deleteById(UUID id) {
|
||||
Industry industry = industryRepository.findById(id).orElseThrow(EntityNotFoundException::new);
|
||||
industryRepository.delete(industry);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package de.iwomm.propify_api.service;
|
||||
|
||||
import de.iwomm.propify_api.dto.NewOrganizationDTO;
|
||||
import de.iwomm.propify_api.dto.OrganizationDTO;
|
||||
import de.iwomm.propify_api.dto.ProjectDTO;
|
||||
import de.iwomm.propify_api.entity.Organization;
|
||||
import de.iwomm.propify_api.entity.Project;
|
||||
import de.iwomm.propify_api.mapper.OrganizationMapper;
|
||||
import de.iwomm.propify_api.repository.OrganizationRepository;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
@Service
|
||||
public class OrganisationService {
|
||||
private final OrganizationRepository organizationRepository;
|
||||
private final OrganizationMapper organizationMapper;
|
||||
|
||||
public OrganisationService(
|
||||
OrganizationRepository organizationRepository,
|
||||
OrganizationMapper organizationMapper
|
||||
) {
|
||||
this.organizationRepository = organizationRepository;
|
||||
this.organizationMapper = organizationMapper;
|
||||
}
|
||||
|
||||
public List<Organization> findAll() {
|
||||
return organizationRepository.findAll();
|
||||
}
|
||||
|
||||
public Optional<Organization> findById(UUID id) {
|
||||
return organizationRepository.findById(id);
|
||||
}
|
||||
|
||||
public void deleteBbyId(UUID id) {
|
||||
organizationRepository.deleteById(id);
|
||||
}
|
||||
|
||||
public void delete(Organization organization) {
|
||||
organizationRepository.delete(organization);
|
||||
}
|
||||
|
||||
public List<OrganizationDTO> toDTOs(List<Organization> organizations) {
|
||||
List<OrganizationDTO> dtos = new ArrayList<>();
|
||||
|
||||
organizations.forEach(organization -> {
|
||||
dtos.add(this.organizationMapper.toDto(organization));
|
||||
});
|
||||
|
||||
return dtos;
|
||||
}
|
||||
|
||||
public Organization save(OrganizationDTO dto) {
|
||||
return organizationRepository.save(organizationMapper.fromDto(dto));
|
||||
}
|
||||
}
|
||||
@@ -39,6 +39,7 @@ spring:
|
||||
resourceserver:
|
||||
jwt:
|
||||
issuer-uri: ${KEYCLOAK_ISSUER_URI:https://kc.dev.localhost/realms/skamp}
|
||||
#issuer-uri: ${KEYCLOAK_ISSUER_URI:http://localhost:8888/realms/skamp}
|
||||
jwk-set-uri: ${spring.security.oauth2.resourceserver.jwt.issuer-uri}/protocol/openid-connect/certs
|
||||
|
||||
logging:
|
||||
|
||||
Reference in New Issue
Block a user