/
UserPostgreDAO.scala
144 lines (130 loc) · 3.95 KB
/
UserPostgreDAO.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
package daos
import scala.concurrent.Future
import scala.language.postfixOps
import anorm.SQL
import anorm.SqlParser._
import play.api.Play.current
import play.api.db.DB
import playground.db.sql.SqlParsers._
import playground.models._
import models._
import models.requests._
import models.exceptions._
object UserPostgreDAO extends UserDAO with PostgreDAO {
val simple = id("id") ~
str("first_name") ~
str("last_name") ~
str("email") ~
bool("active") ~
joda.date("creation") map flatten
def create(request: UserCreate, login: String, password: String, salt: String): Future[User] = Future {
DB.withTransaction { implicit c =>
val credentialsId = SQL("""
INSERT INTO T_CREDENTIALS(login, password, salt, creation)
VALUES ({login}, {password}, {salt}, {creation})
""").on(
"login" -> login,
"password" -> password,
"salt" -> salt,
"creation" -> param(request.creation)
).executeInsert().map(Id(_)).get
SQL("""
INSERT INTO T_USER(first_name, last_name, email, creation, credentials_id)
VALUES ({firstName}, {lastName}, {email}, {creation}, {credentialsId})
""").on(
"firstName" -> request.firstName,
"lastName" -> request.lastName,
"email" -> request.email,
"creation" -> param(request.creation),
"credentialsId" -> param(credentialsId)
).executeInsert().map(Id(_)).map(request.withId).get
}
}.transform(identity, {
case x: org.postgresql.util.PSQLException => x.getSQLState match {
case `unique_violation` => AccountAlreadyExistsException(login, x)
case _ => x
}
case x: org.h2.jdbc.JdbcSQLException => x.getErrorCode.toString match {
case `unique_violation` => AccountAlreadyExistsException(login, x)
case _ => x
}
})
def update(user: User, request: UserUpdate): Future[Option[User]] = Future {
DB.withTransaction { implicit c =>
SQL("""
UPDATE T_USER
SET
first_name = {firstName},
last_name = {lastName},
email = {email},
active = {active}
WHERE id = {id}
""").on(
"id" -> param(user.id),
"firstName" -> request.firstName,
"lastName" -> request.lastName,
"email" -> request.email,
"active" -> request.active
).executeUpdate
}
} flatMap { _ =>
byId(user.id)
}
def salt(login: String): Future[Option[String]] = Future {
DB.withTransaction { implicit c =>
SQL("""
SELECT salt
FROM T_CREDENTIALS
WHERE login = {login}
""").on("login" -> login).as(scalar[String].singleOpt)
}
}
def authenticate(login: String, password: String): Future[Option[User]] = Future {
DB.withTransaction { implicit c =>
SQL("""
SELECT
u.*
FROM
T_CREDENTIALS c
INNER JOIN T_USER u ON u.credentials_id = c.id
WHERE
c.login = {login}
AND c.password = {password}
AND u.active
""").on(
"login" -> login,
"password" -> password
).as(simple.singleOpt.map(_.map(User.apply _ tupled)))
}
}
def byLogin(login: String): Future[Option[User]] = Future {
DB.withTransaction { implicit c =>
SQL("""
SELECT
u.*
FROM
T_CREDENTIALS c
INNER JOIN T_USER u ON u.credentials_id = c.id
WHERE c.login = {login}
""").on(
"login" -> login
).as(simple.singleOpt.map(_.map(User.apply _ tupled)))
}
}
def all(): Future[Seq[User]] = Future {
DB.withTransaction { implicit c =>
SQL("SELECT * FROM T_USER ORDER BY creation").as(simple *).map(User.apply _ tupled)
}
}
def byId(id: Id): Future[Option[User]] = Future {
DB.withTransaction { implicit c =>
SQL("""
SELECT *
FROM T_USER
WHERE id = {id}
""").on(
"id" -> param(id)
).as(simple.singleOpt.map(_.map(User.apply _ tupled)))
}
}
}