Skip to content

Commit

Permalink
fixup!: review feedback
Browse files Browse the repository at this point in the history
  • Loading branch information
xitij2000 committed Nov 28, 2024
1 parent 92cb74e commit 65b9c39
Show file tree
Hide file tree
Showing 13 changed files with 82 additions and 63 deletions.
16 changes: 9 additions & 7 deletions app/src/main/java/org/openedx/app/AppActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import org.openedx.app.databinding.ActivityAppBinding
import org.openedx.app.deeplink.DeepLink
import org.openedx.auth.presentation.logistration.LogistrationFragment
import org.openedx.auth.presentation.signin.SignInFragment
import org.openedx.core.ApiConstants
import org.openedx.core.data.storage.CorePreferences
import org.openedx.core.presentation.global.InsetHolder
import org.openedx.core.presentation.global.WindowSizeHolder
Expand Down Expand Up @@ -68,8 +69,8 @@ class AppActivity : AppCompatActivity(), InsetHolder, WindowSizeHolder {
private val authCode: String?
get() {
val data = intent?.data
if (data is Uri && data.scheme == BuildConfig.APPLICATION_ID && data.host == "oauth2Callback") {
return data.getQueryParameter("code")
if (data is Uri && data.scheme == BuildConfig.APPLICATION_ID && data.host == ApiConstants.BrowserLogin.REDIRECT_HOST) {
return data.getQueryParameter(ApiConstants.BrowserLogin.CODE_QUERY_PARAM)
}
return null
}
Expand Down Expand Up @@ -151,14 +152,11 @@ class AppActivity : AppCompatActivity(), InsetHolder, WindowSizeHolder {
when {
corePreferencesManager.user == null -> {
val authCode = authCode;

if (viewModel.isLogistrationEnabled && authCode == null) {
addFragment(LogistrationFragment())
} else {
val bundle = Bundle()
bundle.putString("auth_code", authCode)
val fragment = SignInFragment()
fragment.arguments = bundle
addFragment(fragment)
addFragment(SignInFragment.newInstance(null, null, authCode = authCode))
}
}

Expand Down Expand Up @@ -208,6 +206,10 @@ class AppActivity : AppCompatActivity(), InsetHolder, WindowSizeHolder {
super.onNewIntent(intent)
this.intent = intent

if (authCode != null) {
addFragment(SignInFragment.newInstance(null, null, authCode = authCode))
}

val extras = intent?.extras
if (extras?.containsKey(DeepLink.Keys.NOTIFICATION_TYPE.value) == true) {
handlePushNotification(extras)
Expand Down
3 changes: 2 additions & 1 deletion app/src/main/java/org/openedx/app/di/ScreenModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ val screenModule = module {
)
}

viewModel { (courseId: String?, infoType: String?) ->
viewModel { (courseId: String?, infoType: String?, authCode:String) ->
SignInViewModel(
get(),
get(),
Expand All @@ -122,6 +122,7 @@ val screenModule = module {
get(),
courseId,
infoType,
authCode,
)
}

Expand Down
4 changes: 3 additions & 1 deletion auth/src/main/java/org/openedx/auth/data/api/AuthApi.kt
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@ interface AuthApi {
@Field("grant_type") grantType: String,
@Field("client_id") clientId: String,
@Field("code") code: String,
@Field("redirect_uri") redirectUri: String
@Field("redirect_uri") redirectUri: String,
@Field("token_type") tokenType: String,
@Field("asymmetric_jwt") isAsymmetricJwt: Boolean = true,
): AuthResponse

@FormUrlEncoded
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ class AuthRepository(
grantType = ApiConstants.GRANT_TYPE_CODE,
clientId = config.getOAuthClientId(),
code = code,
redirectUri = "${config.getApplicationID()}://oauth2Callback"
redirectUri = "${config.getAppId()}://${ApiConstants.BrowserLogin.REDIRECT_HOST}",
tokenType = config.getAccessTokenType(),
).mapToDomain().processAuthResponse()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import androidx.fragment.app.Fragment
import org.koin.androidx.viewmodel.ext.android.viewModel
import org.koin.core.parameter.parametersOf
import org.openedx.auth.R
import org.openedx.core.ApiConstants
import org.openedx.core.ui.AuthButtonsPanel
import org.openedx.core.ui.SearchBar
import org.openedx.core.ui.displayCutoutForLandscape
Expand Down Expand Up @@ -80,7 +81,7 @@ class LogistrationFragment : Fragment() {
UrlUtils.openInBrowser(
activity = context,
apiHostUrl = viewModel.apiHostUrl,
url = "/register",
url = ApiConstants.URL_REGISTER_BROWSER,
)
} else {
viewModel.navigateToSignUp(parentFragmentManager)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ class SignInFragment : Fragment() {
private val viewModel: SignInViewModel by viewModel {
parametersOf(
requireArguments().getString(ARG_COURSE_ID, ""),
requireArguments().getString(ARG_INFO_TYPE, "")
requireArguments().getString(ARG_INFO_TYPE, ""),
requireArguments().getString(ARG_AUTH_CODE, ""),
)
}

Expand All @@ -43,10 +44,8 @@ class SignInFragment : Fragment() {
val appUpgradeEvent by viewModel.appUpgradeEvent.observeAsState(null)

if (appUpgradeEvent == null) {
val authCode = arguments?.getString("auth_code")
if (authCode is String && !state.loginFailure && !state.loginSuccess) {
arguments?.remove("auth_code")
viewModel.signInAuthCode(authCode)
if (viewModel.authCode != "" && !state.loginFailure && !state.loginSuccess) {
viewModel.signInAuthCode(viewModel.authCode)
}
LoginScreen(
windowSize = windowSize,
Expand Down Expand Up @@ -101,11 +100,13 @@ class SignInFragment : Fragment() {
companion object {
private const val ARG_COURSE_ID = "courseId"
private const val ARG_INFO_TYPE = "info_type"
fun newInstance(courseId: String?, infoType: String?): SignInFragment {
private const val ARG_AUTH_CODE = "auth_code"
fun newInstance(courseId: String?, infoType: String?, authCode: String? = null): SignInFragment {
val fragment = SignInFragment()
fragment.arguments = bundleOf(
ARG_COURSE_ID to courseId,
ARG_INFO_TYPE to infoType
ARG_INFO_TYPE to infoType,
ARG_AUTH_CODE to authCode,
)
return fragment
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ class SignInViewModel(
val config: Config,
val courseId: String?,
val infoType: String?,
val authCode: String,
) : BaseViewModel() {

private val logger = Logger("SignInViewModel")
Expand Down Expand Up @@ -190,9 +191,9 @@ class SignInViewModel(
onUnknownError()
_uiState.update { it.copy(loginFailure = true) }
}.onSuccess {
logger.d { "Browser login success" }
_uiState.update { it.copy(loginSuccess = true) }
setUserId()
appNotifier.send(SignInEvent())
_uiState.update { it.copy(showProgress = false) }
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -234,28 +234,30 @@ private fun AuthForm(
description = stringResource(id = R.string.auth_enter_email_username),
onValueChanged = {
login = it
isEmailError = false
},
isError = isEmailError,
errorMessages = stringResource(id = R.string.auth_error_empty_username_email)
)
isEmailError = false
},
isError = isEmailError,
errorMessages = stringResource(id = R.string.auth_error_empty_username_email)
)

Spacer(modifier = Modifier.height(18.dp))
PasswordTextField(
modifier = Modifier
.fillMaxWidth(),
onValueChanged = {
password = it
isPasswordError = false},
onPressDone = {keyboardController?.hide()
if (password.isNotEmpty()) {
onEvent(AuthEvent.SignIn(login = login, password = password))
}else {
isEmailError = login.isEmpty()
isPasswordError = password.isEmpty()
}
},
isError = isPasswordError,
isPasswordError = false
},
onPressDone = {
keyboardController?.hide()
if (password.isNotEmpty()) {
onEvent(AuthEvent.SignIn(login = login, password = password))
} else {
isEmailError = login.isEmpty()
isPasswordError = password.isEmpty()
}
},
isError = isPasswordError,
)
} else {
Spacer(modifier = Modifier.height(40.dp))
Expand All @@ -270,10 +272,10 @@ private fun AuthForm(
if (state.isLogistrationEnabled.not() && state.isRegistrationEnabled) {
Text(
modifier = Modifier
.testTag("txt_register")
.noRippleClickable {
onEvent(AuthEvent.RegisterClick)
},
.testTag("txt_register")
.noRippleClickable {
onEvent(AuthEvent.RegisterClick)
},
text = stringResource(id = coreR.string.core_register),
color = MaterialTheme.appColors.primary,
style = MaterialTheme.appTypography.labelLarge
Expand All @@ -282,10 +284,10 @@ private fun AuthForm(
Spacer(modifier = Modifier.weight(1f))
Text(
modifier = Modifier
.testTag("txt_forgot_password")
.noRippleClickable {
onEvent(AuthEvent.ForgotPasswordClick)
},
.testTag("txt_forgot_password")
.noRippleClickable {
onEvent(AuthEvent.ForgotPasswordClick)
},
text = stringResource(id = R.string.auth_forgot_password),
color = MaterialTheme.appColors.info_variant,
style = MaterialTheme.appTypography.labelLarge
Expand All @@ -302,17 +304,16 @@ private fun AuthForm(
textColor = MaterialTheme.appColors.primaryButtonText,
backgroundColor = MaterialTheme.appColors.secondaryButtonBackground,
onClick = {
if(state.isBrowserLoginEnabled) {
if (state.isBrowserLoginEnabled) {
onEvent(AuthEvent.SignInBrowser)
} else {
keyboardController?.hide()
if (login.isNotEmpty() && password.isNotEmpty()) {
onEvent(AuthEvent.SignIn(login = login, password = password))
} else {
isEmailError = login.isEmpty()
isPasswordError = password.isEmpty()
}

keyboardController?.hide()
if (login.isNotEmpty() && password.isNotEmpty()) {
onEvent(AuthEvent.SignIn(login = login, password = password))
} else {
isEmailError = login.isEmpty()
isPasswordError = password.isEmpty()
}
}
}
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import android.content.Intent.FLAG_ACTIVITY_NEW_TASK
import android.net.Uri
import androidx.annotation.WorkerThread
import androidx.browser.customtabs.CustomTabsIntent
import org.openedx.core.ApiConstants
import org.openedx.core.config.Config
import org.openedx.core.utils.Logger

Expand All @@ -15,10 +16,10 @@ class BrowserAuthHelper(private val config: Config) {
@WorkerThread
suspend fun signIn(activityContext: Activity) {
logger.d { "Browser-based auth initiated" }
val uri = Uri.parse("${config.getApiHostURL()}/oauth2/authorize").buildUpon()
val uri = Uri.parse("${config.getApiHostURL()}${ApiConstants.URL_AUTHORIZE}").buildUpon()
.appendQueryParameter("client_id", config.getOAuthClientId())
.appendQueryParameter("redirect_uri", "${activityContext.packageName}://oauth2Callback")
.appendQueryParameter("response_type", "code").build()
.appendQueryParameter("redirect_uri", "${activityContext.packageName}://${ApiConstants.BrowserLogin.REDIRECT_HOST}")
.appendQueryParameter("response_type", ApiConstants.BrowserLogin.RESPONSE_TYPE).build()
val intent =
CustomTabsIntent.Builder().setUrlBarHidingEnabled(true).setShowTitle(true).build()
intent.intent.setFlags(FLAG_ACTIVITY_NEW_TASK)
Expand Down
9 changes: 9 additions & 0 deletions core/src/main/java/org/openedx/core/ApiConstants.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ package org.openedx.core

object ApiConstants {
const val URL_LOGIN = "/oauth2/login/"
const val URL_AUTHORIZE = "/oauth2/authorize/"
const val URL_ACCESS_TOKEN = "/oauth2/access_token/"
const val URL_EXCHANGE_TOKEN = "/oauth2/exchange_access_token/{auth_type}/"
const val GET_USER_PROFILE = "/api/mobile/v0.5/my_user_info"
const val URL_REVOKE_TOKEN = "/oauth2/revoke_token/"
const val URL_REGISTRATION_FIELDS = "/user_api/v1/account/registration"
const val URL_VALIDATE_REGISTRATION_FIELDS = "/api/user/v1/validation/registration"
const val URL_REGISTER = "/api/user/v1/account/registration/"
const val URL_REGISTER_BROWSER = "/register"
const val URL_PASSWORD_RESET = "/password_reset/"

const val GRANT_TYPE_PASSWORD = "password"
Expand All @@ -19,6 +21,7 @@ object ApiConstants {
const val TOKEN_TYPE_REFRESH = "refresh_token"

const val ACCESS_TOKEN = "access_token"

const val CLIENT_ID = "client_id"
const val EMAIL = "email"
const val NAME = "name"
Expand All @@ -36,4 +39,10 @@ object ApiConstants {
const val HONOR_CODE = "honor_code"
const val MARKETING_EMAILS = "marketing_emails_opt_in"
}

object BrowserLogin {
const val REDIRECT_HOST = "oauth2Callback"
const val CODE_QUERY_PARAM = "code"
const val RESPONSE_TYPE = "code"
}
}
4 changes: 0 additions & 4 deletions core/src/main/java/org/openedx/core/config/Config.kt
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,6 @@ class Config(context: Context) {
return getString(URI_SCHEME)
}

fun getApplicationID(): String {
return getString(APPLICATION_ID, "")
}

fun getOAuthClientId(): String {
return getString(OAUTH_CLIENT_ID)
}
Expand Down
2 changes: 1 addition & 1 deletion default_config/dev/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ SOCIAL_AUTH_ENABLED: false
#feature flag to enable registration from app
REGISTRATION_ENABLED: true
#feature flag to do the authentication flow in the browser to log in
BROWSER_LOGIN: false
BROWSER_LOGIN: true
#feature flag to do the registration for in the browser
BROWSER_REGISTRATION: false
#Course navigation feature flags
Expand Down
11 changes: 7 additions & 4 deletions docs/how-tos/auth-using-browser.rst
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
How to user Browser-based Login and Registration
================================================
How to use Browser-based Login and Registration
===============================================

Introduction
------------
Expand All @@ -14,7 +14,8 @@ the application.

The ``BROWSER_REGISTRATION`` flag is used to redirect registration to the browser. In this case
clicking on the registration button will open the registration page in a regular browser tab. Once
registered, the user will **not** be automatically redirected to the application.
registered, the user will as of writing this document **not** be automatically redirected to the
application.

Usage
-----
Expand Down Expand Up @@ -42,4 +43,6 @@ schemes here, including ``"https"`` and ``"http"``.

The authentication will then redirect to the browser in a custom tab that redirects back to the app.

NOTE: If a user logs out from the application, they might still be logged in, in the browser.
..note::

If a user logs out from the application, they might still be logged in, in the browser.

0 comments on commit 65b9c39

Please sign in to comment.