Skip to content

Commit

Permalink
Merge pull request #91 from RocketChat/new/cas-login-support
Browse files Browse the repository at this point in the history
[NEW] Add support to login through CAS.
  • Loading branch information
philipbrito authored Mar 12, 2018
2 parents f149641 + e7596c3 commit 67b55d5
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package chat.rocket.core.internal.model

import se.ansman.kotshi.JsonSerializable

@JsonSerializable
data class CasLoginPayload(val cas: Data)

@JsonSerializable
data class Data(val credentialToken: String)
31 changes: 30 additions & 1 deletion core/src/main/kotlin/chat/rocket/core/internal/rest/Login.kt
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@ suspend fun RocketChatClient.loginWithEmail(email: String, password: String, pin
result
}


/**
* Login with username and password through LDAP.
* On success this will also call [chat.rocket.core.TokenRepository].save(token)
Expand Down Expand Up @@ -106,6 +105,36 @@ suspend fun RocketChatClient.loginWithLdap(username: String, password: String):
result
}

/**
* Login through CAS protocol.
* On success this will also call [chat.rocket.core.TokenRepository].save(token)
*
* @param casCredential The CAS credential to authenticate with.
*
* @return [Token]
* @throws [RocketChatException] on errors.
* @see [Token]
* @see [chat.rocket.core.TokenRepository]
*/
suspend fun RocketChatClient.loginWithCas(casCredential: String): Token = withContext(CommonPool) {
val payload = CasLoginPayload(Data(casCredential))
val adapter = moshi.adapter(CasLoginPayload::class.java)

val payloadBody = adapter.toJson(payload)
val body = RequestBody.create(MEDIA_TYPE_JSON, payloadBody)

val url = requestUrl(restUrl, "login").build()

val request = Request.Builder().url(url).post(body).build()

val type = Types.newParameterizedType(RestResult::class.java, Token::class.java)
val result = handleRestCall<RestResult<Token>>(request, type).result()

tokenRepository.save(result)

result
}

/**
* Registers a new user within the server.
* Note, this doesn't authenticate the user.
Expand Down
2 changes: 1 addition & 1 deletion core/src/main/kotlin/chat/rocket/core/model/Myself.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ data class Myself(
override val name: String?,
val status: UserStatus?,
val statusConnection: UserStatus?,
val utcOffset: Float,
val utcOffset: Float?,
val active: Boolean,
val emails: List<Email>?
) : BaseUser
79 changes: 79 additions & 0 deletions core/src/test/kotlin/chat/rocket/core/internal/rest/LoginTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,85 @@ class LoginTest {
}
}

@Test
fun `loginWithCas() should succeed with right credentials`() {
mockServer.expect()
.post()
.withPath("/api/v1/login")
.andReturn(200, LOGIN_SUCCESS)
.once()

runBlocking {
val token = sut.loginWithCas("12345678901234567")
assertThat(token, isEqualTo(authToken))
assertThat(token.userId, isEqualTo("userId"))
assertThat(token.authToken, isEqualTo("authToken"))

verify(tokenProvider).save(check {
assertThat(it.userId, isEqualTo("userId"))
assertThat(it.authToken, isEqualTo("authToken"))
})
}
}

@Test
fun `loginWithLCas() should fail with RocketChatAuthException on wrong credentials`() {
mockServer.expect()
.post()
.withPath("/api/v1/login")
.andReturn(401, LOGIN_ERROR)
.once()

runBlocking {
try {
sut.loginWithCas("12345678901234567")

throw RuntimeException("unreachable code")
} catch (ex: Exception) {
assertThat(ex, isEqualTo(instanceOf(RocketChatAuthException::class.java)))
assertThat(ex.message, isEqualTo("Unauthorized"))
}
verify(tokenProvider, never()).save(check { })
}
}

@Test
fun `loginWithCas() should fail with RocketChatInvalidResponseException on invalid response`() {
mockServer.expect()
.post()
.withPath("/api/v1/login")
.andReturn(200, "NOT A JSON")
.once()

runBlocking {
try {
sut.loginWithCas("12345678901234567")

throw RuntimeException("unreachable code")
} catch (ex: Exception) {
assertThat(ex, isEqualTo(instanceOf(RocketChatInvalidResponseException::class.java)))
assertThat(ex.message, isEqualTo("Use JsonReader.setLenient(true) to accept malformed JSON at path $"))
assertThat(ex.cause, isEqualTo(instanceOf(JsonEncodingException::class.java)))
}

verify(tokenProvider, never()).save(check { })
}
}

@Test
fun `loginWithCas() should fail with RocketChatApiException when response is not 200 OK`() {
runBlocking {
try {
sut.loginWithCas("12345678901234567")

throw RuntimeException("unreachable code")
} catch (ex: Exception) {
assertThat(ex, isEqualTo(instanceOf(RocketChatApiException::class.java)))
}
verify(tokenProvider, never()).save(check { })
}
}

@Test
fun `signup() should succeed with valid parameters`() {
mockServer.expect()
Expand Down

0 comments on commit 67b55d5

Please sign in to comment.