package com.android.trisolarisserver.controller import com.android.trisolarisserver.controller.dto.OrgCreateRequest import com.android.trisolarisserver.controller.dto.OrgResponse import com.android.trisolarisserver.repo.AppUserRepo import com.android.trisolarisserver.repo.OrganizationRepo import com.android.trisolarisserver.repo.PropertyUserRepo import com.android.trisolarisserver.models.booking.TransportMode import com.android.trisolarisserver.models.property.Organization import com.android.trisolarisserver.models.property.Role import com.android.trisolarisserver.security.MyPrincipal import org.springframework.http.HttpStatus import org.springframework.security.core.annotation.AuthenticationPrincipal import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.PathVariable import org.springframework.web.bind.annotation.PostMapping import org.springframework.web.bind.annotation.RequestBody import org.springframework.web.bind.annotation.RequestMapping import org.springframework.web.bind.annotation.ResponseStatus import org.springframework.web.bind.annotation.RestController import org.springframework.web.server.ResponseStatusException import java.util.UUID @RestController @RequestMapping("/orgs") class Orgs( private val orgRepo: OrganizationRepo, private val appUserRepo: AppUserRepo, private val propertyUserRepo: PropertyUserRepo ) { @PostMapping @ResponseStatus(HttpStatus.CREATED) fun createOrg( @AuthenticationPrincipal principal: MyPrincipal?, @RequestBody request: OrgCreateRequest ): OrgResponse { val user = requireUser(principal) val orgId = user.org.id ?: throw ResponseStatusException(HttpStatus.UNAUTHORIZED, "Org missing") if (!propertyUserRepo.hasAnyRoleInOrg(orgId, user.id!!, setOf(Role.ADMIN))) { throw ResponseStatusException(HttpStatus.FORBIDDEN, "Missing role") } val org = Organization().apply { name = request.name emailAliases = request.emailAliases?.toMutableSet() ?: mutableSetOf() if (request.allowedTransportModes != null) { allowedTransportModes = parseTransportModes(request.allowedTransportModes) } } val saved = orgRepo.save(org) return OrgResponse( id = saved.id ?: throw ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "Org id missing"), name = saved.name ?: "", emailAliases = saved.emailAliases.toSet(), allowedTransportModes = saved.allowedTransportModes.map { it.name }.toSet() ) } @GetMapping("/{orgId}") fun getOrg( @PathVariable orgId: UUID, @AuthenticationPrincipal principal: MyPrincipal? ): OrgResponse { val user = requireUser(principal) if (user.org.id != orgId) { throw ResponseStatusException(HttpStatus.FORBIDDEN, "No access to org") } val org = orgRepo.findById(orgId).orElseThrow { ResponseStatusException(HttpStatus.NOT_FOUND, "Org not found") } return OrgResponse( id = org.id ?: throw ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "Org id missing"), name = org.name ?: "", emailAliases = org.emailAliases.toSet(), allowedTransportModes = org.allowedTransportModes.map { it.name }.toSet() ) } private fun requireUser(principal: MyPrincipal?): com.android.trisolarisserver.models.property.AppUser { if (principal == null) { throw ResponseStatusException(HttpStatus.UNAUTHORIZED, "Missing principal") } return appUserRepo.findById(principal.userId).orElseThrow { ResponseStatusException(HttpStatus.UNAUTHORIZED, "User not found") } } private fun parseTransportModes(modes: Set): MutableSet { return try { modes.map { TransportMode.valueOf(it) }.toMutableSet() } catch (_: IllegalArgumentException) { throw ResponseStatusException(HttpStatus.BAD_REQUEST, "Unknown transport mode") } } }