1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
use ockam_core::compat::vec::Vec;
use ockam_core::vault::PublicKey;
use ockam_core::Result;
use serde::{Deserialize, Serialize};

pub use crate::signature::*;
use crate::{CreateKeyChange, EventIdentifier, ProfileEventAttributes, RotateKeyChange};

/// Pre-defined keys in [`ProfileEventAttributes`] map
#[non_exhaustive]
pub struct ProfileEventAttributeKey;

impl ProfileEventAttributeKey {
    /// Human-readable name
    pub const FRIENDLY_NAME: &'static str = "OCKAM_FN";
    /// UTC timestamp
    pub const CREATION_DATE: &'static str = "OCKAM_CD";
}

/// Individual change applied to profile. [`ProfileChangeEvent`] consists of one or more such changes
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct ProfileChange {
    version: u8,
    // TODO: Check attributes serialization
    attributes: ProfileEventAttributes,
    change_type: ProfileChangeType,
}

impl ProfileChange {
    /// Protocol version
    pub fn version(&self) -> u8 {
        self.version
    }
    /// User-specified attributes that will be saved with change
    pub fn attributes(&self) -> &ProfileEventAttributes {
        &self.attributes
    }
    /// Type of change along with type-specific data
    pub fn change_type(&self) -> &ProfileChangeType {
        &self.change_type
    }
}

impl ProfileChange {
    pub(crate) fn new(
        version: u8,
        attributes: ProfileEventAttributes,
        change_type: ProfileChangeType,
    ) -> Self {
        Self {
            version,
            attributes,
            change_type,
        }
    }

    pub fn has_label(&self, label: &str) -> bool {
        self.label() == label
    }

    pub fn label(&self) -> &str {
        match &self.change_type {
            ProfileChangeType::CreateKey(change) => change.data().key_attributes().label(),
            ProfileChangeType::RotateKey(change) => change.data().key_attributes().label(),
        }
    }

    pub(crate) fn public_key(&self) -> Result<PublicKey> {
        Ok(match &self.change_type {
            ProfileChangeType::CreateKey(change) => change.data().public_key(),
            ProfileChangeType::RotateKey(change) => change.data().public_key(),
        }
        .clone())
    }
}

/// Possible types of [`crate::Profile`] changes
#[derive(Serialize, Deserialize, Debug, Clone)]
pub enum ProfileChangeType {
    /// Create key
    CreateKey(CreateKeyChange),
    /// Rotate key
    RotateKey(RotateKeyChange),
}

/// Profile changes with a given event identifier
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ChangeBlock {
    change: ProfileChange,
    prev_event_id: EventIdentifier,
}

impl ChangeBlock {
    /// [`EventIdentifier`] of previous event
    pub fn previous_event_identifier(&self) -> &EventIdentifier {
        &self.prev_event_id
    }
    /// Set of changes been applied
    pub fn change(&self) -> &ProfileChange {
        &self.change
    }
}

impl ChangeBlock {
    /// Create new Changes
    pub fn new(prev_event_id: EventIdentifier, change: ProfileChange) -> Self {
        Self {
            prev_event_id,
            change,
        }
    }
}

/// [`crate::Profile`]s are modified using change events mechanism. One event may have 1 or more [`ProfileChange`]s
/// Proof is used to check whether this event comes from a party authorized to perform such updated
/// Individual changes may include additional proofs, if needed
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ProfileChangeEvent {
    identifier: EventIdentifier,
    change_block: ChangeBlock,
    signatures: Vec<Signature>,
}

pub type Changes = Vec<ProfileChangeEvent>;

impl ProfileChangeEvent {
    /// Unique [`EventIdentifier`]
    pub fn identifier(&self) -> &EventIdentifier {
        &self.identifier
    }
    /// Set of changes been applied
    pub fn change_block(&self) -> &ChangeBlock {
        &self.change_block
    }
    /// Proof is used to check whether this event comes from a party authorized to perform such update
    pub fn signatures(&self) -> &[Signature] {
        &self.signatures
    }
}

impl ProfileChangeEvent {
    /// Create a new profile change event
    pub fn new(
        identifier: EventIdentifier,
        change_block: ChangeBlock,
        signatures: Vec<Signature>,
    ) -> Self {
        ProfileChangeEvent {
            identifier,
            change_block,
            signatures,
        }
    }
}