diff --git a/effectiveOfficeBackend/.env.example b/effectiveOfficeBackend/.env.example new file mode 100644 index 0000000000000000000000000000000000000000..9592f2d0593d67125b93cb23d1bbac89e10c5b8b --- /dev/null +++ b/effectiveOfficeBackend/.env.example @@ -0,0 +1,11 @@ +POSTGRES_PASSWORD=1234567890test +POSTGRES_DB=effectiveOfficeBackendDB +POSTGRES_USER=postgres +DATABASE_PASSWORD=1234567890test +GOOGLE_CLIENT_ID=random +GOOGLE_CLIENT_SECRET=random +VERIFICATION_PLUGIN_ENABLE=false +DATABASE_HOST=0.0.0.0 +DATABASE_PORT=15432 +DATABASE_NAME=effectiveOfficeBackendDB +DATABASE_USERNAME=postgres \ No newline at end of file diff --git a/effectiveOfficeBackend/docker-compose.yml b/effectiveOfficeBackend/docker-compose.yml index 8b159509fb352028cc1386edd3463dee452e1348..59d9458acfc0973232569bc54b696e0760347792 100644 --- a/effectiveOfficeBackend/docker-compose.yml +++ b/effectiveOfficeBackend/docker-compose.yml @@ -6,20 +6,35 @@ services: ports: - "8080:8080" depends_on: - - db_postgres - profiles: - - dev + db_postgres: + condition: service_healthy + environment: + DATABASE_PASSWORD: ${POSTGRES_PASSWORD} + DATABASE_HOST: "db_postgres" # The name of the service in the same network + DATABASE_USERNAME: ${POSTGRES_USER} + DATABASE_PORT: "5432" + DATABASE_NAME: ${POSTGRES_DB} + VERIFICATION_PLUGIN_ENABLE: ${VERIFICATION_PLUGIN_ENABLE} + MIGRATIONS_ENABLE: ${MIGRATIONS_ENABLE} db_postgres: container_name: postgresForKtor image: postgres:15.2-alpine volumes: - - ./sql/init-db.sql:/docker-entrypoint-initdb.d/init-db.sql - env_file: .env + - pgdata:/var/lib/postgresql/data environment: - - POSTGRES_DB=${DOCKER_DB_NAME} - - POSTGRES_USER=postgres - - POSTGRES_PASSWORD=${DOCKER_DB_PASSWORD} + - POSTGRES_DB + - POSTGRES_USER + - POSTGRES_PASSWORD ports: - "15432:5432" - restart: 'no' \ No newline at end of file + restart: "always" + healthcheck: + test: [ "CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}" ] + interval: 1s + timeout: 5s + retries: 10 + + +volumes: + pgdata: {} diff --git a/effectiveOfficeBackend/src/main/kotlin/office/effective/common/utils/commonDiModule.kt b/effectiveOfficeBackend/src/main/kotlin/office/effective/common/utils/commonDiModule.kt index 72004be144005e26ed8e19f4513d55c310d955f9..ab5316118fa472d79ce45e2e2058e6a4519af429 100644 --- a/effectiveOfficeBackend/src/main/kotlin/office/effective/common/utils/commonDiModule.kt +++ b/effectiveOfficeBackend/src/main/kotlin/office/effective/common/utils/commonDiModule.kt @@ -5,10 +5,13 @@ import org.koin.dsl.module import org.ktorm.database.Database val commonDiModule = module(createdAtStart = true) { - val url: String = config.propertyOrNull("database.url") - ?.getString() ?: "jdbc:postgresql://localhost:15432/effectiveOfficeBackendDB" - val username: String = config.propertyOrNull("database.username")?.getString() ?: "postgres" - val password: String = System.getenv("DATABASE_PASSWORD") + val host: String? = System.getenv("DATABASE_HOST") + val port: String? = System.getenv("DATABASE_PORT") + val databaseName: String? = System.getenv("DATABASE_NAME") + + val url: String = String.format("jdbc:postgresql://%s:%s/%s", host, port, databaseName) + val username: String? = System.getenv("DATABASE_USERNAME") + val password: String? = System.getenv("DATABASE_PASSWORD") single { Database.connect( diff --git a/effectiveOfficeBackend/src/main/kotlin/office/effective/dto/BookingDTO.kt b/effectiveOfficeBackend/src/main/kotlin/office/effective/dto/BookingDTO.kt new file mode 100644 index 0000000000000000000000000000000000000000..75fb8d57f3977261af6b8bb93d773f3d4a082514 --- /dev/null +++ b/effectiveOfficeBackend/src/main/kotlin/office/effective/dto/BookingDTO.kt @@ -0,0 +1,15 @@ +package office.effective.dto + +import kotlinx.serialization.Serializable +import office.effective.dto.UserDTO +import office.effective.dto.WorkspaceDTO + +@Serializable +data class BookingDTO ( + val owner: UserDTO, + val participants: List, + val workspace: WorkspaceDTO, + val id: String?, + val beginBooking: Long, + val endBooking: Long +) diff --git a/effectiveOfficeBackend/src/main/kotlin/office/effective/features/user/dto/IntegrationDTO.kt b/effectiveOfficeBackend/src/main/kotlin/office/effective/dto/IntegrationDTO.kt similarity index 77% rename from effectiveOfficeBackend/src/main/kotlin/office/effective/features/user/dto/IntegrationDTO.kt rename to effectiveOfficeBackend/src/main/kotlin/office/effective/dto/IntegrationDTO.kt index 528026f86d0628213981b45c57692f0f3789279a..3dd7c0cd4094d98c86673904ee33b9c9034b7081 100644 --- a/effectiveOfficeBackend/src/main/kotlin/office/effective/features/user/dto/IntegrationDTO.kt +++ b/effectiveOfficeBackend/src/main/kotlin/office/effective/dto/IntegrationDTO.kt @@ -1,4 +1,4 @@ -package office.effective.features.user.dto +package office.effective.dto import kotlinx.serialization.Serializable diff --git a/effectiveOfficeBackend/src/main/kotlin/office/effective/features/user/dto/UserDTO.kt b/effectiveOfficeBackend/src/main/kotlin/office/effective/dto/UserDTO.kt similarity index 85% rename from effectiveOfficeBackend/src/main/kotlin/office/effective/features/user/dto/UserDTO.kt rename to effectiveOfficeBackend/src/main/kotlin/office/effective/dto/UserDTO.kt index 965ab4c2f4643692bc63f78070adaf32b927fa3c..3c602f43bd2d6d55f4353195b67281bbd25c6621 100644 --- a/effectiveOfficeBackend/src/main/kotlin/office/effective/features/user/dto/UserDTO.kt +++ b/effectiveOfficeBackend/src/main/kotlin/office/effective/dto/UserDTO.kt @@ -1,4 +1,4 @@ -package office.effective.features.user.dto +package office.effective.dto import kotlinx.serialization.Serializable diff --git a/effectiveOfficeBackend/src/main/kotlin/office/effective/features/workspace/dto/UtilityDTO.kt b/effectiveOfficeBackend/src/main/kotlin/office/effective/dto/UtilityDTO.kt similarity index 75% rename from effectiveOfficeBackend/src/main/kotlin/office/effective/features/workspace/dto/UtilityDTO.kt rename to effectiveOfficeBackend/src/main/kotlin/office/effective/dto/UtilityDTO.kt index 3f2a7fdc6e74ef66afab37d519e7914ca1a466cc..75ee1cbf93531fcfd89aa096d4e18ca8b95a6c85 100644 --- a/effectiveOfficeBackend/src/main/kotlin/office/effective/features/workspace/dto/UtilityDTO.kt +++ b/effectiveOfficeBackend/src/main/kotlin/office/effective/dto/UtilityDTO.kt @@ -1,4 +1,4 @@ -package office.effective.features.workspace.dto +package office.effective.dto import kotlinx.serialization.Serializable diff --git a/effectiveOfficeBackend/src/main/kotlin/office/effective/features/workspace/dto/WorkspaceDTO.kt b/effectiveOfficeBackend/src/main/kotlin/office/effective/dto/WorkspaceDTO.kt similarity index 80% rename from effectiveOfficeBackend/src/main/kotlin/office/effective/features/workspace/dto/WorkspaceDTO.kt rename to effectiveOfficeBackend/src/main/kotlin/office/effective/dto/WorkspaceDTO.kt index 6748a1023f25954310d976d989266cf2d1ce716e..72c1a58ebf664e9267f58ddf796e109de2546f2c 100644 --- a/effectiveOfficeBackend/src/main/kotlin/office/effective/features/workspace/dto/WorkspaceDTO.kt +++ b/effectiveOfficeBackend/src/main/kotlin/office/effective/dto/WorkspaceDTO.kt @@ -1,4 +1,4 @@ -package office.effective.features.workspace.dto +package office.effective.dto import kotlinx.serialization.Serializable diff --git a/effectiveOfficeBackend/src/main/kotlin/office/effective/features/workspace/dto/WorkspaceZoneDTO.kt b/effectiveOfficeBackend/src/main/kotlin/office/effective/dto/WorkspaceZoneDTO.kt similarity index 71% rename from effectiveOfficeBackend/src/main/kotlin/office/effective/features/workspace/dto/WorkspaceZoneDTO.kt rename to effectiveOfficeBackend/src/main/kotlin/office/effective/dto/WorkspaceZoneDTO.kt index 6a7407622be0c7da8cfbe3309732167cabc86e66..daec898d50ef70cd5386e21dd2f6505609a8acd7 100644 --- a/effectiveOfficeBackend/src/main/kotlin/office/effective/features/workspace/dto/WorkspaceZoneDTO.kt +++ b/effectiveOfficeBackend/src/main/kotlin/office/effective/dto/WorkspaceZoneDTO.kt @@ -1,4 +1,4 @@ -package office.effective.features.workspace.dto +package office.effective.dto import kotlinx.serialization.Serializable diff --git a/effectiveOfficeBackend/src/main/kotlin/office/effective/features/booking/converters/BookingFacadeConverter.kt b/effectiveOfficeBackend/src/main/kotlin/office/effective/features/booking/converters/BookingFacadeConverter.kt index 4b8e26bbc121bcbfebd1c4804ecddac16e462d5a..a62e4a4740d4a60fb9fc107708ccda18cb1edcca 100644 --- a/effectiveOfficeBackend/src/main/kotlin/office/effective/features/booking/converters/BookingFacadeConverter.kt +++ b/effectiveOfficeBackend/src/main/kotlin/office/effective/features/booking/converters/BookingFacadeConverter.kt @@ -1,7 +1,7 @@ package office.effective.features.booking.converters import office.effective.common.utils.UuidValidator -import office.effective.features.booking.dto.BookingDTO +import office.effective.dto.BookingDTO import office.effective.features.user.converters.UserDTOModelConverter import office.effective.features.workspace.converters.WorkspaceFacadeConverter import office.effective.model.Booking diff --git a/effectiveOfficeBackend/src/main/kotlin/office/effective/features/booking/dto/BookingDTO.kt b/effectiveOfficeBackend/src/main/kotlin/office/effective/features/booking/dto/BookingDTO.kt deleted file mode 100644 index ac0eadb4efa0bdea67f1549847921db2ff20b56b..0000000000000000000000000000000000000000 --- a/effectiveOfficeBackend/src/main/kotlin/office/effective/features/booking/dto/BookingDTO.kt +++ /dev/null @@ -1,15 +0,0 @@ -package office.effective.features.booking.dto - -import kotlinx.serialization.Serializable -import office.effective.features.user.dto.UserDTO -import office.effective.features.workspace.dto.WorkspaceDTO - -@Serializable -data class BookingDTO ( - var owner: UserDTO, - var participants: List, - var workspace: WorkspaceDTO, - var id: String?, - var beginBooking: Long, - var endBooking: Long -) diff --git a/effectiveOfficeBackend/src/main/kotlin/office/effective/features/booking/facade/BookingFacade.kt b/effectiveOfficeBackend/src/main/kotlin/office/effective/features/booking/facade/BookingFacade.kt index b76b982853adba43d54c393789637063bc648099..f84ac19f87b3cf10c9b3bcd1a7acb49094451c03 100644 --- a/effectiveOfficeBackend/src/main/kotlin/office/effective/features/booking/facade/BookingFacade.kt +++ b/effectiveOfficeBackend/src/main/kotlin/office/effective/features/booking/facade/BookingFacade.kt @@ -4,7 +4,7 @@ import office.effective.common.exception.InstanceNotFoundException import office.effective.common.utils.DatabaseTransactionManager import office.effective.common.utils.UuidValidator import office.effective.features.booking.converters.BookingFacadeConverter -import office.effective.features.booking.dto.BookingDTO +import office.effective.dto.BookingDTO import office.effective.features.booking.service.BookingService import office.effective.model.Booking import office.effective.model.Workspace diff --git a/effectiveOfficeBackend/src/main/kotlin/office/effective/features/booking/routes/BookingRouting.kt b/effectiveOfficeBackend/src/main/kotlin/office/effective/features/booking/routes/BookingRouting.kt index 8c5d88f5b9d9350009c00767fe96540916e244b3..ae3106b6ff3ed704b320a9689eb81de292f715ec 100644 --- a/effectiveOfficeBackend/src/main/kotlin/office/effective/features/booking/routes/BookingRouting.kt +++ b/effectiveOfficeBackend/src/main/kotlin/office/effective/features/booking/routes/BookingRouting.kt @@ -10,7 +10,7 @@ import io.ktor.server.request.* import io.ktor.server.response.* import io.ktor.server.routing.* import office.effective.common.swagger.SwaggerDocument -import office.effective.features.booking.dto.BookingDTO +import office.effective.dto.BookingDTO import office.effective.features.booking.facade.BookingFacade import office.effective.features.booking.routes.swagger.* import org.koin.core.context.GlobalContext diff --git a/effectiveOfficeBackend/src/main/kotlin/office/effective/features/booking/routes/swagger/BookingSwagger.kt b/effectiveOfficeBackend/src/main/kotlin/office/effective/features/booking/routes/swagger/BookingSwagger.kt index b10ae0f44f12c80cb150dc566b57047398299d5f..a5b37d7272eaab59055ae223505a6bccac55b87f 100644 --- a/effectiveOfficeBackend/src/main/kotlin/office/effective/features/booking/routes/swagger/BookingSwagger.kt +++ b/effectiveOfficeBackend/src/main/kotlin/office/effective/features/booking/routes/swagger/BookingSwagger.kt @@ -3,12 +3,11 @@ package office.effective.features.booking.routes.swagger import io.github.smiley4.ktorswaggerui.dsl.OpenApiRoute import io.ktor.http.* import office.effective.common.swagger.SwaggerDocument -import office.effective.features.booking.dto.BookingDTO -import office.effective.features.user.dto.IntegrationDTO -import office.effective.features.user.dto.UserDTO -import office.effective.features.workspace.dto.UtilityDTO -import office.effective.features.workspace.dto.WorkspaceDTO -import office.effective.features.workspace.routes.swagger.WorkspaceTag +import office.effective.dto.BookingDTO +import office.effective.dto.IntegrationDTO +import office.effective.dto.UserDTO +import office.effective.dto.UtilityDTO +import office.effective.dto.WorkspaceDTO fun SwaggerDocument.returnBookingById(): OpenApiRoute.() -> Unit = { description = "Returns booking found by id" diff --git a/effectiveOfficeBackend/src/main/kotlin/office/effective/features/booking/service/BookingService.kt b/effectiveOfficeBackend/src/main/kotlin/office/effective/features/booking/service/BookingService.kt index 084ad08567ec7bda583829694f398134da2dafab..d9d41ff57f618dba2db9cd0aca10364239015d7a 100644 --- a/effectiveOfficeBackend/src/main/kotlin/office/effective/features/booking/service/BookingService.kt +++ b/effectiveOfficeBackend/src/main/kotlin/office/effective/features/booking/service/BookingService.kt @@ -9,9 +9,11 @@ import office.effective.features.workspace.repository.WorkspaceRepository import office.effective.model.* import java.util.UUID -class BookingService(private val bookingRepository: BookingRepository, - private val userRepository: UserRepository, - private val workspaceRepository: WorkspaceRepository) { +class BookingService( + private val bookingRepository: BookingRepository, + private val userRepository: UserRepository, + private val workspaceRepository: WorkspaceRepository +) { /** * Returns whether a booking with the given id exists @@ -37,13 +39,21 @@ class BookingService(private val bookingRepository: BookingRepository, * @author Daniil Zavyalov */ fun findById(id: UUID): Booking? { - val booking = bookingRepository.findById(id) - booking?.let { - for (participant in it.participants) { - participant.integrations = findIntegrations(participant) - } - it.owner.integrations = findIntegrations(it.owner) - it.workspace.utilities = findUtilities(it.workspace) + val booking = bookingRepository.findById(id) ?: return null + val userIds = mutableSetOf() + for (participant in booking.participants) { + userIds.add(participant.id + ?: throw MissingIdException("User with name ${participant.fullName} doesn't have an id") + ) + } + userIds.add(booking.owner.id + ?: throw MissingIdException("User with name ${booking.owner.fullName} doesn't have an id") + ) + val integrations = userRepository.findAllIntegrationsByUserIds(userIds) + booking.workspace.utilities = findUtilities(booking.workspace) + booking.owner.integrations = integrations[booking.owner.id] ?: setOf() + for (participant in booking.participants) { + participant.integrations = integrations[participant.id] ?: setOf() } return booking } @@ -59,24 +69,35 @@ class BookingService(private val bookingRepository: BookingRepository, val bookingList = when { userId != null && workspaceId != null -> { if (!workspaceRepository.workspaceExistsById(workspaceId)) - throw InstanceNotFoundException(UserEntity::class, "User with id $workspaceId not found", workspaceId) + throw InstanceNotFoundException( + UserEntity::class, + "User with id $workspaceId not found", + workspaceId + ) if (!userRepository.existsById(userId)) throw InstanceNotFoundException(UserEntity::class, "User with id $userId not found", userId) bookingRepository.findAllByOwnerAndWorkspaceId(userId, workspaceId) } + userId != null -> { if (!userRepository.existsById(userId)) throw InstanceNotFoundException(UserEntity::class, "User with id $userId not found", userId) bookingRepository.findAllByOwnerId(userId) } + workspaceId != null -> { if (!workspaceRepository.workspaceExistsById(workspaceId)) - throw InstanceNotFoundException(UserEntity::class, "User with id $workspaceId not found", workspaceId) + throw InstanceNotFoundException( + UserEntity::class, + "User with id $workspaceId not found", + workspaceId + ) bookingRepository.findAllByWorkspaceId(workspaceId) } + else -> bookingRepository.findAll() } - return addIntegrationsAndUtilities(bookingList) + return findIntegrationsAndUtilities(bookingList) } /** @@ -87,13 +108,49 @@ class BookingService(private val bookingRepository: BookingRepository, * * @author Daniil Zavyalov */ - private fun addIntegrationsAndUtilities(bookingList: List): List { + private fun findIntegrationsAndUtilities(bookingList: List): List { + val userIds = mutableSetOf() + val workspaceIds = mutableSetOf() + for (booking in bookingList) { + for (participant in booking.participants) { + userIds.add( + participant.id + ?: throw MissingIdException("User with name ${participant.fullName} doesn't have an id") + ) + } + userIds.add( + booking.owner.id + ?: throw MissingIdException("User with name ${booking.owner.fullName} doesn't have an id") + ) + workspaceIds.add( + booking.workspace.id + ?: throw MissingIdException("Workspace with name ${booking.workspace.name} doesn't have an id") + ) + } + val utilities = workspaceRepository.findAllUtilitiesByWorkspaceIds(workspaceIds) + val integrations = userRepository.findAllIntegrationsByUserIds(userIds) + return addIntegrationsAndUtilities(bookingList, integrations, utilities) + } + + /** + * Adds integrations and utilities to users and workspace + * related with the given booking model + * + * @throws MissingIdException if user model doesn't have an id + * + * @author Daniil Zavyalov + */ + private fun addIntegrationsAndUtilities( + bookingList: List, + integrations: HashMap>, + utilities: HashMap> + ): List { for (booking in bookingList) { + booking.workspace.utilities = utilities[booking.workspace.id] ?: listOf() + booking.owner.integrations = integrations[booking.owner.id] ?: setOf() for (participant in booking.participants) { - participant.integrations = findIntegrations(participant) + participant.integrations = integrations[participant.id] } - booking.owner.integrations = findIntegrations(booking.owner) - booking.workspace.utilities = findUtilities(booking.workspace) } return bookingList } @@ -107,7 +164,7 @@ class BookingService(private val bookingRepository: BookingRepository, */ private fun findIntegrations(user: UserModel): Set { val userId = user.id - ?: throw MissingIdException("User with name ${ user.fullName } doesn't have an id") + ?: throw MissingIdException("User with name ${user.fullName} doesn't have an id") return userRepository.findSetOfIntegrationsByUser(userId) } @@ -120,7 +177,7 @@ class BookingService(private val bookingRepository: BookingRepository, */ private fun findUtilities(workspace: Workspace): List { val workspaceId = workspace.id - ?: throw MissingIdException("Workspace with name ${ workspace.name } doesn't have an id") + ?: throw MissingIdException("Workspace with name ${workspace.name} doesn't have an id") return workspaceRepository.findUtilitiesByWorkspaceId(workspaceId) } diff --git a/effectiveOfficeBackend/src/main/kotlin/office/effective/features/user/converters/IntegrationDTOModelConverter.kt b/effectiveOfficeBackend/src/main/kotlin/office/effective/features/user/converters/IntegrationDTOModelConverter.kt index f4ddccecd1d68716407f3ba457326e8f3ec29973..c0d74b2c73204eb2d98fe429456241bc8e9106b3 100644 --- a/effectiveOfficeBackend/src/main/kotlin/office/effective/features/user/converters/IntegrationDTOModelConverter.kt +++ b/effectiveOfficeBackend/src/main/kotlin/office/effective/features/user/converters/IntegrationDTOModelConverter.kt @@ -1,9 +1,8 @@ package office.effective.features.user.converters import office.effective.common.utils.UuidValidator -import office.effective.features.user.dto.IntegrationDTO +import office.effective.dto.IntegrationDTO import office.effective.model.IntegrationModel -import java.util.* class IntegrationDTOModelConverter( private val uuidConverter : UuidValidator diff --git a/effectiveOfficeBackend/src/main/kotlin/office/effective/features/user/converters/UserDTOModelConverter.kt b/effectiveOfficeBackend/src/main/kotlin/office/effective/features/user/converters/UserDTOModelConverter.kt index 484f894a6d8172d24e5c77d5e7dde78b5cf79015..d1879337ff8ec557a013e0e0fc47c2dfd3ac330d 100644 --- a/effectiveOfficeBackend/src/main/kotlin/office/effective/features/user/converters/UserDTOModelConverter.kt +++ b/effectiveOfficeBackend/src/main/kotlin/office/effective/features/user/converters/UserDTOModelConverter.kt @@ -1,14 +1,12 @@ package office.effective.features.user.converters import office.effective.common.utils.UuidValidator -import office.effective.features.user.dto.IntegrationDTO -import office.effective.features.user.dto.UserDTO +import office.effective.dto.IntegrationDTO +import office.effective.dto.UserDTO import office.effective.features.user.repository.UserRepository import office.effective.features.user.repository.UsersTagEntity import office.effective.model.IntegrationModel import office.effective.model.UserModel -import org.koin.core.context.GlobalContext -import java.util.UUID class UserDTOModelConverter( private val repository: UserRepository, diff --git a/effectiveOfficeBackend/src/main/kotlin/office/effective/features/user/di/userDIModule.kt b/effectiveOfficeBackend/src/main/kotlin/office/effective/features/user/di/userDIModule.kt index a4e95222f633eeec9b5203d9b731df8448ec1afd..9b0705c1ee55322c631082fc38f4d198c7bd5ba6 100644 --- a/effectiveOfficeBackend/src/main/kotlin/office/effective/features/user/di/userDIModule.kt +++ b/effectiveOfficeBackend/src/main/kotlin/office/effective/features/user/di/userDIModule.kt @@ -18,7 +18,7 @@ val userDIModule = module(createdAtStart = true) { single { IntegrationModelEntityConverter() } single { UserModelEntityConverter() } single { UserDTOModelConverter(get(), get(), get()) } - single { UserRepository(get(), get()) } + single { UserRepository(get(), get(), get()) } single { UserFacade(get(), get(), get(), get()) } single { IntegrationDTOModelConverter(get()) } } \ No newline at end of file diff --git a/effectiveOfficeBackend/src/main/kotlin/office/effective/features/user/facade/UserFacade.kt b/effectiveOfficeBackend/src/main/kotlin/office/effective/features/user/facade/UserFacade.kt index 78bfcb0d8284e2f4ec758d0957c762f039af12d7..967d520426f2bb043e79291a8bdf293a15db7436 100644 --- a/effectiveOfficeBackend/src/main/kotlin/office/effective/features/user/facade/UserFacade.kt +++ b/effectiveOfficeBackend/src/main/kotlin/office/effective/features/user/facade/UserFacade.kt @@ -3,7 +3,7 @@ package office.effective.features.user.facade import office.effective.common.utils.DatabaseTransactionManager import office.effective.features.user.ITokenVerifier import office.effective.features.user.converters.UserDTOModelConverter -import office.effective.features.user.dto.UserDTO +import office.effective.dto.UserDTO import office.effective.features.user.service.IUserService import office.effective.model.UserModel diff --git a/effectiveOfficeBackend/src/main/kotlin/office/effective/features/user/repository/UserRepository.kt b/effectiveOfficeBackend/src/main/kotlin/office/effective/features/user/repository/UserRepository.kt index 452443668c3bd3329d31542497f2ed804684ab4f..af3310930c5cd1c245da380914200474df3000ee 100644 --- a/effectiveOfficeBackend/src/main/kotlin/office/effective/features/user/repository/UserRepository.kt +++ b/effectiveOfficeBackend/src/main/kotlin/office/effective/features/user/repository/UserRepository.kt @@ -1,6 +1,7 @@ package office.effective.features.user.repository import office.effective.common.exception.* +import office.effective.features.user.converters.IntegrationModelEntityConverter import office.effective.features.user.converters.UserModelEntityConverter import office.effective.model.IntegrationModel import office.effective.model.UserModel @@ -10,7 +11,10 @@ import org.ktorm.dsl.* import org.ktorm.entity.* import java.util.* -class UserRepository(private val db: Database, private val converter: UserModelEntityConverter) { +class UserRepository(private val db: Database, + private val converter: UserModelEntityConverter, + private val integrationConverter: IntegrationModelEntityConverter +) { /** * Checks existence of user by id, using count @@ -119,6 +123,35 @@ class UserRepository(private val db: Database, private val converter: UserModelE return modelsSet; } + /** + * Returns a HashMap that maps user ids and their integrations + * @return HashMap> + * @throws InstanceNotFoundException if user with the given id doesn't exist in the database + * + * @author Daniil Zavyalov + * */ + fun findAllIntegrationsByUserIds(ids: Collection): HashMap> { + for (id in ids) { + if (!existsById(id)) + throw InstanceNotFoundException(UserEntity::class, "User with id $id not found") + } + val result = hashMapOf>() + db + .from(UsersIntegrations) + .innerJoin(right = Integrations, on = UsersIntegrations.integrationId eq Integrations.id) + .select() + .where { UsersIntegrations.integrationId inList ids } + .forEach { row -> + val userId: UUID = row[UsersIntegrations.integrationId] ?: return@forEach + val utility = integrationConverter.entityToModel( + Integrations.createEntity(row), row[UsersIntegrations.valueStr] ?: "" + ) + val integrations: MutableSet = result.getOrPut(userId) { mutableSetOf() } + integrations.add(utility) + } + return result + } + /** * Returns TagModel by value * @return UserTagModel diff --git a/effectiveOfficeBackend/src/main/kotlin/office/effective/features/user/routes/swagger/AuthSwagger.kt b/effectiveOfficeBackend/src/main/kotlin/office/effective/features/user/routes/swagger/AuthSwagger.kt index 5e74e6ce9392d25ed49e8536c25360568818375a..1bffb7b880a5a315c5b0ce66df7b7a6609f0331c 100644 --- a/effectiveOfficeBackend/src/main/kotlin/office/effective/features/user/routes/swagger/AuthSwagger.kt +++ b/effectiveOfficeBackend/src/main/kotlin/office/effective/features/user/routes/swagger/AuthSwagger.kt @@ -3,7 +3,6 @@ package office.effective.features.user.routes.swagger import io.github.smiley4.ktorswaggerui.dsl.OpenApiRoute import io.ktor.http.* import office.effective.common.swagger.SwaggerDocument -import office.effective.features.user.dto.UserDTO fun SwaggerDocument.login(): OpenApiRoute.() -> Unit = { description = "Empty route. Need to redirect to google authentication page" diff --git a/effectiveOfficeBackend/src/main/kotlin/office/effective/features/user/routes/swagger/UserSwagger.kt b/effectiveOfficeBackend/src/main/kotlin/office/effective/features/user/routes/swagger/UserSwagger.kt index fc7cc414056b1c6d6acfde490b3f20abf9854df6..79c0cdfaf276d280d49b26d8b79f18f258a6a0ae 100644 --- a/effectiveOfficeBackend/src/main/kotlin/office/effective/features/user/routes/swagger/UserSwagger.kt +++ b/effectiveOfficeBackend/src/main/kotlin/office/effective/features/user/routes/swagger/UserSwagger.kt @@ -3,9 +3,8 @@ package office.effective.features.user.routes.swagger import io.github.smiley4.ktorswaggerui.dsl.OpenApiRoute import io.ktor.http.* import office.effective.common.swagger.SwaggerDocument -import office.effective.features.booking.dto.BookingDTO -import office.effective.features.user.dto.IntegrationDTO -import office.effective.features.user.dto.UserDTO +import office.effective.dto.IntegrationDTO +import office.effective.dto.UserDTO fun SwaggerDocument.returnUserByEmail(): OpenApiRoute.() -> Unit = { description = "Return user by email" diff --git a/effectiveOfficeBackend/src/main/kotlin/office/effective/features/user/routes/userRouting.kt b/effectiveOfficeBackend/src/main/kotlin/office/effective/features/user/routes/userRouting.kt index 06c2cd045f5275947a6f89bbfe282f31f167a870..cf8045c014f6035c976c3fb8238abde90418dbfe 100644 --- a/effectiveOfficeBackend/src/main/kotlin/office/effective/features/user/routes/userRouting.kt +++ b/effectiveOfficeBackend/src/main/kotlin/office/effective/features/user/routes/userRouting.kt @@ -11,7 +11,7 @@ import io.ktor.server.routing.* import office.effective.common.swagger.SwaggerDocument import office.effective.features.user.ITokenVerifier import office.effective.features.user.converters.UserDTOModelConverter -import office.effective.features.user.dto.UserDTO +import office.effective.dto.UserDTO import office.effective.features.user.facade.UserFacade import office.effective.features.user.repository.UserRepository import office.effective.features.user.routes.swagger.updateUser diff --git a/effectiveOfficeBackend/src/main/kotlin/office/effective/features/workspace/converters/WorkspaceFacadeConverter.kt b/effectiveOfficeBackend/src/main/kotlin/office/effective/features/workspace/converters/WorkspaceFacadeConverter.kt index ae8ea18c6a66a84ba39a1a2977491567da18bf86..e95b7e1c4816cc4c4517a3715095563b5a4e64ec 100644 --- a/effectiveOfficeBackend/src/main/kotlin/office/effective/features/workspace/converters/WorkspaceFacadeConverter.kt +++ b/effectiveOfficeBackend/src/main/kotlin/office/effective/features/workspace/converters/WorkspaceFacadeConverter.kt @@ -1,9 +1,9 @@ package office.effective.features.workspace.converters import office.effective.common.utils.UuidValidator -import office.effective.features.workspace.dto.UtilityDTO -import office.effective.features.workspace.dto.WorkspaceDTO -import office.effective.features.workspace.dto.WorkspaceZoneDTO +import office.effective.dto.UtilityDTO +import office.effective.dto.WorkspaceDTO +import office.effective.dto.WorkspaceZoneDTO import office.effective.model.Utility import office.effective.model.Workspace import office.effective.model.WorkspaceZone diff --git a/effectiveOfficeBackend/src/main/kotlin/office/effective/features/workspace/facade/WorkspaceFacade.kt b/effectiveOfficeBackend/src/main/kotlin/office/effective/features/workspace/facade/WorkspaceFacade.kt index 4b1f03dfbae9e02732cf7b1cfdf5657cd9795c04..265754582877f62f1985031a0e5f9e3a164ce3d8 100644 --- a/effectiveOfficeBackend/src/main/kotlin/office/effective/features/workspace/facade/WorkspaceFacade.kt +++ b/effectiveOfficeBackend/src/main/kotlin/office/effective/features/workspace/facade/WorkspaceFacade.kt @@ -5,8 +5,8 @@ import office.effective.common.exception.ValidationException import office.effective.common.utils.DatabaseTransactionManager import office.effective.common.utils.UuidValidator import office.effective.features.workspace.converters.WorkspaceFacadeConverter -import office.effective.features.workspace.dto.WorkspaceDTO -import office.effective.features.workspace.dto.WorkspaceZoneDTO +import office.effective.dto.WorkspaceDTO +import office.effective.dto.WorkspaceZoneDTO import office.effective.features.workspace.service.WorkspaceService import office.effective.model.Workspace import java.time.Instant diff --git a/effectiveOfficeBackend/src/main/kotlin/office/effective/features/workspace/repository/WorkspaceRepository.kt b/effectiveOfficeBackend/src/main/kotlin/office/effective/features/workspace/repository/WorkspaceRepository.kt index 1a90ff194ec5981ac7ebafba4571857e727d6507..c77ed40756d93bf59391ddf7bfc22e3b72683a78 100644 --- a/effectiveOfficeBackend/src/main/kotlin/office/effective/features/workspace/repository/WorkspaceRepository.kt +++ b/effectiveOfficeBackend/src/main/kotlin/office/effective/features/workspace/repository/WorkspaceRepository.kt @@ -2,6 +2,7 @@ package office.effective.features.workspace.repository import office.effective.common.exception.InstanceNotFoundException import office.effective.features.booking.repository.WorkspaceBooking +import office.effective.features.user.repository.UserEntity import office.effective.features.workspace.converters.WorkspaceRepositoryConverter import office.effective.model.Utility import office.effective.model.Workspace @@ -65,6 +66,35 @@ class WorkspaceRepository(private val database: Database, private val converter: } } + /** + * Returns a HashMap that maps user ids and their integrations + * @return HashMap> + * @throws InstanceNotFoundException if user with the given id doesn't exist in the database + * + * @author Daniil Zavyalov + * */ + fun findAllUtilitiesByWorkspaceIds(ids: Collection): HashMap> { + for (id in ids) { + if (!workspaceExistsById(id)) + throw InstanceNotFoundException(WorkspaceEntity::class, "Workspace with id $id not found") + } + val result = hashMapOf>() + database + .from(WorkspaceUtilities) + .innerJoin(right = Utilities, on = WorkspaceUtilities.utilityId eq Utilities.id) + .select() + .where { WorkspaceUtilities.workspaceId inList ids } + .forEach { row -> + val workspaceId: UUID = row[WorkspaceUtilities.workspaceId] ?: return@forEach + val utility = converter.utilityEntityToModel( + Utilities.createEntity(row), row[WorkspaceUtilities.count] ?: 0 + ) + val utilities: MutableList = result.getOrPut(workspaceId) { mutableListOf() } + utilities.add(utility) + } + return result + } + /** * Retrieves a workspace model by its id * diff --git a/effectiveOfficeBackend/src/main/kotlin/office/effective/features/workspace/routes/swagger/WorkspaceSwagger.kt b/effectiveOfficeBackend/src/main/kotlin/office/effective/features/workspace/routes/swagger/WorkspaceSwagger.kt index fa7a1c9b7a82e37bf7d4211ba77dc3dc6e520881..10fca709e0a8fc526aeb84034f64cc91c564f38c 100644 --- a/effectiveOfficeBackend/src/main/kotlin/office/effective/features/workspace/routes/swagger/WorkspaceSwagger.kt +++ b/effectiveOfficeBackend/src/main/kotlin/office/effective/features/workspace/routes/swagger/WorkspaceSwagger.kt @@ -3,9 +3,9 @@ package office.effective.features.workspace.routes.swagger import io.github.smiley4.ktorswaggerui.dsl.OpenApiRoute import io.ktor.http.* import office.effective.common.swagger.SwaggerDocument -import office.effective.features.workspace.dto.UtilityDTO -import office.effective.features.workspace.dto.WorkspaceDTO -import office.effective.features.workspace.dto.WorkspaceZoneDTO +import office.effective.dto.UtilityDTO +import office.effective.dto.WorkspaceDTO +import office.effective.dto.WorkspaceZoneDTO fun SwaggerDocument.returnWorkspaceById(): OpenApiRoute.() -> Unit = { description = "Return workspace by id" diff --git a/effectiveOfficeBackend/src/main/kotlin/office/effective/plugins/Migration.kt b/effectiveOfficeBackend/src/main/kotlin/office/effective/plugins/Migration.kt index 2fbd12fa5df64adef9006a274376477d1b052ec2..fd9abd4eb4f4e9bc64e6b42efb9cdaa1d10595d5 100644 --- a/effectiveOfficeBackend/src/main/kotlin/office/effective/plugins/Migration.kt +++ b/effectiveOfficeBackend/src/main/kotlin/office/effective/plugins/Migration.kt @@ -9,26 +9,31 @@ import office.effective.config import java.sql.DriverManager fun Application.configureMigration() { - val url: String = config.propertyOrNull("database.url") - ?.getString() ?: "jdbc:postgresql://localhost:15432/effectiveOfficeBackendDB" - val username: String = config.propertyOrNull("database.username")?.getString() ?: "postgres" - val password: String = - System.getenv("DATABASE_PASSWORD") + val host: String? = System.getenv("DATABASE_HOST") + val port: String? = System.getenv("DATABASE_PORT") + val databaseName: String? = System.getenv("DATABASE_NAME") + + val url: String = String.format("jdbc:postgresql://%s:%s/%s", host, port, databaseName) + val username: String? = System.getenv("DATABASE_USERNAME") + val password: String? = System.getenv("DATABASE_PASSWORD") val changelogFile: String = config.propertyOrNull("liquibase.changelogFile") ?.getString() ?: "changelog/changelog-master.yaml" val defaultSchemaName: String = config.propertyOrNull("liquibase.defaultSchemaName") ?.getString() ?: "public" + val migrationsEnable: Boolean = System.getenv("MIGRATIONS_ENABLE").equals("true") - val connection = DriverManager.getConnection( - url, - username, - password - ) - val databaseConnection = JdbcConnection(connection) - val database = DatabaseFactory.getInstance().findCorrectDatabaseImplementation(databaseConnection) - database.defaultSchemaName = defaultSchemaName - val liquibase = Liquibase(changelogFile, ClassLoaderResourceAccessor(), database) - liquibase.update("") - liquibase.database.close() -} \ No newline at end of file + if (migrationsEnable) { + val connection = DriverManager.getConnection( + url, + username, + password + ) + val databaseConnection = JdbcConnection(connection) + val database = DatabaseFactory.getInstance().findCorrectDatabaseImplementation(databaseConnection) + database.defaultSchemaName = defaultSchemaName + val liquibase = Liquibase(changelogFile, ClassLoaderResourceAccessor(), database) + liquibase.update("") + liquibase.database.close() + } +} diff --git a/effectiveOfficeBackend/src/main/kotlin/office/effective/plugins/RequestValidation.kt b/effectiveOfficeBackend/src/main/kotlin/office/effective/plugins/RequestValidation.kt index 8979ebe9e2d56deca860710be3251e4e80e207db..9d6c6d078f5daf0a3d0c4dc1a48b08cc294e52ab 100644 --- a/effectiveOfficeBackend/src/main/kotlin/office/effective/plugins/RequestValidation.kt +++ b/effectiveOfficeBackend/src/main/kotlin/office/effective/plugins/RequestValidation.kt @@ -2,7 +2,7 @@ package office.effective.plugins import io.ktor.server.application.* import io.ktor.server.plugins.requestvalidation.* -import office.effective.features.booking.dto.BookingDTO +import office.effective.dto.BookingDTO fun Application.configureValidation() { install(RequestValidation) { diff --git a/effectiveOfficeBackend/src/main/resources/application.conf b/effectiveOfficeBackend/src/main/resources/application.conf index bbfa22d598052a6947e1e38f7034675537e4021b..3db6edf7203cb39fc7dc1ba5830918e4cbdaa2db 100644 --- a/effectiveOfficeBackend/src/main/resources/application.conf +++ b/effectiveOfficeBackend/src/main/resources/application.conf @@ -1,7 +1,7 @@ ktor { deployment { port = 8080 - host = "localhost" + host = "0.0.0.0" } } database { diff --git a/effectiveOfficeBackend/src/test/kotlin/office/effective/booking/BookingFacadeTest.kt b/effectiveOfficeBackend/src/test/kotlin/office/effective/booking/BookingFacadeTest.kt index 1779cd8da517142ecfaae0afe049d5a09be80a52..824e3e98b0f16d85efad87c030cf6015df62a6e8 100644 --- a/effectiveOfficeBackend/src/test/kotlin/office/effective/booking/BookingFacadeTest.kt +++ b/effectiveOfficeBackend/src/test/kotlin/office/effective/booking/BookingFacadeTest.kt @@ -5,11 +5,11 @@ import office.effective.common.exception.InstanceNotFoundException import office.effective.common.utils.DatabaseTransactionManager import office.effective.common.utils.UuidValidator import office.effective.features.booking.converters.BookingFacadeConverter -import office.effective.features.booking.dto.BookingDTO +import office.effective.dto.BookingDTO import office.effective.features.booking.facade.BookingFacade import office.effective.features.booking.service.BookingService -import office.effective.features.user.dto.UserDTO -import office.effective.features.workspace.dto.WorkspaceDTO +import office.effective.dto.UserDTO +import office.effective.dto.WorkspaceDTO import office.effective.model.Booking import office.effective.model.UserModel import office.effective.model.Workspace diff --git a/effectiveOfficeBackend/src/test/kotlin/office/effective/workspace/WorkspaceFacadeTest.kt b/effectiveOfficeBackend/src/test/kotlin/office/effective/workspace/WorkspaceFacadeTest.kt index 701658ecbb88117d426f1bc0003e47b6ed222dc2..a243c0882e76cd333bf570daf78893d68b818c12 100644 --- a/effectiveOfficeBackend/src/test/kotlin/office/effective/workspace/WorkspaceFacadeTest.kt +++ b/effectiveOfficeBackend/src/test/kotlin/office/effective/workspace/WorkspaceFacadeTest.kt @@ -2,11 +2,10 @@ package office.effective.workspace import junit.framework.TestCase.assertEquals import office.effective.common.exception.InstanceNotFoundException -import office.effective.common.exception.ValidationException import office.effective.common.utils.DatabaseTransactionManager import office.effective.common.utils.UuidValidator import office.effective.features.workspace.converters.WorkspaceFacadeConverter -import office.effective.features.workspace.dto.WorkspaceDTO +import office.effective.dto.WorkspaceDTO import office.effective.features.workspace.facade.WorkspaceFacade import office.effective.features.workspace.service.WorkspaceService import office.effective.model.Workspace