1use std::borrow::Cow;
5
6use reifydb_codec::key::encoded::EncodedKey;
7use reifydb_macro::KeyCodec;
8use reifydb_value::value::identity::IdentityId;
9
10use super::KeyTag;
11use crate::{
12 interface::catalog::{
13 authentication::AuthenticationId,
14 identity::{IdentityAttributeId, RoleId},
15 policy::PolicyId,
16 token::TokenId,
17 },
18 key::{
19 any::{ByteEncoding, Field, KeyFields, Width},
20 bound::TaggedKeyBoundRange,
21 },
22};
23
24#[derive(Debug, Clone, PartialEq, KeyCodec, Hash)]
25#[key(tag = Identity)]
26pub struct IdentityKey {
27 pub identity: IdentityId,
28}
29
30impl IdentityKey {
31 pub fn new(identity: IdentityId) -> Self {
32 Self {
33 identity,
34 }
35 }
36
37 pub fn encoded(identity: IdentityId) -> EncodedKey {
38 Self::new(identity).encode()
39 }
40
41 pub fn full_scan() -> TaggedKeyBoundRange {
42 TaggedKeyBoundRange::kind(Self::TAG)
43 }
44}
45
46#[cfg(test)]
47mod byte_identical_identity_key {
48 use reifydb_codec::key::serializer::KeySerializer;
49 use reifydb_value::value::uuid::Uuid7;
50 use uuid::Uuid;
51
52 use super::*;
53
54 fn legacy_encode(key: &IdentityKey) -> EncodedKey {
55 let mut serializer = KeySerializer::with_capacity(17);
56 serializer.extend_u8(KeyTag::Identity as u8).extend_identity_id(&key.identity);
57 serializer.to_encoded_key()
58 }
59
60 #[test]
61 fn matches_the_flat_key_encoding() {
62 for byte in [0u8, 1, 2] {
63 let identity = IdentityId::from(Uuid7::from(Uuid::from_bytes([byte; 16])));
64 let key = IdentityKey::new(identity);
65 assert_eq!(legacy_encode(&key).as_slice(), key.encode().as_slice());
66 }
67 }
68}
69
70#[derive(Debug, Clone, PartialEq, KeyCodec, Hash)]
71#[key(tag = IdentityAttribute)]
72pub struct IdentityAttributeKey {
73 pub attribute: IdentityAttributeId,
74}
75
76impl IdentityAttributeKey {
77 pub fn new(attribute: IdentityAttributeId) -> Self {
78 Self {
79 attribute,
80 }
81 }
82
83 pub fn encoded(attribute: IdentityAttributeId) -> EncodedKey {
84 Self::new(attribute).encode()
85 }
86
87 pub fn full_scan() -> TaggedKeyBoundRange {
88 TaggedKeyBoundRange::kind(Self::TAG)
89 }
90}
91
92#[cfg(test)]
93mod byte_identical_identity_attribute_key {
94 use reifydb_codec::key::serializer::KeySerializer;
95
96 use super::*;
97
98 fn legacy_encode(key: &IdentityAttributeKey) -> EncodedKey {
99 let mut serializer = KeySerializer::with_capacity(9);
100 serializer.extend_u8(KeyTag::IdentityAttribute as u8).extend_u64(key.attribute);
101 serializer.to_encoded_key()
102 }
103
104 #[test]
105 fn matches_the_flat_key_encoding() {
106 for attribute in [0u64, 1, 42, u64::MAX] {
107 let key = IdentityAttributeKey::new(attribute);
108 assert_eq!(legacy_encode(&key).as_slice(), key.encode().as_slice());
109 }
110 }
111}
112
113#[derive(Debug, Clone, PartialEq, KeyCodec, Hash)]
114#[key(tag = IdentityAttributeValue)]
115pub struct IdentityAttributeValueKey {
116 pub identity: IdentityId,
117 pub attribute: IdentityAttributeId,
118}
119
120impl IdentityAttributeValueKey {
121 pub fn new(identity: IdentityId, attribute: IdentityAttributeId) -> Self {
122 Self {
123 identity,
124 attribute,
125 }
126 }
127
128 pub fn encoded(identity: IdentityId, attribute: IdentityAttributeId) -> EncodedKey {
129 Self::new(identity, attribute).encode()
130 }
131
132 pub fn full_scan() -> TaggedKeyBoundRange {
133 TaggedKeyBoundRange::kind(Self::TAG)
134 }
135
136 pub fn identity_scan(identity: IdentityId) -> TaggedKeyBoundRange {
137 TaggedKeyBoundRange::prefix(
138 Self::TAG,
139 [Field::BytesDesc(ByteEncoding::Escaped, Cow::Owned(identity.as_bytes().to_vec()))],
140 )
141 }
142}
143
144#[cfg(test)]
145mod byte_identical_identity_attribute_value_key {
146 use reifydb_codec::key::serializer::KeySerializer;
147 use reifydb_value::value::uuid::Uuid7;
148 use uuid::Uuid;
149
150 use super::*;
151
152 fn legacy_encode(key: &IdentityAttributeValueKey) -> EncodedKey {
153 let mut serializer = KeySerializer::with_capacity(25);
154 serializer
155 .extend_u8(KeyTag::IdentityAttributeValue as u8)
156 .extend_identity_id(&key.identity)
157 .extend_u64(key.attribute);
158 serializer.to_encoded_key()
159 }
160
161 #[test]
162 fn matches_the_flat_key_encoding() {
163 for byte in [0u8, 1, 2] {
164 let identity = IdentityId::from(Uuid7::from(Uuid::from_bytes([byte; 16])));
165 for attribute in [0u64, 1, u64::MAX] {
166 let key = IdentityAttributeValueKey::new(identity, attribute);
167 assert_eq!(legacy_encode(&key).as_slice(), key.encode().as_slice());
168 }
169 }
170 }
171}
172
173#[cfg(test)]
174mod identity_attribute_value_key_tests {
175 use std::ops::RangeBounds;
176
177 use reifydb_value::value::{identity::IdentityId, uuid::Uuid7};
178 use uuid::Uuid;
179
180 use super::*;
181
182 fn identity(byte: u8) -> IdentityId {
183 IdentityId::from(Uuid7::from(Uuid::from_bytes([byte; 16])))
184 }
185
186 #[test]
187 fn identity_scan_holds_every_attribute_of_that_identity() {
188 let alice = identity(1);
190 let range = IdentityAttributeValueKey::identity_scan(alice).encode();
191
192 for attribute in [0u64, 1, 2, u64::MAX] {
193 let key = IdentityAttributeValueKey::encoded(alice, attribute);
194 assert!(range.contains(&key), "attribute {attribute} must fall inside the identity scan");
195 }
196 }
197
198 #[test]
199 fn identity_scan_excludes_a_neighbouring_identity() {
200 let range = IdentityAttributeValueKey::identity_scan(identity(1)).encode();
202 let other = IdentityAttributeValueKey::encoded(identity(2), 1);
203
204 assert!(!range.contains(&other), "a different identity must stay outside the scan");
205 }
206}
207
208#[derive(Debug, Clone, PartialEq, KeyCodec, Hash)]
209#[key(tag = Authentication)]
210pub struct AuthenticationKey {
211 pub authentication: AuthenticationId,
212}
213
214impl AuthenticationKey {
215 pub fn new(authentication: AuthenticationId) -> Self {
216 Self {
217 authentication,
218 }
219 }
220
221 pub fn encoded(authentication: AuthenticationId) -> EncodedKey {
222 Self::new(authentication).encode()
223 }
224
225 pub fn full_scan() -> TaggedKeyBoundRange {
226 TaggedKeyBoundRange::kind(Self::TAG)
227 }
228}
229
230#[cfg(test)]
231mod byte_identical_authentication_key {
232 use reifydb_codec::key::serializer::KeySerializer;
233
234 use super::*;
235
236 fn legacy_encode(key: &AuthenticationKey) -> EncodedKey {
237 let mut serializer = KeySerializer::with_capacity(9);
238 serializer.extend_u8(KeyTag::Authentication as u8).extend_u64(key.authentication);
239 serializer.to_encoded_key()
240 }
241
242 #[test]
243 fn matches_the_flat_key_encoding() {
244 for authentication in [0u64, 1, 42, u64::MAX] {
245 let key = AuthenticationKey::new(authentication);
246 assert_eq!(legacy_encode(&key).as_slice(), key.encode().as_slice());
247 }
248 }
249}
250
251#[derive(Debug, Clone, PartialEq, KeyCodec, Hash)]
252#[key(tag = Token)]
253pub struct TokenKey {
254 pub token: TokenId,
255}
256
257impl TokenKey {
258 pub fn new(token: TokenId) -> Self {
259 Self {
260 token,
261 }
262 }
263
264 pub fn encoded(token: TokenId) -> EncodedKey {
265 Self::new(token).encode()
266 }
267
268 pub fn full_scan() -> TaggedKeyBoundRange {
269 TaggedKeyBoundRange::kind(Self::TAG)
270 }
271}
272
273#[cfg(test)]
274mod byte_identical_token_key {
275 use reifydb_codec::key::serializer::KeySerializer;
276
277 use super::*;
278
279 fn legacy_encode(key: &TokenKey) -> EncodedKey {
280 let mut serializer = KeySerializer::with_capacity(9);
281 serializer.extend_u8(KeyTag::Token as u8).extend_u64(key.token);
282 serializer.to_encoded_key()
283 }
284
285 #[test]
286 fn matches_the_flat_key_encoding() {
287 for token in [0u64, 1, 42, u64::MAX] {
288 let key = TokenKey::new(token);
289 assert_eq!(legacy_encode(&key).as_slice(), key.encode().as_slice());
290 }
291 }
292}
293
294#[derive(Debug, Clone, PartialEq, KeyCodec, Hash)]
295#[key(tag = Role)]
296pub struct RoleKey {
297 pub role: RoleId,
298}
299
300impl RoleKey {
301 pub fn new(role: RoleId) -> Self {
302 Self {
303 role,
304 }
305 }
306
307 pub fn encoded(role: RoleId) -> EncodedKey {
308 Self::new(role).encode()
309 }
310
311 pub fn full_scan() -> TaggedKeyBoundRange {
312 TaggedKeyBoundRange::kind(Self::TAG)
313 }
314}
315
316#[cfg(test)]
317mod byte_identical_role_key {
318 use reifydb_codec::key::serializer::KeySerializer;
319
320 use super::*;
321
322 fn legacy_encode(key: &RoleKey) -> EncodedKey {
323 let mut serializer = KeySerializer::with_capacity(9);
324 serializer.extend_u8(KeyTag::Role as u8).extend_u64(key.role);
325 serializer.to_encoded_key()
326 }
327
328 #[test]
329 fn matches_the_flat_key_encoding() {
330 for role in [0u64, 1, 42, u64::MAX] {
331 let key = RoleKey::new(role);
332 assert_eq!(legacy_encode(&key).as_slice(), key.encode().as_slice());
333 }
334 }
335}
336
337#[derive(Debug, Clone, PartialEq, KeyCodec, Hash)]
338#[key(tag = GrantedRole)]
339pub struct GrantedRoleKey {
340 pub identity: IdentityId,
341 pub role: RoleId,
342}
343
344impl GrantedRoleKey {
345 pub fn new(identity: IdentityId, role: RoleId) -> Self {
346 Self {
347 identity,
348 role,
349 }
350 }
351
352 pub fn encoded(identity: IdentityId, role: RoleId) -> EncodedKey {
353 Self::new(identity, role).encode()
354 }
355
356 pub fn full_scan() -> TaggedKeyBoundRange {
357 TaggedKeyBoundRange::kind(Self::TAG)
358 }
359
360 pub fn identity_scan(identity: IdentityId) -> TaggedKeyBoundRange {
361 TaggedKeyBoundRange::prefix(
362 Self::TAG,
363 [Field::BytesDesc(ByteEncoding::Escaped, Cow::Owned(identity.as_bytes().to_vec()))],
364 )
365 }
366}
367
368#[cfg(test)]
369mod byte_identical_granted_role_key {
370 use reifydb_codec::key::serializer::KeySerializer;
371 use reifydb_value::value::uuid::Uuid7;
372 use uuid::Uuid;
373
374 use super::*;
375
376 fn legacy_encode(key: &GrantedRoleKey) -> EncodedKey {
377 let mut serializer = KeySerializer::with_capacity(25);
378 serializer.extend_u8(KeyTag::GrantedRole as u8).extend_identity_id(&key.identity).extend_u64(key.role);
379 serializer.to_encoded_key()
380 }
381
382 #[test]
383 fn matches_the_flat_key_encoding() {
384 for byte in [0u8, 1, 2] {
385 let identity = IdentityId::from(Uuid7::from(Uuid::from_bytes([byte; 16])));
386 for role in [0u64, 1, u64::MAX] {
387 let key = GrantedRoleKey::new(identity, role);
388 assert_eq!(legacy_encode(&key).as_slice(), key.encode().as_slice());
389 }
390 }
391 }
392}
393
394#[cfg(test)]
395mod granted_role_key_tests {
396 use std::ops::RangeBounds;
397
398 use reifydb_value::value::{identity::IdentityId, uuid::Uuid7};
399 use uuid::Uuid;
400
401 use super::*;
402
403 fn identity(byte: u8) -> IdentityId {
404 IdentityId::from(Uuid7::from(Uuid::from_bytes([byte; 16])))
405 }
406
407 #[test]
408 fn identity_scan_holds_every_role_of_that_identity() {
409 let alice = identity(1);
411 let range = GrantedRoleKey::identity_scan(alice).encode();
412
413 for role in [0u64, 1, 2, u64::MAX] {
414 let key = GrantedRoleKey::encoded(alice, role);
415 assert!(range.contains(&key), "role {role} must fall inside the identity scan");
416 }
417 }
418
419 #[test]
420 fn identity_scan_excludes_a_neighbouring_identity() {
421 let range = GrantedRoleKey::identity_scan(identity(1)).encode();
423
424 assert!(!range.contains(&GrantedRoleKey::encoded(identity(2), 1)));
425 }
426}
427
428#[derive(Debug, Clone, PartialEq, KeyCodec, Hash)]
429#[key(tag = Policy)]
430pub struct PolicyKey {
431 pub policy: PolicyId,
432}
433
434impl PolicyKey {
435 pub fn new(policy: PolicyId) -> Self {
436 Self {
437 policy,
438 }
439 }
440
441 pub fn encoded(policy: PolicyId) -> EncodedKey {
442 Self::new(policy).encode()
443 }
444
445 pub fn full_scan() -> TaggedKeyBoundRange {
446 TaggedKeyBoundRange::kind(Self::TAG)
447 }
448}
449
450#[cfg(test)]
451mod byte_identical_policy_key {
452 use reifydb_codec::key::serializer::KeySerializer;
453
454 use super::*;
455
456 fn legacy_encode(key: &PolicyKey) -> EncodedKey {
457 let mut serializer = KeySerializer::with_capacity(9);
458 serializer.extend_u8(KeyTag::Policy as u8).extend_u64(key.policy);
459 serializer.to_encoded_key()
460 }
461
462 #[test]
463 fn matches_the_flat_key_encoding() {
464 for policy in [0u64, 1, 42, u64::MAX] {
465 let key = PolicyKey::new(policy);
466 assert_eq!(legacy_encode(&key).as_slice(), key.encode().as_slice());
467 }
468 }
469}
470
471#[derive(Debug, Clone, PartialEq, KeyCodec, Hash)]
472#[key(tag = PolicyOp)]
473pub struct PolicyOpKey {
474 pub policy: PolicyId,
475 pub op_index: u64,
476}
477
478impl PolicyOpKey {
479 pub fn new(policy: PolicyId, op_index: u64) -> Self {
480 Self {
481 policy,
482 op_index,
483 }
484 }
485
486 pub fn encoded(policy: PolicyId, op_index: u64) -> EncodedKey {
487 Self::new(policy, op_index).encode()
488 }
489
490 pub fn full_scan() -> TaggedKeyBoundRange {
491 TaggedKeyBoundRange::kind(Self::TAG)
492 }
493
494 pub fn policy_scan(policy: PolicyId) -> TaggedKeyBoundRange {
495 TaggedKeyBoundRange::prefix(Self::TAG, [Field::UDesc(Width::U64, policy as u128)])
496 }
497}
498
499#[cfg(test)]
500mod byte_identical_policy_op_key {
501 use reifydb_codec::key::serializer::KeySerializer;
502
503 use super::*;
504
505 fn legacy_encode(key: &PolicyOpKey) -> EncodedKey {
506 let mut serializer = KeySerializer::with_capacity(17);
507 serializer.extend_u8(KeyTag::PolicyOp as u8).extend_u64(key.policy).extend_u64(key.op_index);
508 serializer.to_encoded_key()
509 }
510
511 #[test]
512 fn matches_the_flat_key_encoding() {
513 for policy in [0u64, 1, u64::MAX] {
514 for op_index in [0u64, 1, u64::MAX] {
515 let key = PolicyOpKey::new(policy, op_index);
516 assert_eq!(legacy_encode(&key).as_slice(), key.encode().as_slice());
517 }
518 }
519 }
520}
521
522#[cfg(test)]
523mod policy_op_key_tests {
524 use std::ops::RangeBounds;
525
526 use super::*;
527
528 #[test]
529 fn policy_scan_holds_every_op_index_of_that_policy() {
530 let range = PolicyOpKey::policy_scan(7).encode();
532
533 for op_index in [0u64, 1, 2, u64::MAX] {
534 let key = PolicyOpKey::encoded(7, op_index);
535 assert!(range.contains(&key), "op index {op_index} must fall inside the policy scan");
536 }
537 }
538
539 #[test]
540 fn policy_scan_excludes_a_neighbouring_policy() {
541 let range = PolicyOpKey::policy_scan(7).encode();
543
544 assert!(!range.contains(&PolicyOpKey::encoded(6, 1)));
545 assert!(!range.contains(&PolicyOpKey::encoded(8, 1)));
546 }
547}