From 04860d14e5b54d727a0374ba25abf710f1ee9c78 Mon Sep 17 00:00:00 2001 From: avalin Date: Thu, 23 May 2024 10:14:38 +0200 Subject: [PATCH] Fix friends --- .../kotlin/allin/data/FriendDataSource.kt | 4 +- .../allin/data/mock/MockFriendDataSource.kt | 3 +- .../allin/data/mock/MockUserDataSource.kt | 13 +-- .../data/postgres/PostgresFriendDataSource.kt | 14 +-- Sources/src/main/kotlin/allin/model/User.kt | 12 ++- .../main/kotlin/allin/routing/friendRouter.kt | 93 ++++++++++--------- 6 files changed, 73 insertions(+), 66 deletions(-) diff --git a/Sources/src/main/kotlin/allin/data/FriendDataSource.kt b/Sources/src/main/kotlin/allin/data/FriendDataSource.kt index bb72df0..cc2e98c 100644 --- a/Sources/src/main/kotlin/allin/data/FriendDataSource.kt +++ b/Sources/src/main/kotlin/allin/data/FriendDataSource.kt @@ -1,8 +1,10 @@ package allin.data +import allin.dto.UserDTO + interface FriendDataSource { fun addFriend(sender: String, receiver: String) - fun getFriendFromUserId(id: String): List + fun getFriendFromUserId(id: String): List fun deleteFriend(senderId: String, receiverId: String): Boolean fun isFriend(firstUser: String, secondUser: String): Boolean } \ No newline at end of file diff --git a/Sources/src/main/kotlin/allin/data/mock/MockFriendDataSource.kt b/Sources/src/main/kotlin/allin/data/mock/MockFriendDataSource.kt index f8f0bac..2ab4979 100644 --- a/Sources/src/main/kotlin/allin/data/mock/MockFriendDataSource.kt +++ b/Sources/src/main/kotlin/allin/data/mock/MockFriendDataSource.kt @@ -6,6 +6,7 @@ import allin.model.Friend class MockFriendDataSource(private val mockData: MockDataSource.MockData) : FriendDataSource { private val friends get() = mockData.friends + private val users get() = mockData.users override fun addFriend(sender: String, receiver: String) { mockData.friends.add(Friend(sender, receiver)) @@ -14,7 +15,7 @@ class MockFriendDataSource(private val mockData: MockDataSource.MockData) : Frie override fun getFriendFromUserId(id: String) = friends.map { Friend(sender = it.sender, receiver = it.receiver) } .filter { it.sender == id } - .map { it.receiver } + .mapNotNull { users.find { usr -> it.receiver == usr.id }?.toDto() } override fun deleteFriend(senderId: String, receiverId: String) = friends.removeIf { (it.sender == senderId) && (it.receiver == receiverId) } diff --git a/Sources/src/main/kotlin/allin/data/mock/MockUserDataSource.kt b/Sources/src/main/kotlin/allin/data/mock/MockUserDataSource.kt index 454357f..047aa06 100644 --- a/Sources/src/main/kotlin/allin/data/mock/MockUserDataSource.kt +++ b/Sources/src/main/kotlin/allin/data/mock/MockUserDataSource.kt @@ -3,8 +3,6 @@ package allin.data.mock import allin.data.UserDataSource import allin.dto.UserDTO import allin.model.User -import org.ktorm.dsl.eq -import org.ktorm.dsl.or import java.time.ZonedDateTime class MockUserDataSource(private val mockData: MockDataSource.MockData) : UserDataSource { @@ -13,16 +11,7 @@ class MockUserDataSource(private val mockData: MockDataSource.MockData) : UserDa override fun getUserByUsername(username: String): Pair = users.find { (it.username == username) or (it.email == username) }?.let { - Pair( - UserDTO( - id = it.id, - username = it.username, - email = it.email, - nbCoins = it.nbCoins, - token = it.token - ), - it.password - ) + it.toDto() to it.password } ?: Pair(null, null) override fun addUser(user: User) { diff --git a/Sources/src/main/kotlin/allin/data/postgres/PostgresFriendDataSource.kt b/Sources/src/main/kotlin/allin/data/postgres/PostgresFriendDataSource.kt index 130205a..1be8ba3 100644 --- a/Sources/src/main/kotlin/allin/data/postgres/PostgresFriendDataSource.kt +++ b/Sources/src/main/kotlin/allin/data/postgres/PostgresFriendDataSource.kt @@ -3,13 +3,11 @@ package allin.data.postgres import allin.data.FriendDataSource import allin.data.postgres.entities.FriendEntity import allin.data.postgres.entities.friends +import allin.data.postgres.entities.users import org.ktorm.database.Database import org.ktorm.dsl.and import org.ktorm.dsl.eq -import org.ktorm.entity.add -import org.ktorm.entity.filter -import org.ktorm.entity.map -import org.ktorm.entity.removeIf +import org.ktorm.entity.* class PostgresFriendDataSource(private val database: Database) : FriendDataSource { override fun addFriend(sender: String, receiver: String) { @@ -24,11 +22,15 @@ class PostgresFriendDataSource(private val database: Database) : FriendDataSourc override fun getFriendFromUserId(id: String) = database.friends.map { it.toFriend() } .filter { it.sender == id } - .map { it.receiver } + .mapNotNull { + database.users.find { usr -> + usr.id eq it.receiver + }?.toUserDTO() + } override fun deleteFriend(senderId: String, receiverId: String): Boolean { - database.friends.removeIf { (it.sender eq senderId) and (it.receiver eq receiverId) } + database.friends.removeIf { (it.sender eq receiverId) and (it.receiver eq senderId) } return database.friends.removeIf { (it.sender eq senderId) and (it.receiver eq receiverId) } > 0 } diff --git a/Sources/src/main/kotlin/allin/model/User.kt b/Sources/src/main/kotlin/allin/model/User.kt index 423986e..87ac89d 100644 --- a/Sources/src/main/kotlin/allin/model/User.kt +++ b/Sources/src/main/kotlin/allin/model/User.kt @@ -1,5 +1,6 @@ package allin.model +import allin.dto.UserDTO import kotlinx.serialization.Serializable const val DEFAULT_COIN_AMOUNT = 500 @@ -14,7 +15,16 @@ data class User( var password: String, var nbCoins: Int = DEFAULT_COIN_AMOUNT, var token: String? = null -) +) { + fun toDto() = + UserDTO( + id = id, + username = username, + email = email, + nbCoins = nbCoins, + token = token + ) +} @Serializable data class UserRequest( diff --git a/Sources/src/main/kotlin/allin/routing/friendRouter.kt b/Sources/src/main/kotlin/allin/routing/friendRouter.kt index f7d857c..24f1880 100644 --- a/Sources/src/main/kotlin/allin/routing/friendRouter.kt +++ b/Sources/src/main/kotlin/allin/routing/friendRouter.kt @@ -1,14 +1,13 @@ package allin.routing import allin.dataSource +import allin.dto.UserDTO import allin.ext.hasToken import allin.ext.verifyUserFromToken import allin.model.ApiMessage -import allin.model.Bet import io.github.smiley4.ktorswaggerui.dsl.get import io.github.smiley4.ktorswaggerui.dsl.post import io.ktor.http.* - import io.ktor.server.application.* import io.ktor.server.auth.* import io.ktor.server.auth.jwt.* @@ -32,7 +31,7 @@ fun Application.friendRouter() { response { HttpStatusCode.Accepted to { description = "The list of friends is available" - body> { + body> { description = "List of friends" } } @@ -47,53 +46,54 @@ fun Application.friendRouter() { } } - post("/friends/add", { - description = "Allows a user to add a friend" - request { - headerParameter("JWT token of the logged user") - body { - description = "User to add in the friends list" - } - } - response { - HttpStatusCode.Created to { - description = "the friend has been added" - body() { - description = "Friend with assigned id" + post("/friends/add", { + description = "Allows a user to add a friend" + request { + headerParameter("JWT token of the logged user") + body { + description = "User to add in the friends list" } } - HttpStatusCode.Conflict to { - description = "Friend already exist in the friends list" - body(ApiMessage.FRIENDS_ALREADY_EXISTS) + response { + HttpStatusCode.Created to { + description = "the friend has been added" + body { + description = "Friend with assigned id" + } + } + HttpStatusCode.Conflict to { + description = "Friend already exist in the friends list" + body(ApiMessage.FRIENDS_ALREADY_EXISTS) + } } - } - }) { - hasToken { principal -> - val requestMap = call.receive>() - val usernameFriend = requestMap["username"] ?: return@hasToken call.respond(HttpStatusCode.BadRequest, "Username is missing") - val username = tokenManagerBet.getUsernameFromToken(principal) + }) { + hasToken { principal -> + val requestMap = call.receive>() + val usernameFriend = requestMap["username"] ?: return@hasToken call.respond( + HttpStatusCode.BadRequest, + "Username is missing" + ) + val username = tokenManagerBet.getUsernameFromToken(principal) - val user = userDataSource.getUserByUsername(username).first - val userFriend = userDataSource.getUserByUsername(usernameFriend).first + val user = userDataSource.getUserByUsername(username).first + val userFriend = userDataSource.getUserByUsername(usernameFriend).first - if (user == null || userFriend == null) { - call.respond(HttpStatusCode.Conflict, ApiMessage.USER_NOT_FOUND) - } - else if (userFriend == user) { - call.respond(HttpStatusCode.Conflict,ApiMessage.FRIENDS_REQUEST_HIMSELF) - } - else { - val friendlist = friendDataSource.getFriendFromUserId(user.id) - if (friendlist.contains(userFriend.id)) { - call.respond(HttpStatusCode.Conflict,ApiMessage.FRIENDS_ALREADY_EXISTS) + if (user == null || userFriend == null) { + call.respond(HttpStatusCode.Conflict, ApiMessage.USER_NOT_FOUND) + } else if (userFriend == user) { + call.respond(HttpStatusCode.Conflict, ApiMessage.FRIENDS_REQUEST_HIMSELF) } else { - friendDataSource.addFriend(user.id, userFriend.id) - call.respond(HttpStatusCode.Created, usernameFriend) + val friendlist = friendDataSource.getFriendFromUserId(user.id) + if (friendlist.map { it.id }.contains(userFriend.id)) { + call.respond(HttpStatusCode.Conflict, ApiMessage.FRIENDS_ALREADY_EXISTS) + } else { + friendDataSource.addFriend(user.id, userFriend.id) + call.respond(HttpStatusCode.Created, usernameFriend) + } } } - } - } + } post("/friends/delete", { description = "Allows a user to delete a friend" request { @@ -105,7 +105,7 @@ fun Application.friendRouter() { response { HttpStatusCode.Created to { description = "the friend has been delete" - body() { + body { description = "Friend with assigned id" } } @@ -117,7 +117,10 @@ fun Application.friendRouter() { }) { hasToken { principal -> val requestMap = call.receive>() - val usernameFriend = requestMap["username"] ?: return@hasToken call.respond(HttpStatusCode.BadRequest, "Username is missing") + val usernameFriend = requestMap["username"] ?: return@hasToken call.respond( + HttpStatusCode.BadRequest, + "Username is missing" + ) val username = tokenManagerBet.getUsernameFromToken(principal) val user = userDataSource.getUserByUsername(username).first @@ -127,8 +130,8 @@ fun Application.friendRouter() { call.respond(HttpStatusCode.Conflict, ApiMessage.USER_NOT_FOUND) } else { val friendlist = friendDataSource.getFriendFromUserId(user.id) - if (!friendlist.contains(userFriend.id)) { - call.respond(HttpStatusCode.Conflict,ApiMessage.FRIENDS_DOESNT_EXISTS) + if (!friendlist.map { it.id }.contains(userFriend.id)) { + call.respond(HttpStatusCode.Conflict, ApiMessage.FRIENDS_DOESNT_EXISTS) } else { friendDataSource.deleteFriend(user.id, userFriend.id) call.respond(HttpStatusCode.Created, usernameFriend)