Skip to content

Commit 418e87f

Browse files
committed
Fixed problems with users
1 parent 9a74f63 commit 418e87f

File tree

14 files changed

+147
-184
lines changed

14 files changed

+147
-184
lines changed

src/main/kotlin/ua/pp/lumivoid/iwtcms/PREIWTCMS.kt

Lines changed: 12 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,21 @@ package ua.pp.lumivoid.iwtcms
22

33
import kotlinx.coroutines.runBlocking
44
import net.fabricmc.loader.api.entrypoint.PreLaunchEntrypoint
5-
import org.apache.commons.codec.digest.DigestUtils
65
import org.jetbrains.exposed.v1.core.StdOutSqlLogger
7-
import org.jetbrains.exposed.v1.r2dbc.insert
8-
import org.jetbrains.exposed.v1.r2dbc.selectAll
96
import org.jetbrains.exposed.v1.r2dbc.R2dbcDatabase
107
import org.jetbrains.exposed.v1.r2dbc.SchemaUtils
8+
import org.jetbrains.exposed.v1.r2dbc.selectAll
119
import org.jetbrains.exposed.v1.r2dbc.transactions.suspendTransaction
1210
import org.slf4j.LoggerFactory
1311
import ua.pp.lumivoid.iwtcms.ktor.KtorServer
12+
import ua.pp.lumivoid.iwtcms.ktor.api.requests.CreateUser
1413
import ua.pp.lumivoid.iwtcms.ktor.tables.UserPermissionsTable
1514
import ua.pp.lumivoid.iwtcms.ktor.tables.UsersTable
1615
import ua.pp.lumivoid.iwtcms.ktor.util.Config
1716
import ua.pp.lumivoid.iwtcms.ktor.util.ErrorMessages
1817
import ua.pp.lumivoid.iwtcms.util.CustomLogger
1918
import java.io.File
20-
import java.util.TimeZone
19+
import java.util.*
2120
import kotlin.system.exitProcess
2221

2322
object PREIWTCMS : PreLaunchEntrypoint {
@@ -57,24 +56,18 @@ object PREIWTCMS : PreLaunchEntrypoint {
5756
password = config.databasePassword,
5857
)
5958

60-
runBlocking { suspendTransaction {
61-
if (config.devMode) addLogger(StdOutSqlLogger)
59+
runBlocking {
60+
suspendTransaction {
61+
if (config.devMode) addLogger(StdOutSqlLogger)
6262

63-
SchemaUtils.create(
64-
UsersTable,
65-
UserPermissionsTable,
66-
)
63+
SchemaUtils.create(
64+
UsersTable,
65+
UserPermissionsTable,
66+
)
6767

68-
if (UsersTable.selectAll().empty()) {
69-
UsersTable.insert {
70-
it[username] = "admin"
71-
it[passwordHash] = DigestUtils.sha256Hex("iwtcms" + "ySXBvMifqXULEm1uRKP91ctmL6tCwCMi").toString()
72-
it[salt] = "ySXBvMifqXULEm1uRKP91ctmL6tCwCMi"
73-
it[uniqueId] = DigestUtils.sha256Hex("admin+iwtcms").toString()
74-
it[admin] = true
75-
}
68+
if (UsersTable.selectAll().empty()) CreateUser.create("admin", "iwtcms", true, emptyList())
7669
}
77-
}}
70+
}
7871

7972
KtorServer.setup()
8073
}

src/main/kotlin/ua/pp/lumivoid/iwtcms/ktor/api/PermissionsList.kt

Lines changed: 0 additions & 27 deletions
This file was deleted.

src/main/kotlin/ua/pp/lumivoid/iwtcms/ktor/api/doAuth.kt

Lines changed: 11 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,10 @@
11
package ua.pp.lumivoid.iwtcms.ktor.api
22

3-
import io.ktor.http.HttpStatusCode
4-
import io.ktor.server.response.respond
5-
import io.ktor.server.routing.RoutingCall
6-
import io.ktor.server.sessions.get
7-
import io.ktor.server.sessions.sessions
8-
import kotlinx.coroutines.flow.first
9-
import kotlinx.coroutines.flow.firstOrNull
10-
import org.jetbrains.exposed.v1.core.ResultRow
3+
import io.ktor.http.*
4+
import io.ktor.server.response.*
5+
import io.ktor.server.routing.*
6+
import io.ktor.server.sessions.*
7+
import kotlinx.coroutines.flow.singleOrNull
118
import org.jetbrains.exposed.v1.core.and
129
import org.jetbrains.exposed.v1.core.eq
1310
import org.jetbrains.exposed.v1.r2dbc.selectAll
@@ -41,10 +38,9 @@ suspend fun doAuth(
4138
}
4239

4340
val status = suspendTransaction {
44-
val user = UsersTable
45-
.selectAll()
41+
val user = UsersTable.selectAll()
4642
.where { (UsersTable.username eq session.name) and (UsersTable.uniqueId eq session.id) }
47-
.firstOrNull()
43+
.singleOrNull()
4844

4945
if (user == null) {
5046
return@suspendTransaction HttpStatusCode.Unauthorized
@@ -54,16 +50,11 @@ suspend fun doAuth(
5450
return@suspendTransaction HttpStatusCode.OK
5551
}
5652

57-
val permission: ResultRow = try {
58-
UserPermissionsTable
59-
.selectAll()
60-
.where { (UserPermissionsTable.userId eq user[UsersTable.id]) and (UserPermissionsTable.permissionName eq permission) }
61-
.first()
62-
} catch (_: NoSuchElementException) {
63-
return@suspendTransaction HttpStatusCode.Forbidden
64-
}
53+
val found = UserPermissionsTable.selectAll()
54+
.where { (UserPermissionsTable.userId eq user[UsersTable.id]) and (UserPermissionsTable.permissionName eq permission) }
55+
.singleOrNull()
6556

66-
if (permission[UserPermissionsTable.permissionState]) {
57+
if (found != null) {
6758
return@suspendTransaction HttpStatusCode.OK
6859
} else {
6960
return@suspendTransaction HttpStatusCode.Forbidden

src/main/kotlin/ua/pp/lumivoid/iwtcms/ktor/api/requests/Configs.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import io.ktor.server.routing.put
1010
import kotlinx.serialization.Serializable
1111
import kotlinx.serialization.decodeFromString
1212
import ua.pp.lumivoid.iwtcms.Constants
13-
import ua.pp.lumivoid.iwtcms.ktor.api.PermissionsList
1413
import ua.pp.lumivoid.iwtcms.ktor.api.doAuth
1514
import java.io.File
1615

src/main/kotlin/ua/pp/lumivoid/iwtcms/ktor/api/requests/CreateUser.kt

Lines changed: 33 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,12 @@ import io.ktor.server.request.receive
55
import io.ktor.server.response.respond
66
import io.ktor.server.routing.Routing
77
import io.ktor.server.routing.post
8-
import kotlinx.coroutines.flow.first
98
import kotlinx.serialization.Serializable
109
import org.apache.commons.codec.digest.DigestUtils
1110
import org.jetbrains.exposed.v1.core.eq
1211
import org.jetbrains.exposed.v1.r2dbc.insert
1312
import org.jetbrains.exposed.v1.r2dbc.selectAll
1413
import org.jetbrains.exposed.v1.r2dbc.transactions.suspendTransaction
15-
import ua.pp.lumivoid.iwtcms.ktor.api.PermissionsList
1614
import ua.pp.lumivoid.iwtcms.ktor.api.doAuth
1715
import ua.pp.lumivoid.iwtcms.ktor.tables.UserPermissionsTable
1816
import ua.pp.lumivoid.iwtcms.ktor.tables.UsersTable
@@ -28,59 +26,56 @@ object CreateUser : Request() {
2826
call = call,
2927
permission = PermissionsList.Permission.USERS_MANAGE.value,
3028
success = {
31-
val success = suspendTransaction {
32-
var salt = generateSequence { genSalt() }
33-
.first { saltCandidate ->
34-
UsersTable.selectAll().where(UsersTable.salt eq saltCandidate).empty()
35-
}
29+
if (create(payload.username, payload.password, payload.admin, payload.permissions)) call.respond("User created")
30+
else call.respond(HttpStatusCode.Conflict, "User already exists")
31+
},
32+
)
33+
}
34+
}
3635

37-
runCatching {
38-
UsersTable.insert {
39-
it[UsersTable.username] = payload.username
40-
it[UsersTable.passwordHash] = DigestUtils.sha256Hex(payload.password + salt)
41-
it[UsersTable.salt] = salt
42-
it[UsersTable.uniqueId] = DigestUtils.sha256Hex("${payload.username}+${payload.password}+${salt}")
43-
it[UsersTable.admin] = payload.admin
44-
}
45-
}.onFailure {
46-
return@suspendTransaction false
47-
}
36+
suspend fun create(username: String, password: String, admin: Boolean, permissions: List<String>): Boolean {
37+
return suspendTransaction {
38+
val salt = generateSequence { genSalt() }.first { saltCandidate ->
39+
UsersTable.selectAll().where(UsersTable.salt eq saltCandidate).empty()
40+
}
4841

49-
payload.permissions.forEach { (key, value) ->
50-
if (key in PermissionsList.getPermissionsList()) {
51-
runCatching {
52-
val userId = UsersTable.selectAll().where{ UsersTable.username eq payload.username }.first()[UsersTable.id]
53-
UserPermissionsTable.insert {
54-
it[UserPermissionsTable.permissionName] = key
55-
it[UserPermissionsTable.permissionState] = value
56-
it[UserPermissionsTable.userId] = userId
57-
}
58-
}
59-
}
60-
}
42+
runCatching {
43+
val user = UsersTable.insert {
44+
it[UsersTable.username] = username
45+
it[UsersTable.passwordHash] = DigestUtils.sha256Hex(password + salt)
46+
it[UsersTable.salt] = salt
47+
it[UsersTable.uniqueId] = DigestUtils.sha256Hex("${username}+${password}+${salt}")
48+
it[UsersTable.admin] = admin
49+
}
6150

62-
true
51+
if (!admin) {
52+
permissions.forEach { permission ->
53+
UserPermissionsTable.insert {
54+
it[UserPermissionsTable.userId] = user[UsersTable.id]
55+
it[UserPermissionsTable.permissionName] = permission
56+
}
6357
}
58+
}
59+
}.onFailure {
60+
return@suspendTransaction false
61+
}
6462

65-
if (success) call.respond("User created")
66-
else call.respond(HttpStatusCode.Conflict, "User already exists")
67-
},
68-
)
63+
true
6964
}
7065
}
7166

72-
fun genSalt(): String {
67+
private fun genSalt(): String {
7368
val allowedChars = ('A'..'Z') + ('a'..'z') + ('0'..'9')
7469
return (1..32)
7570
.map { allowedChars.random() }
7671
.joinToString("")
7772
}
7873

7974
@Serializable
80-
data class CreateUserPayload(
75+
private data class CreateUserPayload(
8176
val username: String,
8277
val password: String,
8378
val admin: Boolean,
84-
val permissions: Map<String, Boolean>,
79+
val permissions: List<String>
8580
)
8681
}

src/main/kotlin/ua/pp/lumivoid/iwtcms/ktor/api/requests/DeleteUser.kt

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,16 @@
11
package ua.pp.lumivoid.iwtcms.ktor.api.requests
22

3-
import io.ktor.http.HttpStatusCode
4-
import io.ktor.server.request.receive
5-
import io.ktor.server.response.respond
6-
import io.ktor.server.routing.Routing
7-
import io.ktor.server.routing.delete
8-
import kotlinx.coroutines.flow.firstOrNull
3+
import io.ktor.http.*
4+
import io.ktor.server.request.*
5+
import io.ktor.server.response.*
6+
import io.ktor.server.routing.*
7+
import kotlinx.coroutines.flow.singleOrNull
98
import kotlinx.serialization.Serializable
109
import org.jetbrains.exposed.v1.core.eq
1110
import org.jetbrains.exposed.v1.r2dbc.deleteWhere
1211
import org.jetbrains.exposed.v1.r2dbc.selectAll
1312
import org.jetbrains.exposed.v1.r2dbc.transactions.suspendTransaction
14-
import ua.pp.lumivoid.iwtcms.ktor.api.PermissionsList
1513
import ua.pp.lumivoid.iwtcms.ktor.api.doAuth
16-
import ua.pp.lumivoid.iwtcms.ktor.tables.UserPermissionsTable
1714
import ua.pp.lumivoid.iwtcms.ktor.tables.UsersTable
1815

1916
object DeleteUser : Request() {
@@ -28,15 +25,13 @@ object DeleteUser : Request() {
2825
permission = PermissionsList.Permission.USERS_MANAGE.value,
2926
success = {
3027
val success = suspendTransaction {
31-
val user = UsersTable
32-
.selectAll()
28+
val user = UsersTable.selectAll()
3329
.where { UsersTable.username eq payload.username }
34-
.firstOrNull()
30+
.singleOrNull()
3531

3632
if (user == null) return@suspendTransaction false
3733

3834
UsersTable.deleteWhere { UsersTable.username eq payload.username }
39-
UserPermissionsTable.deleteWhere { UserPermissionsTable.userId eq userId }
4035
true
4136
}
4237

Lines changed: 20 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,16 @@
11
package ua.pp.lumivoid.iwtcms.ktor.api.requests
22

3-
import io.ktor.http.HttpStatusCode
4-
import io.ktor.server.request.receive
5-
import io.ktor.server.response.respond
6-
import io.ktor.server.routing.Routing
7-
import io.ktor.server.routing.post
8-
import kotlinx.coroutines.flow.first
3+
import io.ktor.http.*
4+
import io.ktor.server.request.*
5+
import io.ktor.server.response.*
6+
import io.ktor.server.routing.*
7+
import kotlinx.coroutines.flow.single
98
import kotlinx.serialization.Serializable
10-
import org.jetbrains.exposed.v1.core.and
119
import org.jetbrains.exposed.v1.core.eq
10+
import org.jetbrains.exposed.v1.r2dbc.deleteWhere
11+
import org.jetbrains.exposed.v1.r2dbc.insert
1212
import org.jetbrains.exposed.v1.r2dbc.selectAll
1313
import org.jetbrains.exposed.v1.r2dbc.transactions.suspendTransaction
14-
import org.jetbrains.exposed.v1.r2dbc.update
15-
import ua.pp.lumivoid.iwtcms.ktor.api.PermissionsList
1614
import ua.pp.lumivoid.iwtcms.ktor.api.doAuth
1715
import ua.pp.lumivoid.iwtcms.ktor.tables.UserPermissionsTable
1816
import ua.pp.lumivoid.iwtcms.ktor.tables.UsersTable
@@ -21,54 +19,36 @@ object EditPermissions : Request() {
2119
override val path = "/api/editPermissions"
2220

2321
override val request: Routing.() -> Unit = {
24-
post(path) {
22+
put(path) {
2523
val payload = call.receive<EditPermissionPayload>()
2624

2725
doAuth(
2826
call = call,
2927
permission = PermissionsList.Permission.USERS_MANAGE.value,
3028
success = {
31-
val result: TransactionState = suspendTransaction {
32-
val userId: Int = try {
33-
UsersTable
34-
.selectAll()
35-
.where { UsersTable.username eq payload.username }
36-
.first()[UsersTable.id]
37-
} catch (_: NoSuchElementException) {
38-
return@suspendTransaction TransactionState.USER_NOT_FOUND
39-
}
29+
suspendTransaction {
30+
val user = UsersTable.selectAll()
31+
.where { UsersTable.username eq payload.username }.single()
32+
33+
UserPermissionsTable.deleteWhere { userId eq user[UsersTable.id] }
4034

41-
try {
42-
payload.permissions.forEach { (key, value) ->
43-
UserPermissionsTable.update({ (UserPermissionsTable.userId eq userId) and (UserPermissionsTable.permissionName eq key) }) {
44-
it[UserPermissionsTable.permissionState] = value
45-
}
35+
payload.permissions.forEach { permission ->
36+
UserPermissionsTable.insert {
37+
it[UserPermissionsTable.userId] = user[UsersTable.id]
38+
it[UserPermissionsTable.permissionName] = permission
4639
}
47-
return@suspendTransaction TransactionState.SUCCESS
48-
} catch (_: NoSuchElementException) {
49-
return@suspendTransaction TransactionState.PERMISSION_NOT_FOUND
5040
}
5141
}
5242

53-
54-
when (result) {
55-
TransactionState.PERMISSION_NOT_FOUND -> call.respond(HttpStatusCode.NotFound, "Permission not found")
56-
TransactionState.USER_NOT_FOUND -> call.respond(HttpStatusCode.NotFound, "User not found")
57-
TransactionState.SUCCESS -> call.respond(HttpStatusCode.OK, "User permissions updated")
58-
}
43+
call.respond(HttpStatusCode.OK, "User permissions updated")
5944
}
6045
)
6146
}
6247
}
6348

6449
@Serializable
65-
data class EditPermissionPayload(
50+
private data class EditPermissionPayload(
6651
val username: String,
67-
val permissions: Map<String, Boolean>,
52+
val permissions: List<String>,
6853
)
69-
70-
private enum class TransactionState {
71-
USER_NOT_FOUND, PERMISSION_NOT_FOUND, SUCCESS
72-
}
73-
7454
}

0 commit comments

Comments
 (0)