Add full Basic authorization and sync with backend-server
This commit is contained in:
parent
60a7e7544e
commit
72b3324821
@ -4,7 +4,7 @@ import com.google.gson.annotations.SerializedName
|
|||||||
|
|
||||||
class LoginDto(
|
class LoginDto(
|
||||||
@SerializedName("username")
|
@SerializedName("username")
|
||||||
val username: String?,
|
val username: String,
|
||||||
@SerializedName("password")
|
@SerializedName("password")
|
||||||
val password: String?
|
val password: String
|
||||||
)
|
)
|
5
app/src/main/java/ru/myitschool/work/data/dto/Role.kt
Normal file
5
app/src/main/java/ru/myitschool/work/data/dto/Role.kt
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
package ru.myitschool.work.data.dto
|
||||||
|
|
||||||
|
enum class Role {
|
||||||
|
ADMIN, USER
|
||||||
|
}
|
@ -3,12 +3,20 @@ package ru.myitschool.work.data.dto
|
|||||||
import com.google.gson.annotations.SerializedName
|
import com.google.gson.annotations.SerializedName
|
||||||
|
|
||||||
class UserInfoDto(
|
class UserInfoDto(
|
||||||
|
@SerializedName("id")
|
||||||
|
val id: Int,
|
||||||
@SerializedName("name")
|
@SerializedName("name")
|
||||||
val fullname: String?,
|
val fullname: String,
|
||||||
|
@SerializedName("login")
|
||||||
|
val login: String,
|
||||||
|
@SerializedName("role")
|
||||||
|
val role: Role,
|
||||||
|
@SerializedName("blocked")
|
||||||
|
val blocked: Boolean,
|
||||||
@SerializedName("photo")
|
@SerializedName("photo")
|
||||||
val imageUrl: String?,
|
val imageUrl: String,
|
||||||
@SerializedName("position")
|
@SerializedName("position")
|
||||||
val position: String?,
|
val position: String,
|
||||||
@SerializedName("lastVisit")
|
@SerializedName("lastVisit")
|
||||||
val lastEntry: String?,
|
val lastEntry: String,
|
||||||
)
|
)
|
@ -15,18 +15,18 @@ class AccountRepositoryImpl @Inject constructor(
|
|||||||
private val accountNetworkDataSource: AccountNetworkDataSource,
|
private val accountNetworkDataSource: AccountNetworkDataSource,
|
||||||
private val userInfoMapper: Lazy<UserInfoMapper>,
|
private val userInfoMapper: Lazy<UserInfoMapper>,
|
||||||
): UserInfoRepository {
|
): UserInfoRepository {
|
||||||
override suspend fun getInfo(username: String): Result<UserInfoEntity> {
|
override suspend fun getInfo(basicAuth: String): Result<UserInfoEntity> {
|
||||||
return withContext(Dispatchers.IO) {
|
return withContext(Dispatchers.IO) {
|
||||||
accountNetworkDataSource.getInfo(username).fold(
|
accountNetworkDataSource.getInfo(basicAuth).fold(
|
||||||
onSuccess = { value -> userInfoMapper.get().invoke(value) },
|
onSuccess = { value -> userInfoMapper.get().invoke(value) },
|
||||||
onFailure = { error -> Result.failure(error) }
|
onFailure = { error -> Result.failure(error) }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun openByQr(username: String, content: String): Result<Unit> {
|
override suspend fun openByQr(basicAuth: String, content: String): Result<Unit> {
|
||||||
return withContext(Dispatchers.IO) {
|
return withContext(Dispatchers.IO) {
|
||||||
accountNetworkDataSource.openByQr(username, content)
|
accountNetworkDataSource.openByQr(basicAuth, content)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,5 +1,6 @@
|
|||||||
package ru.myitschool.work.data.repo
|
package ru.myitschool.work.data.repo
|
||||||
|
|
||||||
|
import android.util.Base64
|
||||||
import dagger.Reusable
|
import dagger.Reusable
|
||||||
import ru.myitschool.work.data.source.AuthorizationNetworkDataSource
|
import ru.myitschool.work.data.source.AuthorizationNetworkDataSource
|
||||||
import ru.myitschool.work.data.source.AuthorizationStorageDataSource
|
import ru.myitschool.work.data.source.AuthorizationStorageDataSource
|
||||||
@ -19,19 +20,21 @@ class AuthorizationRepositoryImpl @Inject constructor(
|
|||||||
|
|
||||||
override suspend fun login(data: LoginDto): Result<Unit> {
|
override suspend fun login(data: LoginDto): Result<Unit> {
|
||||||
return withContext(Dispatchers.IO) {
|
return withContext(Dispatchers.IO) {
|
||||||
authorizationNetworkDataSource.get().checkLogin(data.username!!)
|
val basicAuthToken = Base64.encodeToString("${data.username}:${data.password}".toByteArray(), Base64.NO_WRAP)
|
||||||
|
|
||||||
|
authorizationNetworkDataSource.get().checkAuthCredentials(basicAuthToken)
|
||||||
.onSuccess {
|
.onSuccess {
|
||||||
authorizationStorageDataSource.get().updateLogin(data.username)
|
authorizationStorageDataSource.get().updateBasicAuth(basicAuthToken)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun logout() {
|
override suspend fun logout() {
|
||||||
authorizationStorageDataSource.get().updateLogin(null)
|
authorizationStorageDataSource.get().updateBasicAuth(null)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun getLogin(): Result<String> {
|
override suspend fun getLogin(): Result<String> {
|
||||||
val result = authorizationStorageDataSource.get().login.firstOrNull()
|
val result = authorizationStorageDataSource.get().basicAuthToken.firstOrNull()
|
||||||
return if (result == null) {
|
return if (result == null) {
|
||||||
Result.failure(Exception("Not authorize"))
|
Result.failure(Exception("Not authorize"))
|
||||||
} else {
|
} else {
|
||||||
|
@ -2,20 +2,21 @@ package ru.myitschool.work.data.source
|
|||||||
|
|
||||||
import retrofit2.http.Body
|
import retrofit2.http.Body
|
||||||
import retrofit2.http.GET
|
import retrofit2.http.GET
|
||||||
|
import retrofit2.http.Header
|
||||||
import retrofit2.http.PATCH
|
import retrofit2.http.PATCH
|
||||||
import retrofit2.http.Path
|
import retrofit2.http.Path
|
||||||
import ru.myitschool.work.data.dto.OpenQrDto
|
import ru.myitschool.work.data.dto.OpenQrDto
|
||||||
import ru.myitschool.work.data.dto.UserInfoDto
|
import ru.myitschool.work.data.dto.UserInfoDto
|
||||||
|
|
||||||
interface AccountApi {
|
interface AccountApi {
|
||||||
@GET("api/{username}/info")
|
@GET("api/employee/info")
|
||||||
suspend fun getInfo(
|
suspend fun getInfo(
|
||||||
@Path("username") username: String
|
@Header("Authorization") basicAuth: String
|
||||||
) : UserInfoDto
|
) : UserInfoDto
|
||||||
|
|
||||||
@PATCH("api/{username}/open")
|
@PATCH("api/employee/open")
|
||||||
suspend fun openByQr(
|
suspend fun openByQr(
|
||||||
@Path("username") username: String,
|
@Header("Authorization") basicAuth: String,
|
||||||
@Body content: OpenQrDto
|
@Body content: OpenQrDto
|
||||||
)
|
)
|
||||||
}
|
}
|
@ -14,14 +14,14 @@ class AccountNetworkDataSource @Inject constructor(
|
|||||||
retrofit.create(AccountApi::class.java)
|
retrofit.create(AccountApi::class.java)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getInfo(username: String): Result<UserInfoDto> {
|
suspend fun getInfo(basicAuth: String): Result<UserInfoDto> {
|
||||||
return kotlin.runCatching { api.getInfo(username = username) }
|
return kotlin.runCatching { api.getInfo(basicAuth = basicAuth) }
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun openByQr(username: String, content: String): Result<Unit> {
|
suspend fun openByQr(basicAuth: String, content: String): Result<Unit> {
|
||||||
return kotlin.runCatching {
|
return kotlin.runCatching {
|
||||||
api.openByQr(
|
api.openByQr(
|
||||||
username = username,
|
basicAuth = basicAuth,
|
||||||
content = OpenQrDto(value = content)
|
content = OpenQrDto(value = content)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,19 +1,14 @@
|
|||||||
package ru.myitschool.work.data.source
|
package ru.myitschool.work.data.source
|
||||||
|
|
||||||
import retrofit2.Response
|
import retrofit2.Response
|
||||||
import retrofit2.http.Body
|
|
||||||
import retrofit2.http.GET
|
import retrofit2.http.GET
|
||||||
|
import retrofit2.http.Header
|
||||||
import retrofit2.http.POST
|
import retrofit2.http.POST
|
||||||
import retrofit2.http.Path
|
import retrofit2.http.Path
|
||||||
|
|
||||||
interface AuthorizationApi {
|
interface AuthorizationApi {
|
||||||
@GET("api/{username}/auth")
|
@POST("api/login")
|
||||||
suspend fun checkLogin(
|
|
||||||
@Path("username") username: String
|
|
||||||
) : Response<Unit>
|
|
||||||
|
|
||||||
@GET("api/login")
|
|
||||||
suspend fun login(
|
suspend fun login(
|
||||||
@Body content: AccountApi
|
@Header("Authorization") basicAuthorization: String,
|
||||||
): Response<Unit>
|
): Response<Unit>
|
||||||
}
|
}
|
@ -13,8 +13,8 @@ class AuthorizationNetworkDataSource @Inject constructor(
|
|||||||
retrofit.create(AuthorizationApi::class.java)
|
retrofit.create(AuthorizationApi::class.java)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun checkLogin(username: String): Result<Unit> {
|
suspend fun checkAuthCredentials(basicAuth: String): Result<Unit> {
|
||||||
return kotlin.runCatching { api.checkLogin(username = username) }.fold(
|
return kotlin.runCatching { api.login("Basic $basicAuth") }.fold(
|
||||||
onSuccess = { response ->
|
onSuccess = { response ->
|
||||||
when (response.code()) {
|
when (response.code()) {
|
||||||
200 -> Result.success(Unit)
|
200 -> Result.success(Unit)
|
||||||
|
@ -17,22 +17,22 @@ class AuthorizationStorageDataSource @Inject constructor(
|
|||||||
@ApplicationContext private val context: Context,
|
@ApplicationContext private val context: Context,
|
||||||
) {
|
) {
|
||||||
private val Context.storage: DataStore<Preferences> by preferencesDataStore(name = NAME)
|
private val Context.storage: DataStore<Preferences> by preferencesDataStore(name = NAME)
|
||||||
val login: Flow<String?> = context.storage.data.map { preferences ->
|
val basicAuthToken: Flow<String?> = context.storage.data.map { preferences ->
|
||||||
preferences[LOGIN_KEY]
|
preferences[TOKEN_KEY]
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun updateLogin(username: String?) {
|
suspend fun updateBasicAuth(token: String?) {
|
||||||
context.storage.edit { settings ->
|
context.storage.edit { settings ->
|
||||||
if (username != null) {
|
if (token != null) {
|
||||||
settings[LOGIN_KEY] = username
|
settings[TOKEN_KEY] = "Basic $token"
|
||||||
} else {
|
} else {
|
||||||
settings.remove(LOGIN_KEY)
|
settings.remove(TOKEN_KEY)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private companion object {
|
private companion object {
|
||||||
const val NAME = "auth_data"
|
const val NAME = "auth_data"
|
||||||
val LOGIN_KEY = stringPreferencesKey("login")
|
val TOKEN_KEY = stringPreferencesKey("basicAuthToken")
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -11,7 +11,7 @@ class GetUserInfoUseCase @Inject constructor(
|
|||||||
) {
|
) {
|
||||||
suspend operator fun invoke(): Result<UserInfoEntity> {
|
suspend operator fun invoke(): Result<UserInfoEntity> {
|
||||||
return getLoginUseCase().fold(
|
return getLoginUseCase().fold(
|
||||||
onSuccess = { username -> repo.getInfo(username = username) },
|
onSuccess = { basicAuth -> repo.getInfo(basicAuth) },
|
||||||
onFailure = { error -> Result.failure(error) }
|
onFailure = { error -> Result.failure(error) }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ class OpenByQrUseCase @Inject constructor(
|
|||||||
) {
|
) {
|
||||||
suspend operator fun invoke(content: String): Result<Unit> {
|
suspend operator fun invoke(content: String): Result<Unit> {
|
||||||
return getLoginUseCase().fold(
|
return getLoginUseCase().fold(
|
||||||
onSuccess = { username -> repo.openByQr(username = username, content = content) },
|
onSuccess = { basicAuth -> repo.openByQr(basicAuth = basicAuth, content = content) },
|
||||||
onFailure = { error -> Result.failure(error) }
|
onFailure = { error -> Result.failure(error) }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ package ru.myitschool.work.domain.profile.repo
|
|||||||
import ru.myitschool.work.domain.profile.entities.UserInfoEntity
|
import ru.myitschool.work.domain.profile.entities.UserInfoEntity
|
||||||
|
|
||||||
interface UserInfoRepository {
|
interface UserInfoRepository {
|
||||||
suspend fun getInfo(username: String) : Result<UserInfoEntity>
|
suspend fun getInfo(basicAuth: String) : Result<UserInfoEntity>
|
||||||
|
|
||||||
suspend fun openByQr(username: String, content: String) : Result<Unit>
|
suspend fun openByQr(basicAuth: String, content: String) : Result<Unit>
|
||||||
}
|
}
|
@ -64,6 +64,11 @@ class LoginFragment : Fragment(R.layout.fragment_login) {
|
|||||||
viewModel.inputLogin(s.toString())
|
viewModel.inputLogin(s.toString())
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
binding.password.addTextChangedListener(object : TextChangedListener() {
|
||||||
|
override fun afterTextChanged(s: Editable?) {
|
||||||
|
viewModel.inputPassword(s.toString())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ class LoginViewModel @Inject constructor(
|
|||||||
val state = _state.asStateFlow()
|
val state = _state.asStateFlow()
|
||||||
|
|
||||||
private var login: String = ""
|
private var login: String = ""
|
||||||
private var password: String = "123"//пока пароль по дефалту
|
private var password: String = ""
|
||||||
|
|
||||||
fun clickLogin() {
|
fun clickLogin() {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
@ -67,7 +67,7 @@ class LoginViewModel @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fun passwordCheck(password: String){
|
fun inputPassword(password: String){
|
||||||
this.password = password
|
this.password = password
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user