Fix friends
continuous-integration/drone/push Build is passing Details

pull/14/head
avalin 11 months ago
parent de80aecc63
commit 04860d14e5

@ -1,8 +1,10 @@
package allin.data package allin.data
import allin.dto.UserDTO
interface FriendDataSource { interface FriendDataSource {
fun addFriend(sender: String, receiver: String) fun addFriend(sender: String, receiver: String)
fun getFriendFromUserId(id: String): List<String> fun getFriendFromUserId(id: String): List<UserDTO>
fun deleteFriend(senderId: String, receiverId: String): Boolean fun deleteFriend(senderId: String, receiverId: String): Boolean
fun isFriend(firstUser: String, secondUser: String): Boolean fun isFriend(firstUser: String, secondUser: String): Boolean
} }

@ -6,6 +6,7 @@ import allin.model.Friend
class MockFriendDataSource(private val mockData: MockDataSource.MockData) : FriendDataSource { class MockFriendDataSource(private val mockData: MockDataSource.MockData) : FriendDataSource {
private val friends get() = mockData.friends private val friends get() = mockData.friends
private val users get() = mockData.users
override fun addFriend(sender: String, receiver: String) { override fun addFriend(sender: String, receiver: String) {
mockData.friends.add(Friend(sender, receiver)) mockData.friends.add(Friend(sender, receiver))
@ -14,7 +15,7 @@ class MockFriendDataSource(private val mockData: MockDataSource.MockData) : Frie
override fun getFriendFromUserId(id: String) = override fun getFriendFromUserId(id: String) =
friends.map { Friend(sender = it.sender, receiver = it.receiver) } friends.map { Friend(sender = it.sender, receiver = it.receiver) }
.filter { it.sender == id } .filter { it.sender == id }
.map { it.receiver } .mapNotNull { users.find { usr -> it.receiver == usr.id }?.toDto() }
override fun deleteFriend(senderId: String, receiverId: String) = override fun deleteFriend(senderId: String, receiverId: String) =
friends.removeIf { (it.sender == senderId) && (it.receiver == receiverId) } friends.removeIf { (it.sender == senderId) && (it.receiver == receiverId) }

@ -3,8 +3,6 @@ package allin.data.mock
import allin.data.UserDataSource import allin.data.UserDataSource
import allin.dto.UserDTO import allin.dto.UserDTO
import allin.model.User import allin.model.User
import org.ktorm.dsl.eq
import org.ktorm.dsl.or
import java.time.ZonedDateTime import java.time.ZonedDateTime
class MockUserDataSource(private val mockData: MockDataSource.MockData) : UserDataSource { 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<UserDTO?, String?> = override fun getUserByUsername(username: String): Pair<UserDTO?, String?> =
users.find { (it.username == username) or (it.email == username) }?.let { users.find { (it.username == username) or (it.email == username) }?.let {
Pair( it.toDto() to it.password
UserDTO(
id = it.id,
username = it.username,
email = it.email,
nbCoins = it.nbCoins,
token = it.token
),
it.password
)
} ?: Pair(null, null) } ?: Pair(null, null)
override fun addUser(user: User) { override fun addUser(user: User) {

@ -3,13 +3,11 @@ package allin.data.postgres
import allin.data.FriendDataSource import allin.data.FriendDataSource
import allin.data.postgres.entities.FriendEntity import allin.data.postgres.entities.FriendEntity
import allin.data.postgres.entities.friends import allin.data.postgres.entities.friends
import allin.data.postgres.entities.users
import org.ktorm.database.Database import org.ktorm.database.Database
import org.ktorm.dsl.and import org.ktorm.dsl.and
import org.ktorm.dsl.eq import org.ktorm.dsl.eq
import org.ktorm.entity.add import org.ktorm.entity.*
import org.ktorm.entity.filter
import org.ktorm.entity.map
import org.ktorm.entity.removeIf
class PostgresFriendDataSource(private val database: Database) : FriendDataSource { class PostgresFriendDataSource(private val database: Database) : FriendDataSource {
override fun addFriend(sender: String, receiver: String) { override fun addFriend(sender: String, receiver: String) {
@ -24,11 +22,15 @@ class PostgresFriendDataSource(private val database: Database) : FriendDataSourc
override fun getFriendFromUserId(id: String) = override fun getFriendFromUserId(id: String) =
database.friends.map { it.toFriend() } database.friends.map { it.toFriend() }
.filter { it.sender == id } .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 { 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 return database.friends.removeIf { (it.sender eq senderId) and (it.receiver eq receiverId) } > 0
} }

@ -1,5 +1,6 @@
package allin.model package allin.model
import allin.dto.UserDTO
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
const val DEFAULT_COIN_AMOUNT = 500 const val DEFAULT_COIN_AMOUNT = 500
@ -14,7 +15,16 @@ data class User(
var password: String, var password: String,
var nbCoins: Int = DEFAULT_COIN_AMOUNT, var nbCoins: Int = DEFAULT_COIN_AMOUNT,
var token: String? = null var token: String? = null
) ) {
fun toDto() =
UserDTO(
id = id,
username = username,
email = email,
nbCoins = nbCoins,
token = token
)
}
@Serializable @Serializable
data class UserRequest( data class UserRequest(

@ -1,14 +1,13 @@
package allin.routing package allin.routing
import allin.dataSource import allin.dataSource
import allin.dto.UserDTO
import allin.ext.hasToken import allin.ext.hasToken
import allin.ext.verifyUserFromToken import allin.ext.verifyUserFromToken
import allin.model.ApiMessage import allin.model.ApiMessage
import allin.model.Bet
import io.github.smiley4.ktorswaggerui.dsl.get import io.github.smiley4.ktorswaggerui.dsl.get
import io.github.smiley4.ktorswaggerui.dsl.post import io.github.smiley4.ktorswaggerui.dsl.post
import io.ktor.http.* import io.ktor.http.*
import io.ktor.server.application.* import io.ktor.server.application.*
import io.ktor.server.auth.* import io.ktor.server.auth.*
import io.ktor.server.auth.jwt.* import io.ktor.server.auth.jwt.*
@ -32,7 +31,7 @@ fun Application.friendRouter() {
response { response {
HttpStatusCode.Accepted to { HttpStatusCode.Accepted to {
description = "The list of friends is available" description = "The list of friends is available"
body<List<Bet>> { body<List<UserDTO>> {
description = "List of friends" description = "List of friends"
} }
} }
@ -47,53 +46,54 @@ fun Application.friendRouter() {
} }
} }
post("/friends/add", { post("/friends/add", {
description = "Allows a user to add a friend" description = "Allows a user to add a friend"
request { request {
headerParameter<JWTPrincipal>("JWT token of the logged user") headerParameter<JWTPrincipal>("JWT token of the logged user")
body<String> { body<String> {
description = "User to add in the friends list" description = "User to add in the friends list"
}
}
response {
HttpStatusCode.Created to {
description = "the friend has been added"
body<String>() {
description = "Friend with assigned id"
} }
} }
HttpStatusCode.Conflict to { response {
description = "Friend already exist in the friends list" HttpStatusCode.Created to {
body(ApiMessage.FRIENDS_ALREADY_EXISTS) description = "the friend has been added"
body<String> {
description = "Friend with assigned id"
}
}
HttpStatusCode.Conflict to {
description = "Friend already exist in the friends list"
body(ApiMessage.FRIENDS_ALREADY_EXISTS)
}
} }
} }) {
}) { hasToken { principal ->
hasToken { principal -> val requestMap = call.receive<Map<String, String>>()
val requestMap = call.receive<Map<String, String>>() val usernameFriend = requestMap["username"] ?: return@hasToken call.respond(
val usernameFriend = requestMap["username"] ?: return@hasToken call.respond(HttpStatusCode.BadRequest, "Username is missing") HttpStatusCode.BadRequest,
val username = tokenManagerBet.getUsernameFromToken(principal) "Username is missing"
)
val username = tokenManagerBet.getUsernameFromToken(principal)
val user = userDataSource.getUserByUsername(username).first val user = userDataSource.getUserByUsername(username).first
val userFriend = userDataSource.getUserByUsername(usernameFriend).first val userFriend = userDataSource.getUserByUsername(usernameFriend).first
if (user == null || userFriend == null) { if (user == null || userFriend == null) {
call.respond(HttpStatusCode.Conflict, ApiMessage.USER_NOT_FOUND) call.respond(HttpStatusCode.Conflict, ApiMessage.USER_NOT_FOUND)
} } else if (userFriend == user) {
else if (userFriend == user) { call.respond(HttpStatusCode.Conflict, ApiMessage.FRIENDS_REQUEST_HIMSELF)
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)
} else { } else {
friendDataSource.addFriend(user.id, userFriend.id) val friendlist = friendDataSource.getFriendFromUserId(user.id)
call.respond(HttpStatusCode.Created, usernameFriend) 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", { post("/friends/delete", {
description = "Allows a user to delete a friend" description = "Allows a user to delete a friend"
request { request {
@ -105,7 +105,7 @@ fun Application.friendRouter() {
response { response {
HttpStatusCode.Created to { HttpStatusCode.Created to {
description = "the friend has been delete" description = "the friend has been delete"
body<String>() { body<String> {
description = "Friend with assigned id" description = "Friend with assigned id"
} }
} }
@ -117,7 +117,10 @@ fun Application.friendRouter() {
}) { }) {
hasToken { principal -> hasToken { principal ->
val requestMap = call.receive<Map<String, String>>() val requestMap = call.receive<Map<String, String>>()
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 username = tokenManagerBet.getUsernameFromToken(principal)
val user = userDataSource.getUserByUsername(username).first val user = userDataSource.getUserByUsername(username).first
@ -127,8 +130,8 @@ fun Application.friendRouter() {
call.respond(HttpStatusCode.Conflict, ApiMessage.USER_NOT_FOUND) call.respond(HttpStatusCode.Conflict, ApiMessage.USER_NOT_FOUND)
} else { } else {
val friendlist = friendDataSource.getFriendFromUserId(user.id) val friendlist = friendDataSource.getFriendFromUserId(user.id)
if (!friendlist.contains(userFriend.id)) { if (!friendlist.map { it.id }.contains(userFriend.id)) {
call.respond(HttpStatusCode.Conflict,ApiMessage.FRIENDS_DOESNT_EXISTS) call.respond(HttpStatusCode.Conflict, ApiMessage.FRIENDS_DOESNT_EXISTS)
} else { } else {
friendDataSource.deleteFriend(user.id, userFriend.id) friendDataSource.deleteFriend(user.id, userFriend.id)
call.respond(HttpStatusCode.Created, usernameFriend) call.respond(HttpStatusCode.Created, usernameFriend)

Loading…
Cancel
Save