Skip to content

Commit

Permalink
Add new user/device invitation events in testbed (and add them to coo…
Browse files Browse the repository at this point in the history
…lorg)
  • Loading branch information
touilleMan committed Nov 3, 2023
1 parent 43cd516 commit 4be4582
Show file tree
Hide file tree
Showing 6 changed files with 187 additions and 7 deletions.
31 changes: 31 additions & 0 deletions libparsec/crates/testbed/src/template/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ const SEQUESTER_SERVICE_IDENTITIES: &[SequesterServiceIdentityType] = &[
pub(super) struct TestbedTemplateBuilderCounters {
current_timestamp: DateTime,
current_certificate_index: IndexInt,
current_invitation_token: u128,
current_entry_id: u128,
current_256bits_key: [u8; 32],
current_sequester_service_identity: std::slice::Iter<'static, SequesterServiceIdentityType>,
Expand All @@ -115,6 +116,7 @@ impl Default for TestbedTemplateBuilderCounters {
Self {
current_timestamp: "2000-01-01T00:00:00Z".parse().unwrap(),
current_certificate_index: 0,
current_invitation_token: 0xE000_0000_0000_0000_0000_0000_0000_0000,
current_entry_id: 0xF000_0000_0000_0000_0000_0000_0000_0000,
// All our keys start with 0xAA, then grow up
current_256bits_key: hex!(
Expand All @@ -141,6 +143,10 @@ impl TestbedTemplateBuilderCounters {
self.current_entry_id += 1;
self.current_entry_id.to_be_bytes().into()
}
pub fn next_invitation_token(&mut self) -> InvitationToken {
self.current_invitation_token += 1;
self.current_invitation_token.to_be_bytes().into()
}
fn next_256bits_key(&mut self) -> &[u8; 32] {
// 256 keys should be far enough for our needs
self.current_256bits_key[31]
Expand Down Expand Up @@ -436,6 +442,31 @@ impl<'a> TestbedEventRevokeUserBuilder<'a> {
impl_customize_field_meth!(author, DeviceID);
}

/*
* TestbedEventNewDeviceInvitation
*/

impl_event_builder!(NewDeviceInvitation, [greeter_user_id: UserID]);

impl<'a> TestbedEventNewDeviceInvitationBuilder<'a> {
impl_customize_field_meth!(greeter_user_id, UserID);
impl_customize_field_meth!(created_on, DateTime);
impl_customize_field_meth!(token, InvitationToken);
}

/*
* TestbedEventNewUserInvitation
*/

impl_event_builder!(NewUserInvitation, [claimer_email: String]);

impl<'a> TestbedEventNewUserInvitationBuilder<'a> {
impl_customize_field_meth!(claimer_email, String);
impl_customize_field_meth!(greeter_user_id, UserID);
impl_customize_field_meth!(created_on, DateTime);
impl_customize_field_meth!(token, InvitationToken);
}

/*
* TestbedEventNewRealmBuilder
*/
Expand Down
78 changes: 78 additions & 0 deletions libparsec/crates/testbed/src/template/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,8 @@ pub enum TestbedEvent {
ShareRealm(TestbedEventShareRealm),

// 2) Client/server interaction events not producing certificates
NewDeviceInvitation(TestbedEventNewDeviceInvitation),
NewUserInvitation(TestbedEventNewUserInvitation),
StartRealmReencryption(TestbedEventStartRealmReencryption),
FinishRealmReencryption(TestbedEventFinishRealmReencryption),
CreateOrUpdateUserManifestVlob(TestbedEventCreateOrUpdateUserManifestVlob),
Expand Down Expand Up @@ -185,6 +187,8 @@ impl CrcHash for TestbedEvent {
TestbedEvent::NewDevice(x) => x.crc_hash(hasher),
TestbedEvent::UpdateUserProfile(x) => x.crc_hash(hasher),
TestbedEvent::RevokeUser(x) => x.crc_hash(hasher),
TestbedEvent::NewDeviceInvitation(x) => x.crc_hash(hasher),
TestbedEvent::NewUserInvitation(x) => x.crc_hash(hasher),
TestbedEvent::NewRealm(x) => x.crc_hash(hasher),
TestbedEvent::ShareRealm(x) => x.crc_hash(hasher),
TestbedEvent::StartRealmReencryption(x) => x.crc_hash(hasher),
Expand Down Expand Up @@ -316,6 +320,8 @@ impl TestbedEvent {
| TestbedEvent::NewDevice(_)
| TestbedEvent::UpdateUserProfile(_)
| TestbedEvent::RevokeUser(_)
| TestbedEvent::NewDeviceInvitation(_)
| TestbedEvent::NewUserInvitation(_)
| TestbedEvent::NewRealm(_)
| TestbedEvent::ShareRealm(_)
| TestbedEvent::StartRealmReencryption(_)
Expand Down Expand Up @@ -1247,6 +1253,78 @@ impl TestbedEventShareRealm {
}
}

/*
* TestbedEventNewDeviceInvitation
*/

no_certificate_event!(
TestbedEventNewDeviceInvitation,
[
greeter_user_id: UserID,
created_on: DateTime,
token: InvitationToken,
]
);

impl TestbedEventNewDeviceInvitation {
pub(super) fn from_builder(
builder: &mut TestbedTemplateBuilder,
greeter_user_id: UserID,
) -> Self {
// 1) Consistency checks

utils::assert_organization_bootstrapped(&builder.events);
utils::assert_user_exists_and_not_revoked(&builder.events, &greeter_user_id);

// 2) Actual creation

let token = builder.counters.next_invitation_token();
Self {
created_on: builder.counters.next_timestamp(),
greeter_user_id,
token,
}
}
}

/*
* TestbedEventNewUserInvitation
*/

no_certificate_event!(
TestbedEventNewUserInvitation,
[
greeter_user_id: UserID,
claimer_email: String,
created_on: DateTime,
token: InvitationToken,
]
);

impl TestbedEventNewUserInvitation {
pub(super) fn from_builder(
builder: &mut TestbedTemplateBuilder,
claimer_email: String,
) -> Self {
// 1) Consistency checks

let greeter_user_id = utils::assert_organization_bootstrapped(&builder.events)
.first_user_device_id
.user_id()
.to_owned();

// 2) Actual creation

let token = builder.counters.next_invitation_token();
Self {
created_on: builder.counters.next_timestamp(),
greeter_user_id,
claimer_email,
token,
}
}
}

/*
* TestbedEventStartRealmReencryption
*/
Expand Down
17 changes: 12 additions & 5 deletions libparsec/crates/testbed/src/templates/coolorg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,31 @@ use libparsec_types::prelude::*;
use crate::TestbedTemplate;

/// Coolorg contains:
/// - 3 users: Alice (admin), bob (regular) and mallory (outsider)
/// - 3 users: `alice` (admin), `bob` (regular) and `mallory` (outsider)
/// - devices `alice@dev1`, `bob@dev1` and `mallory@dev1` whose storages are up to date
/// - devices `alice@dev2` and `bob@dev2` whose storages are empty
/// - 1 workspace `wksp1` shared between alice (owner) and bob (reader)
/// - Alice & Bob have their user realm created and user manifest v1 synced with `wksp1` in it
/// - Mallory has not user realm created
/// - 1 pending invitation from Alice for a new user with email `[email protected]`
/// - 1 pending invitation for a new device for Alice
pub(crate) fn generate() -> Arc<TestbedTemplate> {
let mut builder = TestbedTemplate::from_builder("coolorg");

// 1) Create user & devices

builder.bootstrap_organization("alice");
builder.bootstrap_organization("alice"); // alice@dev1
builder.new_user("bob"); // bob@dev1
builder.new_device("alice"); // alice@dev2
builder.new_device("bob"); // bob@dev2
builder.new_user("mallory"); // mallory@dev1

// 2) Create workspace's realm shared between Alice&Bob, and it initial workspace manifest
// 2) Create user & device invitations

builder.new_user_invitation("[email protected]");
builder.new_device_invitation("alice");

// 3) Create workspace's realm shared between Alice&Bob, and it initial workspace manifest

let (wksp1_id, wksp1_key, realm_timestamp) = {
let event = builder.new_realm("alice");
Expand All @@ -40,7 +47,7 @@ pub(crate) fn generate() -> Arc<TestbedTemplate> {

builder.create_or_update_workspace_manifest_vlob("alice@dev1", wksp1_id);

// 3) Create users realms & and v1 manifest for Alice and Bob
// 4) Create users realms & and v1 manifest for Alice and Bob

let wksp1_entry = WorkspaceEntry::new(
wksp1_id,
Expand All @@ -63,7 +70,7 @@ pub(crate) fn generate() -> Arc<TestbedTemplate> {
.then_create_initial_user_manifest_vlob()
.customize(|e| Arc::make_mut(&mut e.manifest).workspaces.push(wksp1_entry));

// 3) Initialize client storages for alice@dev1 and bob@dev1
// 5) Initialize client storages for alice@dev1 and bob@dev1

builder.certificates_storage_fetch_certificates("alice@dev1");
builder.user_storage_fetch_user_vlob("alice@dev1");
Expand Down
12 changes: 12 additions & 0 deletions server/parsec/_parsec_pyi/testbed.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ from parsec._parsec import (
UserProfile,
UserUpdateCertificate,
VlobID,
InvitationToken,
)

def test_get_testbed_template(id: str) -> TestbedTemplateContent | None: ...
Expand Down Expand Up @@ -137,6 +138,17 @@ class TestbedEventRevokeUser:
raw_redacted_certificate: bytes
raw_certificate: bytes

class TestbedEventNewUserInvitation:
claimer_email: str
greeter_user_id: UserID
created_on: DateTime
token: InvitationToken

class TestbedEventNewDeviceInvitation:
greeter_user_id: UserID
created_on: DateTime
token: InvitationToken

class TestbedEventNewRealm:
timestamp: DateTime
author: DeviceID
Expand Down
2 changes: 2 additions & 0 deletions server/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,8 @@ fn entrypoint(py: Python, m: &PyModule) -> PyResult<()> {
tm.add_class::<TestbedEventNewDevice>()?;
tm.add_class::<TestbedEventUpdateUserProfile>()?;
tm.add_class::<TestbedEventRevokeUser>()?;
tm.add_class::<TestbedEventNewUserInvitation>()?;
tm.add_class::<TestbedEventNewDeviceInvitation>()?;
tm.add_class::<TestbedEventNewRealm>()?;
tm.add_class::<TestbedEventShareRealm>()?;
tm.add_class::<TestbedEventStartRealmReencryption>()?;
Expand Down
54 changes: 52 additions & 2 deletions server/src/testbed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ use pyo3::{
use std::sync::Arc;

use crate::{
BlockID, DateTime, DeviceCertificate, DeviceID, DeviceLabel, HumanHandle, PrivateKey,
RealmRole, RealmRoleCertificate, RevokedUserCertificate, SecretKey,
BlockID, DateTime, DeviceCertificate, DeviceID, DeviceLabel, HumanHandle, InvitationToken,
PrivateKey, RealmRole, RealmRoleCertificate, RevokedUserCertificate, SecretKey,
SequesterAuthorityCertificate, SequesterPrivateKeyDer, SequesterPublicKeyDer,
SequesterServiceCertificate, SequesterServiceID, SequesterSigningKeyDer, SequesterVerifyKeyDer,
SigningKey, UserCertificate, UserID, UserProfile, UserUpdateCertificate, VlobID,
Expand Down Expand Up @@ -215,6 +215,37 @@ event_wrapper!(
}
);

event_wrapper!(
TestbedEventNewDeviceInvitation,
[
greeter_user_id: UserID,
created_on: DateTime,
token: InvitationToken,
],
|_py, x: &TestbedEventNewDeviceInvitation| -> PyResult<String> {
Ok(format!(
"greeter_user_id={:?}, created_on={:?}, token={:?}",
x.greeter_user_id.0, x.created_on.0, x.token.0,
))
}
);

event_wrapper!(
TestbedEventNewUserInvitation,
[
claimer_email: String,
greeter_user_id: UserID,
created_on: DateTime,
token: InvitationToken,
],
|_py, x: &TestbedEventNewUserInvitation| -> PyResult<String> {
Ok(format!(
"claimer_email={:?}, greeter_user_id={:?}, created_on={:?}, token={:?}",
x.claimer_email, x.greeter_user_id.0, x.created_on.0, x.token.0,
))
}
);

event_wrapper!(
TestbedEventNewRealm,
[
Expand Down Expand Up @@ -594,6 +625,25 @@ fn event_to_pyobject(
Some(obj.into_py(py))
}

libparsec_testbed::TestbedEvent::NewDeviceInvitation(x) => {
let obj = TestbedEventNewDeviceInvitation {
greeter_user_id: x.greeter_user_id.clone().into(),
created_on: x.created_on.into(),
token: x.token.clone().into(),
};
Some(obj.into_py(py))
}

libparsec_testbed::TestbedEvent::NewUserInvitation(x) => {
let obj = TestbedEventNewUserInvitation {
claimer_email: x.claimer_email.clone(),
greeter_user_id: x.greeter_user_id.clone().into(),
created_on: x.created_on.into(),
token: x.token.clone().into(),
};
Some(obj.into_py(py))
}

libparsec_testbed::TestbedEvent::NewRealm(x) => {
let (certificate, raw_certificate, raw_redacted_certificate) =
single_certificate!(py, x, template, RealmRole);
Expand Down

0 comments on commit 4be4582

Please sign in to comment.