From c5318cb8d8fc28278851804502f653a3e8cf16e8 Mon Sep 17 00:00:00 2001 From: TAKESHI SHIMADA <> Date: Wed, 17 Jul 2019 20:54:38 +0900 Subject: [PATCH] Support social authentication (#230) --- .../cactacea/addons/oauth/OAuthFilter.scala | 2 +- .../repositories/AccountsRepository.scala | 34 +-- .../repositories/DevicesRepository.scala | 14 +- .../core/infrastructure/dao/AccountsDAO.scala | 13 + .../dao/AuthenticationsDAO.scala | 2 +- .../validators/AuthenticationsValidator.scala | 33 +++ .../backend/core/util/configs/Config.scala | 42 +++- .../core/util/configs/OAuth1Config.scala | 10 + .../core/util/configs/OAuth2Config.scala | 10 + .../repositories/AccountsRepositorySpec.scala | 32 +-- .../repositories/DevicesRepositorySpec.scala | 1 - .../core/helpers/RepositorySpec.scala | 22 +- .../cactacea/core/helpers/ServiceSpec.scala | 3 +- .../github/cactacea/backend/APIServer.scala | 4 +- .../cactacea/backend/APIServerSpec.scala | 6 +- .../providers/oauth2/FacebookProvider.scala | 18 +- .../providers/oauth2/GoogleProvider.scala | 9 +- .../controllers/AccountsController.scala | 2 +- .../controllers/BlocksController.scala | 3 +- .../controllers/CommentLikesController.scala | 3 +- .../controllers/CommentsController.scala | 3 +- .../controllers/FeedLikesController.scala | 3 +- .../backend/controllers/FeedsController.scala | 3 +- .../controllers/FollowsController.scala | 3 +- .../FriendRequestsController.scala | 3 +- .../controllers/FriendsController.scala | 2 +- .../controllers/GroupsController.scala | 3 +- .../controllers/InvitationsController.scala | 3 +- .../controllers/MediumsController.scala | 3 +- .../controllers/MessagesController.scala | 3 +- .../backend/controllers/MutesController.scala | 3 +- .../controllers/NotificationsController.scala | 3 +- .../controllers/SessionController.scala | 5 +- .../controllers/SessionsController.scala | 5 +- .../controllers/SettingsController.scala | 3 +- .../session/PutSessionAccountName.scala | 2 +- .../requests/session/PutSessionPassword.scala | 2 +- .../models/requests/sessions/PostSignUp.scala | 2 +- .../utils/auth/CactaceaAPIKeyValidator.scala | 20 -- .../utils/auth/CactaceaAuthModule.scala | 116 --------- .../utils/auth/CactaceaIdentityService.scala | 17 -- .../{auth => context}/CactaceaContext.scala | 2 +- .../utils/filters/CactaceaAPIKeyFilter.scala | 16 +- .../CactaceaAuthenticationFilter.scala | 7 +- .../utils/filters/CactaceaLocaleFilter.scala | 2 +- .../User.scala} | 10 +- .../utils/modules/AuthenticationModule.scala | 235 ++++++++++++++++++ .../utils/repositories/OAuth2Repository.scala | 42 ++++ .../PasswordsRepository.scala} | 10 +- .../AuthenticationsService.scala} | 36 +-- .../SocialAuthenticationsService.scala | 53 ++++ .../backend/utils/services/UserService.scala | 19 ++ .../CactaceaValidations.scala | 2 +- .../cactacea/backend/CactaceaServerSpec.scala | 6 +- 54 files changed, 606 insertions(+), 304 deletions(-) create mode 100644 core/src/main/scala/io/github/cactacea/backend/core/infrastructure/validators/AuthenticationsValidator.scala create mode 100644 core/src/main/scala/io/github/cactacea/backend/core/util/configs/OAuth1Config.scala create mode 100644 core/src/main/scala/io/github/cactacea/backend/core/util/configs/OAuth2Config.scala delete mode 100644 server/src/main/scala/io/github/cactacea/backend/utils/auth/CactaceaAPIKeyValidator.scala delete mode 100644 server/src/main/scala/io/github/cactacea/backend/utils/auth/CactaceaAuthModule.scala delete mode 100644 server/src/main/scala/io/github/cactacea/backend/utils/auth/CactaceaIdentityService.scala rename server/src/main/scala/io/github/cactacea/backend/utils/{auth => context}/CactaceaContext.scala (97%) rename server/src/main/scala/io/github/cactacea/backend/utils/{auth/CactaceaAccount.scala => models/User.scala} (50%) create mode 100644 server/src/main/scala/io/github/cactacea/backend/utils/modules/AuthenticationModule.scala create mode 100644 server/src/main/scala/io/github/cactacea/backend/utils/repositories/OAuth2Repository.scala rename server/src/main/scala/io/github/cactacea/backend/utils/{auth/CactaceaAuthenticationsRepository.scala => repositories/PasswordsRepository.scala} (83%) rename server/src/main/scala/io/github/cactacea/backend/utils/{auth/SessionsService.scala => services/AuthenticationsService.scala} (68%) create mode 100644 server/src/main/scala/io/github/cactacea/backend/utils/services/SocialAuthenticationsService.scala create mode 100644 server/src/main/scala/io/github/cactacea/backend/utils/services/UserService.scala rename server/src/main/scala/io/github/cactacea/backend/utils/{validaters => validators}/CactaceaValidations.scala (96%) diff --git a/addons/oauth/src/main/scala/io/github/cactacea/addons/oauth/OAuthFilter.scala b/addons/oauth/src/main/scala/io/github/cactacea/addons/oauth/OAuthFilter.scala index 87a30d4e..3d02cb5f 100644 --- a/addons/oauth/src/main/scala/io/github/cactacea/addons/oauth/OAuthFilter.scala +++ b/addons/oauth/src/main/scala/io/github/cactacea/addons/oauth/OAuthFilter.scala @@ -7,7 +7,7 @@ import com.twitter.finagle.{OAuth2, Service, SimpleFilter} import com.twitter.inject.Logging import com.twitter.util.Future import io.github.cactacea.backend.core.domain.repositories.AccountsRepository -import io.github.cactacea.backend.utils.auth.CactaceaContext +import io.github.cactacea.backend.utils.context.CactaceaContext @Singleton class OAuthFilter @Inject()( diff --git a/core/src/main/scala/io/github/cactacea/backend/core/domain/repositories/AccountsRepository.scala b/core/src/main/scala/io/github/cactacea/backend/core/domain/repositories/AccountsRepository.scala index a63e34fa..d2ff0f6a 100644 --- a/core/src/main/scala/io/github/cactacea/backend/core/domain/repositories/AccountsRepository.scala +++ b/core/src/main/scala/io/github/cactacea/backend/core/domain/repositories/AccountsRepository.scala @@ -2,9 +2,9 @@ package io.github.cactacea.backend.core.domain.repositories import com.google.inject.{Inject, Singleton} import com.twitter.util.Future -import io.github.cactacea.backend.core.domain.enums.{AccountStatusType, DeviceType} +import io.github.cactacea.backend.core.domain.enums.AccountStatusType import io.github.cactacea.backend.core.domain.models.{Account, AccountStatus} -import io.github.cactacea.backend.core.infrastructure.dao.{AccountsDAO, DevicesDAO, PushNotificationSettingsDAO} +import io.github.cactacea.backend.core.infrastructure.dao.{AccountsDAO, AuthenticationsDAO, DevicesDAO, PushNotificationSettingsDAO} import io.github.cactacea.backend.core.infrastructure.identifiers.{AccountId, MediumId, SessionId} import io.github.cactacea.backend.core.infrastructure.models.Accounts import io.github.cactacea.backend.core.infrastructure.validators.{AccountsValidator, MediumsValidator} @@ -15,21 +15,30 @@ import io.github.cactacea.backend.core.util.responses.CactaceaErrors._ class AccountsRepository @Inject()( accountsValidator: AccountsValidator, mediumsValidator: MediumsValidator, + authenticationsDAO: AuthenticationsDAO, accountsDAO: AccountsDAO, devicesDAO: DevicesDAO, notificationSettingsDAO: PushNotificationSettingsDAO ) { - def create(accountName: String, - udid: String, - deviceType: DeviceType, - userAgent: Option[String]): Future[Account] = { + def save(providerId: String, providerKey: String, accountName: String, displayName: Option[String]): Future[Account] = { + authenticationsDAO.find(providerId, providerKey).map(_.flatMap(_.accountId)).flatMap(_ match { + case Some(id) => + accountsValidator.find(id.toSessionId) + case None => + for { + i <- accountsDAO.create(accountName, displayName.getOrElse(accountName)) + _ <- notificationSettingsDAO.create(i.toSessionId) + a <- accountsValidator.find(i.toSessionId) + } yield (a) + }) + } + def create(accountName: String): Future[Account] = { for { _ <- accountsValidator.notExist(accountName) i <- accountsDAO.create(accountName) - _ <- devicesDAO.create(udid, deviceType, userAgent, i.toSessionId) _ <- notificationSettingsDAO.create(i.toSessionId) a <- accountsValidator.find(i.toSessionId) } yield (a) @@ -42,13 +51,6 @@ class AccountsRepository @Inject()( } yield (()) } - def find(accountName: String, udid: String, deviceType: DeviceType, userAgent: Option[String]): Future[Account] = { - for { - a <- accountsValidator.find(accountName) - _ <- devicesDAO.create(udid, deviceType, userAgent, a.id.toSessionId) - } yield (a) - } - def find(sessionId: SessionId): Future[Account] = { accountsValidator.find(sessionId) } @@ -143,5 +145,9 @@ class AccountsRepository @Inject()( }) } + def link(providerId: String, providerKey: String, accountId: AccountId): Future[Unit] = { + authenticationsDAO.link(providerId, providerKey, accountId) + } + } diff --git a/core/src/main/scala/io/github/cactacea/backend/core/domain/repositories/DevicesRepository.scala b/core/src/main/scala/io/github/cactacea/backend/core/domain/repositories/DevicesRepository.scala index 002e72b2..9e33e9e6 100644 --- a/core/src/main/scala/io/github/cactacea/backend/core/domain/repositories/DevicesRepository.scala +++ b/core/src/main/scala/io/github/cactacea/backend/core/domain/repositories/DevicesRepository.scala @@ -2,15 +2,25 @@ package io.github.cactacea.backend.core.domain.repositories import com.google.inject.{Inject, Singleton} import com.twitter.util.Future -import io.github.cactacea.backend.core.domain.enums.ActiveStatusType +import io.github.cactacea.backend.core.domain.enums.{ActiveStatusType, DeviceType} import io.github.cactacea.backend.core.infrastructure.dao.DevicesDAO -import io.github.cactacea.backend.core.infrastructure.identifiers.SessionId +import io.github.cactacea.backend.core.infrastructure.identifiers.{AccountId, SessionId} +import io.github.cactacea.backend.core.infrastructure.validators.AuthenticationsValidator @Singleton class DevicesRepository @Inject()( + authenticationsValidator: AuthenticationsValidator, devicesDAO: DevicesDAO ) { + def save(providerId: String, providerKey: String, udid: String, deviceType: DeviceType, userAgent: Option[String]): Future[AccountId] = { + for { + a <- authenticationsValidator.findAccountId(providerId, providerKey) + _ <- devicesDAO.create(udid, deviceType, userAgent, a.toSessionId) + } yield (a) + } + + def update(udid: String, pushToken: Option[String], sessionId: SessionId): Future[Unit] = { devicesDAO.update(udid, pushToken, sessionId).flatMap(_ => Future.Unit) } diff --git a/core/src/main/scala/io/github/cactacea/backend/core/infrastructure/dao/AccountsDAO.scala b/core/src/main/scala/io/github/cactacea/backend/core/infrastructure/dao/AccountsDAO.scala index ecb07e26..437565ef 100644 --- a/core/src/main/scala/io/github/cactacea/backend/core/infrastructure/dao/AccountsDAO.scala +++ b/core/src/main/scala/io/github/cactacea/backend/core/infrastructure/dao/AccountsDAO.scala @@ -26,6 +26,19 @@ class AccountsDAO @Inject()(db: DatabaseService) { run(q) } + def create(accountName: String, displayName: String): Future[AccountId] = { + + val accountStatus = AccountStatusType.normally + val q = quote { + query[Accounts].insert( + _.accountName -> lift(accountName), + _.displayName -> lift(displayName), + _.accountStatus -> lift(accountStatus) + ).returning(_.id) + } + run(q) + } + def updateProfile(displayName: String, web: Option[String], birthday: Option[Long], diff --git a/core/src/main/scala/io/github/cactacea/backend/core/infrastructure/dao/AuthenticationsDAO.scala b/core/src/main/scala/io/github/cactacea/backend/core/infrastructure/dao/AuthenticationsDAO.scala index 21502605..50ee3941 100644 --- a/core/src/main/scala/io/github/cactacea/backend/core/infrastructure/dao/AuthenticationsDAO.scala +++ b/core/src/main/scala/io/github/cactacea/backend/core/infrastructure/dao/AuthenticationsDAO.scala @@ -49,7 +49,7 @@ class AuthenticationsDAO @Inject()(db: DatabaseService) { run(q).map(_ => Unit) } - def updateAccountId(providerId: String, providerKey: String, accountId: AccountId): Future[Unit] = { + def link(providerId: String, providerKey: String, accountId: AccountId): Future[Unit] = { val q = quote { query[Authentications] .filter(_.providerId == lift(providerId)) diff --git a/core/src/main/scala/io/github/cactacea/backend/core/infrastructure/validators/AuthenticationsValidator.scala b/core/src/main/scala/io/github/cactacea/backend/core/infrastructure/validators/AuthenticationsValidator.scala new file mode 100644 index 00000000..b4745ce1 --- /dev/null +++ b/core/src/main/scala/io/github/cactacea/backend/core/infrastructure/validators/AuthenticationsValidator.scala @@ -0,0 +1,33 @@ +package io.github.cactacea.backend.core.infrastructure.validators + +import com.google.inject.{Inject, Singleton} +import com.twitter.util.Future +import io.github.cactacea.backend.core.infrastructure.dao.AuthenticationsDAO +import io.github.cactacea.backend.core.infrastructure.identifiers.AccountId +import io.github.cactacea.backend.core.util.exceptions.CactaceaException +import io.github.cactacea.backend.core.util.responses.CactaceaErrors._ + +@Singleton +class AuthenticationsValidator @Inject()( + authenticationsDAO: AuthenticationsDAO + ) { + + def findAccountId(providerId: String, providerKey: String): Future[AccountId] = { + authenticationsDAO.find(providerId, providerKey).flatMap(_ match { + case Some(a) => + a.accountId match { + case Some(id) => + Future.value(id) + case None => + Future.exception(CactaceaException(AccountNotFound)) + } + case None => + Future.exception(CactaceaException(AccountNotFound)) + }) + + } + + +} + + diff --git a/core/src/main/scala/io/github/cactacea/backend/core/util/configs/Config.scala b/core/src/main/scala/io/github/cactacea/backend/core/util/configs/Config.scala index 4f40205d..0fcc6a2f 100644 --- a/core/src/main/scala/io/github/cactacea/backend/core/util/configs/Config.scala +++ b/core/src/main/scala/io/github/cactacea/backend/core/util/configs/Config.scala @@ -2,13 +2,13 @@ package io.github.cactacea.backend.core.util.configs import java.net.InetAddress -import com.twitter.util.Duration import com.twitter.conversions.DurationOps._ +import com.twitter.conversions.StorageUnitOps._ +import com.twitter.util.Duration import com.typesafe.config.ConfigFactory import io.github.cactacea.backend.core.domain.enums.DeviceType import net.ceedubs.ficus.Ficus._ import net.ceedubs.ficus.readers.ArbitraryTypeReader._ -import com.twitter.conversions.StorageUnitOps._ object Config extends DurationReader { @@ -19,7 +19,8 @@ object Config extends DurationReader { private val authConfig = config.as[AuthConfig]("auth") private val passwordConfig = config.as[PasswordConfig]("password") private val storageConfig = config.as[StorageConfig]("storage") - + private val facebookConfig = config.as[OAuth2Config]("socials.facebook") + private val twitterConfig = config.as[OAuth1Config]("socials.twitte") object db { // scalastyle:ignore trait config { @@ -110,11 +111,28 @@ object Config extends DurationReader { lazy val keyLength = passwordConfig.keyLength.getOrElse(128) } - object crypter { + object crypter { // scalastyle:ignore lazy val signerKey = crypterConfig.signerKey.getOrElse("todo") lazy val crypterKey = crypterConfig.crypterKey.getOrElse("todo") } + object facebook { // scalastyle:ignore + val authorizationURL = facebookConfig.authorizationURL + val accessTokenURL = facebookConfig.accessTokenURL.getOrElse("") + val redirectURL = facebookConfig.redirectURL + val clientID = facebookConfig.clientID.getOrElse("") + val clientSecret = facebookConfig.clientSecret.getOrElse("") + val scope = facebookConfig.scope + } + + object twitter { // scalastyle:ignore + val requestTokenURL = twitterConfig.requestTokenURL.getOrElse("") + val accessTokenURL = twitterConfig.accessTokenURL.getOrElse("") + val authorizationURL = twitterConfig.authorizationURL.getOrElse("") + val callbackURL = twitterConfig.callbackURL.getOrElse("") + val consumerKey = twitterConfig.consumerKey.getOrElse("") + val consumerSecret = twitterConfig.consumerSecret.getOrElse("") + } println( // scalastyle:ignore """ ___ _ ___ _ _ @@ -162,8 +180,20 @@ object Config extends DurationReader { println(s"password.salt = ${password.salt}") // scalastyle:ignore println(s"password.iterations = ${password.iterations}") // scalastyle:ignore println(s"password.keyLength = ${password.keyLength}") // scalastyle:ignore - println(s"crypter.crypterKey = ${crypter.crypterKey}") - println(s"crypter.signerKey = ${crypter.signerKey}") + println(s"crypter.crypterKey = ${crypter.crypterKey}") // scalastyle:ignore + println(s"crypter.signerKey = ${crypter.signerKey}") // scalastyle:ignore + println(s"facebook.authorizationURL = ${facebook.authorizationURL}") // scalastyle:ignore + println(s"facebook.accessTokenURL = ${facebook.accessTokenURL}") // scalastyle:ignore + println(s"facebook.redirectURL = ${facebook.redirectURL}") // scalastyle:ignore + println(s"facebook.clientID = ${facebook.clientID}") // scalastyle:ignore + println(s"facebook.clientSecret = ${facebook.clientSecret}") // scalastyle:ignore + println(s"facebook.scope = ${facebook.scope}") // scalastyle:ignore + println(s"twitter.requestTokenURL = ${twitter.requestTokenURL}") // scalastyle:ignore + println(s"twitter.accessTokenURL = ${twitter.accessTokenURL}") // scalastyle:ignore + println(s"twitter.authorizationURL = ${twitter.authorizationURL}") // scalastyle:ignore + println(s"twitter.callbackURL = ${twitter.callbackURL}") // scalastyle:ignore + println(s"twitter.consumerKey = ${twitter.consumerKey}") // scalastyle:ignore + println(s"twitter.consumerSecret = ${twitter.consumerSecret}") // scalastyle:ignore println("") // scalastyle:ignore } diff --git a/core/src/main/scala/io/github/cactacea/backend/core/util/configs/OAuth1Config.scala b/core/src/main/scala/io/github/cactacea/backend/core/util/configs/OAuth1Config.scala new file mode 100644 index 00000000..a58adb8a --- /dev/null +++ b/core/src/main/scala/io/github/cactacea/backend/core/util/configs/OAuth1Config.scala @@ -0,0 +1,10 @@ +package io.github.cactacea.backend.core.util.configs + +case class OAuth1Config ( + requestTokenURL: Option[String], + accessTokenURL: Option[String], + authorizationURL: Option[String], + callbackURL: Option[String], + consumerKey: Option[String], + consumerSecret: Option[String] + ) diff --git a/core/src/main/scala/io/github/cactacea/backend/core/util/configs/OAuth2Config.scala b/core/src/main/scala/io/github/cactacea/backend/core/util/configs/OAuth2Config.scala new file mode 100644 index 00000000..475cd68f --- /dev/null +++ b/core/src/main/scala/io/github/cactacea/backend/core/util/configs/OAuth2Config.scala @@ -0,0 +1,10 @@ +package io.github.cactacea.backend.core.util.configs + +case class OAuth2Config ( + authorizationURL: Option[String], + accessTokenURL: Option[String], + redirectURL: Option[String], + clientID: Option[String], + clientSecret: Option[String], + scope: Option[String] + ) diff --git a/core/src/test/scala/io/github/cactacea/core/domain/repositories/AccountsRepositorySpec.scala b/core/src/test/scala/io/github/cactacea/core/domain/repositories/AccountsRepositorySpec.scala index 69494799..3acc6da4 100644 --- a/core/src/test/scala/io/github/cactacea/core/domain/repositories/AccountsRepositorySpec.scala +++ b/core/src/test/scala/io/github/cactacea/core/domain/repositories/AccountsRepositorySpec.scala @@ -1,8 +1,8 @@ package io.github.cactacea.backend.core.domain.repositories -import io.github.cactacea.backend.core.domain.enums.{AccountStatusType, DeviceType, MediumType} +import io.github.cactacea.backend.core.domain.enums.{AccountStatusType, MediumType} import io.github.cactacea.backend.core.helpers.RepositorySpec -import io.github.cactacea.backend.core.infrastructure.dao.{AccountsDAO, DevicesDAO, PushNotificationSettingsDAO} +import io.github.cactacea.backend.core.infrastructure.dao.{AccountsDAO, PushNotificationSettingsDAO} import io.github.cactacea.backend.core.infrastructure.identifiers.{AccountId, MediumId} import io.github.cactacea.backend.core.util.exceptions.CactaceaException import io.github.cactacea.backend.core.util.responses.CactaceaErrors.{AccountNotFound, AccountTerminated, MediumNotFound, SessionTimeout} @@ -11,7 +11,7 @@ class AccountsRepositorySpec extends RepositorySpec { val blocksRepository = injector.instance[BlocksRepository] val mediumRepository = injector.instance[MediumsRepository] - val devicesDAO = injector.instance[DevicesDAO] +// val devicesDAO = injector.instance[DevicesDAO] var notificationSettingsDAO = injector.instance[PushNotificationSettingsDAO] val accountsDAO = injector.instance[AccountsDAO] @@ -20,10 +20,10 @@ class AccountsRepositorySpec extends RepositorySpec { val accountName = "SessionsRepositorySpec2" val displayName = "SessionsRepositorySpec2" // val password = "password" - val udid = "0123456789012345678901234567890123456789" - val userAgent = Some("userAgent") - val result = execute(accountsRepository.create(accountName, udid, DeviceType.ios, userAgent)) - val account = execute(accountsRepository.find(result.accountName, udid, DeviceType.ios, userAgent)) +// val udid = "0123456789012345678901234567890123456789" +// val userAgent = Some("userAgent") + val result = execute(accountsRepository.create(accountName)) + val account = execute(accountsRepository.find(result.id.toSessionId)) assert(account.displayName == displayName) @@ -48,8 +48,8 @@ class AccountsRepositorySpec extends RepositorySpec { val accountName = "SessionsRepositorySpec4" // val password = "password" val udid = "0123456789012345678901234567890123456789" - val userAgent = Some("userAgent") - val session = execute(accountsRepository.create(accountName, udid, DeviceType.ios, userAgent)) +// val userAgent = Some("userAgent") + val session = execute(accountsRepository.create(accountName)) execute(accountsRepository.signOut(udid, session.id.toSessionId)) } @@ -60,16 +60,16 @@ class AccountsRepositorySpec extends RepositorySpec { val displayName = "SessionsRepositorySpec1" // val password = "password" val udid = "0123456789012345678901234567890123456789" - val userAgent = Some("userAgent") - val account = execute(accountsRepository.create(accountName, udid, DeviceType.ios, userAgent)) +// val userAgent = Some("userAgent") + val account = execute(accountsRepository.create(accountName)) // result user assert(account.accountName == accountName) assert(account.displayName == displayName) - // result device - val devices = execute(devicesDAO.exist(account.id.toSessionId, udid)) - assert(devices == true) +// // result device +// val devices = execute(devicesDAO.exist(account.id.toSessionId, udid)) +// assert(devices == true) // result notificationSettings val notificationSettings = execute(notificationSettingsDAO.find(account.id.toSessionId)) @@ -267,8 +267,8 @@ class AccountsRepositorySpec extends RepositorySpec { val accountName = "SessionsRepositorySpec5" // val password = "password" val udid = "0123456789012345678901234567890123456789" - val userAgent = Some("userAgent") - val session = execute(accountsRepository.create(accountName, udid, DeviceType.ios, userAgent)) +// val userAgent = Some("userAgent") + val session = execute(accountsRepository.create(accountName)) val expired = System.currentTimeMillis() execute(accountsRepository.find(session.id.toSessionId, expired)) diff --git a/core/src/test/scala/io/github/cactacea/core/domain/repositories/DevicesRepositorySpec.scala b/core/src/test/scala/io/github/cactacea/core/domain/repositories/DevicesRepositorySpec.scala index 23316f7d..c815688d 100644 --- a/core/src/test/scala/io/github/cactacea/core/domain/repositories/DevicesRepositorySpec.scala +++ b/core/src/test/scala/io/github/cactacea/core/domain/repositories/DevicesRepositorySpec.scala @@ -7,7 +7,6 @@ import io.github.cactacea.backend.core.infrastructure.dao.DevicesDAO class DevicesRepositorySpec extends RepositorySpec { val devicesRepository = injector.instance[DevicesRepository] - val devicesDAO = injector.instance[DevicesDAO] test("updateDeviceToken") { diff --git a/core/src/test/scala/io/github/cactacea/core/helpers/RepositorySpec.scala b/core/src/test/scala/io/github/cactacea/core/helpers/RepositorySpec.scala index 0fe45cd5..218c8450 100644 --- a/core/src/test/scala/io/github/cactacea/core/helpers/RepositorySpec.scala +++ b/core/src/test/scala/io/github/cactacea/core/helpers/RepositorySpec.scala @@ -9,6 +9,7 @@ import io.github.cactacea.backend.core.application.components.services.DatabaseS import io.github.cactacea.backend.core.domain.enums.DeviceType import io.github.cactacea.backend.core.domain.models.Account import io.github.cactacea.backend.core.domain.repositories.AccountsRepository +import io.github.cactacea.backend.core.infrastructure.dao.DevicesDAO import io.github.cactacea.core.helpers.HelperDAO import org.scalatest.BeforeAndAfter @@ -35,22 +36,23 @@ class RepositorySpec extends IntegrationTest with BeforeAndAfter with Logging { val db = injector.instance[DatabaseService] val accountsRepository = injector.instance[AccountsRepository] + val devicesDAO = injector.instance[DevicesDAO] val helperDAO = injector.instance[HelperDAO] def signUp(accountName: String, password: String, udid: String): Account = { - execute(accountsRepository.create(accountName, udid, DeviceType.ios, Some("user agent"))) - val authentication = execute(accountsRepository.find(accountName, udid, DeviceType.ios, Some("user agent"))) - authentication + val a = execute(accountsRepository.create(accountName)) + execute(devicesDAO.create(udid, DeviceType.ios, Some("user agent"), a.id.toSessionId)) + a } - def signIn(accountName: String, password: String, udid: String): Account = { - -// val result = execute(accountsRepository.signIn(accountName, password, udid, DeviceType.ios, Some("user agent"))) - val authentication = execute(accountsRepository.find(accountName, udid, DeviceType.ios, Some("user agent"))) - authentication - - } +// def signIn(accountName: String, password: String, udid: String): Account = { +// +// val result = execute(accountsRepository.find(accountName, password, udid, DeviceType.ios, Some("user agent"))) +//// val authentication = execute(devicesDAO.update(accountName, udid, DeviceType.ios, Some("user agent"))) +//// authentication +// +// } } diff --git a/core/src/test/scala/io/github/cactacea/core/helpers/ServiceSpec.scala b/core/src/test/scala/io/github/cactacea/core/helpers/ServiceSpec.scala index 9b3eddc2..91220290 100644 --- a/core/src/test/scala/io/github/cactacea/core/helpers/ServiceSpec.scala +++ b/core/src/test/scala/io/github/cactacea/core/helpers/ServiceSpec.scala @@ -7,7 +7,6 @@ import com.twitter.util.{Await, Future} import io.github.cactacea.backend.core.application.components.modules._ import io.github.cactacea.backend.core.application.components.services.DatabaseService import io.github.cactacea.backend.core.application.services.FeedsService -import io.github.cactacea.backend.core.domain.enums.DeviceType import io.github.cactacea.backend.core.domain.repositories.AccountsRepository import org.scalatest.BeforeAndAfter @@ -37,7 +36,7 @@ class ServiceSpec extends IntegrationTest with BeforeAndAfter with Logging { val feedsService = injector.instance[FeedsService] def signUp(accountName: String, password: String, udid: String) = { - execute(accountsRepository.create(accountName, udid, DeviceType.ios, Some("user-agent"))) + execute(accountsRepository.create(accountName)) //, udid, DeviceType.ios, Some("user-agent"))) } diff --git a/demo/api/src/main/scala/io/github/cactacea/backend/APIServer.scala b/demo/api/src/main/scala/io/github/cactacea/backend/APIServer.scala index 84bde0ac..3b675a61 100644 --- a/demo/api/src/main/scala/io/github/cactacea/backend/APIServer.scala +++ b/demo/api/src/main/scala/io/github/cactacea/backend/APIServer.scala @@ -2,7 +2,7 @@ package io.github.cactacea.backend import com.twitter.finatra.http.routing.HttpRouter import io.cactacea.finagger.DocsController -import io.github.cactacea.backend.utils.auth.CactaceaAuthModule +import io.github.cactacea.backend.utils.modules.AuthenticationModule import io.github.cactacea.backend.utils.swagger.CactaceaSwaggerModule import io.github.cactacea.backend.utils.warmups.CactaceaQueueHandler @@ -15,7 +15,7 @@ class APIServer extends CactaceaServer { } addFrameworkModule(CactaceaSwaggerModule) - addFrameworkModule(CactaceaAuthModule) + addFrameworkModule(AuthenticationModule) override def warmup() { handle[MigrationHandler]() diff --git a/demo/api/src/test/scala/io/github/cactacea/backend/APIServerSpec.scala b/demo/api/src/test/scala/io/github/cactacea/backend/APIServerSpec.scala index cbbaad14..1cd70717 100644 --- a/demo/api/src/test/scala/io/github/cactacea/backend/APIServerSpec.scala +++ b/demo/api/src/test/scala/io/github/cactacea/backend/APIServerSpec.scala @@ -10,7 +10,7 @@ import com.twitter.inject.app.TestInjector import com.twitter.inject.server.FeatureTest import io.github.cactacea.backend.core.application.components.modules._ import io.github.cactacea.backend.helpers._ -import io.github.cactacea.backend.utils.auth.CactaceaAuthModule +import io.github.cactacea.backend.utils.modules.AuthenticationModule @Singleton class APIServerSpec extends FeatureTest with Helpers { @@ -26,7 +26,7 @@ class APIServerSpec extends FeatureTest with Helpers { override def storageModule: TwitterModule = DemoStorageModule - addFrameworkModule(CactaceaAuthModule) + addFrameworkModule(AuthenticationModule) } ) @@ -35,7 +35,7 @@ class APIServerSpec extends FeatureTest with Helpers { TestInjector( modules = Seq( DatabaseModule, - CactaceaAuthModule, + AuthenticationModule, DefaultChatModule, DefaultDeepLinkModule, DefaultJacksonModule, diff --git a/libs/filhouette/src/main/scala/io/github/cactacea/filhouette/impl/providers/oauth2/FacebookProvider.scala b/libs/filhouette/src/main/scala/io/github/cactacea/filhouette/impl/providers/oauth2/FacebookProvider.scala index 4f7a7c6d..59751feb 100644 --- a/libs/filhouette/src/main/scala/io/github/cactacea/filhouette/impl/providers/oauth2/FacebookProvider.scala +++ b/libs/filhouette/src/main/scala/io/github/cactacea/filhouette/impl/providers/oauth2/FacebookProvider.scala @@ -23,9 +23,9 @@ package io.github.cactacea.filhouette.impl.providers.oauth2 import com.fasterxml.jackson.databind.JsonNode -import com.google.inject.Inject -import com.twitter.finagle.http.{Method, Request, Version} -import com.twitter.finatra.httpclient.HttpClient +import com.twitter.finatra.httpclient.modules.HttpClientModule +import com.twitter.finatra.httpclient.{HttpClient, RequestBuilder} +import com.twitter.finatra.json.FinatraObjectMapper import com.twitter.util.Future import io.github.cactacea.filhouette.api.LoginInfo import io.github.cactacea.filhouette.impl.exceptions.ProfileRetrievalException @@ -64,7 +64,7 @@ trait BaseFacebookProvider extends OAuth2Provider { * @return On success the build social profile, otherwise a failure. */ override protected def buildProfile(authInfo: OAuth2Info): Future[Profile] = { - val request = Request(Version.Http11, Method.Get, urls("api").format(authInfo.accessToken)) + val request = RequestBuilder.get(urls("api").format(authInfo.accessToken)) httpLayer.execute(request).flatMap({ response => val json = Json.obj(response.contentString) val error = json.get("error") @@ -92,7 +92,7 @@ class FacebookProfileParser extends SocialProfileParser[JsonNode, CommonSocialPr * @param authInfo The auth info to query the provider again for additional data. * @return The social profile from given result. */ - override def parse(json: JsonNode, authInfo: OAuth2Info) = Future.value { + override def parse(json: JsonNode, authInfo: OAuth2Info): Future[CommonSocialProfile] = Future.value { val userID = json.get("id").asText() val firstName = Some(json.get("first_name").asText()) val lastName = Some(json.get("last_name").asText()) @@ -121,10 +121,14 @@ class FacebookProvider ( val settings: OAuth2Settings) extends BaseFacebookProvider with CommonSocialProfileBuilder { + private val httpClientModule = new HttpClientModule() { + val dest = "graph.facebook.com" + } + /** * The HTTP layer implementation. */ - @Inject var httpLayer: HttpClient = _ + var httpLayer: HttpClient = httpClientModule.provideHttpClient(FinatraObjectMapper.create(), httpClientModule.provideHttpService) /** * The type of this class. @@ -142,7 +146,7 @@ class FacebookProvider ( * @param f A function which gets the settings passed and returns different settings. * @return An instance of the provider initialized with new settings. */ - override def withSettings(f: (Settings) => Settings) = new FacebookProvider(stateHandler, f(settings)) + override def withSettings(f: (Settings) => Settings): FacebookProvider = new FacebookProvider(stateHandler, f(settings)) } /** diff --git a/libs/filhouette/src/main/scala/io/github/cactacea/filhouette/impl/providers/oauth2/GoogleProvider.scala b/libs/filhouette/src/main/scala/io/github/cactacea/filhouette/impl/providers/oauth2/GoogleProvider.scala index f09d494e..32f135b4 100644 --- a/libs/filhouette/src/main/scala/io/github/cactacea/filhouette/impl/providers/oauth2/GoogleProvider.scala +++ b/libs/filhouette/src/main/scala/io/github/cactacea/filhouette/impl/providers/oauth2/GoogleProvider.scala @@ -94,6 +94,7 @@ class GoogleProfileParser extends SocialProfileParser[JsonNode, CommonSocialProf * @return The social profile from given result. */ override def parse(json: JsonNode, authInfo: OAuth2Info) = Future.value { + // https://developers.google.com/+/api/latest/people#emails.type val userID = json.get("id").asText() val firstName = Some(json.get("name").get("givenName").asText()) val lastName = Some(json.get("name").get("familyName").asText()) @@ -101,14 +102,6 @@ class GoogleProfileParser extends SocialProfileParser[JsonNode, CommonSocialProf val avatarURL = Some(json.get("image").get("url").asText()) val isDefaultAvatar = json.get("image").get("isDefault").asBoolean(false) -// // https://developers.google.com/+/api/latest/people#emails.type -// val emailIndex = (json \ "emails" \\ "type").indexWhere(_.as[String] == "account") -// val emailValue = if ((json \ "emails" \\ "value").isDefinedAt(emailIndex)) { -// (json \ "emails" \\ "value")(emailIndex).asOpt[String] -// } else { -// None -// } - // TODO // val emailIndex = "" val emailValue = Some("") diff --git a/server/src/main/scala/io/github/cactacea/backend/controllers/AccountsController.scala b/server/src/main/scala/io/github/cactacea/backend/controllers/AccountsController.scala index f3bd2095..e0a94960 100644 --- a/server/src/main/scala/io/github/cactacea/backend/controllers/AccountsController.scala +++ b/server/src/main/scala/io/github/cactacea/backend/controllers/AccountsController.scala @@ -11,7 +11,7 @@ import io.github.cactacea.backend.models.requests.account._ import io.github.cactacea.backend.models.requests.feed.GetAccountFeeds import io.github.cactacea.backend.models.requests.group.{GetAccountGroup, GetAccountGroups} import io.github.cactacea.backend.swagger.CactaceaSwaggerController -import io.github.cactacea.backend.utils.auth.CactaceaContext +import io.github.cactacea.backend.utils.context.CactaceaContext import io.swagger.models.Swagger @Singleton diff --git a/server/src/main/scala/io/github/cactacea/backend/controllers/BlocksController.scala b/server/src/main/scala/io/github/cactacea/backend/controllers/BlocksController.scala index a7e0f5bd..087344d6 100644 --- a/server/src/main/scala/io/github/cactacea/backend/controllers/BlocksController.scala +++ b/server/src/main/scala/io/github/cactacea/backend/controllers/BlocksController.scala @@ -8,8 +8,7 @@ import io.github.cactacea.backend.core.util.responses.CactaceaErrors import io.github.cactacea.backend.core.util.responses.CactaceaErrors._ import io.github.cactacea.backend.models.requests.account.{DeleteBlock, PostBlock} import io.github.cactacea.backend.swagger.CactaceaSwaggerController -import io.github.cactacea.backend.utils.auth.CactaceaContext - +import io.github.cactacea.backend.utils.context.CactaceaContext import io.swagger.models.Swagger @Singleton diff --git a/server/src/main/scala/io/github/cactacea/backend/controllers/CommentLikesController.scala b/server/src/main/scala/io/github/cactacea/backend/controllers/CommentLikesController.scala index 408189c2..022248fd 100644 --- a/server/src/main/scala/io/github/cactacea/backend/controllers/CommentLikesController.scala +++ b/server/src/main/scala/io/github/cactacea/backend/controllers/CommentLikesController.scala @@ -9,8 +9,7 @@ import io.github.cactacea.backend.core.util.responses.CactaceaErrors._ import io.github.cactacea.backend.core.util.responses.CactaceaErrors import io.github.cactacea.backend.models.requests.comment._ import io.github.cactacea.backend.swagger.CactaceaSwaggerController -import io.github.cactacea.backend.utils.auth.CactaceaContext - +import io.github.cactacea.backend.utils.context.CactaceaContext import io.swagger.models.Swagger @Singleton diff --git a/server/src/main/scala/io/github/cactacea/backend/controllers/CommentsController.scala b/server/src/main/scala/io/github/cactacea/backend/controllers/CommentsController.scala index 886243f1..595a8d90 100644 --- a/server/src/main/scala/io/github/cactacea/backend/controllers/CommentsController.scala +++ b/server/src/main/scala/io/github/cactacea/backend/controllers/CommentsController.scala @@ -10,8 +10,7 @@ import io.github.cactacea.backend.core.util.responses.CactaceaErrors import io.github.cactacea.backend.models.requests.comment._ import io.github.cactacea.backend.models.responses.CommentCreated import io.github.cactacea.backend.swagger.CactaceaSwaggerController -import io.github.cactacea.backend.utils.auth.CactaceaContext - +import io.github.cactacea.backend.utils.context.CactaceaContext import io.swagger.models.Swagger @Singleton diff --git a/server/src/main/scala/io/github/cactacea/backend/controllers/FeedLikesController.scala b/server/src/main/scala/io/github/cactacea/backend/controllers/FeedLikesController.scala index e8e913f1..50282b02 100644 --- a/server/src/main/scala/io/github/cactacea/backend/controllers/FeedLikesController.scala +++ b/server/src/main/scala/io/github/cactacea/backend/controllers/FeedLikesController.scala @@ -9,8 +9,7 @@ import io.github.cactacea.backend.core.util.responses.CactaceaErrors._ import io.github.cactacea.backend.core.util.responses.CactaceaErrors import io.github.cactacea.backend.models.requests.feed._ import io.github.cactacea.backend.swagger.CactaceaSwaggerController -import io.github.cactacea.backend.utils.auth.CactaceaContext - +import io.github.cactacea.backend.utils.context.CactaceaContext import io.swagger.models.Swagger @Singleton diff --git a/server/src/main/scala/io/github/cactacea/backend/controllers/FeedsController.scala b/server/src/main/scala/io/github/cactacea/backend/controllers/FeedsController.scala index be2739f0..2971771c 100644 --- a/server/src/main/scala/io/github/cactacea/backend/controllers/FeedsController.scala +++ b/server/src/main/scala/io/github/cactacea/backend/controllers/FeedsController.scala @@ -10,8 +10,7 @@ import io.github.cactacea.backend.core.util.responses.CactaceaErrors import io.github.cactacea.backend.models.requests.feed._ import io.github.cactacea.backend.models.responses.FeedCreated import io.github.cactacea.backend.swagger.CactaceaSwaggerController -import io.github.cactacea.backend.utils.auth.CactaceaContext - +import io.github.cactacea.backend.utils.context.CactaceaContext import io.swagger.models.Swagger @Singleton diff --git a/server/src/main/scala/io/github/cactacea/backend/controllers/FollowsController.scala b/server/src/main/scala/io/github/cactacea/backend/controllers/FollowsController.scala index 679788f2..f582c8df 100644 --- a/server/src/main/scala/io/github/cactacea/backend/controllers/FollowsController.scala +++ b/server/src/main/scala/io/github/cactacea/backend/controllers/FollowsController.scala @@ -9,8 +9,7 @@ import io.github.cactacea.backend.core.util.responses.CactaceaErrors.{AccountNot import io.github.cactacea.backend.core.util.responses.CactaceaErrors import io.github.cactacea.backend.models.requests.account._ import io.github.cactacea.backend.swagger.CactaceaSwaggerController -import io.github.cactacea.backend.utils.auth.CactaceaContext - +import io.github.cactacea.backend.utils.context.CactaceaContext import io.swagger.models.Swagger @Singleton diff --git a/server/src/main/scala/io/github/cactacea/backend/controllers/FriendRequestsController.scala b/server/src/main/scala/io/github/cactacea/backend/controllers/FriendRequestsController.scala index 7e0c0de8..2f9bdd34 100644 --- a/server/src/main/scala/io/github/cactacea/backend/controllers/FriendRequestsController.scala +++ b/server/src/main/scala/io/github/cactacea/backend/controllers/FriendRequestsController.scala @@ -9,8 +9,7 @@ import io.github.cactacea.backend.core.util.responses.CactaceaErrors._ import io.github.cactacea.backend.models.requests.account.{DeleteFriendRequest, PostAcceptFriendRequest, PostFriendRequest, PostRejectFriendRequest} import io.github.cactacea.backend.models.responses.FriendRequestCreated import io.github.cactacea.backend.swagger.CactaceaSwaggerController -import io.github.cactacea.backend.utils.auth.CactaceaContext - +import io.github.cactacea.backend.utils.context.CactaceaContext import io.swagger.models.Swagger @Singleton diff --git a/server/src/main/scala/io/github/cactacea/backend/controllers/FriendsController.scala b/server/src/main/scala/io/github/cactacea/backend/controllers/FriendsController.scala index d36944f7..29dedef1 100644 --- a/server/src/main/scala/io/github/cactacea/backend/controllers/FriendsController.scala +++ b/server/src/main/scala/io/github/cactacea/backend/controllers/FriendsController.scala @@ -8,7 +8,7 @@ import io.github.cactacea.backend.core.util.responses.CactaceaErrors import io.github.cactacea.backend.core.util.responses.CactaceaErrors.AccountNotFriend import io.github.cactacea.backend.models.requests.account.DeleteFriend import io.github.cactacea.backend.swagger.CactaceaSwaggerController -import io.github.cactacea.backend.utils.auth.CactaceaContext +import io.github.cactacea.backend.utils.context.CactaceaContext import io.swagger.models.Swagger @Singleton diff --git a/server/src/main/scala/io/github/cactacea/backend/controllers/GroupsController.scala b/server/src/main/scala/io/github/cactacea/backend/controllers/GroupsController.scala index f3182065..060e0861 100644 --- a/server/src/main/scala/io/github/cactacea/backend/controllers/GroupsController.scala +++ b/server/src/main/scala/io/github/cactacea/backend/controllers/GroupsController.scala @@ -10,8 +10,7 @@ import io.github.cactacea.backend.core.util.responses.CactaceaErrors import io.github.cactacea.backend.models.requests.group._ import io.github.cactacea.backend.models.responses.GroupCreated import io.github.cactacea.backend.swagger.CactaceaSwaggerController -import io.github.cactacea.backend.utils.auth.CactaceaContext - +import io.github.cactacea.backend.utils.context.CactaceaContext import io.swagger.models.Swagger @Singleton diff --git a/server/src/main/scala/io/github/cactacea/backend/controllers/InvitationsController.scala b/server/src/main/scala/io/github/cactacea/backend/controllers/InvitationsController.scala index b661edb7..001addc4 100644 --- a/server/src/main/scala/io/github/cactacea/backend/controllers/InvitationsController.scala +++ b/server/src/main/scala/io/github/cactacea/backend/controllers/InvitationsController.scala @@ -10,8 +10,7 @@ import io.github.cactacea.backend.models.requests.account.{PostInvitationAccount import io.github.cactacea.backend.models.requests.group.{PostAcceptInvitation, PostRejectInvitation} import io.github.cactacea.backend.models.responses.InvitationCreated import io.github.cactacea.backend.swagger.CactaceaSwaggerController -import io.github.cactacea.backend.utils.auth.CactaceaContext - +import io.github.cactacea.backend.utils.context.CactaceaContext import io.swagger.models.Swagger @Singleton diff --git a/server/src/main/scala/io/github/cactacea/backend/controllers/MediumsController.scala b/server/src/main/scala/io/github/cactacea/backend/controllers/MediumsController.scala index 5998dd06..d34304ec 100644 --- a/server/src/main/scala/io/github/cactacea/backend/controllers/MediumsController.scala +++ b/server/src/main/scala/io/github/cactacea/backend/controllers/MediumsController.scala @@ -11,8 +11,7 @@ import io.github.cactacea.backend.core.util.responses.CactaceaErrors._ import io.github.cactacea.backend.models.requests.medium.DeleteMedium import io.github.cactacea.backend.models.responses.MediumCreated import io.github.cactacea.backend.swagger.CactaceaSwaggerController -import io.github.cactacea.backend.utils.auth.CactaceaContext - +import io.github.cactacea.backend.utils.context.CactaceaContext import io.swagger.models.Swagger @Singleton diff --git a/server/src/main/scala/io/github/cactacea/backend/controllers/MessagesController.scala b/server/src/main/scala/io/github/cactacea/backend/controllers/MessagesController.scala index c0704af7..9374d585 100644 --- a/server/src/main/scala/io/github/cactacea/backend/controllers/MessagesController.scala +++ b/server/src/main/scala/io/github/cactacea/backend/controllers/MessagesController.scala @@ -9,8 +9,7 @@ import io.github.cactacea.backend.core.util.responses.CactaceaErrors import io.github.cactacea.backend.core.util.responses.CactaceaErrors._ import io.github.cactacea.backend.models.requests.message.{DeleteMessages, GetMessages, PostMedium, PostText} import io.github.cactacea.backend.swagger.CactaceaSwaggerController -import io.github.cactacea.backend.utils.auth.CactaceaContext - +import io.github.cactacea.backend.utils.context.CactaceaContext import io.swagger.models.Swagger @Singleton diff --git a/server/src/main/scala/io/github/cactacea/backend/controllers/MutesController.scala b/server/src/main/scala/io/github/cactacea/backend/controllers/MutesController.scala index 7d8e3886..d4b70bf2 100644 --- a/server/src/main/scala/io/github/cactacea/backend/controllers/MutesController.scala +++ b/server/src/main/scala/io/github/cactacea/backend/controllers/MutesController.scala @@ -8,8 +8,7 @@ import io.github.cactacea.backend.core.util.responses.CactaceaErrors._ import io.github.cactacea.backend.core.util.responses.CactaceaErrors import io.github.cactacea.backend.models.requests.account.{DeleteMute, PostMute} import io.github.cactacea.backend.swagger.CactaceaSwaggerController -import io.github.cactacea.backend.utils.auth.CactaceaContext - +import io.github.cactacea.backend.utils.context.CactaceaContext import io.swagger.models.Swagger @Singleton diff --git a/server/src/main/scala/io/github/cactacea/backend/controllers/NotificationsController.scala b/server/src/main/scala/io/github/cactacea/backend/controllers/NotificationsController.scala index f7bdc3af..0b737527 100644 --- a/server/src/main/scala/io/github/cactacea/backend/controllers/NotificationsController.scala +++ b/server/src/main/scala/io/github/cactacea/backend/controllers/NotificationsController.scala @@ -5,10 +5,9 @@ import com.twitter.finagle.http.Status import com.twitter.inject.annotations.Flag import io.github.cactacea.backend.models.requests.notification.GetNotifications import io.github.cactacea.backend.swagger.CactaceaSwaggerController -import io.github.cactacea.backend.utils.auth.CactaceaContext - import io.github.cactacea.backend.core.application.services.NotificationsService import io.github.cactacea.backend.core.domain.models.Notification +import io.github.cactacea.backend.utils.context.CactaceaContext import io.swagger.models.Swagger @Singleton diff --git a/server/src/main/scala/io/github/cactacea/backend/controllers/SessionController.scala b/server/src/main/scala/io/github/cactacea/backend/controllers/SessionController.scala index a1deceb6..6488d848 100644 --- a/server/src/main/scala/io/github/cactacea/backend/controllers/SessionController.scala +++ b/server/src/main/scala/io/github/cactacea/backend/controllers/SessionController.scala @@ -15,7 +15,8 @@ import io.github.cactacea.backend.models.requests.session._ import io.github.cactacea.backend.models.requests.sessions.DeleteSignOut import io.github.cactacea.backend.models.responses.AccountNameNotExists import io.github.cactacea.backend.swagger.CactaceaSwaggerController -import io.github.cactacea.backend.utils.auth.{CactaceaContext, SessionsService} +import io.github.cactacea.backend.utils.context.CactaceaContext +import io.github.cactacea.backend.utils.services.AuthenticationsService import io.swagger.models.Swagger @@ -32,7 +33,7 @@ class SessionController @Inject()( friendsService: FriendsService, invitationService: GroupInvitationsService, mutesService: MutesService, - sessionService: SessionsService, + sessionService: AuthenticationsService, friendRequestsService: FriendRequestsService, blocksService: BlocksService ) extends CactaceaSwaggerController { diff --git a/server/src/main/scala/io/github/cactacea/backend/controllers/SessionsController.scala b/server/src/main/scala/io/github/cactacea/backend/controllers/SessionsController.scala index 3a4f2b63..137a3d97 100644 --- a/server/src/main/scala/io/github/cactacea/backend/controllers/SessionsController.scala +++ b/server/src/main/scala/io/github/cactacea/backend/controllers/SessionsController.scala @@ -8,14 +8,15 @@ import io.github.cactacea.backend.core.util.responses.CactaceaErrors import io.github.cactacea.backend.core.util.responses.CactaceaErrors.{AccountTerminated, InvalidAccountNameOrPassword} import io.github.cactacea.backend.models.requests.sessions.{GetSignIn, PostSignUp} import io.github.cactacea.backend.swagger.CactaceaSwaggerController -import io.github.cactacea.backend.utils.auth.{CactaceaContext, SessionsService} +import io.github.cactacea.backend.utils.context.CactaceaContext +import io.github.cactacea.backend.utils.services.AuthenticationsService import io.swagger.models.Swagger @Singleton class SessionsController @Inject()( @Flag("cactacea.api.prefix") apiPrefix: String, s: Swagger, - sessionsService: SessionsService + sessionsService: AuthenticationsService ) extends CactaceaSwaggerController { diff --git a/server/src/main/scala/io/github/cactacea/backend/controllers/SettingsController.scala b/server/src/main/scala/io/github/cactacea/backend/controllers/SettingsController.scala index 5ac98bc2..8333fb12 100644 --- a/server/src/main/scala/io/github/cactacea/backend/controllers/SettingsController.scala +++ b/server/src/main/scala/io/github/cactacea/backend/controllers/SettingsController.scala @@ -7,8 +7,7 @@ import io.github.cactacea.backend.core.application.services._ import io.github.cactacea.backend.core.domain.models.PushNotificationSetting import io.github.cactacea.backend.models.requests.setting.{PostActiveStatus, PostDevicePushToken, PutNotificationSetting} import io.github.cactacea.backend.swagger.CactaceaSwaggerController -import io.github.cactacea.backend.utils.auth.CactaceaContext - +import io.github.cactacea.backend.utils.context.CactaceaContext import io.swagger.models.Swagger @Singleton diff --git a/server/src/main/scala/io/github/cactacea/backend/models/requests/session/PutSessionAccountName.scala b/server/src/main/scala/io/github/cactacea/backend/models/requests/session/PutSessionAccountName.scala index 986d65ea..a5bf0537 100644 --- a/server/src/main/scala/io/github/cactacea/backend/models/requests/session/PutSessionAccountName.scala +++ b/server/src/main/scala/io/github/cactacea/backend/models/requests/session/PutSessionAccountName.scala @@ -1,7 +1,7 @@ package io.github.cactacea.backend.models.requests.session import com.twitter.finatra.validation.{MethodValidation, Size, ValidationResult} -import io.github.cactacea.backend.utils.validaters.CactaceaValidations +import io.github.cactacea.backend.utils.validators.CactaceaValidations import io.swagger.annotations.ApiModelProperty case class PutSessionAccountName( diff --git a/server/src/main/scala/io/github/cactacea/backend/models/requests/session/PutSessionPassword.scala b/server/src/main/scala/io/github/cactacea/backend/models/requests/session/PutSessionPassword.scala index 9e97d134..cd340710 100644 --- a/server/src/main/scala/io/github/cactacea/backend/models/requests/session/PutSessionPassword.scala +++ b/server/src/main/scala/io/github/cactacea/backend/models/requests/session/PutSessionPassword.scala @@ -2,7 +2,7 @@ package io.github.cactacea.backend.models.requests.session import com.twitter.finagle.http.Request import com.twitter.finatra.validation.{MethodValidation, Size, ValidationResult} -import io.github.cactacea.backend.utils.validaters.CactaceaValidations +import io.github.cactacea.backend.utils.validators.CactaceaValidations import io.swagger.annotations.ApiModelProperty case class PutSessionPassword( diff --git a/server/src/main/scala/io/github/cactacea/backend/models/requests/sessions/PostSignUp.scala b/server/src/main/scala/io/github/cactacea/backend/models/requests/sessions/PostSignUp.scala index ed51314b..a807f66c 100644 --- a/server/src/main/scala/io/github/cactacea/backend/models/requests/sessions/PostSignUp.scala +++ b/server/src/main/scala/io/github/cactacea/backend/models/requests/sessions/PostSignUp.scala @@ -3,7 +3,7 @@ package io.github.cactacea.backend.models.requests.sessions import com.twitter.finagle.http.Request import com.twitter.finatra.request.Header import com.twitter.finatra.validation._ -import io.github.cactacea.backend.utils.validaters.CactaceaValidations +import io.github.cactacea.backend.utils.validators.CactaceaValidations import io.swagger.annotations.ApiModelProperty case class PostSignUp( diff --git a/server/src/main/scala/io/github/cactacea/backend/utils/auth/CactaceaAPIKeyValidator.scala b/server/src/main/scala/io/github/cactacea/backend/utils/auth/CactaceaAPIKeyValidator.scala deleted file mode 100644 index 033e8edf..00000000 --- a/server/src/main/scala/io/github/cactacea/backend/utils/auth/CactaceaAPIKeyValidator.scala +++ /dev/null @@ -1,20 +0,0 @@ -package io.github.cactacea.backend.utils.auth - -import com.twitter.util.Future -import io.github.cactacea.backend.core.domain.enums.DeviceType -import io.github.cactacea.backend.core.util.configs.Config -import io.github.cactacea.backend.core.util.exceptions.CactaceaException -import io.github.cactacea.backend.core.util.responses.CactaceaErrors.APIKeyIsInValid - -object CactaceaAPIKeyValidator { - - def check(apiKey: Option[String]): Future[DeviceType] = { - apiKey.flatMap(key => Config.auth.keys.all.filter({ case (_, k) => k == key}).headOption.map({ case (d, _) => d})) match { - case Some(t) => - Future.value(t) - case None => - Future.exception(CactaceaException(APIKeyIsInValid)) - } - } - -} diff --git a/server/src/main/scala/io/github/cactacea/backend/utils/auth/CactaceaAuthModule.scala b/server/src/main/scala/io/github/cactacea/backend/utils/auth/CactaceaAuthModule.scala deleted file mode 100644 index 31e6be24..00000000 --- a/server/src/main/scala/io/github/cactacea/backend/utils/auth/CactaceaAuthModule.scala +++ /dev/null @@ -1,116 +0,0 @@ -package io.github.cactacea.backend.utils.auth - -import com.google.inject.{Provides, Singleton} -import com.twitter.inject.TwitterModule -import io.github.cactacea.backend.core.util.configs.Config -import io.github.cactacea.filhouette.api.actions._ -import io.github.cactacea.filhouette.api.crypto.CrypterAuthenticatorEncoder -import io.github.cactacea.filhouette.api.repositories.AuthInfoRepository -import io.github.cactacea.filhouette.api.services.IdentityService -import io.github.cactacea.filhouette.api.util._ -import io.github.cactacea.filhouette.impl.authenticators._ -import io.github.cactacea.filhouette.impl.crypto.{JcaCrypter, JcaCrypterSettings} -import io.github.cactacea.filhouette.impl.providers._ -import io.github.cactacea.filhouette.impl.util.{DefaultFingerprintGenerator, SecureRandomIDGenerator} -import io.github.cactacea.filhouette.password.{BCryptPasswordHasher, BCryptSha256PasswordHasher} -import io.github.cactacea.filhouette.persistence.daos.DelegableAuthInfoDAO -import io.github.cactacea.filhouette.persistence.repositories.DelegableAuthInfoRepository - -object CactaceaAuthModule extends TwitterModule { - - /** - * Configures the module. - */ - override def configure(): Unit = { - bind[IDGenerator].toInstance(new SecureRandomIDGenerator()) - bind[FingerprintGenerator].toInstance(new DefaultFingerprintGenerator(false)) - bind[Clock].toInstance(Clock()) - bindSingleton[IdentityService[CactaceaAccount]].to[CactaceaIdentityService] - bindSingleton[DelegableAuthInfoDAO[PasswordInfo]].to[CactaceaAuthenticationsRepository] - } - - /** - * Provides the crypter for the authenticator. - * - * @return The crypter for the authenticator. - */ - @Provides - @Singleton - def provideAuthenticatorCrypter(): JcaCrypter = { - new JcaCrypter(JcaCrypterSettings(Config.crypter.crypterKey)) - } - - /** - * Provides the auth info repository. - * - * @param passwordInfoDAO The implementation of the delegable password auth info DAO. - * @return The auth info repository instance. - */ - @Provides - @Singleton - def provideAuthInfoRepository(passwordInfoDAO: DelegableAuthInfoDAO[PasswordInfo]): AuthInfoRepository = { - new DelegableAuthInfoRepository(passwordInfoDAO) - } - - /** - * Provides the authenticator service. - * -// * @param cookieSigner The cookie signer implementation. - * @param crypter The crypter implementation. - * @param idGenerator The ID generator implementation. - * @param clock The clock instance. - * @return The authenticator service. - */ - @Provides - @Singleton - def provideJWTAuthenticatorService( -// cookieSigner: JcaSigner, - crypter: JcaCrypter, - idGenerator: IDGenerator, - clock: Clock - ): JWTAuthenticatorService = { - - val settings = JWTAuthenticatorSettings(fieldName = Config.auth.headerNames.authorizationKey, sharedSecret = Config.crypter.signerKey) - val encoder = new CrypterAuthenticatorEncoder(crypter) - new JWTAuthenticatorService(settings, None, encoder, idGenerator, clock) - } - - /** - * Provides the password hasher registry. - * - * @return The password hasher registry. - */ - @Provides - @Singleton - def providePasswordHasherRegistry(): PasswordHasherRegistry = { - PasswordHasherRegistry(new BCryptSha256PasswordHasher(), Seq(new BCryptPasswordHasher())) - } - - /** - * Provides the credentials provider. - * - * @param authInfoRepository The auth info repository implementation. - * @param passwordHasherRegistry The password hasher registry. - * @return The credentials provider. - */ - @Provides - @Singleton - def provideCredentialsProvider( - authInfoRepository: AuthInfoRepository, - passwordHasherRegistry: PasswordHasherRegistry): CredentialsProvider = { - - new CredentialsProvider(authInfoRepository, passwordHasherRegistry) - } - - @Provides - @Singleton - def provideSecuredActionBuilder( - identityService: IdentityService[CactaceaAccount], - authenticatorService: JWTAuthenticatorService): SecuredActionBuilder[CactaceaAccount, JWTAuthenticator] = { - val securedErrorHandler = new DefaultSecuredErrorHandler() - val securedRequestHandler = new DefaultSecuredRequestHandler(securedErrorHandler) - val securedAction = new DefaultSecuredAction(securedRequestHandler) - securedAction(identityService, authenticatorService, Seq()) - } - -} diff --git a/server/src/main/scala/io/github/cactacea/backend/utils/auth/CactaceaIdentityService.scala b/server/src/main/scala/io/github/cactacea/backend/utils/auth/CactaceaIdentityService.scala deleted file mode 100644 index 0019b352..00000000 --- a/server/src/main/scala/io/github/cactacea/backend/utils/auth/CactaceaIdentityService.scala +++ /dev/null @@ -1,17 +0,0 @@ -package io.github.cactacea.backend.utils.auth - -import com.google.inject.Inject -import com.twitter.util.Future -import io.github.cactacea.backend.core.infrastructure.dao.AccountsDAO -import io.github.cactacea.filhouette.api.LoginInfo -import io.github.cactacea.filhouette.api.services.IdentityService - -class CactaceaIdentityService @Inject()( - accountsDAO: AccountsDAO - ) extends IdentityService[CactaceaAccount] { - - override def retrieve(loginInfo: LoginInfo): Future[Option[CactaceaAccount]] = { - accountsDAO.find(loginInfo.providerId, loginInfo.providerKey).map(_.map(CactaceaAccount(_))) - } - -} diff --git a/server/src/main/scala/io/github/cactacea/backend/utils/auth/CactaceaContext.scala b/server/src/main/scala/io/github/cactacea/backend/utils/context/CactaceaContext.scala similarity index 97% rename from server/src/main/scala/io/github/cactacea/backend/utils/auth/CactaceaContext.scala rename to server/src/main/scala/io/github/cactacea/backend/utils/context/CactaceaContext.scala index 08a0999f..91fa34a6 100644 --- a/server/src/main/scala/io/github/cactacea/backend/utils/auth/CactaceaContext.scala +++ b/server/src/main/scala/io/github/cactacea/backend/utils/context/CactaceaContext.scala @@ -1,4 +1,4 @@ -package io.github.cactacea.backend.utils.auth +package io.github.cactacea.backend.utils.context import java.util.Locale diff --git a/server/src/main/scala/io/github/cactacea/backend/utils/filters/CactaceaAPIKeyFilter.scala b/server/src/main/scala/io/github/cactacea/backend/utils/filters/CactaceaAPIKeyFilter.scala index f030c21a..c732f6c6 100644 --- a/server/src/main/scala/io/github/cactacea/backend/utils/filters/CactaceaAPIKeyFilter.scala +++ b/server/src/main/scala/io/github/cactacea/backend/utils/filters/CactaceaAPIKeyFilter.scala @@ -4,18 +4,30 @@ import com.google.inject.Singleton import com.twitter.finagle.http.{Request, Response} import com.twitter.finagle.{Service, SimpleFilter} import com.twitter.util.Future +import io.github.cactacea.backend.core.domain.enums.DeviceType import io.github.cactacea.backend.core.util.configs.Config -import io.github.cactacea.backend.utils.auth.{CactaceaAPIKeyValidator, CactaceaContext} +import io.github.cactacea.backend.core.util.exceptions.CactaceaException +import io.github.cactacea.backend.core.util.responses.CactaceaErrors.APIKeyIsInValid +import io.github.cactacea.backend.utils.context.CactaceaContext @Singleton class CactaceaAPIKeyFilter extends SimpleFilter[Request, Response] { override def apply(request: Request, service: Service[Request, Response]): Future[Response] = { val apiKey = request.headerMap.get(Config.auth.headerNames.apiKey) - CactaceaAPIKeyValidator.check(apiKey).flatMap({ deviceType => + check(apiKey).flatMap({ deviceType => CactaceaContext.setDeviceType(deviceType) service(request) }) } + def check(apiKey: Option[String]): Future[DeviceType] = { + apiKey.flatMap(key => Config.auth.keys.all.filter({ case (_, k) => k == key}).headOption.map({ case (d, _) => d})) match { + case Some(t) => + Future.value(t) + case None => + Future.exception(CactaceaException(APIKeyIsInValid)) + } + } + } diff --git a/server/src/main/scala/io/github/cactacea/backend/utils/filters/CactaceaAuthenticationFilter.scala b/server/src/main/scala/io/github/cactacea/backend/utils/filters/CactaceaAuthenticationFilter.scala index 259573fd..b6c2218b 100644 --- a/server/src/main/scala/io/github/cactacea/backend/utils/filters/CactaceaAuthenticationFilter.scala +++ b/server/src/main/scala/io/github/cactacea/backend/utils/filters/CactaceaAuthenticationFilter.scala @@ -5,16 +5,17 @@ import com.twitter.finagle.http.{Request, Response} import com.twitter.finagle.{Service, SimpleFilter} import com.twitter.util.Future import io.github.cactacea.backend.core.domain.repositories.AccountsRepository -import io.github.cactacea.backend.utils.auth.{CactaceaAccount, CactaceaContext} +import io.github.cactacea.backend.utils.context.CactaceaContext +import io.github.cactacea.backend.utils.models.User import io.github.cactacea.filhouette.api.actions.{SecuredActionBuilder, SecuredRequest} import io.github.cactacea.filhouette.impl.authenticators.JWTAuthenticator class CactaceaAuthenticationFilter @Inject()(accountsRepository: AccountsRepository, - securedAction: SecuredActionBuilder[CactaceaAccount, JWTAuthenticator] + securedAction: SecuredActionBuilder[User, JWTAuthenticator] ) extends SimpleFilter[Request, Response] { override def apply(request: Request, service: Service[Request, Response]): Future[Response] = { - val block = (securedRequest: SecuredRequest[CactaceaAccount, JWTAuthenticator]) => { + val block = (securedRequest: SecuredRequest[User, JWTAuthenticator]) => { val sessionId = securedRequest.identity.id.toSessionId val expiresIn = securedRequest.authenticator.expirationDateTime.getMillis accountsRepository.find(sessionId, expiresIn).flatMap({ a => diff --git a/server/src/main/scala/io/github/cactacea/backend/utils/filters/CactaceaLocaleFilter.scala b/server/src/main/scala/io/github/cactacea/backend/utils/filters/CactaceaLocaleFilter.scala index 552743e9..e4f04f32 100644 --- a/server/src/main/scala/io/github/cactacea/backend/utils/filters/CactaceaLocaleFilter.scala +++ b/server/src/main/scala/io/github/cactacea/backend/utils/filters/CactaceaLocaleFilter.scala @@ -6,7 +6,7 @@ import com.google.inject.Singleton import com.twitter.finagle.http.{Fields, Request, Response} import com.twitter.finagle.{Service, SimpleFilter} import com.twitter.util.Future -import io.github.cactacea.backend.utils.auth.CactaceaContext +import io.github.cactacea.backend.utils.context.CactaceaContext import scala.collection.JavaConverters._ diff --git a/server/src/main/scala/io/github/cactacea/backend/utils/auth/CactaceaAccount.scala b/server/src/main/scala/io/github/cactacea/backend/utils/models/User.scala similarity index 50% rename from server/src/main/scala/io/github/cactacea/backend/utils/auth/CactaceaAccount.scala rename to server/src/main/scala/io/github/cactacea/backend/utils/models/User.scala index 0c5e6a22..89fef417 100644 --- a/server/src/main/scala/io/github/cactacea/backend/utils/auth/CactaceaAccount.scala +++ b/server/src/main/scala/io/github/cactacea/backend/utils/models/User.scala @@ -1,15 +1,15 @@ -package io.github.cactacea.backend.utils.auth +package io.github.cactacea.backend.utils.models import io.github.cactacea.backend.core.infrastructure.identifiers.AccountId import io.github.cactacea.backend.core.infrastructure.models.Accounts import io.github.cactacea.filhouette.api.Identity -case class CactaceaAccount(id: AccountId) extends Identity +case class User(id: AccountId) extends Identity -object CactaceaAccount { +object User { - def apply(a: Accounts): CactaceaAccount = { - CactaceaAccount(a.id) + def apply(a: Accounts): User = { + User(a.id) } } diff --git a/server/src/main/scala/io/github/cactacea/backend/utils/modules/AuthenticationModule.scala b/server/src/main/scala/io/github/cactacea/backend/utils/modules/AuthenticationModule.scala new file mode 100644 index 00000000..dd57f421 --- /dev/null +++ b/server/src/main/scala/io/github/cactacea/backend/utils/modules/AuthenticationModule.scala @@ -0,0 +1,235 @@ +package io.github.cactacea.backend.utils.modules + +import com.google.inject.{Provides, Singleton} +import com.twitter.inject.TwitterModule +import io.github.cactacea.backend.core.util.configs.Config +import io.github.cactacea.backend.utils.models.User +import io.github.cactacea.backend.utils.repositories.{OAuth2Repository, PasswordsRepository} +import io.github.cactacea.backend.utils.services.UserService +import io.github.cactacea.filhouette.api.actions._ +import io.github.cactacea.filhouette.api.crypto.CrypterAuthenticatorEncoder +import io.github.cactacea.filhouette.api.repositories.AuthInfoRepository +import io.github.cactacea.filhouette.api.services.IdentityService +import io.github.cactacea.filhouette.api.util._ +import io.github.cactacea.filhouette.impl.authenticators._ +import io.github.cactacea.filhouette.impl.crypto.{JcaCrypter, JcaCrypterSettings, JcaSigner, JcaSignerSettings} +import io.github.cactacea.filhouette.impl.providers._ +import io.github.cactacea.filhouette.impl.providers.oauth2.FacebookProvider +import io.github.cactacea.filhouette.impl.providers.state.{CsrfStateItemHandler, CsrfStateSettings} +import io.github.cactacea.filhouette.impl.util.{DefaultFingerprintGenerator, SecureRandomIDGenerator} +import io.github.cactacea.filhouette.password.{BCryptPasswordHasher, BCryptSha256PasswordHasher} +import io.github.cactacea.filhouette.persistence.daos.DelegableAuthInfoDAO +import io.github.cactacea.filhouette.persistence.repositories.DelegableAuthInfoRepository + +object AuthenticationModule extends TwitterModule { + + /** + * Configures the module. + */ + override def configure(): Unit = { + bind[IDGenerator].toInstance(new SecureRandomIDGenerator()) + bind[FingerprintGenerator].toInstance(new DefaultFingerprintGenerator(false)) + bind[Clock].toInstance(Clock()) + bindSingleton[IdentityService[User]].to[UserService] + bindSingleton[DelegableAuthInfoDAO[PasswordInfo]].to[PasswordsRepository] + bindSingleton[DelegableAuthInfoDAO[OAuth2Info]].to[OAuth2Repository] + } + + /** + * Provides the crypter for the authenticator. + * + * @return The crypter for the authenticator. + */ + @Provides + @Singleton + def provideAuthenticatorCrypter(): JcaCrypter = { + new JcaCrypter(JcaCrypterSettings(Config.crypter.crypterKey)) + } + + /** + * Provides the signer for the authenticator. + * + * @return The signer for the authenticator. + */ + @Provides + def provideAuthenticatorSigner(): JcaSigner = { + new JcaSigner(JcaSignerSettings(Config.crypter.signerKey)) + } + + /** + * Provides the auth info repository. + * + * @param passwordInfoDAO The implementation of the delegable password auth info DAO. + * @return The auth info repository instance. + */ + @Provides + @Singleton + def provideAuthInfoRepository(passwordInfoDAO: DelegableAuthInfoDAO[PasswordInfo], oauth2InfoDAO: DelegableAuthInfoDAO[OAuth2Info]): AuthInfoRepository = { + new DelegableAuthInfoRepository(passwordInfoDAO, oauth2InfoDAO) + } + + /** + * Provides the authenticator service. + * + * @param crypter The crypter implementation. + * @param idGenerator The ID generator implementation. + * @param clock The clock instance. + * @return The authenticator service. + */ + @Provides + @Singleton + def provideJWTAuthenticatorService( + crypter: JcaCrypter, + idGenerator: IDGenerator, + clock: Clock + ): JWTAuthenticatorService = { + + val settings = JWTAuthenticatorSettings(fieldName = Config.auth.headerNames.authorizationKey, sharedSecret = Config.crypter.signerKey) + val encoder = new CrypterAuthenticatorEncoder(crypter) + new JWTAuthenticatorService(settings, None, encoder, idGenerator, clock) + } + + /** + * Provides the password hasher registry. + * + * @return The password hasher registry. + */ + @Provides + @Singleton + def providePasswordHasherRegistry(): PasswordHasherRegistry = { + PasswordHasherRegistry(new BCryptSha256PasswordHasher(), Seq(new BCryptPasswordHasher())) + } + + /** + * Provides the credentials provider. + * + * @param authInfoRepository The auth info repository implementation. + * @param passwordHasherRegistry The password hasher registry. + * @return The credentials provider. + */ + @Provides + @Singleton + def provideCredentialsProvider( + authInfoRepository: AuthInfoRepository, + passwordHasherRegistry: PasswordHasherRegistry): CredentialsProvider = { + + new CredentialsProvider(authInfoRepository, passwordHasherRegistry) + } + + @Provides + @Singleton + def provideSecuredActionBuilder( + identityService: IdentityService[User], + authenticatorService: JWTAuthenticatorService): SecuredActionBuilder[User, JWTAuthenticator] = { + val securedErrorHandler = new DefaultSecuredErrorHandler() + val securedRequestHandler = new DefaultSecuredRequestHandler(securedErrorHandler) + val securedAction = new DefaultSecuredAction(securedRequestHandler) + securedAction(identityService, authenticatorService, Seq()) + } + + + + + /** + * Provides the CSRF state item handler. + * + * @param idGenerator The ID generator implementation. + * @param signer The signer implementation. + * @return The CSRF state item implementation. + */ + @Provides + def provideCsrfStateItemHandler(idGenerator: IDGenerator, signer: JcaSigner): CsrfStateItemHandler = { + val settings = CsrfStateSettings() + new CsrfStateItemHandler(settings, idGenerator, signer) + } + + /** + * Provides the social state handler. + * + * @param signer The signer implementation. + * @return The social state handler implementation. + */ + @Provides + def provideSocialStateHandler( + signer: JcaSigner, + csrfStateItemHandler: CsrfStateItemHandler): SocialStateHandler = { + + new DefaultSocialStateHandler(Set(csrfStateItemHandler), signer) + } + + /** + * Provides the Facebook provider. + * + * @param socialStateHandler The social state handler implementation. + * @return The Facebook provider. + */ + @Provides + def provideFacebookProvider(socialStateHandler: SocialStateHandler): FacebookProvider = { + + val settings = OAuth2Settings( + authorizationURL = Config.facebook.authorizationURL, + accessTokenURL = Config.facebook.accessTokenURL, + redirectURL = Config.facebook.redirectURL, + clientID = Config.facebook.clientID, + clientSecret = Config.facebook.clientSecret, + scope = Config.facebook.scope + ) + + new FacebookProvider(socialStateHandler, settings) + } + + + /** + * Provides the social provider registry. + * + * @return The SocialProviderRegistry + */ + @Provides + def provideSocialProviderRegistry(facebookProvider: FacebookProvider): SocialProviderRegistry = { + SocialProviderRegistry(Seq(facebookProvider)) + } + + + + + // /** + // * Provides the OAuth1 token secret provider. + // * + // * @param signer The signer implementation. + // * @param crypter The crypter implementation. + // * @param configuration The Play configuration. + // * @param clock The clock instance. + // * @return The OAuth1 token secret provider implementation. + // */ + // @Provides + // def provideOAuth1TokenSecretProvider( + // @Named("oauth1-token-secret-signer") signer: Signer, + // @Named("oauth1-token-secret-crypter") crypter: Crypter, + // configuration: Configuration, + // clock: Clock): OAuth1TokenSecretProvider = { + // + // val settings = configuration.underlying.as[CookieSecretSettings]("silhouette.oauth1TokenSecretProvider") + // new CookieSecretProvider(settings, signer, crypter, clock) + // } + + // /** + // * Provides the Twitter provider. + // * + // * @param httpLayer The HTTP layer implementation. + // * @param tokenSecretProvider The token secret provider implementation. + // * @param configuration The Play configuration. + // * @return The Twitter provider. + // */ + // @Provides + // def provideTwitterProvider( + // httpLayer: HTTPLayer, + // tokenSecretProvider: OAuth1TokenSecretProvider, + // configuration: Configuration): TwitterProvider = { + // + // val settings = configuration.underlying.as[OAuth1Settings]("silhouette.twitter") + // new TwitterProvider(, new PlayOAuth1Service(settings), tokenSecretProvider, settings) + // } + + + +} diff --git a/server/src/main/scala/io/github/cactacea/backend/utils/repositories/OAuth2Repository.scala b/server/src/main/scala/io/github/cactacea/backend/utils/repositories/OAuth2Repository.scala new file mode 100644 index 00000000..6adce8c9 --- /dev/null +++ b/server/src/main/scala/io/github/cactacea/backend/utils/repositories/OAuth2Repository.scala @@ -0,0 +1,42 @@ +package io.github.cactacea.backend.utils.repositories + +import com.google.inject.Inject +import com.twitter.util.Future +import io.github.cactacea.backend.core.infrastructure.dao.AuthenticationsDAO +import io.github.cactacea.filhouette.api.LoginInfo +import io.github.cactacea.filhouette.impl.providers.OAuth2Info +import io.github.cactacea.filhouette.persistence.daos.DelegableAuthInfoDAO + +class OAuth2Repository @Inject()(authenticationsDAO: AuthenticationsDAO) + extends DelegableAuthInfoDAO[OAuth2Info] { + + override def add(loginInfo: LoginInfo, authInfo: OAuth2Info): Future[OAuth2Info] = { + authenticationsDAO.create(loginInfo.providerId, loginInfo.providerKey, authInfo.accessToken, "").map(_ => authInfo) + } + + override def find(loginInfo: LoginInfo): Future[Option[OAuth2Info]] = { + authenticationsDAO.find(loginInfo.providerId, loginInfo.providerKey).map(_ match { + case Some(a) if (a.confirm) => + Some(OAuth2Info(a.password)) + case _ => None + }) + } + + override def remove(loginInfo: LoginInfo): Future[Unit] = { + authenticationsDAO.delete(loginInfo.providerId, loginInfo.providerKey) + } + + override def update(loginInfo: LoginInfo, authInfo: OAuth2Info): Future[OAuth2Info] = { + authenticationsDAO.update(loginInfo.providerId, loginInfo.providerKey, authInfo.accessToken, "").map(_ => authInfo) + } + + override def save(loginInfo: LoginInfo, authInfo: OAuth2Info): Future[OAuth2Info] = { + authenticationsDAO.find(loginInfo.providerId, loginInfo.providerKey).flatMap(_ match { + case Some(_) => + update(loginInfo, authInfo) + case None => + add(loginInfo, authInfo) + }) + } + +} diff --git a/server/src/main/scala/io/github/cactacea/backend/utils/auth/CactaceaAuthenticationsRepository.scala b/server/src/main/scala/io/github/cactacea/backend/utils/repositories/PasswordsRepository.scala similarity index 83% rename from server/src/main/scala/io/github/cactacea/backend/utils/auth/CactaceaAuthenticationsRepository.scala rename to server/src/main/scala/io/github/cactacea/backend/utils/repositories/PasswordsRepository.scala index d850615e..2463a8db 100644 --- a/server/src/main/scala/io/github/cactacea/backend/utils/auth/CactaceaAuthenticationsRepository.scala +++ b/server/src/main/scala/io/github/cactacea/backend/utils/repositories/PasswordsRepository.scala @@ -1,4 +1,4 @@ -package io.github.cactacea.backend.utils.auth +package io.github.cactacea.backend.utils.repositories import com.google.inject.Inject import com.twitter.util.Future @@ -7,15 +7,11 @@ import io.github.cactacea.filhouette.api.LoginInfo import io.github.cactacea.filhouette.api.util.PasswordInfo import io.github.cactacea.filhouette.persistence.daos.DelegableAuthInfoDAO -class CactaceaAuthenticationsRepository @Inject()(authenticationsDAO: AuthenticationsDAO) +class PasswordsRepository @Inject()(authenticationsDAO: AuthenticationsDAO) extends DelegableAuthInfoDAO[PasswordInfo] { override def add(loginInfo: LoginInfo, authInfo: PasswordInfo): Future[PasswordInfo] = { - authenticationsDAO.create( - loginInfo.providerId, - loginInfo.providerKey, - authInfo.password, - authInfo.hasher).map(_ => authInfo) + authenticationsDAO.create(loginInfo.providerId, loginInfo.providerKey, authInfo.password, authInfo.hasher).map(_ => authInfo) } override def find(loginInfo: LoginInfo): Future[Option[PasswordInfo]] = { diff --git a/server/src/main/scala/io/github/cactacea/backend/utils/auth/SessionsService.scala b/server/src/main/scala/io/github/cactacea/backend/utils/services/AuthenticationsService.scala similarity index 68% rename from server/src/main/scala/io/github/cactacea/backend/utils/auth/SessionsService.scala rename to server/src/main/scala/io/github/cactacea/backend/utils/services/AuthenticationsService.scala index 9e0b29b8..0f143edd 100644 --- a/server/src/main/scala/io/github/cactacea/backend/utils/auth/SessionsService.scala +++ b/server/src/main/scala/io/github/cactacea/backend/utils/services/AuthenticationsService.scala @@ -1,4 +1,4 @@ -package io.github.cactacea.backend.utils.auth +package io.github.cactacea.backend.utils.services import com.google.inject.{Inject, Singleton} import com.twitter.finagle.http.{Request, Response} @@ -7,8 +7,7 @@ import com.twitter.util.Future import io.github.cactacea.backend.core.application.components.interfaces.ListenerService import io.github.cactacea.backend.core.application.components.services.DatabaseService import io.github.cactacea.backend.core.domain.enums.DeviceType -import io.github.cactacea.backend.core.domain.repositories.AccountsRepository -import io.github.cactacea.backend.core.infrastructure.dao.AuthenticationsDAO +import io.github.cactacea.backend.core.domain.repositories.{AccountsRepository, DevicesRepository} import io.github.cactacea.backend.core.infrastructure.identifiers.SessionId import io.github.cactacea.backend.core.infrastructure.validators.AccountsValidator import io.github.cactacea.filhouette.api.LoginInfo @@ -18,17 +17,17 @@ import io.github.cactacea.filhouette.impl.authenticators.JWTAuthenticatorService import io.github.cactacea.filhouette.impl.providers.CredentialsProvider @Singleton -class SessionsService @Inject()( - db: DatabaseService, - response: ResponseBuilder, - accountsValidator: AccountsValidator, - accountsRepository: AccountsRepository, - authInfoRepository: AuthInfoRepository, - authenticationsDAO: AuthenticationsDAO, - credentialsProvider: CredentialsProvider, - passwordHasherRegistry: PasswordHasherRegistry, - authenticatorService: JWTAuthenticatorService, - listenerService: ListenerService +class AuthenticationsService @Inject()( + db: DatabaseService, + response: ResponseBuilder, + accountsValidator: AccountsValidator, + accountsRepository: AccountsRepository, + authInfoRepository: AuthInfoRepository, + credentialsProvider: CredentialsProvider, + devicesRepository: DevicesRepository, + passwordHasherRegistry: PasswordHasherRegistry, + authenticatorService: JWTAuthenticatorService, + listenerService: ListenerService ) { import db._ @@ -40,13 +39,13 @@ class SessionsService @Inject()( deviceType: DeviceType)(implicit request: Request): Future[Response] = { val l = LoginInfo(CredentialsProvider.ID, accountName) - for { (r, a) <- transaction { for { - a <- accountsRepository.create(accountName, udid, deviceType, userAgent) + a <- accountsRepository.create(accountName) _ <- authInfoRepository.add(l, passwordHasherRegistry.current.hash(password)) - _ <- authenticationsDAO.updateAccountId(CredentialsProvider.ID, accountName, a.id) + _ <- accountsRepository.link(l.providerId, l.providerKey, a.id) + _ <- devicesRepository.save(l.providerId, l.providerKey, udid, deviceType, userAgent) s <- authenticatorService.create(l) c <- authenticatorService.init(s) r <- authenticatorService.embed(c, response.ok(a)) @@ -68,7 +67,8 @@ class SessionsService @Inject()( (r, a) <- transaction { for { l <- credentialsProvider.authenticate(Credentials(accountName, password)) - a <- accountsRepository.find(accountName, udid, deviceType, userAgent) + d <- devicesRepository.save(l.providerId, l.providerKey, udid, deviceType, userAgent) + a <- accountsRepository.find(d.toSessionId) s <- authenticatorService.create(l) c <- authenticatorService.init(s) r <- authenticatorService.embed(c, response.ok(a)) diff --git a/server/src/main/scala/io/github/cactacea/backend/utils/services/SocialAuthenticationsService.scala b/server/src/main/scala/io/github/cactacea/backend/utils/services/SocialAuthenticationsService.scala new file mode 100644 index 00000000..e26e8b39 --- /dev/null +++ b/server/src/main/scala/io/github/cactacea/backend/utils/services/SocialAuthenticationsService.scala @@ -0,0 +1,53 @@ +package io.github.cactacea.backend.utils.services + +import com.google.inject.{Inject, Singleton} +import com.twitter.finagle.http.{Request, Response} +import com.twitter.finatra.http.response.ResponseBuilder +import com.twitter.util.Future +import io.github.cactacea.backend.core.application.components.interfaces.ListenerService +import io.github.cactacea.backend.core.application.components.services.DatabaseService +import io.github.cactacea.backend.core.domain.enums.DeviceType +import io.github.cactacea.backend.core.domain.repositories.{AccountsRepository, DevicesRepository} +import io.github.cactacea.filhouette.api.exceptions.ProviderException +import io.github.cactacea.filhouette.api.repositories.AuthInfoRepository +import io.github.cactacea.filhouette.impl.authenticators.JWTAuthenticatorService +import io.github.cactacea.filhouette.impl.providers.{CommonSocialProfileBuilder, SocialProvider, SocialProviderRegistry} + +@Singleton +class SocialAuthenticationsService @Inject()( + db: DatabaseService, + response: ResponseBuilder, + accountsRepository: AccountsRepository, + authInfoRepository: AuthInfoRepository, + devicesRepository: DevicesRepository, + authenticatorService: JWTAuthenticatorService, + socialProviderRegistry: SocialProviderRegistry, + listenerService: ListenerService + ) { + + def signIn(provider: String, + accountName: String, + udid: String, + userAgent: Option[String], + deviceType: DeviceType)(implicit request: Request): Future[Response] = { + + (socialProviderRegistry.get[SocialProvider](provider) match { + case Some(p: SocialProvider with CommonSocialProfileBuilder) => + p.authenticate().flatMap { + case Left(result) => Future.value(result) + case Right(authInfo) => for { + profile <- p.retrieveProfile(authInfo) + a <- accountsRepository.save(profile.loginInfo.providerId, profile.loginInfo.providerKey, accountName, profile.fullName) + _ <- authInfoRepository.save(profile.loginInfo, authInfo) + _ <- accountsRepository.link(profile.loginInfo.providerId, profile.loginInfo.providerKey, a.id) + _ <- devicesRepository.save(profile.loginInfo.providerId, profile.loginInfo.providerKey, udid, deviceType, userAgent) + s <- authenticatorService.create(profile.loginInfo) + c <- authenticatorService.init(s) + r <- authenticatorService.embed(c, response.ok(a)) + } yield (r) + } + case _ => Future.exception(new ProviderException(s"Cannot authenticate with unexpected social provider $provider")) + }) + } + +} diff --git a/server/src/main/scala/io/github/cactacea/backend/utils/services/UserService.scala b/server/src/main/scala/io/github/cactacea/backend/utils/services/UserService.scala new file mode 100644 index 00000000..da255837 --- /dev/null +++ b/server/src/main/scala/io/github/cactacea/backend/utils/services/UserService.scala @@ -0,0 +1,19 @@ +package io.github.cactacea.backend.utils.services + +import com.google.inject.Inject +import com.twitter.util.Future +import io.github.cactacea.backend.core.infrastructure.dao.{AccountsDAO, AuthenticationsDAO} +import io.github.cactacea.backend.utils.models.User +import io.github.cactacea.filhouette.api.LoginInfo +import io.github.cactacea.filhouette.api.services.IdentityService + +class UserService @Inject()( + accountsDAO: AccountsDAO, + authenticationsDAO: AuthenticationsDAO + ) extends IdentityService[User] { + + override def retrieve(loginInfo: LoginInfo): Future[Option[User]] = { + accountsDAO.find(loginInfo.providerId, loginInfo.providerKey).map(_.map(User(_))) + } + +} diff --git a/server/src/main/scala/io/github/cactacea/backend/utils/validaters/CactaceaValidations.scala b/server/src/main/scala/io/github/cactacea/backend/utils/validators/CactaceaValidations.scala similarity index 96% rename from server/src/main/scala/io/github/cactacea/backend/utils/validaters/CactaceaValidations.scala rename to server/src/main/scala/io/github/cactacea/backend/utils/validators/CactaceaValidations.scala index ab330630..617a958e 100644 --- a/server/src/main/scala/io/github/cactacea/backend/utils/validaters/CactaceaValidations.scala +++ b/server/src/main/scala/io/github/cactacea/backend/utils/validators/CactaceaValidations.scala @@ -1,4 +1,4 @@ -package io.github.cactacea.backend.utils.validaters +package io.github.cactacea.backend.utils.validators import com.twitter.finatra.validation.ValidationResult diff --git a/server/src/test/scala/io/github/cactacea/backend/CactaceaServerSpec.scala b/server/src/test/scala/io/github/cactacea/backend/CactaceaServerSpec.scala index f650611f..5e25bee4 100644 --- a/server/src/test/scala/io/github/cactacea/backend/CactaceaServerSpec.scala +++ b/server/src/test/scala/io/github/cactacea/backend/CactaceaServerSpec.scala @@ -6,7 +6,7 @@ import com.twitter.finatra.json.FinatraObjectMapper import com.twitter.inject.app.TestInjector import com.twitter.inject.server.FeatureTest import io.github.cactacea.backend.core.application.components.modules._ -import io.github.cactacea.backend.utils.auth.CactaceaAuthModule +import io.github.cactacea.backend.utils.modules.AuthenticationModule @Singleton class CactaceaServerSpec extends FeatureTest @@ -30,7 +30,7 @@ class CactaceaServerSpec extends FeatureTest override val server = new EmbeddedHttpServer( twitterServer = new CactaceaServer { - addFrameworkModule(CactaceaAuthModule) + addFrameworkModule(AuthenticationModule) } ) @@ -39,7 +39,7 @@ class CactaceaServerSpec extends FeatureTest TestInjector( modules = Seq( DatabaseModule, - CactaceaAuthModule, + AuthenticationModule, DefaultChatModule, DefaultDeepLinkModule, DefaultJacksonModule,