SimpleUserRepository.scala 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. /*
  2. * Copyright (C) 2020 Prasoon Joshi
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation, either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  16. */
  17. package repository
  18. import repository.NiosxGraph._
  19. import models.{
  20. NiosxUser, AuthPayload
  21. }
  22. import utils.{FileUtils, SecurityUtils}
  23. import graphql.SchemaInputObjects.UserInput
  24. import play.api.libs.ws.WSClient
  25. import play.api.Configuration
  26. import scala.util.Try
  27. import scala.collection.mutable
  28. sealed trait UserRole
  29. object UserRole {
  30. val PartnerPermissions =
  31. "VIEW_USER" :: "EDIT_ENTITY" :: "VIEW_ENTITY" :: "EDIT_ANNO" :: "VIEW_ANNO" :: Nil
  32. val PatronPermissions =
  33. "VIEW_USER" :: "EDIT_ANNO" :: "VIEW_ANNO" :: Nil
  34. val AdminPermissions = PartnerPermissions ++ PatronPermissions ++
  35. ("EDIT_USER" :: "VIEW_USER" :: "SUPER_USER" :: Nil)
  36. def getUserPermissions(r: String): List[String] = getRole(r) match {
  37. case NiosxAdminRole => AdminPermissions
  38. case NiosxPartnerRole => PartnerPermissions
  39. case NiosxPatronRole => PatronPermissions
  40. }
  41. def getRole(r: String): UserRole = r match {
  42. case "admin" => NiosxAdminRole
  43. case "partner" => NiosxPartnerRole
  44. case "patron" => NiosxPatronRole
  45. }
  46. def roleToString(r: UserRole): String = r match {
  47. case NiosxAdminRole => "admin"
  48. case NiosxPartnerRole => "partner"
  49. case NiosxPatronRole => "patron"
  50. }
  51. }
  52. case object NiosxAdminRole extends UserRole
  53. case object NiosxPartnerRole extends UserRole
  54. case object NiosxPatronRole extends UserRole
  55. class SimpleUserRepository(ws: WSClient,
  56. gs: GremlinServer,
  57. conf: Configuration) extends UserRepository {
  58. //TODO: This needs a better approach to be able to support large
  59. //number of concurrent users.
  60. var UserTokenMap: mutable.Map[String, String] = mutable.Map()
  61. //TODO: Handle bulk upload better!
  62. val BULK_UPLOAD_USER: NiosxUser =
  63. new NiosxUser(graphId = "NA",
  64. username = "bulk_upload_user",
  65. passHash = SecurityUtils.hashPass(
  66. conf.get[String]("default.bulk.upload.key")),
  67. permissions = List("BULK_UPLOAD"),
  68. role = NiosxAdminRole)
  69. /**
  70. * A note on "super_duper_user":
  71. * In a "perfect" world, recommendation engines should be illegal.
  72. * People using the platform should be able to recommend stuff to
  73. * other people, the platform's task is to create these human connections
  74. * possible, not to create a trap!
  75. * A people graph is a powerful tool. It can be used effectively to
  76. * supress human connections or to mitigate falsehoods from spreading.
  77. * The design of the platform decides how people interact. The
  78. * "super_duper_user" is a step towards building a people graph which
  79. * enables people driven information sharing. Penalty for bad behaviour
  80. * would cascade down to all people/actors added to the system by the bad actor
  81. * and include the actor that introduced this bad actor into the system.
  82. */
  83. val SuperDuperUser: String = "superduperuser"
  84. //TODO: Move this to some initialize component/block.
  85. val suDuUsPass = conf.get[String]("default.admin.password")
  86. println(suDuUsPass)
  87. val suDuUser: Option[NiosxUser] =
  88. gs
  89. .Save[NiosxUser]
  90. .save(
  91. NiosxUser(graphId = SuperDuperUser,
  92. username = SuperDuperUser,
  93. passHash = SecurityUtils.hashPass(suDuUsPass),
  94. role = NiosxAdminRole,
  95. permissions = UserRole.getUserPermissions("admin")),
  96. edge = Darkness) match {
  97. case f: gs.SaveFailure => None
  98. case s: gs.SaveSuccess => gs.VertToCC[NiosxUser].convert(s.v)
  99. }
  100. def addUser(u: UserInput): String = {
  101. val user: NiosxUser = NiosxUser(
  102. graphId = FileUtils.getNewGraphId,
  103. username = u.username,
  104. passHash = SecurityUtils.hashPass(u.password),
  105. role = UserRole.getRole(u.role),
  106. permissions = UserRole.getUserPermissions(u.role))
  107. gs
  108. .findUserByUsername(u.username)
  109. .fold(
  110. gs
  111. .Save[NiosxUser]
  112. .save(user, Darkness) match {//Some(SuperDuperUser))
  113. case f: gs.SaveFailure => "Could not create user"
  114. case s: gs.SaveSuccess => s"User ${u.username} created."
  115. })(_ => s"User ${u.username} already exists!")
  116. }
  117. def editUser(u: UserInput): Option[NiosxUser] = ???
  118. // val user: NiosxUser = NiosxUser(
  119. // gremlinServer.Save[NiosxUser].save(user, None)
  120. /*
  121. * Gives back a token wrapped inside an `AuthPayload`
  122. * that identifies a user session.
  123. *
  124. */
  125. def authenticate(username: String,
  126. password: String): Option[AuthPayload] = {
  127. val user: Option[NiosxUser] = username match {
  128. case "bulk_upload_user" => Some(BULK_UPLOAD_USER)
  129. case _ => gs.findUserByUsername(username)
  130. }
  131. user.flatMap({ u: NiosxUser =>
  132. SecurityUtils.checkPass(password, u.passHash) match {
  133. case false => None
  134. case true => {
  135. val token: String = SecurityUtils.genUserToken
  136. UserTokenMap += (token -> u.username)
  137. //println("Token saved in map: " + token + ":" + UserTokenMap.get(token))
  138. Some(AuthPayload(token, u))
  139. }
  140. }
  141. })
  142. }
  143. //TODO: Redundant. Remove.
  144. def findUserByUsername(username: String): Option[NiosxUser] =
  145. gs.findUserByUsername(username)
  146. /**
  147. * Gives a user object with permissions.
  148. */
  149. def authorise(token: String): Option[NiosxUser] = {
  150. val user: Option[String] = UserTokenMap.get(token)
  151. user match {
  152. case Some("bulk_upload_user") => Some(BULK_UPLOAD_USER)
  153. case Some(u) => gs.findUserByUsername(u)
  154. case None => None
  155. }
  156. }
  157. }