Skip to content

Commit

Permalink
Permissions Cleanup Squeezing in: jellyfin/jellyfin-web#6361
Browse files Browse the repository at this point in the history
  • Loading branch information
JPKribs committed Dec 6, 2024
1 parent 9e73af0 commit b3f6ac8
Show file tree
Hide file tree
Showing 10 changed files with 111 additions and 71 deletions.
41 changes: 41 additions & 0 deletions Shared/Objects/UserPermissions.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
//
// Swiftfin is subject to the terms of the Mozilla Public
// License, v2.0. If a copy of the MPL was not distributed with this
// file, you can obtain one at https://mozilla.org/MPL/2.0/.
//
// Copyright (c) 2024 Jellyfin & Jellyfin Contributors
//

import JellyfinAPI

struct UserPermissions {

let isAdministrator: Bool
let items: UserItemPermissions

init(_ policy: UserPolicy?) {
self.isAdministrator = policy?.isAdministrator ?? false
self.items = UserItemPermissions(policy, isAdministrator: isAdministrator)
}

struct UserItemPermissions {

let canDelete: Bool
let canDownload: Bool
let canEditMetadata: Bool
let canManageSubtitles: Bool
let canManageCollections: Bool
let canManageLyrics: Bool

init(_ policy: UserPolicy?, isAdministrator: Bool) {
self.canDelete = policy?.enableContentDeletion ?? false || policy?.enableContentDeletionFromFolders != []
self.canDownload = policy?.enableContentDownloading ?? false
self.canEditMetadata = isAdministrator
// TODO: SDK 10.9 Enable Comments
self.canManageSubtitles = isAdministrator // || policy?.enableSubtitleManagement ?? false
self.canManageCollections = isAdministrator // || policy?.enableCollectionManagement ?? false
// TODO: SDK 10.10 Enable Comments
self.canManageLyrics = isAdministrator // || policy?.enableSubtitleManagement ?? false
}
}
}
2 changes: 2 additions & 0 deletions Shared/Strings/Strings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ internal enum L10n {
internal static let allGenres = L10n.tr("Localizable", "allGenres", fallback: "All Genres")
/// All Media
internal static let allMedia = L10n.tr("Localizable", "allMedia", fallback: "All Media")
/// Allow collection management
internal static let allowCollectionManagement = L10n.tr("Localizable", "allowCollectionManagement", fallback: "Allow collection management")
/// Allow media item deletion
internal static let allowItemDeletion = L10n.tr("Localizable", "allowItemDeletion", fallback: "Allow media item deletion")
/// Allow media item editing
Expand Down
14 changes: 11 additions & 3 deletions Shared/SwiftfinStore/StoredValue/StoredValues+User.swift
Original file line number Diff line number Diff line change
Expand Up @@ -149,10 +149,10 @@ extension StoredValues.Keys {
)
}

static var enableItemEditor: Key<Bool> {
static var enableItemEditing: Key<Bool> {
CurrentUserKey(
"enableItemEditor",
domain: "enableItemEditor",
"enableItemEditing",
domain: "enableItemEditing",
default: false
)
}
Expand All @@ -164,5 +164,13 @@ extension StoredValues.Keys {
default: false
)
}

static var enableCollectionManagement: Key<Bool> {
CurrentUserKey(
"enableCollectionManagement",
domain: "enableCollectionManagement",
default: false
)
}
}
}
38 changes: 2 additions & 36 deletions Shared/SwiftfinStore/SwiftinStore+UserState.swift
Original file line number Diff line number Diff line change
Expand Up @@ -64,42 +64,8 @@ extension UserState {
}
}

/// User has administrator permissions
var isAdministrator: Bool {
data.policy?.isAdministrator ?? false
}

/// User has permission to delete something whether from a folder or all folders
var hasItemDeletionPermissions: Bool {
data.policy?.enableContentDeletion ?? false || data.policy?.enableContentDeletionFromFolders != []
}

/// User has permission to download items
var hasItemDownloadPermissions: Bool {
data.policy?.enableContentDownloading ?? false
}

/// User has permission to edit items
var hasMetadataEditingPermissions: Bool {
isAdministrator
}

/// User has permission to edit item subtitles
var hasSubtitleManagementPermissions: Bool {
// TODO: SDK 10.9, enable enableSubtitleManagement
isAdministrator // || data.policy?.enableSubtitleManagement ?? false
}

/// User has permission to edit collections
var hasCollectionManagementPermissions: Bool {
// TODO: SDK 10.9, enable enableCollectionManagement
isAdministrator // || data.policy?.enableCollectionManagement ?? false
}

/// User has permission to edit item lyrics
var hasLyricManagementPermissions: Bool {
// TODO: SDK 10.10, enable enableSubtitleManagement
isAdministrator // || data.policy?.enableSubtitleManagement ?? false
var permissions: UserPermissions {
UserPermissions(data.policy)
}

var pinHint: String {
Expand Down
6 changes: 6 additions & 0 deletions Swiftfin.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@
4E5071DB2CFCEC1D003FA2AD /* GenreEditorViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E5071D92CFCEC0E003FA2AD /* GenreEditorViewModel.swift */; };
4E5071E42CFCEFD3003FA2AD /* AddItemElementView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E5071E32CFCEFD1003FA2AD /* AddItemElementView.swift */; };
4E5334A22CD1A28700D59FA8 /* ActionButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E5334A12CD1A28400D59FA8 /* ActionButton.swift */; };
4E556AB02D036F6900733377 /* UserPermissions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E556AAF2D036F5E00733377 /* UserPermissions.swift */; };
4E556AB12D036F6900733377 /* UserPermissions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E556AAF2D036F5E00733377 /* UserPermissions.swift */; };
4E5E48E52AB59806003F1B48 /* CustomizeViewsSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E5E48E42AB59806003F1B48 /* CustomizeViewsSettings.swift */; };
4E63B9FA2C8A5BEF00C25378 /* AdminDashboardView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E63B9F42C8A5BEF00C25378 /* AdminDashboardView.swift */; };
4E63B9FC2C8A5C3E00C25378 /* ActiveSessionsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E63B9FB2C8A5C3E00C25378 /* ActiveSessionsViewModel.swift */; };
Expand Down Expand Up @@ -1202,6 +1204,7 @@
4E5071D92CFCEC0E003FA2AD /* GenreEditorViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GenreEditorViewModel.swift; sourceTree = "<group>"; };
4E5071E32CFCEFD1003FA2AD /* AddItemElementView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddItemElementView.swift; sourceTree = "<group>"; };
4E5334A12CD1A28400D59FA8 /* ActionButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionButton.swift; sourceTree = "<group>"; };
4E556AAF2D036F5E00733377 /* UserPermissions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserPermissions.swift; sourceTree = "<group>"; };
4E5E48E42AB59806003F1B48 /* CustomizeViewsSettings.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomizeViewsSettings.swift; sourceTree = "<group>"; };
4E63B9F42C8A5BEF00C25378 /* AdminDashboardView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AdminDashboardView.swift; sourceTree = "<group>"; };
4E63B9FB2C8A5C3E00C25378 /* ActiveSessionsViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ActiveSessionsViewModel.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -2789,6 +2792,7 @@
E1C8CE7B28FF015000DF5D7B /* TrailingTimestampType.swift */,
4E01446B2D0292E000193038 /* Trie.swift */,
E1EA09682BED78BB004CDE76 /* UserAccessPolicy.swift */,
4E556AAF2D036F5E00733377 /* UserPermissions.swift */,
DFB7C3DE2C7AA42700CE7CDC /* UserSignInState.swift */,
E1D8429229340B8300D1041A /* Utilities.swift */,
E1BDF2E42951475300CC0294 /* VideoPlayerActionButton.swift */,
Expand Down Expand Up @@ -5185,6 +5189,7 @@
E133328929538D8D00EE76AB /* Files.swift in Sources */,
E154967A296CB4B000C4EF88 /* VideoPlayerSettingsView.swift in Sources */,
C46008742A97DFF2002B1C7A /* LiveLoadingOverlay.swift in Sources */,
4E556AB12D036F6900733377 /* UserPermissions.swift in Sources */,
E1575EA0293E7B1E001665B1 /* CGPoint.swift in Sources */,
E1C926132887565C002A7A66 /* EpisodeSelector.swift in Sources */,
E12CC1CD28D135C700678D5D /* NextUpView.swift in Sources */,
Expand Down Expand Up @@ -5796,6 +5801,7 @@
E1D27EE72BBC955F00152D16 /* UnmaskSecureField.swift in Sources */,
E1CAF65D2BA345830087D991 /* MediaType.swift in Sources */,
E1AD105F26D9ADDD003E4A08 /* NameGuidPair.swift in Sources */,
4E556AB02D036F6900733377 /* UserPermissions.swift in Sources */,
E18A8E7D28D606BE00333B9A /* BaseItemDto+VideoPlayerViewModel.swift in Sources */,
4EC2B19B2CC96E7400D866BE /* ServerUsersView.swift in Sources */,
E18E01F1288747230022598C /* PlayButton.swift in Sources */,
Expand Down
2 changes: 1 addition & 1 deletion Swiftfin/Views/ItemEditorView/ItemEditorView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ struct ItemEditorView: View {
private var refreshButtonView: some View {
Section {
RefreshMetadataButton(item: viewModel.item)
.environment(\.isEnabled, userSession?.user.isAdministrator ?? false)
.environment(\.isEnabled, userSession?.user.permissions.isAdministrator ?? false)
} footer: {
LearnMoreButton(L10n.metadata) {
TextPair(
Expand Down
24 changes: 17 additions & 7 deletions Swiftfin/Views/ItemView/ItemView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,21 +32,31 @@ struct ItemView: View {

@StoredValue(.User.enableItemDeletion)
private var enableItemDeletion: Bool
@StoredValue(.User.enableItemEditor)
private var enableItemEditor: Bool
@StoredValue(.User.enableItemEditing)
private var enableItemEditing: Bool
@StoredValue(.User.enableCollectionManagement)
private var enableCollectionManagement: Bool

private var canDelete: Bool {
enableItemDeletion && viewModel.item.canDelete ?? false
if viewModel.item.type == .boxSet {
return enableCollectionManagement && viewModel.item.canDelete ?? false
} else {
return enableItemDeletion && viewModel.item.canDelete ?? false
}
}

private var canDownload: Bool {
viewModel.item.canDownload ?? false
private var canEdit: Bool {
if viewModel.item.type == .boxSet {
return enableCollectionManagement
} else {
return enableItemEditing
}
}

// Use to hide the menu button when not needed.
// Add more checks as needed. For example, canDownload.
private var enableMenu: Bool {
canDelete || enableItemEditor
canDelete || canEdit
}

private static func typeViewModel(for item: BaseItemDto) -> ItemViewModel {
Expand Down Expand Up @@ -132,7 +142,7 @@ struct ItemView: View {
isLoading: viewModel.backgroundStates.contains(.refresh),
isHidden: !enableMenu
) {
if enableItemEditor {
if canEdit {
Button(L10n.edit, systemImage: "pencil") {
router.route(to: \.itemEditor, viewModel)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,36 +17,39 @@ extension CustomizeViewsSettings {
@Injected(\.currentUserSession)
private var userSession

@StoredValue(.User.enableItemEditor)
private var enableItemEditor
@StoredValue(.User.enableItemEditing)
private var enableItemEditing
@StoredValue(.User.enableItemDeletion)
private var enableItemDeletion
@StoredValue(.User.enableCollectionManagement)
private var enableCollectionManagement

var body: some View {
Section(L10n.items) {
/* if userSession?.user.hasItemDownloadPermissions ?? false {
Toggle(L10n.allowItemDeletion, isOn: $enableItemDeletion)
} */

if userSession?.user.hasMetadataEditingPermissions ?? false {
Toggle(L10n.allowItemEditing, isOn: $enableItemEditor)
/// Enable Editing Items from All Visible LIbraries
if userSession?.user.permissions.items.canEditMetadata ?? false {
Toggle(L10n.allowItemEditing, isOn: $enableItemEditing)
}

/* if userSession?.user.hasCollectionManagementPermissions ?? false {
Toggle(L10n.allowItemDeletion, isOn: $enableItemDeletion)
}*/

if userSession?.user.hasItemDeletionPermissions ?? false {
Toggle(L10n.allowItemDeletion, isOn: $enableItemDeletion)
/// Enable Downloading All Items
/* if userSession?.user.permissions.items.canDownload ?? false {
Toggle(L10n.allowItemDownloading, isOn: $enableItemDownloads)
} */
/// Enable Deleting or Editing Collections
if userSession?.user.permissions.items.canManageCollections ?? false {
Toggle(L10n.allowCollectionManagement, isOn: $enableCollectionManagement)
}

/* if userSession?.user.hasLyricManagementPermissions ?? false {
Toggle(L10n.allowItemDeletion, isOn: $enableItemDeletion)
}

if userSession?.user.hasSubtitleManagementPermissions ?? false {
Toggle(L10n.allowItemDeletion, isOn: $enableItemDeletion)
}*/
/// Manage Item Lyrics
/* if userSession?.user.permissions.items.canManageLyrics ?? false {
Toggle(L10n.allowLyricsManagement isOn: $enableLyricsManagement)
} */
/// Manage Item Subtitles
/* if userSession?.user.items.canManageSubtitles ?? false {
Toggle(L10n.allowSubtitleManagement, isOn: $enableSubtitleManagement)
} */
}
/// Enable Deleting Items from Approved Libraries
if userSession?.user.permissions.items.canDelete ?? false {
Toggle(L10n.allowItemDeletion, isOn: $enableItemDeletion)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ struct SettingsView: View {
router.route(to: \.serverConnection, viewModel.userSession.server)
}

if viewModel.userSession.user.isAdministrator {
if viewModel.userSession.user.permissions.isAdministrator {
ChevronButton(L10n.dashboard)
.onSelect {
router.route(to: \.adminDashboard)
Expand Down
4 changes: 4 additions & 0 deletions Translations/en.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -1453,6 +1453,10 @@
// Toggle option for enabling media item editing
"allowItemEditing" = "Allow media item editing";

// Allow Collection Management - Toggle
// Toggle option for enabling collection editing / deletion
"allowCollectionManagement" = "Allow collection management";

// Allow Media Item Deletion - Toggle
// Toggle option for enabling media item deletion
"allowItemDeletion" = "Allow media item deletion";
Expand Down

0 comments on commit b3f6ac8

Please sign in to comment.