neo3/neo_fs/
container.rs

1// Copyright (c) 2023-2025 R3E Network
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6//     http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14//! # NeoFS Container
15//!
16//! This module provides types and functions for working with NeoFS containers.
17
18use chrono::{DateTime, Utc};
19use serde::{Deserialize, Serialize};
20
21use crate::neo_fs::types::{Attributes, ContainerId, OwnerId, PlacementPolicy};
22
23/// Versioning information for a container
24#[derive(Debug, Clone, Serialize, Deserialize)]
25pub struct Version {
26	/// Major version number
27	pub major: u32,
28	/// Minor version number
29	pub minor: u32,
30}
31
32impl Default for Version {
33	fn default() -> Self {
34		Self { major: 1, minor: 0 }
35	}
36}
37
38/// Represents a storage container in NeoFS
39#[derive(Debug, Clone, Serialize, Deserialize)]
40pub struct Container {
41	/// Container ID
42	pub id: Option<ContainerId>,
43
44	/// Owner ID of the container
45	pub owner_id: OwnerId,
46
47	/// Basic ACL
48	pub basic_acl: u32,
49
50	/// Container name
51	pub name: String,
52
53	/// Container creation timestamp
54	#[serde(skip_serializing_if = "Option::is_none")]
55	#[serde(with = "chrono::serde::ts_seconds_option")]
56	pub creation: Option<DateTime<Utc>>,
57
58	/// Container version
59	pub version: Option<Version>,
60
61	/// Container attributes
62	pub attributes: Attributes,
63
64	/// Placement policy for the container
65	pub placement_policy: PlacementPolicy,
66}
67
68impl Container {
69	/// Creates a new container with the given ID and owner ID
70	pub fn new(id: ContainerId, owner_id: OwnerId) -> Self {
71		Self {
72			id: Some(id),
73			owner_id,
74			basic_acl: 0,
75			name: String::new(),
76			creation: None,
77			version: Some(Version::default()),
78			attributes: Attributes::new(),
79			placement_policy: Default::default(),
80		}
81	}
82
83	/// Sets the basic ACL for the container
84	pub fn with_basic_acl(mut self, acl: u32) -> Self {
85		self.basic_acl = acl;
86		self
87	}
88
89	/// Sets the container name
90	pub fn with_name(mut self, name: String) -> Self {
91		self.name = name;
92		self
93	}
94
95	/// Sets the container creation timestamp
96	pub fn with_creation(mut self, creation: DateTime<Utc>) -> Self {
97		self.creation = Some(creation);
98		self
99	}
100
101	/// Sets the container version
102	pub fn with_version(mut self, version: Version) -> Self {
103		self.version = Some(version);
104		self
105	}
106
107	/// Adds an attribute to the container
108	pub fn with_attribute(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
109		self.attributes.add(key, value);
110		self
111	}
112}
113
114/// Permissions for the basic ACL
115#[derive(Debug, Clone)]
116pub struct BasicACL {
117	/// Create and delete objects in the container
118	pub put_allowed: bool,
119	/// Read objects from the container
120	pub get_allowed: bool,
121	/// Query object headers from the container
122	pub head_allowed: bool,
123	/// Delete objects from the container
124	pub delete_allowed: bool,
125	/// List objects in the container
126	pub list_allowed: bool,
127}
128
129impl BasicACL {
130	/// Creates a basic ACL with all permissions set
131	pub fn full_access() -> Self {
132		Self {
133			put_allowed: true,
134			get_allowed: true,
135			head_allowed: true,
136			delete_allowed: true,
137			list_allowed: true,
138		}
139	}
140
141	/// Creates a basic ACL with read-only permissions
142	pub fn read_only() -> Self {
143		Self {
144			put_allowed: false,
145			get_allowed: true,
146			head_allowed: true,
147			delete_allowed: false,
148			list_allowed: true,
149		}
150	}
151
152	/// Converts basic ACL to a bitmask
153	pub fn to_bitmask(&self) -> u32 {
154		let mut bitmask = 0;
155
156		if self.put_allowed {
157			bitmask |= 0b00001;
158		}
159		if self.get_allowed {
160			bitmask |= 0b00010;
161		}
162		if self.head_allowed {
163			bitmask |= 0b00100;
164		}
165		if self.delete_allowed {
166			bitmask |= 0b01000;
167		}
168		if self.list_allowed {
169			bitmask |= 0b10000;
170		}
171
172		bitmask
173	}
174
175	/// Creates a basic ACL from a bitmask
176	pub fn from_bitmask(bitmask: u32) -> Self {
177		Self {
178			put_allowed: (bitmask & 0b00001) != 0,
179			get_allowed: (bitmask & 0b00010) != 0,
180			head_allowed: (bitmask & 0b00100) != 0,
181			delete_allowed: (bitmask & 0b01000) != 0,
182			list_allowed: (bitmask & 0b10000) != 0,
183		}
184	}
185}