Files
Client/lib/api/marianumcloud/files_sharing/share_permissions.dart
T

83 lines
2.8 KiB
Dart

/// Nextcloud share permission bitmask helpers. These mirror the constants the
/// OCS `files_sharing` API expects in the `permissions` field. Kept as pure
/// functions (no Flutter/IO) so they are unit-testable.
library;
/// Individual permission bits (Nextcloud `OCS\Constants`).
const int kPermissionRead = 1;
const int kPermissionUpdate = 2;
const int kPermissionCreate = 4;
const int kPermissionDelete = 8;
const int kPermissionShare = 16;
/// User-facing presets that map onto a bitmask.
enum SharePreset {
/// Recipient can only view/download.
readOnly,
/// Recipient can view, edit, add and remove (full editing).
edit,
/// Upload-only "file request" — recipient can add files to a folder but not
/// see existing contents. Only meaningful for folders.
fileDrop,
}
extension SharePresetLabel on SharePreset {
String get label {
switch (this) {
case SharePreset.readOnly:
return 'Nur Lesen';
case SharePreset.edit:
return 'Bearbeiten';
case SharePreset.fileDrop:
return 'Datei-Anfrage';
}
}
}
/// Returns true if [mask] contains the given [flag].
bool hasPermission(int mask, int flag) => mask & flag == flag;
/// Builds the permission bitmask for a [preset].
///
/// [isFolder] matters for the `edit` preset: a file can only carry
/// read+update, while a folder additionally supports create+delete. Nextcloud
/// rejects create/delete on a file ("Failed to update share"), so they must be
/// omitted there. When [allowReshare] is true the reshare bit is added to the
/// editing presets — mirroring how the Nextcloud clients respect the
/// `resharing` capability.
int permissionsFor(
SharePreset preset, {
bool allowReshare = false,
bool isFolder = false,
}) {
switch (preset) {
case SharePreset.readOnly:
return kPermissionRead;
case SharePreset.edit:
var base = kPermissionRead | kPermissionUpdate;
if (isFolder) base |= kPermissionCreate | kPermissionDelete;
return allowReshare ? base | kPermissionShare : base;
case SharePreset.fileDrop:
return kPermissionCreate;
}
}
/// Classifies an arbitrary permission bitmask into the closest preset, or null
/// if it doesn't match any (e.g. a custom combination). The reshare bit is
/// ignored for matching so an "edit" share stays "edit" regardless of reshare.
SharePreset? presetFromBitmask(int mask) {
final normalized = mask & ~kPermissionShare;
if (normalized == kPermissionCreate) return SharePreset.fileDrop;
if (normalized == kPermissionRead) return SharePreset.readOnly;
// Any read share that also carries a write bit (update/create/delete) is
// surfaced as "edit".
const writeBits = kPermissionUpdate | kPermissionCreate | kPermissionDelete;
if (hasPermission(normalized, kPermissionRead) &&
normalized & writeBits != 0) {
return SharePreset.edit;
}
return null;
}