diff --git a/legalconsenthub-backend/api/legalconsenthub.yml b/legalconsenthub-backend/api/legalconsenthub.yml index 273875c..8084a23 100644 --- a/legalconsenthub-backend/api/legalconsenthub.yml +++ b/legalconsenthub-backend/api/legalconsenthub.yml @@ -20,6 +20,12 @@ paths: operationId: getAllApplicationForms tags: - application-form + parameters: + - in: query + name: organizationId + schema: + type: string + description: Filter application forms by organization ID responses: "200": description: Paged list of application forms @@ -580,6 +586,7 @@ components: - name - formElements - isTemplate + - organizationId - createdBy - lastModifiedBy - createdAt @@ -596,6 +603,8 @@ components: $ref: "#/components/schemas/FormElementDto" isTemplate: type: boolean + organizationId: + type: string createdBy: $ref: "#/components/schemas/UserDto" lastModifiedBy: @@ -612,8 +621,6 @@ components: - name - formElements - isTemplate - - createdBy - - lastModifiedBy type: object properties: name: @@ -625,6 +632,8 @@ components: isTemplate: type: boolean default: false + organizationId: + type: string PagedApplicationFormDto: type: object diff --git a/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/application_form/ApplicationForm.kt b/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/application_form/ApplicationForm.kt index b605875..df86c27 100644 --- a/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/application_form/ApplicationForm.kt +++ b/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/application_form/ApplicationForm.kt @@ -34,6 +34,8 @@ class ApplicationForm( @Column(nullable = false) var isTemplate: Boolean, + var organizationId: String = "", + @Embedded @AttributeOverrides( AttributeOverride(name = "id", column = Column(name = "created_by_id", nullable = false)), diff --git a/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/application_form/ApplicationFormController.kt b/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/application_form/ApplicationFormController.kt index 47b37d5..340dd8a 100644 --- a/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/application_form/ApplicationFormController.kt +++ b/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/application_form/ApplicationFormController.kt @@ -24,10 +24,10 @@ class ApplicationFormController( ) } - override fun getAllApplicationForms(): ResponseEntity { + override fun getAllApplicationForms(organizationId: String?): ResponseEntity { return ResponseEntity.ok( pagedApplicationFormMapper.toPagedApplicationFormDto( - applicationFormService.getApplicationForms() + applicationFormService.getApplicationForms(organizationId) ) ) } diff --git a/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/application_form/ApplicationFormMapper.kt b/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/application_form/ApplicationFormMapper.kt index d962e52..87bef25 100644 --- a/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/application_form/ApplicationFormMapper.kt +++ b/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/application_form/ApplicationFormMapper.kt @@ -17,6 +17,7 @@ class ApplicationFormMapper(private val formElementMapper: FormElementMapper, pr name = applicationForm.name, formElements = applicationForm.formElements.map { formElementMapper.toFormElementDto(it) }, isTemplate = applicationForm.isTemplate, + organizationId = applicationForm.organizationId, createdBy = userMapper.toUserDto(applicationForm.createdBy), lastModifiedBy = userMapper.toUserDto(applicationForm.lastModifiedBy), createdAt = applicationForm.createdAt ?: LocalDateTime.now(), @@ -30,6 +31,7 @@ class ApplicationFormMapper(private val formElementMapper: FormElementMapper, pr name = applicationForm.name, formElements = applicationForm.formElements.map { formElementMapper.toFormElement(it) }.toMutableList(), isTemplate = applicationForm.isTemplate, + organizationId = applicationForm.organizationId, createdBy = userMapper.toUser(applicationForm.createdBy), lastModifiedBy = userMapper.toUser(applicationForm.lastModifiedBy), createdAt = applicationForm.createdAt, @@ -38,6 +40,7 @@ class ApplicationFormMapper(private val formElementMapper: FormElementMapper, pr } fun toApplicationForm(createApplicationFormDto: CreateApplicationFormDto): ApplicationForm { + // TODO: Move this in upper layer val principal = SecurityContextHolder.getContext().authentication.principal as CustomJwtTokenPrincipal val createdBy = User(principal.name ?: "UNKNOWN USER", principal.id ?: "") val lastModifiedBy = User(principal.name ?: "UNKNOWN USER", principal.id ?: "") @@ -45,6 +48,7 @@ class ApplicationFormMapper(private val formElementMapper: FormElementMapper, pr val applicationForm = ApplicationForm( name = createApplicationFormDto.name, isTemplate = createApplicationFormDto.isTemplate, + organizationId = createApplicationFormDto.organizationId ?: "", createdBy = createdBy, lastModifiedBy = lastModifiedBy, ) diff --git a/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/application_form/ApplicationFormRepository.kt b/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/application_form/ApplicationFormRepository.kt index 3d36f05..3007769 100644 --- a/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/application_form/ApplicationFormRepository.kt +++ b/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/application_form/ApplicationFormRepository.kt @@ -3,11 +3,14 @@ package com.betriebsratkanzlei.legalconsenthub.application_form import org.springframework.data.domain.Page import org.springframework.data.domain.Pageable import org.springframework.data.jpa.repository.JpaRepository +import org.springframework.data.jpa.repository.Query import org.springframework.stereotype.Repository import java.util.UUID @Repository interface ApplicationFormRepository : JpaRepository { fun findAllByIsTemplateTrue(page: Pageable): Page - fun findAllByIsTemplateFalse(page: Pageable): Page + + @Query("SELECT c FROM ApplicationForm c WHERE (c.isTemplate IS false) AND (:organizationId is null or c.organizationId = :organizationId)") + fun findAllByIsTemplateFalseAndOrganizationId(organizationId: String?, page: Pageable): Page } diff --git a/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/application_form/ApplicationFormService.kt b/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/application_form/ApplicationFormService.kt index 420654b..51ba940 100644 --- a/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/application_form/ApplicationFormService.kt +++ b/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/application_form/ApplicationFormService.kt @@ -33,12 +33,13 @@ class ApplicationFormService( return applicationFormRepository.findById(id).orElseThrow { ApplicationFormNotFoundException(id) } } - fun getApplicationForms(): Page { + fun getApplicationForms(organizationId: String?): Page { val pageable = PageRequest.of(0, 10) - return applicationFormRepository.findAllByIsTemplateFalse(pageable) + return applicationFormRepository.findAllByIsTemplateFalseAndOrganizationId(organizationId, pageable) } fun updateApplicationForm(applicationFormDto: ApplicationFormDto): ApplicationForm { + // TODO find statt mappen? val applicationForm = applicationFormMapper.toApplicationForm(applicationFormDto) val updatedApplicationForm: ApplicationForm diff --git a/legalconsenthub-backend/src/main/resources/db/migrations/001-schema.sql b/legalconsenthub-backend/src/main/resources/db/migrations/001-schema.sql index 8d6d553..53f05f9 100644 --- a/legalconsenthub-backend/src/main/resources/db/migrations/001-schema.sql +++ b/legalconsenthub-backend/src/main/resources/db/migrations/001-schema.sql @@ -9,6 +9,7 @@ create table application_form last_modified_by_id varchar(255) not null, last_modified_by_name varchar(255) not null, name varchar(255) not null, + organization_id varchar(255), primary key (id) ); diff --git a/legalconsenthub/composables/applicationForm/useApplicationForm.ts b/legalconsenthub/composables/applicationForm/useApplicationForm.ts index 6048008..5c24ff4 100644 --- a/legalconsenthub/composables/applicationForm/useApplicationForm.ts +++ b/legalconsenthub/composables/applicationForm/useApplicationForm.ts @@ -27,9 +27,9 @@ export function useApplicationForm() { } } - async function getAllApplicationForms(): Promise { + async function getAllApplicationForms(organizationId: string): Promise { try { - return await applicationFormApi.getAllApplicationForms() + return await applicationFormApi.getAllApplicationForms(organizationId) } catch (e: unknown) { if (e instanceof ResponseError) { console.error('Failed retrieving application forms:', e.response) diff --git a/legalconsenthub/composables/applicationForm/useApplicationFormApi.ts b/legalconsenthub/composables/applicationForm/useApplicationFormApi.ts index fc8f6c1..b1fbbed 100644 --- a/legalconsenthub/composables/applicationForm/useApplicationFormApi.ts +++ b/legalconsenthub/composables/applicationForm/useApplicationFormApi.ts @@ -21,8 +21,8 @@ export function useApplicationFormApi() { return applicationFormApiClient.createApplicationForm({ createApplicationFormDto }) } - async function getAllApplicationForms(): Promise { - return applicationFormApiClient.getAllApplicationForms() + async function getAllApplicationForms(organizationId: string): Promise { + return applicationFormApiClient.getAllApplicationForms({ organizationId }) } async function getApplicationFormById(id: string): Promise { diff --git a/legalconsenthub/composables/useAuth.ts b/legalconsenthub/composables/useAuth.ts index 1c662b7..9c97e9f 100644 --- a/legalconsenthub/composables/useAuth.ts +++ b/legalconsenthub/composables/useAuth.ts @@ -11,6 +11,22 @@ interface RuntimeAuthConfig { redirectGuestTo: RouteLocationRaw | string } +const session = ref | null>(null) +const user = ref | null>(null) +const sessionFetching = import.meta.server ? ref(false) : ref(false) +const jwt = ref(null) +const organizations = ref< + { id: string; name: string; createdAt: Date; slug: string; metadata?: any; logo?: string | null }[] +>([]) +const selectedOrganization = ref<{ + id: string + name: string + createdAt: Date + slug: string + metadata?: any + logo?: string | null +} | null>(null) + export function useAuth() { const url = useRequestURL() const headers = import.meta.server ? useRequestHeaders() : undefined @@ -27,10 +43,6 @@ export function useAuth() { redirectUserTo: '/', redirectGuestTo: '/login' }) - const session = useState | null>('auth:session', () => null) - const user = useState | null>('auth:user', () => null) - const sessionFetching = import.meta.server ? ref(false) : useState('auth:sessionFetching', () => false) - const jwt = useState('auth:jwt', () => null) async function fetchSession() { if (sessionFetching.value) { @@ -43,13 +55,33 @@ export function useAuth() { headers } }) - jwt.value = (await client.token()).data?.token ?? null session.value = data?.session || null user.value = data?.user || null sessionFetching.value = false + + // Fetch JWT - workaround for not working extraction of JWT out of session (https://github.com/better-auth/better-auth/issues/1835) + jwt.value = (await client.token()).data?.token ?? null + + // Fetch organization + organizations.value = (await client.organization.list()).data ?? [] + if (!selectedOrganization.value && organizations.value.length > 0) { + selectedOrganization.value = organizations.value[0] + } + return data } + watch( + () => selectedOrganization.value, + async (newValue) => { + if (newValue) { + await client.organization.setActive({ + organizationId: newValue?.id + }) + } + } + ) + if (import.meta.client) { client.$store.listen('$sessionSignal', async (signal) => { if (!signal) return @@ -79,6 +111,8 @@ export function useAuth() { signUp: client.signUp, signOut, organization: client.organization, + organizations, + selectedOrganization, options, fetchSession, client, diff --git a/legalconsenthub/pages/create.vue b/legalconsenthub/pages/create.vue index 18d1f41..afbdb79 100644 --- a/legalconsenthub/pages/create.vue +++ b/legalconsenthub/pages/create.vue @@ -16,6 +16,7 @@