Skip to content

Commit

Permalink
feat: login with Google, Facebook, Microsoft (openedx#89)
Browse files Browse the repository at this point in the history
* feat: login with Google, Facebook, Microsoft

* fix: crash on social login

* refactor: moved auth helpers out of singletons

* fix: generateMockedRawFile task running from direct task run only

* refactor: applied new configuration management

* feat: login with Google, Facebook, Microsoft

* refactor: changes in colors and variables renaming

* refactor: configuration updates

* fix: updated SignInViewModelTest
  • Loading branch information
k1rill authored Dec 11, 2023
1 parent db65070 commit 73ed462
Show file tree
Hide file tree
Showing 41 changed files with 1,387 additions and 557 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/unit_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ jobs:
uses: gradle/[email protected]
with:
cache-read-only: ${{ github.ref != 'refs/heads/develop' }}

- name: Generate mock files
run: ./gradlew generateMockedRawFile
- name: Run unit tests
run: ./gradlew testProdReleaseUnitTest $CI_GRADLE_ARG_PROPERTIES

Expand Down
5 changes: 4 additions & 1 deletion app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,14 @@ plugins {
id 'com.google.firebase.crashlytics'
}

def config = configHelper.fetchConfig()
def appId = config.getOrDefault("APPLICATION_ID", "org.openedx.app")

android {
compileSdk 34

defaultConfig {
applicationId "org.openedx.app"
applicationId appId
minSdk 24
targetSdk 34
versionCode 1
Expand Down
9 changes: 8 additions & 1 deletion app/src/main/java/org/openedx/app/di/AppModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ import org.openedx.app.room.DATABASE_NAME
import org.openedx.app.system.notifier.AppNotifier
import org.openedx.auth.presentation.AuthAnalytics
import org.openedx.auth.presentation.AuthRouter
import org.openedx.auth.presentation.sso.FacebookAuthHelper
import org.openedx.auth.presentation.sso.GoogleAuthHelper
import org.openedx.auth.presentation.sso.MicrosoftAuthHelper
import org.openedx.core.config.Config
import org.openedx.core.data.storage.CorePreferences
import org.openedx.core.data.storage.InAppReviewPreferences
Expand Down Expand Up @@ -154,4 +157,8 @@ val appModule = module {
single<ProfileAnalytics> { get<AnalyticsManager>() }
single<CourseAnalytics> { get<AnalyticsManager>() }
single<DiscussionAnalytics> { get<AnalyticsManager>() }
}

factory { FacebookAuthHelper() }
factory { GoogleAuthHelper(get()) }
factory { MicrosoftAuthHelper() }
}
17 changes: 15 additions & 2 deletions app/src/main/java/org/openedx/app/di/ScreenModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,20 @@ val screenModule = module {
factory { AuthRepository(get(), get(), get()) }
factory { AuthInteractor(get()) }
factory { Validator() }
viewModel { SignInViewModel(get(), get(), get(), get(), get(), get(), get()) }
viewModel {
SignInViewModel(
get(),
get(),
get(),
get(),
get(),
get(),
get(),
get(),
get(),
get()
)
}
viewModel { SignUpViewModel(get(), get(), get(), get(), get()) }
viewModel { RestorePasswordViewModel(get(), get(), get(), get()) }

Expand Down Expand Up @@ -223,4 +236,4 @@ val screenModule = module {
}

viewModel { WhatsNewViewModel(get()) }
}
}
9 changes: 7 additions & 2 deletions auth/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,12 @@ android {
dependencies {
implementation project(path: ':core')

implementation "androidx.credentials:credentials:1.2.0"
implementation "androidx.credentials:credentials-play-services-auth:1.2.0"
implementation "com.facebook.android:facebook-login:16.2.0"
implementation "com.google.android.gms:play-services-auth:20.7.0"
implementation "com.google.android.libraries.identity.googleid:googleid:1.1.0"
implementation 'com.microsoft.identity.client:msal:4.9.0'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_version"
Expand All @@ -64,5 +70,4 @@ dependencies {
testImplementation "io.mockk:mockk-android:$mockk_version"
testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutines_version"
testImplementation "androidx.arch.core:core-testing:$android_arch_version"

}
}
7 changes: 6 additions & 1 deletion auth/proguard-rules.pro
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,9 @@

# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
#-renamesourcefileattribute SourceFile

-if class androidx.credentials.CredentialManager
-keep class androidx.credentials.playservices.** {
*;
}
10 changes: 10 additions & 0 deletions auth/src/main/java/org/openedx/auth/data/api/AuthApi.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,16 @@ import retrofit2.http.*

interface AuthApi {

@FormUrlEncoded
@POST(ApiConstants.URL_EXCHANGE_TOKEN)
suspend fun exchangeAccessToken(
@Field("access_token") accessToken: String,
@Field("client_id") clientId: String,
@Field("token_type") tokenType: String,
@Field("asymmetric_jwt") isAsymmetricJwt: Boolean = true,
@Path("auth_type") authType: String,
): AuthResponse

@FormUrlEncoded
@POST(ApiConstants.URL_ACCESS_TOKEN)
suspend fun getAccessToken(
Expand Down
16 changes: 16 additions & 0 deletions auth/src/main/java/org/openedx/auth/data/model/AuthType.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package org.openedx.auth.data.model

import org.openedx.core.ApiConstants

/**
* Enum class with types of supported auth types
*
* @param postfix postfix to add to the API call
* @param methodName name of the login type
*/
enum class AuthType(val postfix: String, val methodName: String) {
PASSWORD("", "Password"),
GOOGLE(ApiConstants.AUTH_TYPE_GOOGLE, "Google"),
FACEBOOK(ApiConstants.AUTH_TYPE_FB, "Facebook"),
MICROSOFT(ApiConstants.AUTH_TYPE_MICROSOFT, "Microsoft"),
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.openedx.auth.data.repository

import org.openedx.auth.data.api.AuthApi
import org.openedx.auth.data.model.AuthType
import org.openedx.auth.data.model.ValidationFields
import org.openedx.auth.domain.model.AuthResponse
import org.openedx.core.ApiConstants
Expand All @@ -19,21 +20,27 @@ class AuthRepository(
username: String,
password: String,
) {
val authResponse: AuthResponse = api.getAccessToken(
api.getAccessToken(
ApiConstants.GRANT_TYPE_PASSWORD,
config.getOAuthClientId(),
username,
password,
config.getAccessTokenType(),
).mapToDomain()
if (authResponse.error != null) {
throw EdxError.UnknownException(authResponse.error!!)
}
preferencesManager.accessToken = authResponse.accessToken ?: ""
preferencesManager.refreshToken = authResponse.refreshToken ?: ""
preferencesManager.accessTokenExpiresAt = authResponse.getTokenExpiryTime()
val user = api.getProfile()
preferencesManager.user = user
)
.mapToDomain()
.processAuthResponse()
}

suspend fun socialLogin(token: String?, authType: AuthType) {
if (token.isNullOrBlank()) throw IllegalArgumentException("Token is null")
api.exchangeAccessToken(
accessToken = token,
clientId = config.getOAuthClientId(),
tokenType = config.getAccessTokenType(),
authType = authType.postfix
)
.mapToDomain()
.processAuthResponse()
}

suspend fun getRegistrationFields(): List<RegistrationField> {
Expand All @@ -51,4 +58,15 @@ class AuthRepository(
suspend fun passwordReset(email: String): Boolean {
return api.passwordReset(email).success
}

private suspend fun AuthResponse.processAuthResponse() {
if (error != null) {
throw EdxError.UnknownException(error!!)
}
preferencesManager.accessToken = accessToken ?: ""
preferencesManager.refreshToken = refreshToken ?: ""
preferencesManager.accessTokenExpiresAt = getTokenExpiryTime()
val user = api.getProfile()
preferencesManager.user = user
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.openedx.auth.domain.interactor

import org.openedx.auth.data.model.AuthType
import org.openedx.auth.data.model.ValidationFields
import org.openedx.auth.data.repository.AuthRepository
import org.openedx.core.domain.model.RegistrationField
Expand All @@ -13,6 +14,10 @@ class AuthInteractor(private val repository: AuthRepository) {
repository.login(username, password)
}

suspend fun loginSocial(token: String?, authType: AuthType) {
repository.socialLogin(token, authType)
}

suspend fun getRegistrationFields(): List<RegistrationField> {
return repository.getRegistrationFields()
}
Expand Down
Loading

0 comments on commit 73ed462

Please sign in to comment.