Unverified Commit 02023100 authored by Aniket Singh's avatar Aniket Singh Committed by GitHub

Merge branch 'develop' into aniket/feat/create-new-channel

parents 6467d655 e5b6f8bf
...@@ -23,21 +23,22 @@ ...@@ -23,21 +23,22 @@
android:networkSecurityConfig="@xml/network_security_config" android:networkSecurityConfig="@xml/network_security_config"
android:roundIcon="@mipmap/ic_launcher_round" android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"> android:supportsRtl="true">
<activity <activity
android:name=".authentication.ui.AuthenticationActivity" android:name=".authentication.ui.AuthenticationActivity"
android:configChanges="orientation" android:configChanges="orientation"
android:screenOrientation="portrait" android:screenOrientation="portrait"
android:theme="@style/AuthenticationTheme" android:theme="@style/AuthenticationTheme"
android:windowSoftInputMode="adjustResize"> android:windowSoftInputMode="adjustResize">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter> </intent-filter>
<intent-filter> <intent-filter>
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" /> <category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
...@@ -50,25 +51,31 @@ ...@@ -50,25 +51,31 @@
android:scheme="https" /> android:scheme="https" />
</intent-filter> </intent-filter>
</activity> </activity>
<activity <activity
android:name=".server.ui.ChangeServerActivity" android:name=".server.ui.ChangeServerActivity"
android:theme="@style/AuthenticationTheme" /> android:theme="@style/AuthenticationTheme" />
<activity <activity
android:name=".main.ui.MainActivity" android:name=".main.ui.MainActivity"
android:theme="@style/AppTheme" android:theme="@style/AppTheme"
android:windowSoftInputMode="adjustResize|stateAlwaysHidden" /> android:windowSoftInputMode="adjustResize|stateAlwaysHidden" />
<activity <activity
android:name=".webview.ui.WebViewActivity" android:name=".webview.ui.WebViewActivity"
android:theme="@style/AppTheme" android:theme="@style/AppTheme"
android:windowSoftInputMode="adjustResize|stateAlwaysHidden" /> android:windowSoftInputMode="adjustResize|stateAlwaysHidden" />
<activity <activity
android:name=".webview.cas.ui.CasWebViewActivity" android:name=".webview.sso.ui.SsoWebViewActivity"
android:theme="@style/AppTheme" android:theme="@style/AppTheme"
android:windowSoftInputMode="adjustResize|stateAlwaysHidden" /> android:windowSoftInputMode="adjustResize|stateAlwaysHidden" />
<activity <activity
android:name=".webview.oauth.ui.OauthWebViewActivity" android:name=".webview.oauth.ui.OauthWebViewActivity"
android:theme="@style/AppTheme" android:theme="@style/AppTheme"
android:windowSoftInputMode="adjustResize|stateAlwaysHidden" /> android:windowSoftInputMode="adjustResize|stateAlwaysHidden" />
<activity <activity
android:name=".chatroom.ui.ChatRoomActivity" android:name=".chatroom.ui.ChatRoomActivity"
android:theme="@style/AppTheme" android:theme="@style/AppTheme"
...@@ -103,6 +110,7 @@ ...@@ -103,6 +110,7 @@
<category android:name="${applicationId}" /> <category android:name="${applicationId}" />
</intent-filter> </intent-filter>
</receiver> </receiver>
<receiver <receiver
android:name=".push.DirectReplyReceiver" android:name=".push.DirectReplyReceiver"
android:enabled="true" android:enabled="true"
...@@ -119,6 +127,7 @@ ...@@ -119,6 +127,7 @@
<action android:name="com.google.firebase.INSTANCE_ID_EVENT" /> <action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
</intent-filter> </intent-filter>
</service> </service>
<service <service
android:name=".push.GcmListenerService" android:name=".push.GcmListenerService"
android:exported="false"> android:exported="false">
...@@ -126,6 +135,7 @@ ...@@ -126,6 +135,7 @@
<action android:name="com.google.android.c2dm.intent.RECEIVE" /> <action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter> </intent-filter>
</service> </service>
<service <service
android:name=".chatroom.service.MessageService" android:name=".chatroom.service.MessageService"
android:exported="true" android:exported="true"
......
...@@ -17,8 +17,8 @@ object DateTimeHelper { ...@@ -17,8 +17,8 @@ object DateTimeHelper {
* @param long The [Long] * @param long The [Long]
* @return The [LocalDateTime] from a [Long]. * @return The [LocalDateTime] from a [Long].
*/ */
fun getLocalDateTime(long: Long): LocalDateTime { fun getLocalDateTime(long: Long?): LocalDateTime {
return LocalDateTime.ofInstant(Instant.ofEpochMilli(long), ZoneId.systemDefault()) return LocalDateTime.ofInstant(long?.let { Instant.ofEpochMilli(it) }, ZoneId.systemDefault())
} }
/** /**
......
...@@ -25,8 +25,9 @@ import javax.inject.Inject ...@@ -25,8 +25,9 @@ import javax.inject.Inject
private const val TYPE_LOGIN_USER_EMAIL = 0 private const val TYPE_LOGIN_USER_EMAIL = 0
private const val TYPE_LOGIN_CAS = 1 private const val TYPE_LOGIN_CAS = 1
private const val TYPE_LOGIN_OAUTH = 2 private const val TYPE_LOGIN_SAML = 2
private const val TYPE_LOGIN_DEEP_LINK = 3 private const val TYPE_LOGIN_OAUTH = 3
private const val TYPE_LOGIN_DEEP_LINK = 4
private const val SERVICE_NAME_FACEBOOK = "facebook" private const val SERVICE_NAME_FACEBOOK = "facebook"
private const val SERVICE_NAME_GITHUB = "github" private const val SERVICE_NAME_GITHUB = "github"
private const val SERVICE_NAME_GOOGLE = "google" private const val SERVICE_NAME_GOOGLE = "google"
...@@ -82,14 +83,19 @@ class LoginPresenter @Inject constructor( ...@@ -82,14 +83,19 @@ class LoginPresenter @Inject constructor(
} }
} }
fun authenticateWithCas(token: String) { fun authenticateWithCas(casToken: String) {
credentialToken = token credentialToken = casToken
doAuthentication(TYPE_LOGIN_CAS) doAuthentication(TYPE_LOGIN_CAS)
} }
fun authenticateWithOauth(token: String, secret: String) { fun authenticateWithSaml(samlToken: String) {
credentialToken = token credentialToken = samlToken
credentialSecret = secret doAuthentication(TYPE_LOGIN_SAML)
}
fun authenticateWithOauth(oauthToken: String, oauthSecret: String) {
credentialToken = oauthToken
credentialSecret = oauthSecret
doAuthentication(TYPE_LOGIN_OAUTH) doAuthentication(TYPE_LOGIN_OAUTH)
} }
...@@ -99,7 +105,6 @@ class LoginPresenter @Inject constructor( ...@@ -99,7 +105,6 @@ class LoginPresenter @Inject constructor(
deepLinkUserId = deepLinkInfo.userId deepLinkUserId = deepLinkInfo.userId
deepLinkToken = deepLinkInfo.token deepLinkToken = deepLinkInfo.token
tokenRepository.save(serverUrl, Token(deepLinkUserId, deepLinkToken)) tokenRepository.save(serverUrl, Token(deepLinkUserId, deepLinkToken))
doAuthentication(TYPE_LOGIN_DEEP_LINK) doAuthentication(TYPE_LOGIN_DEEP_LINK)
} }
...@@ -124,8 +129,11 @@ class LoginPresenter @Inject constructor( ...@@ -124,8 +129,11 @@ class LoginPresenter @Inject constructor(
private fun setupCasView() { private fun setupCasView() {
if (settings.isCasAuthenticationEnabled()) { if (settings.isCasAuthenticationEnabled()) {
val token = generateRandomString(17) val casToken = generateRandomString(17)
view.setupCasButtonListener(settings.casLoginUrl().casUrl(currentServer, token), token) view.setupCasButtonListener(
settings.casLoginUrl().casUrl(currentServer, casToken),
casToken
)
view.showCasButton() view.showCasButton()
} }
} }
...@@ -216,7 +224,7 @@ class LoginPresenter @Inject constructor( ...@@ -216,7 +224,7 @@ class LoginPresenter @Inject constructor(
// totalSocialAccountsEnabled++ // totalSocialAccountsEnabled++
} }
if (settings.isTwitterAuthenticationEnabled()) { if (settings.isTwitterAuthenticationEnabled()) {
//TODO: Remove until we have this implemented //TODO: Remove until Twitter provides support to OAuth2
// view.enableLoginByTwitter() // view.enableLoginByTwitter()
// totalSocialAccountsEnabled++ // totalSocialAccountsEnabled++
} }
...@@ -261,8 +269,23 @@ class LoginPresenter @Inject constructor( ...@@ -261,8 +269,23 @@ class LoginPresenter @Inject constructor(
customOauthUrl, customOauthUrl,
state, state,
serviceName, serviceName,
getCustomOauthServiceNameColor(service), getServiceNameColor(service),
getCustomOauthButtonColor(service) getServiceButtonColor(service)
)
totalSocialAccountsEnabled++
}
}
getSamlServices(services).let {
val samlToken = generateRandomString(17)
for (service in it) {
view.addSamlServiceButton(
currentServer.samlUrl(getSamlProvider(service), samlToken),
samlToken,
getSamlServiceName(service),
getServiceNameColor(service),
getServiceButtonColor(service)
) )
totalSocialAccountsEnabled++ totalSocialAccountsEnabled++
} }
...@@ -307,6 +330,10 @@ class LoginPresenter @Inject constructor( ...@@ -307,6 +330,10 @@ class LoginPresenter @Inject constructor(
delay(3, TimeUnit.SECONDS) delay(3, TimeUnit.SECONDS)
client.loginWithCas(credentialToken) client.loginWithCas(credentialToken)
} }
TYPE_LOGIN_SAML -> {
delay(3, TimeUnit.SECONDS)
client.loginWithSaml(credentialToken)
}
TYPE_LOGIN_OAUTH -> { TYPE_LOGIN_OAUTH -> {
client.loginWithOauth(credentialToken, credentialSecret) client.loginWithOauth(credentialToken, credentialSecret)
} }
...@@ -319,7 +346,7 @@ class LoginPresenter @Inject constructor( ...@@ -319,7 +346,7 @@ class LoginPresenter @Inject constructor(
} }
} }
else -> { else -> {
throw IllegalStateException("Expected TYPE_LOGIN_USER_EMAIL, TYPE_LOGIN_CAS, TYPE_LOGIN_OAUTH or TYPE_LOGIN_DEEP_LINK") throw IllegalStateException("Expected TYPE_LOGIN_USER_EMAIL, TYPE_LOGIN_CAS,TYPE_LOGIN_SAML, TYPE_LOGIN_OAUTH or TYPE_LOGIN_DEEP_LINK")
} }
} }
} }
...@@ -365,6 +392,18 @@ class LoginPresenter @Inject constructor( ...@@ -365,6 +392,18 @@ class LoginPresenter @Inject constructor(
}.toString() }.toString()
} }
private fun getSamlServices(listMap: List<Map<String, Any>>): List<Map<String, Any>> {
return listMap.filter { map -> map["service"] == "saml" }
}
private fun getSamlServiceName(service: Map<String, Any>): String {
return service["buttonLabelText"].toString()
}
private fun getSamlProvider(service: Map<String, Any>): String {
return (service["clientConfig"] as Map<*, *>)["provider"].toString()
}
private fun getCustomOauthServices(listMap: List<Map<String, Any>>): List<Map<String, Any>> { private fun getCustomOauthServices(listMap: List<Map<String, Any>>): List<Map<String, Any>> {
return listMap.filter { map -> map["custom"] == true } return listMap.filter { map -> map["custom"] == true }
} }
...@@ -389,11 +428,11 @@ class LoginPresenter @Inject constructor( ...@@ -389,11 +428,11 @@ class LoginPresenter @Inject constructor(
return service["scope"].toString() return service["scope"].toString()
} }
private fun getCustomOauthButtonColor(service: Map<String, Any>): Int { private fun getServiceButtonColor(service: Map<String, Any>): Int {
return service["buttonColor"].toString().parseColor() return service["buttonColor"].toString().parseColor()
} }
private fun getCustomOauthServiceNameColor(service: Map<String, Any>): Int { private fun getServiceNameColor(service: Map<String, Any>): Int {
return service["buttonLabelColor"].toString().parseColor() return service["buttonLabelColor"].toString().parseColor()
} }
......
...@@ -87,7 +87,7 @@ interface LoginView : LoadingView, MessageView { ...@@ -87,7 +87,7 @@ interface LoginView : LoadingView, MessageView {
* Enables and shows the oauth view if there is login via social accounts enabled by the server settings. * Enables and shows the oauth view if there is login via social accounts enabled by the server settings.
* *
* REMARK: We must show at maximum *three* social accounts views ([enableLoginByFacebook], [enableLoginByGithub], [enableLoginByGoogle], * REMARK: We must show at maximum *three* social accounts views ([enableLoginByFacebook], [enableLoginByGithub], [enableLoginByGoogle],
* [enableLoginByLinkedin], [enableLoginByMeteor], [enableLoginByTwitter], [enableLoginByGitlab] or [addCustomOauthServiceButton]) for the oauth view. * [enableLoginByLinkedin], [enableLoginByMeteor], [enableLoginByTwitter], [enableLoginByGitlab], [addCustomOauthServiceButton] or [addSamlServiceButton]) for the oauth view.
* If the possibility of login via social accounts exceeds 3 different ways we should set up the FAB ([setupFabListener]) to show the remaining view(s). * If the possibility of login via social accounts exceeds 3 different ways we should set up the FAB ([setupFabListener]) to show the remaining view(s).
*/ */
fun enableOauthView() fun enableOauthView()
...@@ -197,7 +197,7 @@ interface LoginView : LoadingView, MessageView { ...@@ -197,7 +197,7 @@ interface LoginView : LoadingView, MessageView {
* @state A random string generated by the app, which you'll verify later (to protect against forgery attacks). * @state A random string generated by the app, which you'll verify later (to protect against forgery attacks).
* @serviceName The custom OAuth service name. * @serviceName The custom OAuth service name.
* @serviceNameColor The custom OAuth service name color (just stylizing). * @serviceNameColor The custom OAuth service name color (just stylizing).
* @buttonColor The color of the custom OAuth button (just stylizing). * @buttonColor The custom OAuth button color (just stylizing).
* @see [enableOauthView] * @see [enableOauthView]
*/ */
fun addCustomOauthServiceButton( fun addCustomOauthServiceButton(
...@@ -208,6 +208,23 @@ interface LoginView : LoadingView, MessageView { ...@@ -208,6 +208,23 @@ interface LoginView : LoadingView, MessageView {
buttonColor: Int buttonColor: Int
) )
/**
* Adds a SAML button in the oauth view.
*
* @samlUrl The SAML url to sets up the button (the listener).
* @serviceName The SAML service name.
* @serviceNameColor The SAML service name color (just stylizing).
* @buttonColor The SAML button color (just stylizing).
* @see [enableOauthView]
*/
fun addSamlServiceButton(
samlUrl: String,
samlToken: String,
serviceName: String,
serviceNameColor: Int,
buttonColor: Int
)
/** /**
* Setups the FloatingActionButton to show more social accounts views (expanding the oauth view interface to show the remaining view(s)). * Setups the FloatingActionButton to show more social accounts views (expanding the oauth view interface to show the remaining view(s)).
*/ */
......
...@@ -25,8 +25,8 @@ import chat.rocket.android.authentication.login.presentation.LoginView ...@@ -25,8 +25,8 @@ import chat.rocket.android.authentication.login.presentation.LoginView
import chat.rocket.android.helper.KeyboardHelper import chat.rocket.android.helper.KeyboardHelper
import chat.rocket.android.helper.TextHelper import chat.rocket.android.helper.TextHelper
import chat.rocket.android.util.extensions.* import chat.rocket.android.util.extensions.*
import chat.rocket.android.webview.cas.ui.INTENT_CAS_TOKEN import chat.rocket.android.webview.sso.ui.INTENT_SSO_TOKEN
import chat.rocket.android.webview.cas.ui.casWebViewIntent import chat.rocket.android.webview.sso.ui.ssoWebViewIntent
import chat.rocket.android.webview.oauth.ui.INTENT_OAUTH_CREDENTIAL_SECRET import chat.rocket.android.webview.oauth.ui.INTENT_OAUTH_CREDENTIAL_SECRET
import chat.rocket.android.webview.oauth.ui.INTENT_OAUTH_CREDENTIAL_TOKEN import chat.rocket.android.webview.oauth.ui.INTENT_OAUTH_CREDENTIAL_TOKEN
import chat.rocket.android.webview.oauth.ui.oauthWebViewIntent import chat.rocket.android.webview.oauth.ui.oauthWebViewIntent
...@@ -42,12 +42,12 @@ import kotlinx.android.synthetic.main.fragment_authentication_log_in.* ...@@ -42,12 +42,12 @@ import kotlinx.android.synthetic.main.fragment_authentication_log_in.*
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
internal const val REQUEST_CODE_FOR_CAS = 1 internal const val REQUEST_CODE_FOR_CAS = 1
internal const val REQUEST_CODE_FOR_OAUTH = 2 internal const val REQUEST_CODE_FOR_SAML = 2
internal const val MULTIPLE_CREDENTIALS_READ = 3 internal const val REQUEST_CODE_FOR_OAUTH = 3
internal const val NO_CREDENTIALS_EXIST = 4 internal const val MULTIPLE_CREDENTIALS_READ = 4
internal const val SAVE_CREDENTIALS = 5 internal const val NO_CREDENTIALS_EXIST = 5
internal const val SAVE_CREDENTIALS = 6
lateinit var googleApiClient: GoogleApiClient lateinit var googleApiClient: GoogleApiClient
...@@ -121,7 +121,10 @@ class LoginFragment : Fragment(), LoginView, GoogleApiClient.ConnectionCallbacks ...@@ -121,7 +121,10 @@ class LoginFragment : Fragment(), LoginView, GoogleApiClient.ConnectionCallbacks
if (data != null) { if (data != null) {
when (requestCode) { when (requestCode) {
REQUEST_CODE_FOR_CAS -> data.apply { REQUEST_CODE_FOR_CAS -> data.apply {
presenter.authenticateWithCas(getStringExtra(INTENT_CAS_TOKEN)) presenter.authenticateWithCas(getStringExtra(INTENT_SSO_TOKEN))
}
REQUEST_CODE_FOR_SAML -> data.apply {
presenter.authenticateWithSaml(getStringExtra(INTENT_SSO_TOKEN))
} }
REQUEST_CODE_FOR_OAUTH -> { REQUEST_CODE_FOR_OAUTH -> {
isOauthSuccessful = true isOauthSuccessful = true
...@@ -371,7 +374,7 @@ class LoginFragment : Fragment(), LoginView, GoogleApiClient.ConnectionCallbacks ...@@ -371,7 +374,7 @@ class LoginFragment : Fragment(), LoginView, GoogleApiClient.ConnectionCallbacks
ui { activity -> ui { activity ->
button_cas.setOnClickListener { button_cas.setOnClickListener {
startActivityForResult( startActivityForResult(
activity.casWebViewIntent(casUrl, casToken), activity.ssoWebViewIntent(casUrl, casToken),
REQUEST_CODE_FOR_CAS REQUEST_CODE_FOR_CAS
) )
activity.overridePendingTransition(R.anim.slide_up, R.anim.hold) activity.overridePendingTransition(R.anim.slide_up, R.anim.hold)
...@@ -566,7 +569,7 @@ class LoginFragment : Fragment(), LoginView, GoogleApiClient.ConnectionCallbacks ...@@ -566,7 +569,7 @@ class LoginFragment : Fragment(), LoginView, GoogleApiClient.ConnectionCallbacks
buttonColor: Int buttonColor: Int
) { ) {
ui { activity -> ui { activity ->
val button = getCustomOauthButton(serviceName, serviceNameColor, buttonColor) val button = getCustomServiceButton(serviceName, serviceNameColor, buttonColor)
social_accounts_container.addView(button) social_accounts_container.addView(button)
button.setOnClickListener { button.setOnClickListener {
...@@ -579,6 +582,27 @@ class LoginFragment : Fragment(), LoginView, GoogleApiClient.ConnectionCallbacks ...@@ -579,6 +582,27 @@ class LoginFragment : Fragment(), LoginView, GoogleApiClient.ConnectionCallbacks
} }
} }
override fun addSamlServiceButton(
samlUrl: String,
samlToken: String,
serviceName: String,
serviceNameColor: Int,
buttonColor: Int
) {
ui { activity ->
val button = getCustomServiceButton(serviceName, serviceNameColor, buttonColor)
social_accounts_container.addView(button)
button.setOnClickListener {
startActivityForResult(
activity.ssoWebViewIntent(samlUrl, samlToken),
REQUEST_CODE_FOR_SAML
)
activity.overridePendingTransition(R.anim.slide_up, R.anim.hold)
}
}
}
override fun setupFabListener() { override fun setupFabListener() {
ui { ui {
button_fab.isVisible = true button_fab.isVisible = true
...@@ -696,9 +720,9 @@ class LoginFragment : Fragment(), LoginView, GoogleApiClient.ConnectionCallbacks ...@@ -696,9 +720,9 @@ class LoginFragment : Fragment(), LoginView, GoogleApiClient.ConnectionCallbacks
} }
/** /**
* Gets a stylized custom OAuth button. * Gets a stylized custom service button.
*/ */
private fun getCustomOauthButton( private fun getCustomServiceButton(
buttonText: String, buttonText: String,
buttonTextColor: Int, buttonTextColor: Int,
buttonBgColor: Int buttonBgColor: Int
......
...@@ -507,6 +507,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR ...@@ -507,6 +507,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
ui { ui {
val clipboard = it.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager val clipboard = it.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
clipboard.primaryClip = ClipData.newPlainText("", message) clipboard.primaryClip = ClipData.newPlainText("", message)
showToast(R.string.msg_message_copied)
} }
} }
......
...@@ -40,8 +40,11 @@ fun String.safeUrl(): String { ...@@ -40,8 +40,11 @@ fun String.safeUrl(): String {
fun String.serverLogoUrl(favicon: String) = "${removeTrailingSlash()}/$favicon" fun String.serverLogoUrl(favicon: String) = "${removeTrailingSlash()}/$favicon"
fun String.casUrl(serverUrl: String, token: String) = fun String.casUrl(serverUrl: String, casToken: String) =
"${removeTrailingSlash()}?service=${serverUrl.removeTrailingSlash()}/_cas/$token" "${removeTrailingSlash()}?service=${serverUrl.removeTrailingSlash()}/_cas/$casToken"
fun String.samlUrl(provider: String, samlToken: String) =
"${removeTrailingSlash()}/_saml/authorize/$provider/$samlToken"
fun String.termsOfServiceUrl() = "${removeTrailingSlash()}/terms-of-service" fun String.termsOfServiceUrl() = "${removeTrailingSlash()}/terms-of-service"
......
...@@ -36,7 +36,6 @@ class OauthWebViewActivity : AppCompatActivity() { ...@@ -36,7 +36,6 @@ class OauthWebViewActivity : AppCompatActivity() {
private lateinit var state: String private lateinit var state: String
private var isWebViewSetUp: Boolean = false private var isWebViewSetUp: Boolean = false
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(R.layout.activity_web_view) setContentView(R.layout.activity_web_view)
......
package chat.rocket.android.webview.cas.ui package chat.rocket.android.webview.sso.ui
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.app.Activity import android.app.Activity
...@@ -13,19 +13,23 @@ import chat.rocket.android.R ...@@ -13,19 +13,23 @@ import chat.rocket.android.R
import kotlinx.android.synthetic.main.activity_web_view.* import kotlinx.android.synthetic.main.activity_web_view.*
import kotlinx.android.synthetic.main.app_bar.* import kotlinx.android.synthetic.main.app_bar.*
fun Context.casWebViewIntent(webPageUrl: String, casToken: String): Intent { fun Context.ssoWebViewIntent(webPageUrl: String, casToken: String): Intent {
return Intent(this, CasWebViewActivity::class.java).apply { return Intent(this, SsoWebViewActivity::class.java).apply {
putExtra(INTENT_WEB_PAGE_URL, webPageUrl) putExtra(INTENT_WEB_PAGE_URL, webPageUrl)
putExtra(INTENT_CAS_TOKEN, casToken) putExtra(INTENT_SSO_TOKEN, casToken)
} }
} }
private const val INTENT_WEB_PAGE_URL = "web_page_url" private const val INTENT_WEB_PAGE_URL = "web_page_url"
const val INTENT_CAS_TOKEN = "cas_token" const val INTENT_SSO_TOKEN = "cas_token"
class CasWebViewActivity : AppCompatActivity() { /**
* This class is responsible to handle the authentication thought single sign-on protocol (CAS and SAML).
*/
class SsoWebViewActivity : AppCompatActivity() {
private lateinit var webPageUrl: String private lateinit var webPageUrl: String
private lateinit var casToken: String private lateinit var casToken: String
private var isWebViewSetUp: Boolean = false
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
...@@ -34,7 +38,7 @@ class CasWebViewActivity : AppCompatActivity() { ...@@ -34,7 +38,7 @@ class CasWebViewActivity : AppCompatActivity() {
webPageUrl = intent.getStringExtra(INTENT_WEB_PAGE_URL) webPageUrl = intent.getStringExtra(INTENT_WEB_PAGE_URL)
requireNotNull(webPageUrl) { "no web_page_url provided in Intent extras" } requireNotNull(webPageUrl) { "no web_page_url provided in Intent extras" }
casToken = intent.getStringExtra(INTENT_CAS_TOKEN) casToken = intent.getStringExtra(INTENT_SSO_TOKEN)
requireNotNull(casToken) { "no cas_token provided in Intent extras" } requireNotNull(casToken) { "no cas_token provided in Intent extras" }
setupToolbar() setupToolbar()
...@@ -42,7 +46,10 @@ class CasWebViewActivity : AppCompatActivity() { ...@@ -42,7 +46,10 @@ class CasWebViewActivity : AppCompatActivity() {
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
setupWebView() if (!isWebViewSetUp) {
setupWebView()
isWebViewSetUp = true
}
} }
override fun onBackPressed() { override fun onBackPressed() {
...@@ -64,15 +71,16 @@ class CasWebViewActivity : AppCompatActivity() { ...@@ -64,15 +71,16 @@ class CasWebViewActivity : AppCompatActivity() {
web_view.settings.javaScriptEnabled = true web_view.settings.javaScriptEnabled = true
web_view.webViewClient = object : WebViewClient() { web_view.webViewClient = object : WebViewClient() {
override fun onPageStarted(view: WebView, url: String, favicon: Bitmap?) { override fun onPageStarted(view: WebView, url: String, favicon: Bitmap?) {
// The user may have already been logged in the CAS, so check if the URL contains the "ticket" word // The user may have already been logged in the SSO, so check if the URL contains
// (that means the user is successful authenticated and we don't need to wait until the page is fully loaded). // the "ticket" or "validate" word (that means the user is successful authenticated
if (url.contains("ticket")) { // and we don't need to wait until the page is fully loaded).
if (url.contains("ticket") || url.contains("validate")) {
closeView(Activity.RESULT_OK) closeView(Activity.RESULT_OK)
} }
} }
override fun onPageFinished(view: WebView, url: String) { override fun onPageFinished(view: WebView, url: String) {
if (url.contains("ticket")) { if (url.contains("ticket") || url.contains("validate")) {
closeView(Activity.RESULT_OK) closeView(Activity.RESULT_OK)
} else { } else {
view_loading.hide() view_loading.hide()
...@@ -83,7 +91,7 @@ class CasWebViewActivity : AppCompatActivity() { ...@@ -83,7 +91,7 @@ class CasWebViewActivity : AppCompatActivity() {
} }
private fun closeView(activityResult: Int = Activity.RESULT_CANCELED) { private fun closeView(activityResult: Int = Activity.RESULT_CANCELED) {
setResult(activityResult, Intent().putExtra(INTENT_CAS_TOKEN, casToken)) setResult(activityResult, Intent().putExtra(INTENT_SSO_TOKEN, casToken))
finish() finish()
overridePendingTransition(R.anim.hold, R.anim.slide_down) overridePendingTransition(R.anim.hold, R.anim.slide_down)
} }
......
...@@ -139,6 +139,7 @@ ...@@ -139,6 +139,7 @@
<string name="msg_add_members">Add Members</string> <string name="msg_add_members">Add Members</string>
// TODO: Add proper translation. // TODO: Add proper translation.
<string name="msg_search">Search</string> <string name="msg_search">Search</string>
<string name="msg_message_copied">Mensaje copiado</string>
<!-- System messages --> <!-- System messages -->
<string name="message_room_name_changed">Nombre de la sala cambiado para: %1$s por %2$s</string> <string name="message_room_name_changed">Nombre de la sala cambiado para: %1$s por %2$s</string>
......
...@@ -139,6 +139,7 @@ ...@@ -139,6 +139,7 @@
<string name="msg_add_members">Add Members</string> <string name="msg_add_members">Add Members</string>
// TODO: Add proper translation. // TODO: Add proper translation.
<string name="msg_search">Search</string> <string name="msg_search">Search</string>
<string name="msg_message_copied">Message copié</string>
<!-- System messages --> <!-- System messages -->
<string name="message_room_name_changed">Le nom de le salle a changé à: %1$s par %2$s</string> <string name="message_room_name_changed">Le nom de le salle a changé à: %1$s par %2$s</string>
......
...@@ -141,6 +141,7 @@ ...@@ -141,6 +141,7 @@
<string name="msg_add_members">Add Members</string> <string name="msg_add_members">Add Members</string>
// TODO: Add proper translation. // TODO: Add proper translation.
<string name="msg_search">Search</string> <string name="msg_search">Search</string>
<string name="msg_message_copied">संदेश कॉपी किया गया</string>
<!-- System messages --> <!-- System messages -->
<string name="message_room_name_changed">%2$s ने रूम का नाम बदलकर %1$s किया</string> <string name="message_room_name_changed">%2$s ने रूम का नाम बदलकर %1$s किया</string>
......
...@@ -131,6 +131,7 @@ ...@@ -131,6 +131,7 @@
<string name="msg_add_members">Add Members</string> <string name="msg_add_members">Add Members</string>
// TODO: Add proper translation. // TODO: Add proper translation.
<string name="msg_search">Search</string> <string name="msg_search">Search</string>
<string name="msg_message_copied">Mensagem copiada</string>
<!-- System messages --> <!-- System messages -->
<string name="message_room_name_changed">Nome da sala alterado para: %1$s por %2$s</string> <string name="message_room_name_changed">Nome da sala alterado para: %1$s por %2$s</string>
......
<resources>
<!-- Titles -->
<string name="title_sign_in_your_server">Войдите на ваш сервер</string>
<string name="title_log_in">Войти</string>
<string name="title_register_username">Зарегистрировать имя</string>
<string name="title_reset_password">Сброс пароля</string>
<string name="title_sign_up">Зарегистрироваться</string>
<string name="title_authentication">Аутентификация</string>
<string name="title_legal_terms">Юридические условия</string>
<string name="title_chats">Чаты</string>
<string name="title_profile">Профиль</string>
<string name="title_members">Пользователи (%d)</string>
<string name="title_settings">Настройки</string>
<string name="title_password">Изменить пароль</string>
<string name="title_update_profile">Обновить профиль</string>
<string name="title_about">О программе</string>
<!-- Actions -->
<string name="action_connect">Соединение</string>
<string name="action_use_this_username">Использовать это имя</string>
<string name="action_login_or_sign_up">Нажмите эту кнопку, чтобы войти в систему или создать учетную запись</string>
<string name="action_terms_of_service">Условия использования</string>
<string name="action_privacy_policy">Политика конфиденциальности</string>
<string name="action_search">Поиск</string>
<string name="action_update">Обновить</string>
<string name="action_settings">Настройки</string>
<string name="action_logout">Выйти</string>
<string name="action_files">Файлы</string>
<string name="action_confirm_password">Подтверждение изменения пароля</string>
<string name="action_join_chat">Присоединиться к чату</string>
<string name="action_add_account">Добавить аккаунт</string>
<string name="action_online">Онлайн</string>
<string name="action_away">Отошел</string>
<string name="action_busy">Занят</string>
<string name="action_invisible">Невидимый</string>
<string name="action_save_to_gallery">Сохранить в галерею</string>
<!-- Settings List -->
<string-array name="settings_actions">
<item name="item_password">Изменить пароль</item>
<item name="item_password">О программе</item>
</string-array>
<!-- Regular information messages -->
<string name="msg_generic_error">Произошла ошибка, повторите попытку.</string>
<string name="msg_no_data_to_display">Нет данных для отображения</string>
<string name="msg_profile_update_successfully">Профиль успешно обновлен</string>
<string name="msg_username">имя пользователя</string>
<string name="msg_username_or_email">имя пользователя или e-mail</string>
<string name="msg_password">пароль</string>
<string name="msg_name">Имя</string>
<string name="msg_email">e-mail</string>
<string name="msg_avatar_url">URL аватара</string>
<string name="msg_or_continue_using_social_accounts">Или продолжить, используя социальные учетные записи</string>
<string name="msg_new_user">Новый пользователь? %1$s</string>
<string name="msg_forgot_password">Забыли пароль? %1$s</string>
<string name="msg_reset">Сброс</string>
<string name="msg_check_your_email_to_reset_your_password">Письмо отправлено! Проверьте свой почтовый ящик, чтобы сбросить пароль.</string>
<string name="msg_invalid_email">Введите действующий e-mail</string>
<string name="msg_new_user_agreement">Продолжая, вы соглашаетесь с нашими\n%1$s и %2$s</string>
<string name="msg_2fa_code">Код 2FA</string>
<string name="msg_yesterday">Вчера</string>
<string name="msg_message">Сообщение</string>
<string name="msg_this_room_is_read_only">Этот канал только для чтения</string>
<string name="msg_invalid_2fa_code">Неверный код 2FA</string>
<string name="msg_invalid_file">Неверный файл</string>
<string name="msg_invalid_server_url">Неверный URL-адрес сервера.</string>
<string name="msg_content_description_log_in_using_facebook">Войти используя Facebook</string>
<string name="msg_content_description_log_in_using_github">Войти используя Github</string>
<string name="msg_content_description_log_in_using_google">Войти используя Google</string>
<string name="msg_content_description_log_in_using_linkedin">Войти используя Linkedin</string>
<string name="msg_content_description_log_in_using_meteor">Войти используя Meteor</string>
<string name="msg_content_description_log_in_using_twitter">Войти используя Twitter</string>
<string name="msg_content_description_log_in_using_gitlab">Войти используя Gitlab</string>
<string name="msg_content_description_send_message">Отправить сообщение</string>
<string name="msg_content_description_show_attachment_options">Показать параметры вложения</string>
<string name="msg_you">Вы</string>
<string name="msg_unknown">Неизвестный</string>
<string name="msg_email_address">E-mail адрес</string>
<string name="msg_utc_offset">Смещение UTC</string>
<string name="msg_new_password">Введите новый пароль</string>
<string name="msg_confirm_password">Подтвердите новый пароль</string>
<string name="msg_unread_messages">Непрочитанные сообщения</string>
<string name="msg_preview_video">Видео</string>
<string name="msg_preview_audio">Аудио</string>
<string name="msg_preview_photo">Фото</string>
<string name="msg_preview_file">Файл</string>
<string name="msg_no_messages_yet">Нет сообщений</string>
<string name="msg_version">Версия %1$s</string>
<string name="msg_build">Сборка %1$d</string>
<string name="msg_ok">OK</string>
<string name="msg_update_app_version_in_order_to_continue">Версия сервера устарела. Пожалуйста, свяжитесь с администратором, чтобы обновить версию сервера.</string>
<string name="msg_ver_not_recommended">
Похоже ваша версия сервера ниже рекомендуемой %1$s.\nВы можете войти, но будьте готовы столкнуться с непредвиденными трудностями.</string>
<string name="msg_ver_not_minimum">
Похоже ваша версия сервера ниже минимально необходимой версии %1$s.\nОбновите свой сервер чтобы войти в систему!
</string>
<string name="msg_no_chat_title">Нет сообщений чата</string>
<string name="msg_no_chat_description">Начните разговор, чтобы увидеть ваши\nсообщения здесь.</string>
<string name="msg_proceed">ПРОДОЛЖИТЬ</string>
<string name="msg_cancel">ОТМЕНА</string>
<string name="msg_warning">ПРЕДУПРЕЖДЕНИЕ</string>
<string name="msg_http_insecure">При использовании HTTP вы подключаетесь к небезопасному серверу. Мы не рекомендуем вам это делать.</string>
<string name="msg_error_checking_server_version">При проверке версии вашего сервера произошла ошибка, повторите попытку.</string>
<string name="msg_invalid_server_protocol">Выбранный протокол не разрешен на этом сервере, попробуйте использовать HTTPS</string>
<string name="msg_image_saved_successfully">Изображение сохранено в галерее</string>
<string name="msg_image_saved_failed">Не удалось сохранить изображение</string>
<string name="msg_edited">(изменено)</string>
<string name="msg_and">\u0020и\u0020</string>
<string name="msg_is_typing">\u0020печатает…</string>
<string name="msg_are_typing">\u0020печатают…</string>
<string name="msg_several_users_are_typing">Несколько пользователей печатают…</string>
<string name="msg_no_search_found">Результатов не найдено</string>
<string name="msg_message_copied">Скопировано сообщение</string>
<!-- System messages -->
<string name="message_room_name_changed">Название канала изменено на: %1$s by %2$s</string>
<string name="message_user_added_by">Пользователь %1$s добавлен пользователем %2$s</string>
<string name="message_user_removed_by">Пользователь %1$s удален пользователем %2$s</string>
<string name="message_user_left">Покинул канал.</string>
<string name="message_user_joined_channel">Присоединился к каналу.</string>
<string name="message_welcome">Добро пожаловать %s</string>
<string name="message_removed">Сообщение удалено</string>
<string name="message_pinned">Прикрепленное сообщение:</string>
<string name="message_muted">Пользователь %1$s заглушен пользователем %2$s</string>
<string name="message_unmuted">Пользователь %1$s перестал быть заглушенным по решению %2$s</string>
<string name="message_role_add">%1$s был назначен %2$s пользователем %3$s</string>
<string name="message_role_removed">%1$s больше не %2$s по решению %3$s</string>
<string name="message_credentials_saved_successfully">Учетные данные успешно сохранены</string>
<!-- Message actions -->
<string name="action_msg_reply">Ответить</string>
<string name="action_msg_edit">Редактировать</string>
<string name="action_msg_copy">Копировать</string>
<string name="action_msg_quote">Цитата</string>
<string name="action_msg_delete">Удалить</string>
<string name="action_msg_pin">Прикрепить сообщение</string>
<string name="action_msg_unpin">Открепить сообщение</string>
<string name="action_msg_star">Пометить сообщение</string>
<string name="action_msg_unstar">Снять отметку</string>
<string name="action_msg_share">Поделиться</string>
<string name="action_title_editing">Редактирование сообщения</string>
<string name="action_msg_add_reaction">Добавить реакцию</string>
<!-- Permission messages -->
<string name="permission_editing_not_allowed">Редактирование запрещено</string>
<string name="permission_deleting_not_allowed">Удаление запрещено</string>
<string name="permission_pinning_not_allowed">Прикрепление запрещено</string>
<string name="permission_starring_not_allowed">Отмечивание запрещено</string>
<!-- Members List -->
<string name="title_members_list">Пользователи</string>
<!-- Pinned Messages -->
<string name="title_pinned_messages">Прикрепленные сообщения</string>
<string name="no_pinned_messages">Нет прикрепленных сообщений</string>
<string name="no_pinned_description">Все прикрепленные сообщения\nотображаются здесь</string>
<!-- Favorite Messages -->
<string name="title_favorite_messages">Избранные сообщения</string>
<string name="no_favorite_messages">Нет избранных сообщений</string>
<string name="no_favorite_description">Все избранные сообщения\nотображаются здесь</string>
<!-- Files -->
<string name="msg_files">Файлы</string>
<string name="title_files_total">Файлы (%d)</string>
<string name="msg_no_files">Нет файлов</string>
<string name="msg_all_files_appear_here">Все файлы отображаются здесь</string>
<!-- Upload Messages -->
<string name="max_file_size_exceeded">Размер файла %1$d превысил максимально допустимый %2$d bytes</string>
<!-- Socket status -->
<string name="status_connected">Соединено</string>
<string name="status_disconnected">Отключено</string>
<string name="status_connecting">Соединение</string>
<string name="status_authenticating">Аутентификация</string>
<string name="status_disconnecting">Отключение</string>
<string name="status_waiting">Соединение через %d секунд</string>
<!--Suggestions-->
<string name="suggest_all_description">Уведомить всех в этом чате</string>
<string name="suggest_here_description">Уведомить всех активных пользователей в этом чате</string>
<!-- Slash Commands -->
<string name="Slash_Gimme_Description">Показывает ༼ つ ◕_◕ ༽つ перед вашим сообщением</string>
<string name="Slash_LennyFace_Description">Показывает ( ͡° ͜ʖ ͡°) после вашего сообщения</string>
<string name="Slash_Shrug_Description">Показывает ¯\_(ツ)_/¯ после вашего сообщения</string>
<string name="Slash_Tableflip_Description">Показывает (╯°□°)╯︵ ┻━┻</string>
<string name="Slash_TableUnflip_Description">Показывает ┬─┬ ノ( ゜-゜ノ)</string>
<string name="Create_A_New_Channel">Создать новый канал</string>
<string name="Show_the_keyboard_shortcut_list">Показать список горячих клавиш</string>
<string name="Invite_user_to_join_channel_all_from">Пригласить всех пользователей из [#channel] присоединиться к этому каналу</string>
<string name="Invite_user_to_join_channel_all_to">Пригласить всех пользователей присоединиться к [#channel]</string>
<string name="Archive">Архивировать</string>
<string name="Remove_someone_from_room">Удалить кого-либо с канала</string>
<string name="Leave_the_current_channel">Покинуть текущий канал</string>
<string name="Displays_action_text">Отображает текст действия</string>
<string name="Direct_message_someone">Личное сообщение</string>
<string name="Mute_someone_in_room">Заглушить кого-либо на канале</string>
<string name="Unmute_someone_in_room">Отменить заглушивание кого-либо на канале</string>
<string name="Invite_user_to_join_channel">Пригласить пользователя на канал</string>
<string name="Unarchive">Разархивировать</string>
<string name="Join_the_given_channel">Присоединиться к этому каналу</string>
<string name="Guggy_Command_Description">Создает gif на основе предоставленного текста</string>
<string name="Slash_Topic_Description">Установить тему</string>
<!-- Emoji message-->
<string name="msg_no_recent_emoji">Нет недавно используемых emoji</string>
<!-- Sorting and grouping-->
<string name="menu_chatroom_sort">Сортировать</string>
<string name="dialog_sort_title">Сортировать по</string>
<string name="dialog_sort_by_alphabet">По алфавиту</string>
<string name="dialog_sort_by_activity">По активности</string>
<string name="dialog_group_by_type">Группировать по типу</string>
<string name="dialog_group_favourites">Группировать избранное</string>
<string name="chatroom_header">Заголовок</string>
<!--ChatRooms Headers-->
<string name="header_channel">Каналы</string>
<string name="header_private_groups">Приватные группы</string>
<string name="header_direct_messages">Личная переписка</string>
<string name="header_live_chats">Живые чаты</string>
<string name="header_unknown">Неизвестные</string>
<!--Notifications-->
<string name="notif_action_reply_hint">ОТВЕТИТЬ</string>
<string name="notif_error_sending">Ошибка ответа. Пожалуйста, попробуйте еще раз.</string>
<string name="notif_success_sending">Сообщение отправлено %1$s!</string>
</resources>
...@@ -129,6 +129,7 @@ ...@@ -129,6 +129,7 @@
<string name="public_channel_type">Public</string> <string name="public_channel_type">Public</string>
<string name="private_channel_type_description">Visible only to you and those whom you invite</string> <string name="private_channel_type_description">Visible only to you and those whom you invite</string>
<string name="public_channel_description">Visible to everyone</string> <string name="public_channel_description">Visible to everyone</string>
<string name="msg_message_copied">Message copied</string>
<!-- System messages --> <!-- System messages -->
<string name="message_room_name_changed">Room name changed to: %1$s by %2$s</string> <string name="message_room_name_changed">Room name changed to: %1$s by %2$s</string>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment