✨ [no_ci] Add friend routes
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
parent
7c49c34167
commit
d4da0fd3f6
@ -1,11 +1,8 @@
|
|||||||
package allin.data
|
package allin.data
|
||||||
|
|
||||||
import allin.model.User
|
|
||||||
|
|
||||||
interface FriendDataSource {
|
interface FriendDataSource {
|
||||||
fun addFriend(sender: String, receiver: String)
|
fun addFriend(sender: String, receiver: String)
|
||||||
fun getFriendFromUserId(id: String): List<User>
|
fun getFriendFromUserId(id: String): List<String>
|
||||||
fun getFriendFromUsername(username: String)
|
fun deleteFriend(senderId: String, receiverId: String): Boolean
|
||||||
fun deleteFriend(senderId: String, receiverId: String)
|
fun isFriend(firstUser: String, secondUser: String): Boolean
|
||||||
fun isFriend(firstUser: String, secondUser: String)
|
|
||||||
}
|
}
|
@ -1,26 +1,22 @@
|
|||||||
package allin.data.mock
|
package allin.data.mock
|
||||||
|
|
||||||
import allin.data.FriendDataSource
|
import allin.data.FriendDataSource
|
||||||
import allin.model.User
|
|
||||||
|
|
||||||
class MockFriendDataSource(mockData: MockDataSource.MockData) : FriendDataSource {
|
class MockFriendDataSource(mockData: MockDataSource.MockData) : FriendDataSource {
|
||||||
override fun addFriend(sender: String, receiver: String) {
|
override fun addFriend(sender: String, receiver: String) {
|
||||||
TODO("Not yet implemented")
|
TODO("Not yet implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getFriendFromUserId(id: String): List<User> {
|
override fun getFriendFromUserId(id: String): List<String> {
|
||||||
TODO("Not yet implemented")
|
TODO("Not yet implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getFriendFromUsername(username: String) {
|
override fun deleteFriend(senderId: String, receiverId: String): Boolean {
|
||||||
TODO("Not yet implemented")
|
TODO("Not yet implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun deleteFriend(senderId: String, receiverId: String) {
|
override fun isFriend(firstUser: String, secondUser: String): Boolean {
|
||||||
TODO("Not yet implemented")
|
TODO("Not yet implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun isFriend(firstUser: String, secondUser: String) {
|
|
||||||
TODO("Not yet implemented")
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -1,33 +1,42 @@
|
|||||||
package allin.data.postgres
|
package allin.data.postgres
|
||||||
|
|
||||||
import allin.data.FriendDataSource
|
import allin.data.FriendDataSource
|
||||||
import allin.data.postgres.entities.FriendsEntity
|
import allin.data.postgres.entities.FriendEntity
|
||||||
import allin.model.User
|
import allin.data.postgres.entities.friends
|
||||||
import org.ktorm.database.Database
|
import org.ktorm.database.Database
|
||||||
import org.ktorm.dsl.insert
|
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 {
|
class PostgresFriendDataSource(private val database: Database) : FriendDataSource {
|
||||||
override fun addFriend(sender: String, receiver: String) {
|
override fun addFriend(sender: String, receiver: String) {
|
||||||
database.insert(FriendsEntity) {
|
database.friends.add(
|
||||||
set(it.sender, sender)
|
FriendEntity {
|
||||||
set(it.receiver, receiver)
|
this.sender = sender
|
||||||
|
this.receiver = receiver
|
||||||
}
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getFriendFromUserId(id: String): List<User> {
|
override fun getFriendFromUserId(id: String): List<String> {
|
||||||
TODO()
|
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 getFriendFromUsername(username: String) {
|
override fun deleteFriend(senderId: String, receiverId: String): Boolean {
|
||||||
TODO("Not yet implemented")
|
database.friends.removeIf { it.sender eq senderId }
|
||||||
}
|
return database.friends.removeIf { it.sender eq senderId } > 0
|
||||||
|
|
||||||
override fun deleteFriend(senderId: String, receiverId: String) {
|
|
||||||
TODO("Not yet implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun isFriend(firstUser: String, secondUser: String) {
|
|
||||||
TODO("Not yet implemented")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun isFriend(firstUser: String, secondUser: String) =
|
||||||
|
database.friends
|
||||||
|
.filter { (it.sender eq firstUser) and (it.receiver eq secondUser) }
|
||||||
|
.map { it.toFriend() }
|
||||||
|
.isNotEmpty()
|
||||||
}
|
}
|
@ -1,15 +1,29 @@
|
|||||||
package allin.data.postgres.entities
|
package allin.data.postgres.entities
|
||||||
|
|
||||||
|
import allin.model.Friend
|
||||||
|
import org.ktorm.database.Database
|
||||||
import org.ktorm.entity.Entity
|
import org.ktorm.entity.Entity
|
||||||
|
import org.ktorm.entity.sequenceOf
|
||||||
import org.ktorm.schema.Table
|
import org.ktorm.schema.Table
|
||||||
import org.ktorm.schema.varchar
|
import org.ktorm.schema.varchar
|
||||||
|
|
||||||
interface FriendEntity : Entity<FriendEntity> {
|
interface FriendEntity : Entity<FriendEntity> {
|
||||||
val sender: String
|
companion object : Entity.Factory<FriendEntity>()
|
||||||
val receiver: String
|
|
||||||
|
var sender: String
|
||||||
|
var receiver: String
|
||||||
|
|
||||||
|
fun toFriend() =
|
||||||
|
Friend(
|
||||||
|
sender = sender,
|
||||||
|
receiver = receiver,
|
||||||
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
object FriendsEntity : Table<FriendEntity>("friend") {
|
object FriendsEntity : Table<FriendEntity>("friend") {
|
||||||
val sender = varchar("id").primaryKey().bindTo { it.sender }
|
val sender = varchar("sender").primaryKey().bindTo { it.sender }
|
||||||
val receiver = varchar("bet").primaryKey().bindTo { it.receiver }
|
val receiver = varchar("receiver").primaryKey().bindTo { it.receiver }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val Database.friends get() = this.sequenceOf(FriendsEntity)
|
||||||
|
@ -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…
Reference in new issue