Skip to content

Commit aafdbc1

Browse files
committed
Merge branch 'feat/allow-admin-roles' into feat/signed-doc-tests
2 parents 58df4ac + 2bdf498 commit aafdbc1

File tree

10 files changed

+129
-36
lines changed

10 files changed

+129
-36
lines changed

rust/catalyst-signed-doc-spec/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ serde = { version = "1.0.219", features = ["derive"] }
1717

1818
quote = "1.0"
1919
proc-macro2 = "1.0"
20-
build-info = "0.0.41"
20+
build-info = "0.0.39"
2121

2222
[build-dependencies]
23-
build-info-build = "0.0.41"
23+
build-info-build = "0.0.39"

rust/catalyst-signed-doc-spec/src/signers/roles.rs

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,52 @@
44
#[derive(serde::Deserialize)]
55
#[allow(clippy::missing_docs_in_private_items)]
66
pub struct Roles {
7-
pub user: Vec<Role>,
7+
#[serde(default)]
8+
pub user: Vec<UserRole>,
9+
#[serde(default)]
10+
pub admin: Vec<AdminRole>,
811
}
912

1013
/// Role definition
1114
#[derive(serde::Deserialize)]
1215
#[allow(clippy::missing_docs_in_private_items)]
13-
pub enum Role {
16+
pub enum UserRole {
1417
/// Role 0 - A registered User / Voter - Base Role
1518
Registered,
1619
/// Registered for posting proposals
1720
Proposer,
1821
/// Registered as a rep for voting purposes.
1922
Representative,
2023
}
24+
25+
#[derive(serde::Deserialize)]
26+
#[allow(clippy::missing_docs_in_private_items)]
27+
pub enum AdminRole {
28+
/// Root Certificate Authority role.
29+
#[serde(rename = "Root CA")]
30+
RootCA,
31+
/// Brand Certificate Authority role.
32+
#[serde(rename = "Brand CA")]
33+
BrandCA,
34+
/// Campaign Certificate Authority role.
35+
#[serde(rename = "Campaign CA")]
36+
CampaignCA,
37+
/// Category Certificate Authority role.
38+
#[serde(rename = "Category CA")]
39+
CategoryCA,
40+
/// Root Admin role.
41+
#[serde(rename = "Root Admin")]
42+
RootAdmin,
43+
/// Brand Admin role.
44+
#[serde(rename = "Brand Admin")]
45+
BrandAdmin,
46+
/// Campaign Admin role.
47+
#[serde(rename = "Campaign Admin")]
48+
CampaignAdmin,
49+
/// Category Admin role.
50+
#[serde(rename = "Category Admin")]
51+
CategoryAdmin,
52+
/// Moderator role.
53+
#[serde(rename = "Moderator")]
54+
Moderator,
55+
}

rust/catalyst-types/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "catalyst-types"
3-
version = "0.0.7"
3+
version = "0.0.8"
44
edition.workspace = true
55
license.workspace = true
66
authors.workspace = true

rust/catalyst-types/src/catalyst_id/role_index.rs

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,28 @@ pub enum RoleIdError {
3131
pub enum RoleId {
3232
/// Primary required role use for voting and commenting.
3333
Role0 = 0,
34-
3534
/// Delegated representative (dRep) that vote on behalf of delegators.
3635
DelegatedRepresentative = 1,
37-
3836
/// Proposer that enabling creation, collaboration, and submission of proposals.
3937
Proposer = 3,
40-
38+
/// Root Certificate Authority role.
39+
RootCA = 100,
40+
/// Brand Certificate Authority role.
41+
BrandCA = 101,
42+
/// Campaign Certificate Authority role.
43+
CampaignCA = 102,
44+
/// Category Certificate Authority role.
45+
CategoryCA = 103,
46+
/// Root Admin role.
47+
RootAdmin = 104,
48+
/// Brand Admin role.
49+
BrandAdmin = 105,
50+
/// Campaign Admin role.
51+
CampaignAdmin = 106,
52+
/// Category Admin role.
53+
CategoryAdmin = 107,
54+
/// Moderator role.
55+
Moderator = 108,
4156
/// A custom role.
4257
Unknown(u8),
4358
}
@@ -56,6 +71,15 @@ impl RoleId {
5671
RoleId::Role0 => 0,
5772
RoleId::DelegatedRepresentative => 1,
5873
RoleId::Proposer => 3,
74+
RoleId::RootCA => 100,
75+
RoleId::BrandCA => 101,
76+
RoleId::CampaignCA => 102,
77+
RoleId::CategoryCA => 103,
78+
RoleId::RootAdmin => 104,
79+
RoleId::BrandAdmin => 105,
80+
RoleId::CampaignAdmin => 106,
81+
RoleId::CategoryAdmin => 107,
82+
RoleId::Moderator => 108,
5983
RoleId::Unknown(b) => b,
6084
}
6185
}
@@ -73,6 +97,15 @@ impl From<u8> for RoleId {
7397
0 => Self::Role0,
7498
1 => Self::DelegatedRepresentative,
7599
3 => Self::Proposer,
100+
100 => Self::RootCA,
101+
101 => Self::BrandCA,
102+
102 => Self::CampaignCA,
103+
103 => Self::CategoryCA,
104+
104 => Self::RootAdmin,
105+
105 => Self::BrandAdmin,
106+
106 => Self::CampaignAdmin,
107+
107 => Self::CategoryAdmin,
108+
108 => Self::Moderator,
76109
b => Self::Unknown(b),
77110
}
78111
}

rust/signed_doc/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ license.workspace = true
1111
workspace = true
1212

1313
[dependencies]
14-
catalyst-types = { version = "0.0.7", git = "https://github.com/input-output-hk/catalyst-libs.git", tag = "catalyst-types/v0.0.7" }
14+
catalyst-types = { version = "0.0.8", git = "https://github.com/input-output-hk/catalyst-libs.git", tag = "catalyst-types/v0.0.8" }
1515
cbork-utils = { version = "0.0.2", git = "https://github.com/input-output-hk/catalyst-libs.git", tag = "cbork-utils-v0.0.2" }
1616

1717
catalyst-signed-doc-macro = { version = "0.0.1", path = "../catalyst-signed-doc-macro" }

rust/signed_doc/src/providers.rs

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@ use ed25519_dalek::VerifyingKey;
77

88
use crate::{CatalystSignedDocument, DocumentRef};
99

10-
/// `VerifyingKey` Provider trait
11-
pub trait VerifyingKeyProvider: Send + Sync {
12-
/// Try to get `VerifyingKey`
13-
fn try_get_key(
10+
/// `CatalystId` Provider trait
11+
pub trait CatalystIdProvider: Send + Sync {
12+
/// Try to get `VerifyingKey` by the provided `CatalystId` and corresponding `RoleId`
13+
/// and `KeyRotation` Return `None` if the provided `CatalystId` with the
14+
/// corresponding `RoleId` and `KeyRotation` has not been registered.
15+
fn try_get_registered_key(
1416
&self,
1517
kid: &CatalystId,
1618
) -> impl Future<Output = anyhow::Result<Option<VerifyingKey>>> + Send;
@@ -48,8 +50,8 @@ pub mod tests {
4850
use std::{collections::HashMap, time::Duration};
4951

5052
use super::{
51-
CatalystId, CatalystSignedDocument, CatalystSignedDocumentProvider, VerifyingKey,
52-
VerifyingKeyProvider,
53+
CatalystId, CatalystIdProvider, CatalystSignedDocument, CatalystSignedDocumentProvider,
54+
VerifyingKey,
5355
};
5456
use crate::{DocLocator, DocumentRef};
5557

@@ -123,8 +125,8 @@ pub mod tests {
123125
}
124126
}
125127

126-
impl VerifyingKeyProvider for TestCatalystProvider {
127-
async fn try_get_key(
128+
impl CatalystIdProvider for TestCatalystProvider {
129+
async fn try_get_registered_key(
128130
&self,
129131
kid: &CatalystId,
130132
) -> anyhow::Result<Option<VerifyingKey>> {

rust/signed_doc/src/validator/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use rules::Rules;
99

1010
use crate::{
1111
metadata::DocType,
12-
providers::{CatalystSignedDocumentProvider, VerifyingKeyProvider},
12+
providers::{CatalystIdProvider, CatalystSignedDocumentProvider},
1313
CatalystSignedDocument,
1414
};
1515

@@ -38,7 +38,7 @@ pub async fn validate<Provider>(
3838
provider: &Provider,
3939
) -> anyhow::Result<bool>
4040
where
41-
Provider: CatalystSignedDocumentProvider + VerifyingKeyProvider,
41+
Provider: CatalystSignedDocumentProvider + CatalystIdProvider,
4242
{
4343
let Ok(doc_type) = doc.doc_type() else {
4444
doc.report().missing_field(

rust/signed_doc/src/validator/rules/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
use futures::FutureExt;
55

66
use crate::{
7-
providers::{CatalystSignedDocumentProvider, VerifyingKeyProvider},
7+
providers::{CatalystIdProvider, CatalystSignedDocumentProvider},
88
CatalystSignedDocument,
99
};
1010

@@ -80,7 +80,7 @@ impl Rules {
8080
provider: &Provider,
8181
) -> anyhow::Result<bool>
8282
where
83-
Provider: CatalystSignedDocumentProvider + VerifyingKeyProvider,
83+
Provider: CatalystSignedDocumentProvider + CatalystIdProvider,
8484
{
8585
let rules = [
8686
self.id.check(doc, provider).boxed(),
@@ -139,7 +139,7 @@ impl Rules {
139139
section: SectionRule::NotSpecified,
140140
collaborators: CollaboratorsRule::NotSpecified,
141141
content: ContentRule::new(&doc_spec.payload)?,
142-
kid: SignatureKidRule::new(&doc_spec.signers.roles),
142+
kid: SignatureKidRule::new(&doc_spec.signers.roles)?,
143143
signature: SignatureRule { mutlisig: false },
144144
original_author: OriginalAuthorRule,
145145
};

rust/signed_doc/src/validator/rules/signature.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use anyhow::Context;
44
use catalyst_types::problem_report::ProblemReport;
55

66
use crate::{
7-
providers::{CatalystSignedDocumentProvider, VerifyingKeyProvider},
7+
providers::{CatalystIdProvider, CatalystSignedDocumentProvider},
88
signature::{tbs_data, Signature},
99
CatalystSignedDocument,
1010
};
@@ -28,7 +28,7 @@ impl SignatureRule {
2828
provider: &Provider,
2929
) -> anyhow::Result<bool>
3030
where
31-
Provider: CatalystSignedDocumentProvider + VerifyingKeyProvider,
31+
Provider: CatalystSignedDocumentProvider + CatalystIdProvider,
3232
{
3333
if doc.signatures().is_empty() {
3434
doc.report().other(
@@ -74,11 +74,11 @@ async fn validate_signature<Provider>(
7474
report: &ProblemReport,
7575
) -> anyhow::Result<bool>
7676
where
77-
Provider: VerifyingKeyProvider,
77+
Provider: CatalystIdProvider,
7878
{
7979
let kid = sign.kid();
8080

81-
let Some(pk) = provider.try_get_key(kid).await? else {
81+
let Some(pk) = provider.try_get_registered_key(kid).await? else {
8282
report.other(
8383
&format!("Missing public key for {kid}."),
8484
"During public key extraction",

rust/signed_doc/src/validator/rules/signature_kid.rs

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
//! Catalyst Signed Document COSE signature `kid` (Catalyst Id) role validation
22
3-
use catalyst_signed_doc_spec::signers::roles::{Role, Roles};
3+
use std::collections::HashSet;
4+
5+
use catalyst_signed_doc_spec::signers::roles::{AdminRole, Roles, UserRole};
46
use catalyst_types::catalyst_id::role_index::RoleId;
57

68
use crate::CatalystSignedDocument;
@@ -9,24 +11,43 @@ use crate::CatalystSignedDocument;
911
#[derive(Debug)]
1012
pub(crate) struct SignatureKidRule {
1113
/// expected `RoleId` values for the `kid` field
12-
pub(crate) allowed_roles: Vec<RoleId>,
14+
pub(crate) allowed_roles: HashSet<RoleId>,
1315
}
1416

1517
impl SignatureKidRule {
1618
/// Generating `SignatureKidRule` from specs
17-
pub(crate) fn new(spec: &Roles) -> Self {
18-
let allowed_roles = spec
19+
pub(crate) fn new(spec: &Roles) -> anyhow::Result<Self> {
20+
let allowed_roles: HashSet<_> = spec
1921
.user
2022
.iter()
2123
.map(|v| {
2224
match v {
23-
Role::Registered => RoleId::Role0,
24-
Role::Proposer => RoleId::Proposer,
25-
Role::Representative => RoleId::DelegatedRepresentative,
25+
UserRole::Registered => RoleId::Role0,
26+
UserRole::Proposer => RoleId::Proposer,
27+
UserRole::Representative => RoleId::DelegatedRepresentative,
2628
}
2729
})
30+
.chain(spec.admin.iter().map(|v| {
31+
match v {
32+
AdminRole::RootCA => RoleId::RootCA,
33+
AdminRole::BrandCA => RoleId::BrandCA,
34+
AdminRole::CampaignCA => RoleId::CampaignCA,
35+
AdminRole::CategoryCA => RoleId::CategoryCA,
36+
AdminRole::RootAdmin => RoleId::RootAdmin,
37+
AdminRole::BrandAdmin => RoleId::BrandAdmin,
38+
AdminRole::CampaignAdmin => RoleId::CampaignAdmin,
39+
AdminRole::CategoryAdmin => RoleId::CategoryAdmin,
40+
AdminRole::Moderator => RoleId::Moderator,
41+
}
42+
}))
2843
.collect();
29-
Self { allowed_roles }
44+
45+
anyhow::ensure!(
46+
!allowed_roles.is_empty(),
47+
"A list of allowed roles cannot be empty"
48+
);
49+
50+
Ok(Self { allowed_roles })
3051
}
3152

3253
/// Field validation rule
@@ -73,7 +94,9 @@ mod tests {
7394
#[tokio::test]
7495
async fn signature_kid_rule_test() {
7596
let mut rule = SignatureKidRule {
76-
allowed_roles: vec![RoleId::Role0, RoleId::DelegatedRepresentative],
97+
allowed_roles: [RoleId::Role0, RoleId::DelegatedRepresentative]
98+
.into_iter()
99+
.collect(),
77100
};
78101

79102
let sk = ed25519_dalek::SigningKey::generate(&mut rand::rngs::OsRng);
@@ -92,7 +115,7 @@ mod tests {
92115

93116
assert!(rule.check(&doc).await.unwrap());
94117

95-
rule.allowed_roles = vec![RoleId::Proposer];
118+
rule.allowed_roles = [RoleId::Proposer].into_iter().collect();
96119
assert!(!rule.check(&doc).await.unwrap());
97120
}
98121
}

0 commit comments

Comments
 (0)