Skip to main content

steel_core/player/
permissions.rs

1use super::{
2    Identifier, PermissionContext, PermissionExpr, PermissionMetadataSet, PermissionMetadataValue,
3    PermissionSet, PermissionState, Player,
4};
5
6#[derive(Clone, Debug, Default)]
7pub(super) struct PlayerPermissionState {
8    pub(super) groups: Vec<String>,
9    pub(super) overrides: PermissionSet,
10    pub(super) metadata_overrides: PermissionMetadataSet,
11    pub(super) effective: PermissionSet,
12    pub(super) effective_metadata: PermissionMetadataSet,
13    pub(super) version: u64,
14}
15
16impl PlayerPermissionState {
17    pub(super) fn replace(
18        &mut self,
19        groups: Vec<String>,
20        overrides: PermissionSet,
21        metadata_overrides: PermissionMetadataSet,
22        effective: PermissionSet,
23        effective_metadata: PermissionMetadataSet,
24    ) -> u64 {
25        let version = self.version.wrapping_add(1);
26        *self = Self {
27            groups,
28            overrides,
29            metadata_overrides,
30            effective,
31            effective_metadata,
32            version,
33        };
34        version
35    }
36}
37
38impl Player {
39    /// Replaces assigned groups, direct overrides, metadata, and effective state.
40    pub fn set_permission_state(
41        &self,
42        groups: Vec<String>,
43        overrides: PermissionSet,
44        metadata_overrides: PermissionMetadataSet,
45        effective: PermissionSet,
46        effective_metadata: PermissionMetadataSet,
47    ) -> u64 {
48        self.permissions.lock().replace(
49            groups,
50            overrides,
51            metadata_overrides,
52            effective,
53            effective_metadata,
54        )
55    }
56
57    /// Returns a snapshot of effective permissions.
58    #[must_use]
59    pub fn permissions(&self) -> PermissionSet {
60        self.permissions.lock().effective.clone()
61    }
62
63    /// Returns assigned permission groups.
64    #[must_use]
65    pub fn permission_groups(&self) -> Vec<String> {
66        self.permissions.lock().groups.clone()
67    }
68
69    /// Returns whether the latest published subject state assigns the operator group.
70    #[must_use]
71    pub(crate) fn is_operator(&self) -> bool {
72        self.server
73            .upgrade()
74            .is_some_and(|server| server.is_operator(self.gameprofile.id))
75    }
76
77    /// Returns direct permission overrides.
78    #[must_use]
79    pub fn permission_overrides(&self) -> PermissionSet {
80        self.permissions.lock().overrides.clone()
81    }
82
83    /// Returns direct permission metadata overrides.
84    #[must_use]
85    pub fn permission_metadata_overrides(&self) -> PermissionMetadataSet {
86        self.permissions.lock().metadata_overrides.clone()
87    }
88
89    /// Returns the current permission snapshot version.
90    #[must_use]
91    pub fn permission_state_version(&self) -> u64 {
92        self.permissions.lock().version
93    }
94
95    /// Returns whether the player satisfies an expression in their current world.
96    #[must_use]
97    pub fn has_permission(&self, permission: &PermissionExpr) -> bool {
98        let world = self.get_world();
99        let context = PermissionContext::for_world(world.key.clone());
100        self.has_permission_in(permission, &context)
101    }
102
103    /// Returns whether the player satisfies an expression in an explicit context.
104    #[must_use]
105    pub fn has_permission_in(
106        &self,
107        permission: &PermissionExpr,
108        context: &PermissionContext,
109    ) -> bool {
110        self.permissions
111            .lock()
112            .effective
113            .allows_in(permission, context)
114    }
115
116    /// Resolves an expression in the player's current world.
117    #[must_use]
118    pub fn permission_state(&self, permission: &PermissionExpr) -> Option<PermissionState> {
119        let world = self.get_world();
120        let context = PermissionContext::for_world(world.key.clone());
121        self.permission_state_in(permission, &context)
122    }
123
124    /// Resolves an expression in an explicit context.
125    #[must_use]
126    pub fn permission_state_in(
127        &self,
128        permission: &PermissionExpr,
129        context: &PermissionContext,
130    ) -> Option<PermissionState> {
131        self.permissions
132            .lock()
133            .effective
134            .resolve_in(permission, context)
135    }
136
137    /// Resolves one permission metadata value in the player's current world.
138    #[must_use]
139    pub fn permission_metadata(&self, key: &Identifier) -> Option<PermissionMetadataValue> {
140        let world = self.get_world();
141        let context = PermissionContext::for_world(world.key.clone());
142        self.permission_metadata_in(key, &context)
143    }
144
145    /// Resolves one permission metadata value in an explicit context.
146    #[must_use]
147    pub fn permission_metadata_in(
148        &self,
149        key: &Identifier,
150        context: &PermissionContext,
151    ) -> Option<PermissionMetadataValue> {
152        self.permissions
153            .lock()
154            .effective_metadata
155            .resolve_in(key, context)
156            .cloned()
157    }
158}