mirror of
https://github.com/sudosylabs/vnidrop.git
synced 2026-08-05 10:29:58 +02:00
feat(core): add configurable share access policy
This commit is contained in:
@@ -50,6 +50,7 @@ private class AndroidFileSystemService(
|
||||
file: PickedShareFile,
|
||||
transferName: String,
|
||||
senderName: String,
|
||||
accessPolicy: ShareAccessPolicy,
|
||||
): Result<Share> = runCatching {
|
||||
context.contentResolver.openFileDescriptor(Uri.parse(file.value), "r").use { descriptor ->
|
||||
checkNotNull(descriptor) { "Could not open selected file descriptor" }
|
||||
@@ -58,6 +59,7 @@ private class AndroidFileSystemService(
|
||||
displayName = file.displayName,
|
||||
transferName = transferName,
|
||||
senderName = senderName,
|
||||
accessPolicy = accessPolicy,
|
||||
).getOrThrow()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,16 +21,40 @@ data class CoreEventModel(
|
||||
val dataJson: String,
|
||||
)
|
||||
|
||||
enum class ShareAccessPolicy {
|
||||
RequireApproval,
|
||||
AnyoneWithTransfer,
|
||||
}
|
||||
|
||||
enum class TransferDirection {
|
||||
Send,
|
||||
Receive,
|
||||
}
|
||||
|
||||
enum class TransferStatus {
|
||||
Importing,
|
||||
Sharing,
|
||||
Receiving,
|
||||
Done,
|
||||
Failed,
|
||||
Cancelled,
|
||||
Stopped,
|
||||
}
|
||||
|
||||
data class Transfer(
|
||||
val localId: String,
|
||||
val transferId: ULong,
|
||||
val direction: String,
|
||||
val status: String,
|
||||
val direction: TransferDirection,
|
||||
val status: TransferStatus,
|
||||
val peerId: String?,
|
||||
val transferName: String?,
|
||||
val contentHash: String?,
|
||||
val fileCount: ULong,
|
||||
val totalSize: ULong,
|
||||
val ticket: String?,
|
||||
val accessPolicy: ShareAccessPolicy,
|
||||
val createdAt: Long,
|
||||
val updatedAt: Long,
|
||||
)
|
||||
|
||||
data class Share(
|
||||
@@ -90,9 +114,21 @@ interface CoreGateway {
|
||||
|
||||
suspend fun initialize(appDataDir: String): Result<Unit>
|
||||
fun shutdown()
|
||||
suspend fun sharePath(path: String, transferName: String, senderName: String): Result<Share>
|
||||
suspend fun shareFileDescriptor(fd: Int, displayName: String, transferName: String, senderName: String): Result<Share>
|
||||
suspend fun shareSecurityScopedFileUrl(fileUrl: String, displayName: String, transferName: String, senderName: String): Result<Share>
|
||||
suspend fun sharePath(path: String, transferName: String, senderName: String, accessPolicy: ShareAccessPolicy): Result<Share>
|
||||
suspend fun shareFileDescriptor(
|
||||
fd: Int,
|
||||
displayName: String,
|
||||
transferName: String,
|
||||
senderName: String,
|
||||
accessPolicy: ShareAccessPolicy,
|
||||
): Result<Share>
|
||||
suspend fun shareSecurityScopedFileUrl(
|
||||
fileUrl: String,
|
||||
displayName: String,
|
||||
transferName: String,
|
||||
senderName: String,
|
||||
accessPolicy: ShareAccessPolicy,
|
||||
): Result<Share>
|
||||
suspend fun inspectTicket(ticket: String): Result<TicketInspectionModel>
|
||||
suspend fun receive(ticket: String, outputDir: String, receiverName: String): Result<Unit>
|
||||
suspend fun receiveWithOutputSink(ticket: String, outputSink: ReceiveOutputSink, receiverName: String): Result<Unit>
|
||||
|
||||
@@ -25,6 +25,7 @@ import uniffi.vnidrop.SourceKind
|
||||
import uniffi.vnidrop.StoredTransfer
|
||||
import uniffi.vnidrop.TicketInspection
|
||||
import uniffi.vnidrop.TransferMetadata
|
||||
import uniffi.vnidrop.TransferAccessMode
|
||||
import uniffi.vnidrop.VnidropCore
|
||||
|
||||
class CoreRepository(
|
||||
@@ -64,7 +65,12 @@ class CoreRepository(
|
||||
_state.value = CoreState()
|
||||
}
|
||||
|
||||
override suspend fun sharePath(path: String, transferName: String, senderName: String): Result<Share> =
|
||||
override suspend fun sharePath(
|
||||
path: String,
|
||||
transferName: String,
|
||||
senderName: String,
|
||||
accessPolicy: ShareAccessPolicy,
|
||||
): Result<Share> =
|
||||
shareSources(
|
||||
sources = listOf(
|
||||
ShareSource(
|
||||
@@ -76,6 +82,7 @@ class CoreRepository(
|
||||
),
|
||||
transferName = transferName,
|
||||
senderName = senderName,
|
||||
accessPolicy = accessPolicy,
|
||||
)
|
||||
|
||||
override suspend fun shareFileDescriptor(
|
||||
@@ -83,6 +90,7 @@ class CoreRepository(
|
||||
displayName: String,
|
||||
transferName: String,
|
||||
senderName: String,
|
||||
accessPolicy: ShareAccessPolicy,
|
||||
): Result<Share> =
|
||||
shareSources(
|
||||
sources = listOf(
|
||||
@@ -95,6 +103,7 @@ class CoreRepository(
|
||||
),
|
||||
transferName = transferName,
|
||||
senderName = senderName,
|
||||
accessPolicy = accessPolicy,
|
||||
)
|
||||
|
||||
override suspend fun shareSecurityScopedFileUrl(
|
||||
@@ -102,6 +111,7 @@ class CoreRepository(
|
||||
displayName: String,
|
||||
transferName: String,
|
||||
senderName: String,
|
||||
accessPolicy: ShareAccessPolicy,
|
||||
): Result<Share> =
|
||||
shareSources(
|
||||
sources = listOf(
|
||||
@@ -114,6 +124,7 @@ class CoreRepository(
|
||||
),
|
||||
transferName = transferName,
|
||||
senderName = senderName,
|
||||
accessPolicy = accessPolicy,
|
||||
)
|
||||
|
||||
override suspend fun inspectTicket(ticket: String): Result<TicketInspectionModel> = runCore {
|
||||
@@ -170,6 +181,7 @@ class CoreRepository(
|
||||
sources: List<ShareSource>,
|
||||
transferName: String,
|
||||
senderName: String,
|
||||
accessPolicy: ShareAccessPolicy,
|
||||
): Result<Share> = runCore {
|
||||
withPlatformPathAccess(sources) {
|
||||
requireCore().shareFiles(
|
||||
@@ -178,6 +190,7 @@ class CoreRepository(
|
||||
transferId = nextTransferId(),
|
||||
transferName = transferName.ifBlank { null },
|
||||
senderName = senderName.ifBlank { null },
|
||||
accessMode = accessPolicy.toNative(),
|
||||
),
|
||||
).toModel()
|
||||
}.also { share ->
|
||||
@@ -243,15 +256,46 @@ private fun CoreEvent.toModel(): CoreEventModel = CoreEventModel(
|
||||
private fun StoredTransfer.toModel(): Transfer = Transfer(
|
||||
localId = localId,
|
||||
transferId = transferId,
|
||||
direction = direction,
|
||||
status = status,
|
||||
direction = direction.toTransferDirection(),
|
||||
status = status.toTransferStatus(),
|
||||
peerId = peerId,
|
||||
transferName = transferName,
|
||||
contentHash = contentHash,
|
||||
fileCount = fileCount,
|
||||
totalSize = totalSize,
|
||||
ticket = ticket,
|
||||
accessPolicy = accessMode.toModel(),
|
||||
createdAt = createdAt,
|
||||
updatedAt = updatedAt,
|
||||
)
|
||||
|
||||
private fun ShareAccessPolicy.toNative(): TransferAccessMode = when (this) {
|
||||
ShareAccessPolicy.RequireApproval -> TransferAccessMode.APPROVAL_REQUIRED
|
||||
ShareAccessPolicy.AnyoneWithTransfer -> TransferAccessMode.PUBLIC
|
||||
}
|
||||
|
||||
private fun TransferAccessMode.toModel(): ShareAccessPolicy = when (this) {
|
||||
TransferAccessMode.APPROVAL_REQUIRED -> ShareAccessPolicy.RequireApproval
|
||||
TransferAccessMode.PUBLIC -> ShareAccessPolicy.AnyoneWithTransfer
|
||||
}
|
||||
|
||||
private fun String.toTransferDirection(): TransferDirection = when (this) {
|
||||
"send" -> TransferDirection.Send
|
||||
"receive" -> TransferDirection.Receive
|
||||
else -> error("Unknown transfer direction: $this")
|
||||
}
|
||||
|
||||
private fun String.toTransferStatus(): TransferStatus = when (this) {
|
||||
"importing" -> TransferStatus.Importing
|
||||
"sharing" -> TransferStatus.Sharing
|
||||
"receiving" -> TransferStatus.Receiving
|
||||
"done" -> TransferStatus.Done
|
||||
"failed" -> TransferStatus.Failed
|
||||
"cancelled" -> TransferStatus.Cancelled
|
||||
"stopped" -> TransferStatus.Stopped
|
||||
else -> error("Unknown transfer status: $this")
|
||||
}
|
||||
|
||||
private fun ShareResult.toModel(): Share = Share(
|
||||
transferId = transferId,
|
||||
ticket = ticket,
|
||||
|
||||
@@ -30,6 +30,7 @@ interface FileSystemService {
|
||||
file: PickedShareFile,
|
||||
transferName: String,
|
||||
senderName: String,
|
||||
accessPolicy: ShareAccessPolicy,
|
||||
): Result<Share>
|
||||
}
|
||||
|
||||
|
||||
@@ -47,11 +47,13 @@ private class IosFileSystemService : FileSystemService {
|
||||
file: PickedShareFile,
|
||||
transferName: String,
|
||||
senderName: String,
|
||||
accessPolicy: ShareAccessPolicy,
|
||||
): Result<Share> = repository.shareSecurityScopedFileUrl(
|
||||
file.value,
|
||||
file.displayName,
|
||||
transferName,
|
||||
senderName,
|
||||
accessPolicy,
|
||||
)
|
||||
|
||||
private fun validateSecurityScopedUrl(value: String): FolderAccessStatus {
|
||||
|
||||
@@ -33,5 +33,6 @@ private class JvmFileSystemService : FileSystemService {
|
||||
file: PickedShareFile,
|
||||
transferName: String,
|
||||
senderName: String,
|
||||
): Result<Share> = repository.sharePath(file.value, transferName, senderName)
|
||||
accessPolicy: ShareAccessPolicy,
|
||||
): Result<Share> = repository.sharePath(file.value, transferName, senderName, accessPolicy)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user