Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature] Respect private link capability #3738

Merged
merged 6 commits into from
Aug 30, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.ViewMatchers
import androidx.test.espresso.matcher.ViewMatchers.hasSibling
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
import androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility
import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.test.espresso.matcher.ViewMatchers.withTagValue
import androidx.test.espresso.matcher.ViewMatchers.withText
Expand All @@ -45,6 +44,9 @@ import com.owncloud.android.testutil.OC_ACCOUNT
import com.owncloud.android.testutil.OC_CAPABILITY
import com.owncloud.android.testutil.OC_SHARE
import com.owncloud.android.utils.AppTestUtil.OC_FILE
import com.owncloud.android.utils.matchers.assertVisibility
import com.owncloud.android.utils.matchers.isDisplayed
import com.owncloud.android.utils.matchers.withText
import io.mockk.every
import io.mockk.mockk
import org.hamcrest.CoreMatchers
Expand Down Expand Up @@ -88,19 +90,25 @@ class ShareFileFragmentTest {
@Test
fun showHeader() {
loadShareFileFragment()
onView(withId(R.id.shareFileName)).check(matches(withText("img.png")))
R.id.shareFileName.withText("img.png")
}

@Test
fun fileSizeVisible() {
loadShareFileFragment()
onView(withId(R.id.shareFileSize)).check(matches(isDisplayed()))
R.id.shareFileSize.isDisplayed(displayed = true)
}

@Test
fun showPrivateLink() {
loadShareFileFragment()
onView(withId(R.id.getPrivateLinkButton)).check(matches(isDisplayed()))
R.id.getPrivateLinkButton.isDisplayed(displayed = true)
}

@Test
fun hidePrivateLink() {
loadShareFileFragment(capabilities = OC_CAPABILITY.copy(filesPrivateLinks = CapabilityBooleanType.FALSE))
R.id.getPrivateLinkButton.isDisplayed(displayed = false)
}

/******************************************************************************************************
Expand Down Expand Up @@ -222,8 +230,7 @@ class ShareFileFragmentTest {
shares = publicShareList
)

onView(withId(R.id.shareViaLinkSection))
.check(matches(withEffectiveVisibility(ViewMatchers.Visibility.GONE)))
R.id.shareViaLinkSection.assertVisibility(ViewMatchers.Visibility.GONE)
}

@Test
Expand All @@ -236,8 +243,7 @@ class ShareFileFragmentTest {
shares = listOf(publicShareList[0])
)

onView(withId(R.id.addPublicLinkButton))
.check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE)))
R.id.addPublicLinkButton.assertVisibility(ViewMatchers.Visibility.VISIBLE)
}

@Test
Expand All @@ -250,8 +256,7 @@ class ShareFileFragmentTest {
shares = listOf(publicShareList[0])
)

onView(withId(R.id.addPublicLinkButton))
.check(matches(withEffectiveVisibility(ViewMatchers.Visibility.INVISIBLE)))
R.id.addPublicLinkButton.assertVisibility(ViewMatchers.Visibility.INVISIBLE)
}

@Test
Expand All @@ -263,8 +268,7 @@ class ShareFileFragmentTest {
shares = listOf(publicShareList[0])
)

onView(withId(R.id.addPublicLinkButton))
.check(matches(withEffectiveVisibility(ViewMatchers.Visibility.INVISIBLE)))
R.id.addPublicLinkButton.assertVisibility(ViewMatchers.Visibility.INVISIBLE)
}

/******************************************************************************************************
Expand All @@ -278,11 +282,9 @@ class ShareFileFragmentTest {
filesSharingApiEnabled = CapabilityBooleanType.FALSE
)
)
onView(withId(R.id.shareWithUsersSection))
.check(matches(withEffectiveVisibility(ViewMatchers.Visibility.GONE)))
R.id.shareWithUsersSection.assertVisibility(ViewMatchers.Visibility.GONE)

onView(withId(R.id.shareViaLinkSection))
.check(matches(withEffectiveVisibility(ViewMatchers.Visibility.GONE)))
R.id.shareViaLinkSection.assertVisibility(ViewMatchers.Visibility.GONE)
}

@Test
Expand All @@ -292,7 +294,7 @@ class ShareFileFragmentTest {
error = Throwable("It was not possible to retrieve the shares from server")
)
)
onView(withId(com.google.android.material.R.id.snackbar_text)).check(matches(withText(R.string.get_shares_error)))
com.google.android.material.R.id.snackbar_text.withText(R.string.get_shares_error)
}

private fun loadShareFileFragment(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import android.os.RemoteException
import androidx.core.util.Pair
import com.owncloud.android.MainApp
import com.owncloud.android.authentication.AccountUtils
import com.owncloud.android.data.ProviderMeta
import com.owncloud.android.datamodel.OCFile.AvailableOfflineStatus.AVAILABLE_OFFLINE
import com.owncloud.android.datamodel.OCFile.AvailableOfflineStatus.AVAILABLE_OFFLINE_PARENT
import com.owncloud.android.datamodel.OCFile.AvailableOfflineStatus.NOT_AVAILABLE_OFFLINE
Expand Down Expand Up @@ -114,8 +115,6 @@ import java.io.FileOutputStream
import java.io.IOException
import java.io.InputStream
import java.io.OutputStream
import java.util.ArrayList
import java.util.HashSet
import java.util.Vector

class FileDataStorageManager {
Expand Down Expand Up @@ -1369,6 +1368,9 @@ class FileDataStorageManager {
filesBigFileChunking = CapabilityBooleanType.fromValue(c.getIntFromColumnOrThrow(CAPABILITIES_FILES_BIGFILECHUNKING)),
filesUndelete = CapabilityBooleanType.fromValue(c.getIntFromColumnOrThrow(CAPABILITIES_FILES_UNDELETE)),
filesVersioning = CapabilityBooleanType.fromValue(c.getIntFromColumnOrThrow(CAPABILITIES_FILES_VERSIONING)),
filesPrivateLinks = c.getColumnIndex(ProviderMeta.ProviderTableMeta.CAPABILITIES_FILES_PRIVATE_LINKS).takeUnless { it < 0 }
?.let { index -> CapabilityBooleanType.fromValue(c.getInt(index)) }
?: CapabilityBooleanType.UNKNOWN,
filesOcisProviders = null
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,9 @@ class ShareFileFragment : Fragment(), ShareUserListAdapter.ShareUserAdapterListe
private val isPublicShareEnabled
get() = capabilities?.filesSharingPublicEnabled == CapabilityBooleanType.TRUE

private val isPrivateLinkDisabled
get() = capabilities?.filesPrivateLinks == CapabilityBooleanType.FALSE

private val ocCapabilityViewModel: OCCapabilityViewModel by viewModel {
parametersOf(
account?.name
Expand Down Expand Up @@ -246,23 +249,11 @@ class ShareFileFragment : Fragment(), ShareUserListAdapter.ShareUserAdapterListe
}

// Private link button
if (file?.privateLink.isNullOrEmpty()) {
binding.getPrivateLinkButton.visibility = View.INVISIBLE
} else {
binding.getPrivateLinkButton.visibility = View.VISIBLE
}
showOrHidePrivateLink()

// Hide share features sections that are not enabled
hideSectionsDisabledInBuildTime(view)

binding.getPrivateLinkButton.setOnClickListener { listener?.copyOrSendPrivateLink(file!!) }

binding.getPrivateLinkButton.setOnLongClickListener {
// Show a toast message explaining what a private link is
Toast.makeText(activity, R.string.private_link_info, Toast.LENGTH_LONG).show()
true
}

binding.addUserButton.setOnClickListener {
// Show Search Fragment
listener?.showSearchUsersAndGroups()
Expand Down Expand Up @@ -375,6 +366,23 @@ class ShareFileFragment : Fragment(), ShareUserListAdapter.ShareUserAdapterListe
}
}

private fun showOrHidePrivateLink() {
if (file?.privateLink.isNullOrEmpty() || isPrivateLinkDisabled) {
binding.getPrivateLinkButton.visibility = View.INVISIBLE
} else {
with(binding.getPrivateLinkButton) {
visibility = View.VISIBLE
setOnClickListener { listener?.copyOrSendPrivateLink(file!!) }

setOnLongClickListener {
// Show a toast message explaining what a private link is
Toast.makeText(activity, R.string.private_link_info, Toast.LENGTH_LONG).show()
true
}
}
}
}

/**************************************************************************************************************
************************************************ CAPABILITIES ************************************************
**************************************************************************************************************/
Expand All @@ -384,6 +392,8 @@ class ShareFileFragment : Fragment(), ShareUserListAdapter.ShareUserAdapterListe

updatePublicLinkButton()

showOrHidePrivateLink()

// Update view depending on updated capabilities
binding.shareHeaderDivider.isVisible = isShareApiEnabled
binding.shareWithUsersSection.isVisible = isShareApiEnabled
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"formatVersion": 1,
"database": {
"version": 37,
"identityHash": "9783264d43f5f19e25d5f2325fcb1b26",
"identityHash": "71d1fadd8d9bbd892399ade177041868",
"entities": [
{
"tableName": "ocshares",
Expand Down Expand Up @@ -110,7 +110,7 @@
},
{
"tableName": "capabilities",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`account` TEXT, `version_mayor` INTEGER NOT NULL, `version_minor` INTEGER NOT NULL, `version_micro` INTEGER NOT NULL, `version_string` TEXT, `version_edition` TEXT, `core_pollinterval` INTEGER NOT NULL, `dav_chunking_version` TEXT NOT NULL, `sharing_api_enabled` INTEGER NOT NULL DEFAULT -1, `sharing_public_enabled` INTEGER NOT NULL DEFAULT -1, `sharing_public_password_enforced` INTEGER NOT NULL DEFAULT -1, `sharing_public_password_enforced_read_only` INTEGER NOT NULL DEFAULT -1, `sharing_public_password_enforced_read_write` INTEGER NOT NULL DEFAULT -1, `sharing_public_password_enforced_public_only` INTEGER NOT NULL DEFAULT -1, `sharing_public_expire_date_enabled` INTEGER NOT NULL DEFAULT -1, `sharing_public_expire_date_days` INTEGER NOT NULL, `sharing_public_expire_date_enforced` INTEGER NOT NULL DEFAULT -1, `sharing_public_upload` INTEGER NOT NULL DEFAULT -1, `sharing_public_multiple` INTEGER NOT NULL DEFAULT -1, `supports_upload_only` INTEGER NOT NULL DEFAULT -1, `sharing_resharing` INTEGER NOT NULL DEFAULT -1, `sharing_federation_outgoing` INTEGER NOT NULL DEFAULT -1, `sharing_federation_incoming` INTEGER NOT NULL DEFAULT -1, `sharing_user_profile_picture` INTEGER NOT NULL DEFAULT -1, `files_bigfilechunking` INTEGER NOT NULL DEFAULT -1, `files_undelete` INTEGER NOT NULL DEFAULT -1, `files_versioning` INTEGER NOT NULL DEFAULT -1, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `enabled` INTEGER, `version` TEXT, `appsUrl` TEXT, `openUrl` TEXT, `openWebUrl` TEXT, `newUrl` TEXT)",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`account` TEXT, `version_mayor` INTEGER NOT NULL, `version_minor` INTEGER NOT NULL, `version_micro` INTEGER NOT NULL, `version_string` TEXT, `version_edition` TEXT, `core_pollinterval` INTEGER NOT NULL, `dav_chunking_version` TEXT NOT NULL, `sharing_api_enabled` INTEGER NOT NULL DEFAULT -1, `sharing_public_enabled` INTEGER NOT NULL DEFAULT -1, `sharing_public_password_enforced` INTEGER NOT NULL DEFAULT -1, `sharing_public_password_enforced_read_only` INTEGER NOT NULL DEFAULT -1, `sharing_public_password_enforced_read_write` INTEGER NOT NULL DEFAULT -1, `sharing_public_password_enforced_public_only` INTEGER NOT NULL DEFAULT -1, `sharing_public_expire_date_enabled` INTEGER NOT NULL DEFAULT -1, `sharing_public_expire_date_days` INTEGER NOT NULL, `sharing_public_expire_date_enforced` INTEGER NOT NULL DEFAULT -1, `sharing_public_upload` INTEGER NOT NULL DEFAULT -1, `sharing_public_multiple` INTEGER NOT NULL DEFAULT -1, `supports_upload_only` INTEGER NOT NULL DEFAULT -1, `sharing_resharing` INTEGER NOT NULL DEFAULT -1, `sharing_federation_outgoing` INTEGER NOT NULL DEFAULT -1, `sharing_federation_incoming` INTEGER NOT NULL DEFAULT -1, `sharing_user_profile_picture` INTEGER NOT NULL DEFAULT -1, `files_bigfilechunking` INTEGER NOT NULL DEFAULT -1, `files_undelete` INTEGER NOT NULL DEFAULT -1, `files_versioning` INTEGER NOT NULL DEFAULT -1, `files_private_links` INTEGER NOT NULL DEFAULT -1, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `enabled` INTEGER, `version` TEXT, `appsUrl` TEXT, `openUrl` TEXT, `openWebUrl` TEXT, `newUrl` TEXT)",
"fields": [
{
"fieldPath": "accountName",
Expand Down Expand Up @@ -292,6 +292,13 @@
"notNull": true,
"defaultValue": "-1"
},
{
"fieldPath": "filesPrivateLink",
"columnName": "files_private_links",
"affinity": "INTEGER",
"notNull": true,
"defaultValue": "-1"
},
{
"fieldPath": "id",
"columnName": "id",
Expand Down Expand Up @@ -448,7 +455,7 @@
"views": [],
"setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '9783264d43f5f19e25d5f2325fcb1b26')"
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '71d1fadd8d9bbd892399ade177041868')"
]
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -93,5 +93,6 @@ static public class ProviderTableMeta implements BaseColumns {
public static final String CAPABILITIES_FILES_UNDELETE = "files_undelete";
public static final String CAPABILITIES_FILES_VERSIONING = "files_versioning";
public static final String CAPABILITIES_FILES_APP_PROVIDERS = "files_apps_providers";
public static final String CAPABILITIES_FILES_PRIVATE_LINKS = "files_private_links";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import androidx.annotation.VisibleForTesting
import androidx.lifecycle.LiveData
import androidx.lifecycle.Transformations
import com.owncloud.android.data.capabilities.datasources.LocalCapabilitiesDataSource
import com.owncloud.android.data.capabilities.datasources.implementation.OCLocalCapabilitiesDataSource.Companion.toModel
import com.owncloud.android.data.capabilities.db.OCCapabilityDao
import com.owncloud.android.data.capabilities.db.OCCapabilityEntity
import com.owncloud.android.domain.capabilities.model.CapabilityBooleanType
Expand Down Expand Up @@ -79,7 +78,8 @@ class OCLocalCapabilitiesDataSource(
filesBigFileChunking = CapabilityBooleanType.fromValue(filesBigFileChunking),
filesUndelete = CapabilityBooleanType.fromValue(filesUndelete),
filesVersioning = CapabilityBooleanType.fromValue(filesVersioning),
filesOcisProviders = ocisProvider
filesPrivateLinks = CapabilityBooleanType.fromValue(filesPrivateLinks),
filesOcisProviders = ocisProvider,
)

@VisibleForTesting
Expand Down Expand Up @@ -112,7 +112,8 @@ class OCLocalCapabilitiesDataSource(
filesBigFileChunking = filesBigFileChunking.value,
filesUndelete = filesUndelete.value,
filesVersioning = filesVersioning.value,
ocisProvider = filesOcisProviders
filesPrivateLinks = filesPrivateLinks.value,
ocisProvider = filesOcisProviders,
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ class RemoteCapabilityMapper : RemoteMapper<OCCapability, RemoteCapability> {
filesBigFileChunking = CapabilityBooleanType.fromValue(remote.filesBigFileChunking.value),
filesUndelete = CapabilityBooleanType.fromValue(remote.filesUndelete.value),
filesVersioning = CapabilityBooleanType.fromValue(remote.filesVersioning.value),
filesOcisProviders = remote.remoteOcisProviders?.firstOrNull()?.toOCISProvider()
filesPrivateLinks = CapabilityBooleanType.fromValue(remote.filesPrivateLinks.value),
filesOcisProviders = remote.filesAppProviders?.firstOrNull()?.toOCISProvider()
)
}

Expand Down Expand Up @@ -108,7 +109,8 @@ class RemoteCapabilityMapper : RemoteMapper<OCCapability, RemoteCapability> {
filesBigFileChunking = RemoteCapabilityBooleanType.fromValue(model.filesBigFileChunking.value)!!,
filesUndelete = RemoteCapabilityBooleanType.fromValue(model.filesUndelete.value)!!,
filesVersioning = RemoteCapabilityBooleanType.fromValue(model.filesVersioning.value)!!,
remoteOcisProviders = null
filesPrivateLinks = RemoteCapabilityBooleanType.fromValue(model.filesPrivateLinks.value)!!,
filesAppProviders = null
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import com.owncloud.android.data.ProviderMeta.ProviderTableMeta.CAPABILITIES_ACC
import com.owncloud.android.data.ProviderMeta.ProviderTableMeta.CAPABILITIES_CORE_POLLINTERVAL
import com.owncloud.android.data.ProviderMeta.ProviderTableMeta.CAPABILITIES_DAV_CHUNKING_VERSION
import com.owncloud.android.data.ProviderMeta.ProviderTableMeta.CAPABILITIES_FILES_BIGFILECHUNKING
import com.owncloud.android.data.ProviderMeta.ProviderTableMeta.CAPABILITIES_FILES_PRIVATE_LINKS
import com.owncloud.android.data.ProviderMeta.ProviderTableMeta.CAPABILITIES_FILES_UNDELETE
import com.owncloud.android.data.ProviderMeta.ProviderTableMeta.CAPABILITIES_FILES_VERSIONING
import com.owncloud.android.data.ProviderMeta.ProviderTableMeta.CAPABILITIES_SHARING_API_ENABLED
Expand All @@ -53,6 +54,7 @@ import com.owncloud.android.data.ProviderMeta.ProviderTableMeta.CAPABILITIES_VER
import com.owncloud.android.data.ProviderMeta.ProviderTableMeta.CAPABILITIES_VERSION_MICRO
import com.owncloud.android.data.ProviderMeta.ProviderTableMeta.CAPABILITIES_VERSION_MINOR
import com.owncloud.android.data.ProviderMeta.ProviderTableMeta.CAPABILITIES_VERSION_STRING
import com.owncloud.android.domain.capabilities.model.CapabilityBooleanType
import com.owncloud.android.domain.capabilities.model.CapabilityBooleanType.Companion.capabilityBooleanTypeUnknownString
import com.owncloud.android.domain.capabilities.model.OCCapability

Expand Down Expand Up @@ -115,13 +117,15 @@ data class OCCapabilityEntity(
val filesUndelete: Int,
@ColumnInfo(name = CAPABILITIES_FILES_VERSIONING, defaultValue = capabilityBooleanTypeUnknownString)
val filesVersioning: Int,
@ColumnInfo(name = CAPABILITIES_FILES_PRIVATE_LINKS, defaultValue = capabilityBooleanTypeUnknownString)
val filesPrivateLinks: Int,
@Embedded
val ocisProvider: OCCapability.OcisProvider?
) {
@PrimaryKey(autoGenerate = true) var id: Int = 0

companion object {
fun fromCursor(cursor: Cursor): OCCapabilityEntity = cursor.use {
fun fromCursor(cursor: Cursor): OCCapabilityEntity = cursor.use { it ->
OCCapabilityEntity(
it.getString(it.getColumnIndexOrThrow(CAPABILITIES_ACCOUNT_NAME)),
it.getInt(it.getColumnIndexOrThrow(CAPABILITIES_VERSION_MAYOR)),
Expand Down Expand Up @@ -150,6 +154,8 @@ data class OCCapabilityEntity(
it.getInt(it.getColumnIndexOrThrow(CAPABILITIES_FILES_BIGFILECHUNKING)),
it.getInt(it.getColumnIndexOrThrow(CAPABILITIES_FILES_UNDELETE)),
it.getInt(it.getColumnIndexOrThrow(CAPABILITIES_FILES_VERSIONING)),
it.getColumnIndex(CAPABILITIES_FILES_PRIVATE_LINKS).takeUnless { it < 0 }?.let { index -> it.getInt(index) }
?: CapabilityBooleanType.UNKNOWN.value,
null
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ data class OCCapability(
val filesBigFileChunking: CapabilityBooleanType,
val filesUndelete: CapabilityBooleanType,
val filesVersioning: CapabilityBooleanType,
val filesPrivateLinks: CapabilityBooleanType,
val filesOcisProviders: OcisProvider?,
) {
fun isChunkingAllowed(): Boolean {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,5 +51,6 @@ val OC_CAPABILITY =
filesBigFileChunking = CapabilityBooleanType.FALSE,
filesUndelete = CapabilityBooleanType.FALSE,
filesVersioning = CapabilityBooleanType.FALSE,
filesPrivateLinks = CapabilityBooleanType.TRUE,
filesOcisProviders = null,
)