addFriend #12

Merged
lucas.evard merged 5 commits from addFriend into master 11 months ago

@ -38,7 +38,7 @@ val Application.dataSource: AllInDataSource
get() = allInDataSource
fun main() {
embeddedServer(Netty, port = 8080, host = "0.0.0.0") {
embeddedServer(Netty, port = 10001, host = "0.0.0.0") {
extracted()
}.start(wait = true)
}
@ -85,6 +85,7 @@ private fun Application.extracted() {
betRouter()
participationRouter()
betDetailRouter()
friendRouter()
kronJob(BET_VERIFY_DELAY) {
dataSource.betDataSource.updateBetStatuses(ZonedDateTime.now())

@ -4,4 +4,5 @@ abstract class AllInDataSource {
abstract val userDataSource: UserDataSource
abstract val betDataSource: BetDataSource
abstract val participationDataSource: ParticipationDataSource
abstract val friendDataSource: FriendDataSource
}

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

@ -1,9 +1,6 @@
package allin.data.mock
import allin.data.AllInDataSource
import allin.data.BetDataSource
import allin.data.ParticipationDataSource
import allin.data.UserDataSource
import allin.data.*
import allin.model.*
import java.time.ZonedDateTime
@ -29,4 +26,5 @@ class MockDataSource : AllInDataSource() {
override val userDataSource: UserDataSource by lazy { MockUserDataSource(mockData) }
override val betDataSource: BetDataSource by lazy { MockBetDataSource(mockData) }
override val participationDataSource: ParticipationDataSource by lazy { MockParticipationDataSource(mockData) }
override val friendDataSource: FriendDataSource by lazy { MockFriendDataSource(mockData) }
}

@ -0,0 +1,22 @@
package allin.data.mock
import allin.data.FriendDataSource
class MockFriendDataSource(mockData: MockDataSource.MockData) : FriendDataSource {
override fun addFriend(sender: String, receiver: String) {
TODO("Not yet implemented")
}
override fun getFriendFromUserId(id: String): List<String> {
TODO("Not yet implemented")
}
override fun deleteFriend(senderId: String, receiverId: String): Boolean {
TODO("Not yet implemented")
}
override fun isFriend(firstUser: String, secondUser: String): Boolean {
TODO("Not yet implemented")
}
}

@ -1,9 +1,6 @@
package allin.data.postgres
import allin.data.AllInDataSource
import allin.data.BetDataSource
import allin.data.ParticipationDataSource
import allin.data.UserDataSource
import allin.data.*
import allin.ext.execute
import org.ktorm.database.Database
@ -117,9 +114,20 @@ class PostgresDataSource : AllInDataSource() {
)
""".trimIndent()
)
database.execute(
"""
CREATE TABLE IF NOT EXISTS friend(
sender VARCHAR(255),
receiver VARCHAR(255),
CONSTRAINT pk_friend PRIMARY KEY (sender,receiver)
)
""".trimIndent()
)
}
override val userDataSource: UserDataSource by lazy { PostgresUserDataSource(database) }
override val betDataSource: BetDataSource by lazy { PostgresBetDataSource(database) }
override val participationDataSource: ParticipationDataSource by lazy { PostgresParticipationDataSource(database) }
override val friendDataSource: FriendDataSource by lazy { PostgresFriendDataSource(database) }
}

@ -0,0 +1,42 @@
package allin.data.postgres
import allin.data.FriendDataSource
import allin.data.postgres.entities.FriendEntity
import allin.data.postgres.entities.friends
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
class PostgresFriendDataSource(private val database: Database) : FriendDataSource {
override fun addFriend(sender: String, receiver: String) {
database.friends.add(
FriendEntity {
this.sender = sender
this.receiver = receiver
}
)
}
override fun getFriendFromUserId(id: String): List<String> {
val friendList = database.friends.map { it.toFriend() }
val friendPairs = friendList.map { it.sender to it.receiver }.toSet()
return friendList
.filter { it.sender == id }
.map { it.receiver }
}
override fun deleteFriend(senderId: String, receiverId: String): Boolean {
database.friends.removeIf { it.sender eq senderId }
return database.friends.removeIf { it.sender eq senderId } > 0
}
override fun isFriend(firstUser: String, secondUser: String) =
database.friends
.filter { (it.sender eq firstUser) and (it.receiver eq secondUser) }
.map { it.toFriend() }
.isNotEmpty()
}

@ -0,0 +1,29 @@
package allin.data.postgres.entities
import allin.model.Friend
import org.ktorm.database.Database
import org.ktorm.entity.Entity
import org.ktorm.entity.sequenceOf
import org.ktorm.schema.Table
import org.ktorm.schema.varchar
interface FriendEntity : Entity<FriendEntity> {
companion object : Entity.Factory<FriendEntity>()
var sender: String
var receiver: String
fun toFriend() =
Friend(
sender = sender,
receiver = receiver,
)
}
object FriendsEntity : Table<FriendEntity>("friend") {
val sender = varchar("sender").primaryKey().bindTo { it.sender }
val receiver = varchar("receiver").primaryKey().bindTo { it.receiver }
}
val Database.friends get() = this.sequenceOf(FriendsEntity)

@ -13,4 +13,7 @@ object ApiMessage {
const val NOT_ENOUGH_COINS = "Not enough coins."
const val NO_GIFT = "Can't get daily gift."
const val USER_CANT_BE_DELETE = "This user can't be delete now !"
const val FRIENDS_ALREADY_EXISTS = "User already exists in your Friends List."
const val FRIENDS_DOESNT_EXISTS = "User already exists in your Friends List."
}

@ -0,0 +1,7 @@
package allin.model
data class Friend(
val sender: String,
val receiver: String
)

@ -0,0 +1,114 @@
package allin.routing
import allin.dataSource
import allin.ext.hasToken
import allin.model.ApiMessage
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.*
import io.ktor.server.request.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
fun Application.friendRouter() {
val userDataSource = this.dataSource.userDataSource
val friendDataSource = this.dataSource.friendDataSource
routing {
authenticate {
post("/friend/add", {
description = "Allows a user to add a friend"
request {
headerParameter<JWTPrincipal>("JWT token of the logged user")
body<String> {
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 {
description = "Friend already exist in the friends list"
body(ApiMessage.FRIENDS_ALREADY_EXISTS)
}
}
}) {
hasToken { principal ->
val requestMap = call.receive<Map<String, String>>()
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
if (user == null || userFriend == null) {
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_ALREADY_EXISTS)
} else {
friendDataSource.addFriend(user.id, userFriend.id)
call.respond(HttpStatusCode.Created, usernameFriend)
}
}
}
}
post("/friend/delete", {
description = "Allows a user to delete a friend"
request {
headerParameter<JWTPrincipal>("JWT token of the logged user")
body<String> {
description = "User to delete in the friends list"
}
}
response {
HttpStatusCode.Created to {
description = "the friend has been delete"
body<String>() {
description = "Friend with assigned id"
}
}
HttpStatusCode.Conflict to {
description = "Friend doesn't exist in the friends list"
body(ApiMessage.FRIENDS_DOESNT_EXISTS)
}
}
}) {
hasToken { principal ->
val requestMap = call.receive<Map<String, String>>()
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
if (user == null || userFriend == null) {
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)
} else {
friendDataSource.deleteFriend(user.id, userFriend.id)
call.respond(HttpStatusCode.Created, usernameFriend)
}
}
}
}
}
}
}
Loading…
Cancel
Save