Commit 385c30bd authored by Leonardo Aramaki's avatar Leonardo Aramaki

Implement a Permission repository that uses SharedPreferences

parent 657cd088
...@@ -19,7 +19,7 @@ import chat.rocket.android.dagger.qualifier.ForMessages ...@@ -19,7 +19,7 @@ import chat.rocket.android.dagger.qualifier.ForMessages
import chat.rocket.android.helper.FrescoAuthInterceptor import chat.rocket.android.helper.FrescoAuthInterceptor
import chat.rocket.android.helper.MessageParser import chat.rocket.android.helper.MessageParser
import chat.rocket.android.infrastructure.LocalRepository import chat.rocket.android.infrastructure.LocalRepository
import chat.rocket.android.infrastructure.SharedPrefsLocalRepository import chat.rocket.android.infrastructure.SharedPreferencesLocalRepository
import chat.rocket.android.push.GroupedPush import chat.rocket.android.push.GroupedPush
import chat.rocket.android.push.PushManager import chat.rocket.android.push.PushManager
import chat.rocket.android.server.domain.* import chat.rocket.android.server.domain.*
...@@ -111,11 +111,11 @@ class AppModule { ...@@ -111,11 +111,11 @@ class AppModule {
@Singleton @Singleton
fun provideOkHttpClient(logger: HttpLoggingInterceptor): OkHttpClient { fun provideOkHttpClient(logger: HttpLoggingInterceptor): OkHttpClient {
return OkHttpClient.Builder() return OkHttpClient.Builder()
.addInterceptor(logger) .addInterceptor(logger)
.connectTimeout(15, TimeUnit.SECONDS) .connectTimeout(15, TimeUnit.SECONDS)
.readTimeout(20, TimeUnit.SECONDS) .readTimeout(20, TimeUnit.SECONDS)
.writeTimeout(15, TimeUnit.SECONDS) .writeTimeout(15, TimeUnit.SECONDS)
.build() .build()
} }
@Provides @Provides
...@@ -177,8 +177,8 @@ class AppModule { ...@@ -177,8 +177,8 @@ class AppModule {
@Provides @Provides
@Singleton @Singleton
fun provideLocalRepository(prefs: SharedPreferences): LocalRepository { fun provideLocalRepository(prefs: SharedPreferences, moshi: Moshi): LocalRepository {
return SharedPrefsLocalRepository(prefs) return SharedPreferencesLocalRepository(prefs, moshi)
} }
@Provides @Provides
...@@ -193,6 +193,12 @@ class AppModule { ...@@ -193,6 +193,12 @@ class AppModule {
return SharedPreferencesSettingsRepository(localRepository) return SharedPreferencesSettingsRepository(localRepository)
} }
@Provides
@Singleton
fun providePermissionsRepository(localRepository: LocalRepository, moshi: Moshi): PermissionsRepository {
return SharedPreferencesPermissionsRepository(localRepository, moshi)
}
@Provides @Provides
@Singleton @Singleton
fun provideRoomRepository(): RoomRepository { fun provideRoomRepository(): RoomRepository {
...@@ -258,7 +264,7 @@ class AppModule { ...@@ -258,7 +264,7 @@ class AppModule {
@Provides @Provides
@Singleton @Singleton
fun provideConfiguration(context: Application, client: OkHttpClient): SpannableConfiguration { fun provideConfiguration(context: Application): SpannableConfiguration {
val res = context.resources val res = context.resources
return SpannableConfiguration.builder(context) return SpannableConfiguration.builder(context)
.theme(SpannableTheme.builder() .theme(SpannableTheme.builder()
...@@ -273,12 +279,6 @@ class AppModule { ...@@ -273,12 +279,6 @@ class AppModule {
return MessageParser(context, configuration, settingsInteractor.get(url)) return MessageParser(context, configuration, settingsInteractor.get(url))
} }
@Provides
@Singleton
fun providePermissionInteractor(settingsRepository: SettingsRepository, serverRepository: CurrentServerRepository): GetPermissionsInteractor {
return GetPermissionsInteractor(settingsRepository, serverRepository)
}
@Provides @Provides
@Singleton @Singleton
fun provideAccountsRepository(preferences: SharedPreferences, moshi: Moshi): AccountsRepository = fun provideAccountsRepository(preferences: SharedPreferences, moshi: Moshi): AccountsRepository =
......
...@@ -3,7 +3,21 @@ package chat.rocket.android.dagger.module ...@@ -3,7 +3,21 @@ package chat.rocket.android.dagger.module
import android.content.Context import android.content.Context
import android.content.SharedPreferences import android.content.SharedPreferences
import chat.rocket.android.infrastructure.LocalRepository import chat.rocket.android.infrastructure.LocalRepository
import chat.rocket.android.infrastructure.SharedPrefsLocalRepository import chat.rocket.android.infrastructure.SharedPreferencesLocalRepository
import chat.rocket.android.server.domain.CurrentServerRepository
import chat.rocket.android.server.domain.GetCurrentServerInteractor
import chat.rocket.android.server.infraestructure.SharedPrefsCurrentServerRepository
import chat.rocket.android.util.AppJsonAdapterFactory
import chat.rocket.android.util.TimberLogger
import chat.rocket.common.internal.FallbackSealedClassJsonAdapter
import chat.rocket.common.internal.ISO8601Date
import chat.rocket.common.model.TimestampAdapter
import chat.rocket.common.util.CalendarISO8601Converter
import chat.rocket.common.util.Logger
import chat.rocket.common.util.PlatformLogger
import chat.rocket.core.internal.AttachmentAdapterFactory
import chat.rocket.core.internal.ReactionsAdapter
import com.squareup.moshi.Moshi
import dagger.Module import dagger.Module
import dagger.Provides import dagger.Provides
import javax.inject.Singleton import javax.inject.Singleton
...@@ -11,14 +25,53 @@ import javax.inject.Singleton ...@@ -11,14 +25,53 @@ import javax.inject.Singleton
@Module @Module
class LocalModule { class LocalModule {
@Provides
@Singleton
fun providePlatformLogger(): PlatformLogger {
return TimberLogger
}
@Provides
@Singleton
fun provideCurrentServerRepository(prefs: SharedPreferences): CurrentServerRepository {
return SharedPrefsCurrentServerRepository(prefs)
}
@Provides
@Singleton
fun provideMoshi(
logger: PlatformLogger,
currentServerInteractor: GetCurrentServerInteractor
): Moshi {
val url = currentServerInteractor.get() ?: ""
return Moshi.Builder()
.add(FallbackSealedClassJsonAdapter.ADAPTER_FACTORY)
.add(AppJsonAdapterFactory.INSTANCE)
.add(AttachmentAdapterFactory(Logger(logger, url)))
.add(
java.lang.Long::class.java,
ISO8601Date::class.java,
TimestampAdapter(CalendarISO8601Converter())
)
.add(
Long::class.java,
ISO8601Date::class.java,
TimestampAdapter(CalendarISO8601Converter())
)
.add(ReactionsAdapter())
.build()
}
@Provides @Provides
fun provideSharedPreferences(context: Context): SharedPreferences { fun provideSharedPreferences(context: Context): SharedPreferences {
return context.getSharedPreferences("rocket.chat", Context.MODE_PRIVATE) return context.getSharedPreferences("rocket.chat", Context.MODE_PRIVATE)
} }
@Provides @Provides
@Singleton @Singleton
fun provideLocalRepository(prefs: SharedPreferences): LocalRepository { fun provideLocalRepository(sharedPreferences: SharedPreferences, moshi: Moshi): LocalRepository {
return SharedPrefsLocalRepository(prefs) return SharedPreferencesLocalRepository(sharedPreferences, moshi)
} }
} }
\ No newline at end of file
package chat.rocket.android.infrastructure package chat.rocket.android.infrastructure
import chat.rocket.common.model.User
interface LocalRepository { interface LocalRepository {
fun save(key: String, value: String?) fun save(key: String, value: String?)
...@@ -14,12 +16,16 @@ interface LocalRepository { ...@@ -14,12 +16,16 @@ interface LocalRepository {
fun getLong(key: String, defValue: Long = -1L): Long fun getLong(key: String, defValue: Long = -1L): Long
fun clear(key: String) fun clear(key: String)
fun clearAllFromServer(server: String) fun clearAllFromServer(server: String)
fun getCurrentUser(url: String): User?
fun saveCurrentUser(url: String, user: User)
companion object { companion object {
const val KEY_PUSH_TOKEN = "KEY_PUSH_TOKEN" const val KEY_PUSH_TOKEN = "KEY_PUSH_TOKEN"
const val MIGRATION_FINISHED_KEY = "MIGRATION_FINISHED_KEY" const val MIGRATION_FINISHED_KEY = "MIGRATION_FINISHED_KEY"
const val TOKEN_KEY = "token_" const val TOKEN_KEY = "token_"
const val SETTINGS_KEY = "settings_" const val SETTINGS_KEY = "settings_"
const val PERMISSIONS_KEY = "permissions_"
const val USER_KEY = "user_"
const val CURRENT_USERNAME_KEY = "username_" const val CURRENT_USERNAME_KEY = "username_"
} }
} }
......
...@@ -2,8 +2,26 @@ package chat.rocket.android.infrastructure ...@@ -2,8 +2,26 @@ package chat.rocket.android.infrastructure
import android.content.SharedPreferences import android.content.SharedPreferences
import androidx.core.content.edit import androidx.core.content.edit
import chat.rocket.common.model.User
import com.squareup.moshi.Moshi
class SharedPreferencesLocalRepository(
private val preferences: SharedPreferences,
moshi: Moshi
) : LocalRepository {
private val userAdapter = moshi.adapter(User::class.java)
override fun getCurrentUser(url: String): User? {
return get("${url}_${LocalRepository.USER_KEY}", null)?.let {
userAdapter.fromJson(it)
}
}
override fun saveCurrentUser(url: String, user: User) {
save("${url}_${LocalRepository.USER_KEY}", userAdapter.toJson(user))
}
class SharedPrefsLocalRepository(private val preferences: SharedPreferences) : LocalRepository {
override fun getBoolean(key: String, defValue: Boolean) = preferences.getBoolean(key, defValue) override fun getBoolean(key: String, defValue: Boolean) = preferences.getBoolean(key, defValue)
override fun getFloat(key: String, defValue: Float) = preferences.getFloat(key, defValue) override fun getFloat(key: String, defValue: Float) = preferences.getFloat(key, defValue)
......
package chat.rocket.android.server.domain package chat.rocket.android.server.domain
import chat.rocket.android.infrastructure.LocalRepository
import javax.inject.Inject import javax.inject.Inject
class GetPermissionsInteractor @Inject constructor(private val settingsRepository: SettingsRepository, // Creating rooms
private val currentServerRepository: CurrentServerRepository) { const val CREATE_PUBLIC_CHANNELS = "create-c"
const val CREATE_DIRECT_MESSAGES = "create-d"
const val CREATE_PRIVATE_CHANNELS = "create-p"
private fun publicSettings(): PublicSettings? = settingsRepository.get(currentServerRepository.get()!!) // Messages
const val DELETE_MESSAGE = "delete-message"
const val FORCE_DELETE_MESSAGE = "force-delete-message"
const val EDIT_MESSAGE = "edit-message"
const val PIN_MESSAGE = "pin-message"
const val POST_READONLY = "post-readonly"
class GetPermissionsInteractor @Inject constructor(
private val settingsRepository: SettingsRepository,
private val permissionsRepository: PermissionsRepository,
private val localRepository: LocalRepository,
private val getCurrentServerInteractor: GetCurrentServerInteractor
) {
private fun publicSettings(): PublicSettings? = settingsRepository.get(getCurrentServerUrl()!!)
/** /**
* Check whether user is allowed to delete a message. * Check whether user is allowed to delete a message.
...@@ -31,4 +48,18 @@ class GetPermissionsInteractor @Inject constructor(private val settingsRepositor ...@@ -31,4 +48,18 @@ class GetPermissionsInteractor @Inject constructor(private val settingsRepositor
* Checks whether should show edited message status. * Checks whether should show edited message status.
*/ */
fun showEditedStatus() = publicSettings()?.showEditedStatus() ?: false fun showEditedStatus() = publicSettings()?.showEditedStatus() ?: false
fun canPostToReadOnlyChannels(): Boolean {
val url = getCurrentServerUrl()!!
val currentUserRoles = localRepository.getCurrentUser(url)?.roles
return permissionsRepository.get(url, POST_READONLY)?.let { permission ->
currentUserRoles?.isNotEmpty() == true && permission.roles.any {
currentUserRoles.contains(it)
}
} == true
}
private fun getCurrentServerUrl(): String? {
return getCurrentServerInteractor.get()
}
} }
\ No newline at end of file
package chat.rocket.android.server.domain
import chat.rocket.core.model.Permission
interface PermissionsRepository {
/**
* Store [permission] locally.
*
* @param url The server url from where we're interest to store the permission.
* @param permission The permission to store.
*/
fun save(url: String, permission: Permission)
/**
* Get permission given by the [permissionId] and for the server [url].
*
* @param url The server url from where we're interested on getting the permissions.
* @param permissionId the id of the permission to get.
*
* @return The interested permission or null if not found.
*/
fun get(url: String, permissionId: String): Permission?
}
\ No newline at end of file
...@@ -29,7 +29,8 @@ class SaveActiveUsersInteractor @Inject constructor( ...@@ -29,7 +29,8 @@ class SaveActiveUsersInteractor @Inject constructor(
username = user.username ?: it.username, username = user.username ?: it.username,
status = user.status ?: it.status, status = user.status ?: it.status,
emails = user.emails ?: it.emails, emails = user.emails ?: it.emails,
utcOffset = user.utcOffset ?: it.utcOffset utcOffset = user.utcOffset ?: it.utcOffset,
roles = user.roles
) )
val activeUserList: MutableList<User> = val activeUserList: MutableList<User> =
......
package chat.rocket.android.server.infraestructure
import chat.rocket.android.infrastructure.LocalRepository
import chat.rocket.android.server.domain.PermissionsRepository
import chat.rocket.core.model.Permission
import com.squareup.moshi.Moshi
class SharedPreferencesPermissionsRepository(
private val localRepository: LocalRepository,
moshi: Moshi
) : PermissionsRepository {
private val adapter = moshi.adapter(Permission::class.java)
override fun save(url: String, permission: Permission) {
localRepository.save(getPermissionKey(url, permission.id), adapter.toJson(permission))
}
override fun get(url: String, permissionId: String): Permission? {
return localRepository.get(getPermissionKey(url, permissionId))?.let {
adapter.fromJson(it)
}
}
// Create a key following the pattern: settings_[url]_[permission id]
// eg.: 'settings_https://open.rocket.chat_create-p'
private fun getPermissionKey(url: String, permissionId: String): String {
return "${LocalRepository.PERMISSIONS_KEY}${url}_$permissionId"
}
}
\ No newline at end of file
...@@ -6,7 +6,9 @@ import chat.rocket.android.server.domain.PublicSettings ...@@ -6,7 +6,9 @@ import chat.rocket.android.server.domain.PublicSettings
import chat.rocket.android.server.domain.SettingsRepository import chat.rocket.android.server.domain.SettingsRepository
import chat.rocket.core.internal.SettingsAdapter import chat.rocket.core.internal.SettingsAdapter
class SharedPreferencesSettingsRepository(private val localRepository: LocalRepository) : SettingsRepository { class SharedPreferencesSettingsRepository(
private val localRepository: LocalRepository
) : SettingsRepository {
private val adapter = SettingsAdapter().lenient() private val adapter = SettingsAdapter().lenient()
......
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