Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,10 @@ internal fun WriteopiaDbBackend.isUserInWorkspace(userId: String, workspaceId: S
.any { entity -> entity.workspace_id == workspaceId }


internal fun WriteopiaDbBackend.isUserAdminInWorkspace(userId: String, workspaceId: String): Boolean =
internal fun WriteopiaDbBackend.isUserAdminInWorkspace(
userId: String,
workspaceId: String
): Boolean =
this.workspaceEntityQueries
.getWorkspacesByUserIdIfAdmin(userId)
.executeAsList()
Expand All @@ -99,6 +102,41 @@ internal fun WriteopiaDbBackend.getUsersInWorkspace(workspaceId: String): List<W
)
}

internal suspend fun WriteopiaDbBackend.removeUserFromWorkspace(workspaceId: String, userId: String) {
internal fun WriteopiaDbBackend.getUserInWorkspace(
workspaceId: String,
userEmail: String
): WorkspaceUser? =
this.workspaceToUserQueries
.getUserInWorkspace(workspaceId, userEmail)
.executeAsOneOrNull()
?.let { workspaceToUser ->
WorkspaceUser(
id = workspaceToUser.user_entity_id,
email = workspaceToUser.user_email,
name = workspaceToUser.user_name,
role = workspaceToUser.role
)
}

internal suspend fun WriteopiaDbBackend.removeUserFromWorkspace(
workspaceId: String,
userId: String
) {
this.workspaceToUserQueries.removeUserFromWorkspace(workspaceId, userId)
}

fun WriteopiaDbBackend.changeWorkspaceName(workspaceId: String, newName: String) {
this.workspaceEntityQueries.changeName(newName, workspaceId)
}

fun WriteopiaDbBackend.changeWorkspaceRoleForUser(
workspaceId: String,
userId: String,
newRole: String
) {
this.workspaceToUserQueries.changeRole(
workspace_id = workspaceId,
user_id = userId,
role = newRole
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,6 @@ fun Route.adminProtectedRoute(
call.respond(HttpStatusCode.OK, "User disabled")
}
}


}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,17 @@ import io.ktor.server.routing.Routing
import io.ktor.server.routing.delete
import io.ktor.server.routing.get
import io.ktor.server.routing.post
import io.ktor.server.routing.put
import io.writeopia.api.core.auth.repository.changeWorkspaceName
import io.writeopia.api.core.auth.repository.changeWorkspaceRoleForUser
import io.writeopia.api.core.auth.repository.listWorkspaces
import io.writeopia.api.core.auth.service.WorkspaceService
import io.writeopia.api.core.auth.utils.runIfAdmin
import io.writeopia.app.mapping.toApi
import io.writeopia.app.requests.AddUserToWorkspaceRequest
import io.writeopia.sdk.serialization.data.toApi
import io.writeopia.sdk.serialization.request.WorkspaceNameChangeRequest
import io.writeopia.sdk.serialization.request.WorkspaceRoleChangeRequest
import io.writeopia.sql.WriteopiaDbBackend

fun Routing.workspaceRoute(
Expand Down Expand Up @@ -61,11 +66,35 @@ fun Routing.workspaceRoute(
}
}

authenticate("auth-jwt", optional = debugMode) {
get("/api/workspace/{workspaceId}/user/{userEmail}") {
val userId = getUserId() ?: ""
val workspaceId = call.pathParameters["workspaceId"]
?: throw IllegalArgumentException("Workspace id is required")
val userEmail = call.pathParameters["userEmail"]
?: throw IllegalArgumentException("User email is required")

runIfAdmin(userId, workspaceId, writeopiaDb, debugMode) {
val user = WorkspaceService.getUserInWorkspace(
workspaceId = workspaceId,
userEmail = userEmail,
writeopiaDb = writeopiaDb
)

if (user != null) {
call.respond(HttpStatusCode.OK, user.toApi())
} else {
call.respond(HttpStatusCode.NotFound, "User not found")
}
}
}
}

authenticate("auth-jwt", optional = debugMode) {
get("/api/user/workspaces/{workspaceId}") {
val currentUserId = getUserId() ?: ""
val workspaceId = call.pathParameters["workspaceId"]
?: throw IllegalArgumentException("User id is required")
?: throw IllegalArgumentException("Workspace id is required")

runIfAdmin(currentUserId, workspaceId, writeopiaDb, debugMode) {
val workspaces = WorkspaceService
Expand Down Expand Up @@ -125,6 +154,39 @@ fun Routing.workspaceRoute(
}
}

authenticate("auth-jwt", optional = debugMode) {
put<WorkspaceNameChangeRequest>("/api/workspace/name") { nameChange ->
val userId = getUserId() ?: ""
val (workspaceId, newName) = nameChange

runIfAdmin(userId, workspaceId, writeopiaDb, debugMode) {
writeopiaDb.changeWorkspaceName(
workspaceId = workspaceId,
newName = newName
)

call.respond(status = HttpStatusCode.OK, "Name changed")
}
}
}

authenticate("auth-jwt", optional = debugMode) {
put<WorkspaceRoleChangeRequest>("/api/workspace/role") { roleChange ->
val userId = getUserId() ?: ""
val (workspaceId, changeRoleUserId, newRole) = roleChange

runIfAdmin(userId, workspaceId, writeopiaDb, debugMode) {
writeopiaDb.changeWorkspaceRoleForUser(
workspaceId = workspaceId,
userId = changeRoleUserId,
newRole = newRole
)

call.respond(status = HttpStatusCode.OK, "Name changed")
}
}
}

authenticate("auth-jwt", optional = debugMode) {
delete("/api/workspace/{workspaceId}/user/{userId}") {
val userId = getUserId() ?: ""
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.writeopia.api.core.auth.service

import io.writeopia.api.core.auth.repository.getUserByEmail
import io.writeopia.api.core.auth.repository.getUserInWorkspace
import io.writeopia.api.core.auth.repository.getUsersInWorkspace
import io.writeopia.api.core.auth.repository.getWorkspaceById
import io.writeopia.api.core.auth.repository.getWorkspacesByUserId
Expand Down Expand Up @@ -33,6 +34,12 @@ object WorkspaceService {
writeopiaDb: WriteopiaDbBackend
): List<WorkspaceUser> = writeopiaDb.getUsersInWorkspace(workspaceId)

fun getUserInWorkspace(
workspaceId: String,
userEmail: String,
writeopiaDb: WriteopiaDbBackend
): WorkspaceUser? = writeopiaDb.getUserInWorkspace(workspaceId, userEmail)

fun createWorkspace(
workspaceId: String,
workspaceName: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,8 @@ VALUES (?, ?, ?, ?)
ON CONFLICT(id) DO
UPDATE SET id=excluded.id, name=excluded.name, icon=excluded.icon,
icon_tint=excluded.icon_tint;

changeName:
UPDATE workspace_entity
SET name = ?
WHERE id = ?;
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,22 @@ JOIN user_entity
ON user_entity.id = workspace_to_user.user_id
WHERE workspace_to_user.workspace_id = ?;

getUserInWorkspace:
SELECT
user_entity.id AS user_entity_id,
user_entity.name AS user_name,
user_entity.created_at AS user_created_at,
user_entity.email AS user_email,
user_entity.enabled AS user_enabled,
role
FROM workspace_entity
JOIN workspace_to_user
ON workspace_entity.id = workspace_to_user.workspace_id
JOIN user_entity
ON user_entity.id = workspace_to_user.user_id
WHERE workspace_to_user.workspace_id = ? AND user_entity.email = ?
LIMIT 1;

insertWorkspaceToUser:
INSERT INTO workspace_to_user(workspace_id, user_id, role)
VALUES (?, ?, ?)
Expand All @@ -29,3 +45,8 @@ removeUserFromWorkspace:
DELETE FROM workspace_to_user
WHERE workspace_id = ? AND user_id = ?;

changeRole:
UPDATE workspace_to_user
SET role = ?
WHERE workspace_id = ? AND user_id = ?;

Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ class DocumentationIntegrationTests {

assertEquals(HttpStatusCode.OK, response.status)

val response1 = client.get("/api/workspace/$workspace/document/${documentApiList.first().id}")
val response1 =
client.get("/api/workspace/$workspace/document/${documentApiList.first().id}")
assertEquals(HttpStatusCode.OK, response1.status)

val actual = response1.body<DocumentApi>().copy(lastSyncedAt = 0L)
Expand All @@ -75,6 +76,11 @@ class DocumentationIntegrationTests {
}
}

@Test
fun `it should be possible to change the name of a workspace`() = testApplication {

}

@Test
fun `it should be possible to save and query folder by id`() = testApplication {
application {
Expand Down Expand Up @@ -181,7 +187,8 @@ class DocumentationIntegrationTests {

assertEquals(HttpStatusCode.OK, response.status)

val response1 = client.get("/api/workspace/workspace/document/parent/${documentApi.parentId}")
val response1 =
client.get("/api/workspace/workspace/document/parent/${documentApi.parentId}")

assertEquals(HttpStatusCode.OK, response1.status)
assertEquals(
Expand Down
Loading