mirror of
https://github.com/arcan1s/ffxivbis.git
synced 2025-07-15 22:59:58 +00:00
some tests
This commit is contained in:
@ -0,0 +1,36 @@
|
||||
create table players (
|
||||
party_id text not null,
|
||||
player_id bigserial,
|
||||
created bigint not null,
|
||||
nick text not null,
|
||||
job text not null,
|
||||
bis_link text,
|
||||
priority integer not null default 1);
|
||||
create unique index players_nick_job_idx on players(party_id, nick, job);
|
||||
|
||||
create table loot (
|
||||
loot_id bigserial,
|
||||
player_id bigint not null,
|
||||
created bigint not null,
|
||||
piece text not null,
|
||||
is_tome integer not null,
|
||||
job text not null,
|
||||
foreign key (player_id) references players(player_id) on delete cascade);
|
||||
create index loot_owner_idx on loot(player_id);
|
||||
|
||||
create table bis (
|
||||
player_id bigint not null,
|
||||
created bigint not null,
|
||||
piece text not null,
|
||||
is_tome integer not null,
|
||||
job text not null,
|
||||
foreign key (player_id) references players(player_id) on delete cascade);
|
||||
create unique index bis_piece_player_id_idx on bis(player_id, piece);
|
||||
|
||||
create table users (
|
||||
party_id text not null,
|
||||
user_id bigserial,
|
||||
username text not null,
|
||||
password text not null,
|
||||
permission text not null);
|
||||
create unique index users_username_idx on users(party_id, username);
|
@ -1,6 +1,6 @@
|
||||
create table players (
|
||||
party_id text not null,
|
||||
player_id integer primary key,
|
||||
player_id integer primary key autoincrement,
|
||||
created integer not null,
|
||||
nick text not null,
|
||||
job text not null,
|
||||
@ -9,7 +9,7 @@ create table players (
|
||||
create unique index players_nick_job_idx on players(party_id, nick, job);
|
||||
|
||||
create table loot (
|
||||
loot_id integer primary key,
|
||||
loot_id integer primary key autoincrement,
|
||||
player_id integer not null,
|
||||
created integer not null,
|
||||
piece text not null,
|
||||
@ -29,7 +29,7 @@ create unique index bis_piece_player_id_idx on bis(player_id, piece);
|
||||
|
||||
create table users (
|
||||
party_id text not null,
|
||||
user_id integer primary key,
|
||||
user_id integer primary key autoincrement,
|
||||
username text not null,
|
||||
password text not null,
|
||||
permission text not null);
|
5
src/main/resources/logback.xml
Normal file
5
src/main/resources/logback.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<configuration>
|
||||
|
||||
<logger name="slick.jdbc.JdbcBackend.statement" level="DEBUG" />
|
||||
|
||||
</configuration>
|
@ -22,6 +22,16 @@ me.arcanis.ffxivbis {
|
||||
}
|
||||
numThreads = 10
|
||||
}
|
||||
|
||||
postgresql {
|
||||
profile = "slick.jdbc.PostgresProfile$"
|
||||
db {
|
||||
url = "jdbc:postgresql://localhost/ffxivbis"
|
||||
user = "user"
|
||||
password = "password"
|
||||
}
|
||||
numThreads = 10
|
||||
}
|
||||
}
|
||||
|
||||
settings {
|
||||
|
@ -20,5 +20,5 @@ class AriyalaHelper(ariyala: ActorRef) {
|
||||
|
||||
def downloadBiS(link: String, job: Job.Job)
|
||||
(implicit executionContext: ExecutionContext, timeout: Timeout): Future[BiS] =
|
||||
(ariyala ? Ariyala.GetBiS(link, job)).mapTo[Seq[Piece]].map(BiS(_))
|
||||
(ariyala ? Ariyala.GetBiS(link, job)).mapTo[BiS]
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ class PlayerHelper(storage: ActorRef, ariyala: ActorRef) extends AriyalaHelper(a
|
||||
(implicit executionContext: ExecutionContext, timeout: Timeout): Future[Seq[Player]] =
|
||||
maybePlayerId match {
|
||||
case Some(playerId) =>
|
||||
(storage ? DatabasePartyHandler.GetPlayer(playerId)).mapTo[Player].map(Seq(_))
|
||||
(storage ? DatabasePartyHandler.GetPlayer(playerId)).mapTo[Option[Player]].map(_.toSeq)
|
||||
case None =>
|
||||
(storage ? DatabasePartyHandler.GetParty(partyId)).mapTo[Party].map(_.players.values.toSeq)
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ class UserHelper(storage: ActorRef) {
|
||||
|
||||
def addUser(user: User, isHashedPassword: Boolean)
|
||||
(implicit executionContext: ExecutionContext, timeout: Timeout): Future[Int] =
|
||||
(storage ? DatabaseUserHandler.InsertUser(user, isHashedPassword)).mapTo[Int]
|
||||
(storage ? DatabaseUserHandler.AddUser(user, isHashedPassword)).mapTo[Int]
|
||||
|
||||
def user(partyId: String, username: String)
|
||||
(implicit executionContext: ExecutionContext, timeout: Timeout): Future[Option[User]] =
|
||||
|
@ -22,4 +22,5 @@ case class User(partyId: String,
|
||||
def hash: String = BCrypt.hashpw(password, BCrypt.gensalt)
|
||||
def verify(plain: String): Boolean = BCrypt.checkpw(plain, password)
|
||||
def verityScope(scope: Permission.Value): Boolean = permission >= scope
|
||||
def withHashedPassword: User = copy(password = hash)
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ import akka.stream.ActorMaterializer
|
||||
import akka.stream.scaladsl.{Keep, Sink}
|
||||
import akka.util.ByteString
|
||||
import com.typesafe.scalalogging.StrictLogging
|
||||
import me.arcanis.ffxivbis.models.{Job, Piece}
|
||||
import me.arcanis.ffxivbis.models.{BiS, Job, Piece}
|
||||
import spray.json._
|
||||
|
||||
import scala.concurrent.{ExecutionContext, Future}
|
||||
@ -39,7 +39,7 @@ class Ariyala extends Actor with StrictLogging {
|
||||
override def receive: Receive = {
|
||||
case GetBiS(link, job) =>
|
||||
val client = sender()
|
||||
get(link, job).pipeTo(client)
|
||||
get(link, job).map(BiS(_)).pipeTo(client)
|
||||
}
|
||||
|
||||
private def get(link: String, job: Job.Job): Future[Seq[Piece]] = {
|
||||
|
@ -19,6 +19,11 @@ trait Database extends Actor with StrictLogging {
|
||||
implicit def executionContext: ExecutionContext
|
||||
def profile: DatabaseProfile
|
||||
|
||||
override def postStop(): Unit = {
|
||||
profile.db.close()
|
||||
super.postStop()
|
||||
}
|
||||
|
||||
def filterParty(party: Party, maybePlayerId: Option[PlayerId]): Seq[Player] =
|
||||
(party, maybePlayerId) match {
|
||||
case (_, Some(playerId)) => party.player(playerId).map(Seq(_)).getOrElse(Seq.empty)
|
||||
|
@ -12,6 +12,8 @@ import akka.pattern.pipe
|
||||
import me.arcanis.ffxivbis.models.{BiS, Player, PlayerId}
|
||||
import me.arcanis.ffxivbis.service.Database
|
||||
|
||||
import scala.concurrent.Future
|
||||
|
||||
trait DatabasePartyHandler { this: Database =>
|
||||
import DatabasePartyHandler._
|
||||
|
||||
@ -26,11 +28,16 @@ trait DatabasePartyHandler { this: Database =>
|
||||
|
||||
case GetPlayer(playerId) =>
|
||||
val client = sender()
|
||||
val player = for {
|
||||
bis <- profile.getPiecesBiS(playerId)
|
||||
loot <- profile.getPieces(playerId)
|
||||
} yield Player(playerId.partyId, playerId.job, playerId.nick,
|
||||
BiS(bis.map(_.piece)), loot.map(_.piece))
|
||||
val player = profile.getPlayerFull(playerId).flatMap { maybePlayerData =>
|
||||
Future.traverse(maybePlayerData.toSeq) { playerData =>
|
||||
for {
|
||||
bis <- profile.getPiecesBiS(playerId)
|
||||
loot <- profile.getPieces(playerId)
|
||||
} yield Player(playerId.partyId, playerId.job, playerId.nick,
|
||||
BiS(bis.map(_.piece)), loot.map(_.piece),
|
||||
playerData.link, playerData.priority)
|
||||
}
|
||||
}.map(_.headOption)
|
||||
player.pipeTo(client)
|
||||
|
||||
case RemovePlayer(playerId) =>
|
||||
|
@ -16,6 +16,11 @@ trait DatabaseUserHandler { this: Database =>
|
||||
import DatabaseUserHandler._
|
||||
|
||||
def userHandler: Receive = {
|
||||
case AddUser(user, isHashedPassword) =>
|
||||
val client = sender()
|
||||
val toInsert = if (isHashedPassword) user else user.withHashedPassword
|
||||
profile.insertUser(toInsert).pipeTo(client)
|
||||
|
||||
case DeleteUser(partyId, username) =>
|
||||
val client = sender()
|
||||
profile.deleteUser(partyId, username).pipeTo(client)
|
||||
@ -27,17 +32,12 @@ trait DatabaseUserHandler { this: Database =>
|
||||
case GetUsers(partyId) =>
|
||||
val client = sender()
|
||||
profile.getUsers(partyId).pipeTo(client)
|
||||
|
||||
case InsertUser(user, isHashedPassword) =>
|
||||
val client = sender()
|
||||
val toInsert = if (isHashedPassword) user else user.copy(password = user.hash)
|
||||
profile.insertUser(toInsert).pipeTo(client)
|
||||
}
|
||||
}
|
||||
|
||||
object DatabaseUserHandler {
|
||||
case class AddUser(user: User, isHashedPassword: Boolean)
|
||||
case class DeleteUser(partyId: String, username: String)
|
||||
case class GetUser(partyId: String, username: String)
|
||||
case class GetUsers(partyId: String)
|
||||
case class InsertUser(user: User, isHashedPassword: Boolean)
|
||||
}
|
||||
|
@ -44,7 +44,10 @@ trait LootProfile { this: DatabaseProfile =>
|
||||
}
|
||||
|
||||
def deletePieceById(piece: Piece)(playerId: Long): Future[Int] =
|
||||
db.run(pieceLoot(LootRep.fromPiece(playerId, piece)).take(1).delete)
|
||||
db.run(pieceLoot(LootRep.fromPiece(playerId, piece)).map(_.lootId).max.result).flatMap {
|
||||
case Some(id) => db.run(lootTable.filter(_.lootId === id).delete)
|
||||
case _ => throw new IllegalArgumentException(s"Could not find piece $piece belong to $playerId")
|
||||
}
|
||||
def getPiecesById(playerId: Long): Future[Seq[Loot]] = getPiecesById(Seq(playerId))
|
||||
def getPiecesById(playerIds: Seq[Long]): Future[Seq[Loot]] =
|
||||
db.run(piecesLoot(playerIds).result).map(_.map(_.toLoot))
|
||||
|
@ -10,6 +10,7 @@ package me.arcanis.ffxivbis.storage
|
||||
|
||||
import com.typesafe.config.Config
|
||||
import org.flywaydb.core.Flyway
|
||||
import org.flywaydb.core.api.configuration.ClassicConfiguration
|
||||
|
||||
import scala.concurrent.Future
|
||||
|
||||
@ -21,7 +22,16 @@ class Migration(config: Config) {
|
||||
val username = section.getString("db.user")
|
||||
val password = section.getString("db.password")
|
||||
|
||||
val flyway = Flyway.configure().dataSource(url, username, password).load()
|
||||
val provider = url match {
|
||||
case s"jdbc:$p:$_" => p
|
||||
case other => throw new NotImplementedError(s"unknown could not parse jdbc url from $other")
|
||||
}
|
||||
|
||||
val flywayConfiguration = new ClassicConfiguration
|
||||
flywayConfiguration.setLocationsAsStrings(s"db/migration/$provider")
|
||||
flywayConfiguration.setDataSource(url, username, password)
|
||||
val flyway = new Flyway(flywayConfiguration)
|
||||
|
||||
Future.successful(flyway.migrate())
|
||||
}
|
||||
}
|
||||
|
@ -49,6 +49,8 @@ trait PlayersProfile { this: DatabaseProfile =>
|
||||
})
|
||||
def getPlayer(playerId: PlayerId): Future[Option[Long]] =
|
||||
db.run(player(playerId).map(_.playerId).result.headOption)
|
||||
def getPlayerFull(playerId: PlayerId): Future[Option[Player]] =
|
||||
db.run(player(playerId).result.headOption.map(_.map(_.toPlayer)))
|
||||
def getPlayers(partyId: String): Future[Seq[Long]] =
|
||||
db.run(players(partyId).map(_.playerId).result)
|
||||
def insertPlayer(playerObj: Player): Future[Int] =
|
||||
|
@ -22,7 +22,7 @@ trait UsersProfile { this: DatabaseProfile =>
|
||||
}
|
||||
object UserRep {
|
||||
def fromUser(user: User, id: Option[Long]): UserRep =
|
||||
UserRep(user.partyId, None, user.username, user.password, user.permission.toString)
|
||||
UserRep(user.partyId, id, user.username, user.password, user.permission.toString)
|
||||
}
|
||||
|
||||
class Users(tag: Tag) extends Table[UserRep](tag, "users") {
|
||||
@ -47,8 +47,8 @@ trait UsersProfile { this: DatabaseProfile =>
|
||||
def getUsers(partyId: String): Future[Seq[User]] =
|
||||
db.run(user(partyId, None).result).map(_.map(_.toUser))
|
||||
def insertUser(userObj: User): Future[Int] =
|
||||
db.run(user(userObj.partyId, Some(userObj.username)).result.headOption).map {
|
||||
case Some(user) => db.run(usersTable.update(UserRep.fromUser(userObj, user.userId)))
|
||||
db.run(user(userObj.partyId, Some(userObj.username)).map(_.userId).result.headOption).map {
|
||||
case Some(id) => db.run(usersTable.insertOrUpdate(UserRep.fromUser(userObj, Some(id))))
|
||||
case _ => db.run(usersTable.insertOrUpdate(UserRep.fromUser(userObj, None)))
|
||||
}.flatten
|
||||
|
||||
|
Reference in New Issue
Block a user