scala-news-reader
rss/atom news reader in scala
git clone https://9o.is/git/scala-news-reader.git
User.scala
(8477B)
1 package com.joereader
2 package model
3
4 import org.bson.types._
5
6 import net.liftweb._
7 import util._
8 import common._
9 import http.{ StringField => _, BooleanField => _, _ }
10
11 import net.liftweb.record._
12 import net.liftweb.record.field._
13 import net.liftweb.mongodb.record._
14 import net.liftweb.mongodb.record.field._
15 import net.liftmodules.mongoauth._
16 import net.liftmodules.mongoauth.model._
17
18 import com.joereader._
19 import com.joereader.model.field._
20 import config._
21 import lib.rss._
22
23 class User private () extends ProtoAuthUser[User] with ObjectIdPk[User] {
24 def meta = User
25
26 def userIdAsString: String = id.toString()
27
28 object name extends StringField(this, 64)
29
30 def firstName = name.get.split(" ").headOption getOrElse ""
31
32 object about extends TextareaField(this, 500)
33
34 object img extends StringField(this, 50)
35
36 object bgImg extends StringField(this, 50)
37
38 object otherVid extends MongoListField[User, String](this) with MongoListFieldExtra[User, String]
39
40 object blogs extends ObjectIdRefListField(this, Blog) with ObjectIdRefListFieldExtra[User, Blog]
41
42 def isWriter: Boolean = !blogs.get.isEmpty
43
44 /* List of blog writer users this user follows. */
45 object following extends BlogWriterUserListField(this)
46
47 /*
48 * Follow this user to view his shared articles
49 * (only if this user is a writer)
50 */
51 object followers extends ObjectIdRefListField(this, User) with ObjectIdRefListFieldExtra[User, User]
52
53 object saved extends ArticleListField(this)
54
55 object shared extends ArticleSharedListField(this, this)
56 }
57
58 object User extends User with ProtoAuthUserMeta[User] with Loggable {
59
60 import mongodb.BsonDSL._
61
62 override def collectionName = "user.users"
63
64 ensureIndex(email.name -> 1, unique = true)
65 ensureIndex(username.name -> 1, unique = true)
66 ensureIndex(name.name -> 1, unique = false)
67
68 def defaultId = new ObjectId("0" * 24)
69
70 def findByEmail(in: String): Box[User] = find(email.name, in)
71
72 def findByName(in: String): Box[User] = find(name.name, in)
73
74 def findByUsername(in: String): Box[User] =
75 find(username.name, in.toLowerCase)
76
77 def findByStringId(id: String): Box[User] =
78 if (ObjectId.isValid(id) && id != "0" * 24)
79 find(new ObjectId(id))
80 else
81 Empty
82
83 override def onLogIn: List[User => Unit] =
84 List(user => User.loginCredentials.remove())
85
86 override def onLogOut: List[Box[User] => Unit] = List(
87 x => logger.debug("User.onLogOut called."),
88 boxedUser => boxedUser.foreach {
89 u =>
90 ExtSession.deleteExtCookie()
91 })
92
93 /*
94 * MongoAuth vars
95 */
96 private lazy val siteName = MongoAuth.siteName.vend
97 private lazy val sysUsername = MongoAuth.systemUsername.vend
98 private lazy val indexUrl = MongoAuth.indexUrl.vend
99 private lazy val registerUrl = MongoAuth.registerUrl.vend
100 private lazy val loginTokenAfterUrl = MongoAuth.loginTokenAfterUrl.vend
101
102 /*
103 * LoginToken
104 */
105 override def handleLoginToken(): Box[LiftResponse] = {
106 val resp = S.param("token").flatMap(LoginToken.findByStringId) match {
107 case Full(at) if at.expires.isExpired => {
108 at.delete_!
109 RedirectWithState(indexUrl, RedirectState(() => {
110 S.error("Login token has expired")
111 }))
112 }
113 case Full(at) => find(at.userId.is).map(user => {
114 if (user.validate.length == 0) {
115 user.verified(true).save
116 logUserIn(user)
117 //at.delete_! (token is deleted at Password Reset)
118 RedirectResponse(loginTokenAfterUrl)
119 } else {
120 at.delete_!
121 regUser(user)
122 RedirectWithState(registerUrl, RedirectState(() => {
123 S.notice("Please complete the registration form")
124 }))
125 }
126 }).openOr(RedirectWithState(indexUrl, RedirectState(() => {
127 S.error("User not found")
128 })))
129 case _ => RedirectWithState(indexUrl, RedirectState(() => {
130 S.warning("Login token not provided")
131 }))
132 }
133
134 Full(resp)
135 }
136
137 // send an email to the user with a link for logging in
138 def sendLoginToken(user: User) {
139 import net.liftweb.util.Mailer._
140
141 val token = LoginToken.createForUserId(user.id.get)
142
143 val msgTxt =
144 """
145 |Someone requested a link to change your password on the %s website.
146 |
147 |If you did not request this, you can safely ignore it. It will expire 48 hours from the time this message was sent.
148 |
149 |Follow the link below or copy and paste it into your internet browser.
150 |
151 |%s
152 |
153 |Yours truly,
154 |%s
155 """.format(siteName, token.url, sysUsername).stripMargin
156
157 sendMail(
158 From(MongoAuth.systemFancyEmail),
159 Subject("%s Password Help".format(siteName)),
160 To(user.fancyEmail),
161 PlainMailBodyType(msgTxt))
162 }
163
164 def handleInviteToken(): Box[LiftResponse] = {
165 var resp: LiftResponse = DoRedirectResponse("/")
166
167 S.param("token").flatMap(InviteToken.findByStringId) match {
168 case Full(at) if at.expires.isExpired =>
169 at.delete_!
170 resp = RedirectWithState(indexUrl, RedirectState(() => {
171 S.error("Invite token has expired.")
172 }))
173
174 case Full(at) =>
175
176 // Find user if he is registered already else create user
177 val userBoxed = findByEmail(at.email.is)
178 val user: User = userBoxed openOr {
179 createRecord.
180 email(at.email.get).
181 name(at.name.get).
182 password(StringHelpers.randomString(20), true).
183 username(StringHelpers.randomString(15))
184 }
185
186 Blog.findByStringId(at.blogId.get.toString).map {
187 blog =>
188 val blogWriter =
189 BlogWriter.createRecord.user(user.id.get).name(at.name.get)
190
191 blog.writers.addSafely(blogWriter).save
192 user.blogs.add(blog).verified(true).save
193
194 if (userBoxed.isDefined)
195 resp = RedirectWithState(Site.categoriesLoc.calcHref(blog),
196 RedirectState(() => {
197 S.notice("Congratulations! You are verified with " +
198 blog.name.get + "!")
199 }))
200 else
201 resp = RedirectWithState(Site.signUp3.url,
202 RedirectState(() => {
203 snippet.BlogIdVar(at.blogId.get.toString)
204 snippet.VerifiedVar(true)
205 S.notice("Congratulations! You are verified with " +
206 blog.name.get + "!")
207 }))
208 }
209
210 // Remove token
211 at.delete_!
212
213 // Log user in
214 if (isLoggedIn) logUserOut()
215 logUserIn(user, isAuthed = true)
216
217 case _ =>
218 resp = RedirectWithState(indexUrl, RedirectState(() => {
219 S.warning("Invite token is missing.")
220 }))
221 }
222
223 Full(resp)
224 }
225
226 def sendInviteToken(name: String, email: String, user: User, blog: Blog) {
227 import net.liftweb.util.Mailer._
228
229 val token = InviteToken.create(email, name, blog.id.is)
230 val msgTxt =
231 """
232 |Hi %s,
233 |
234 |%s has invited you to Read Means to become a member of your
235 |current blog, %s.
236 |
237 |Click below to join:
238 |%s
239 |
240 |Yours truly,
241 |%s
242 """.
243 format(name, user.name.get, blog.name.get, token.url,
244 MongoAuth.systemUsername.vend).stripMargin
245
246 sendMail(
247 From(MongoAuth.systemFancyEmail),
248 Subject("%s invites you to %s".
249 format(user.name.get, MongoAuth.siteName.vend)),
250 To(email),
251 PlainMailBodyType(msgTxt))
252 }
253
254 // used during login process (holds email address)
255 object loginCredentials extends SessionVar[String]("")
256
257 object regUser
258 extends SessionVar[User](createRecord.email(loginCredentials.is))
259
260 }
261
262 object SystemUser {
263 private val username = "julio"
264 private val email = "j.cabrra@gmail.com"
265
266 lazy val user: User = User.find("username", username) openOr {
267 User.createRecord
268 .name("Julio")
269 .username(username)
270 .email(email)
271 .verified(true)
272 .password("deanjoe321", isPlain = true)
273 .save
274 }
275 }
276
277 object TestUser {
278 private val username = "testuser"
279 private val email = "test@example.com"
280
281 lazy val user: User = User.find("username", username) openOr {
282 User.createRecord
283 .name("Test Man")
284 .username(username)
285 .email(email)
286 .verified(true)
287 .password("test1234", isPlain = true)
288 .save
289 }
290
291 def isLoggedIn = User.currentUser.
292 exists(_.username.get == TestUser.user.username.get)
293 }