libsignal_service/groups_v2/
model.rs

1use std::{convert::TryFrom, convert::TryInto};
2
3use derivative::Derivative;
4use libsignal_protocol::ServiceId;
5use serde::{Deserialize, Serialize};
6use uuid::Uuid;
7use zkgroup::profiles::ProfileKey;
8
9use super::GroupDecodingError;
10
11#[derive(Copy, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
12pub enum Role {
13    Unknown,
14    Default,
15    Administrator,
16}
17
18#[derive(Derivative, Clone, Deserialize, Serialize)]
19#[derivative(Debug)]
20pub struct Member {
21    pub uuid: Uuid,
22    pub role: Role,
23    #[derivative(Debug = "ignore")]
24    pub profile_key: ProfileKey,
25    pub joined_at_revision: u32,
26}
27
28impl PartialEq for Member {
29    fn eq(&self, other: &Self) -> bool {
30        self.uuid == other.uuid
31    }
32}
33
34#[derive(Clone, Debug, PartialEq, Eq)]
35pub struct PendingMember {
36    pub address: ServiceId,
37    pub role: Role,
38    pub added_by_uuid: Uuid,
39    pub timestamp: u64,
40}
41
42#[derive(Derivative, Clone)]
43#[derivative(Debug)]
44pub struct RequestingMember {
45    pub uuid: Uuid,
46    #[derivative(Debug = "ignore")]
47    pub profile_key: ProfileKey,
48    pub timestamp: u64,
49}
50
51impl PartialEq for RequestingMember {
52    fn eq(&self, other: &Self) -> bool {
53        self.uuid == other.uuid
54    }
55}
56
57#[derive(Copy, Debug, Clone, PartialEq, Serialize, Deserialize)]
58pub enum AccessRequired {
59    Unknown,
60    Any,
61    Member,
62    Administrator,
63    Unsatisfiable,
64}
65
66#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
67pub struct AccessControl {
68    pub attributes: AccessRequired,
69    pub members: AccessRequired,
70    pub add_from_invite_link: AccessRequired,
71}
72
73#[derive(Debug, Clone, PartialEq)]
74pub struct Group {
75    pub title: String,
76    pub avatar: String,
77    pub disappearing_messages_timer: Option<Timer>,
78    pub access_control: Option<AccessControl>,
79    pub revision: u32,
80    pub members: Vec<Member>,
81    pub pending_members: Vec<PendingMember>,
82    pub requesting_members: Vec<RequestingMember>,
83    pub invite_link_password: Vec<u8>,
84    pub description: Option<String>,
85}
86
87#[derive(Debug, Clone)]
88pub struct GroupChanges {
89    pub editor: Uuid,
90    pub revision: u32,
91    pub changes: Vec<GroupChange>,
92}
93
94#[derive(Derivative, Clone)]
95#[derivative(Debug)]
96pub enum GroupChange {
97    NewMember(Member),
98    DeleteMember(Uuid),
99    ModifyMemberRole {
100        uuid: Uuid,
101        role: Role,
102    },
103    ModifyMemberProfileKey {
104        uuid: Uuid,
105        #[derivative(Debug = "ignore")]
106        profile_key: ProfileKey,
107    },
108    // for open groups
109    NewPendingMember(PendingMember),
110    DeletePendingMember(Uuid),
111    PromotePendingMember {
112        uuid: Uuid,
113        #[derivative(Debug = "ignore")]
114        profile_key: ProfileKey,
115    },
116    // when admin control is enabled
117    NewRequestingMember(RequestingMember),
118    DeleteRequestingMember(Uuid),
119    PromoteRequestingMember {
120        uuid: Uuid,
121        role: Role,
122    },
123    // group metadata
124    Title(String),
125    Avatar(String),
126    Timer(Option<Timer>),
127    Description(Option<String>),
128    AttributeAccess(AccessRequired),
129    MemberAccess(AccessRequired),
130    InviteLinkAccess(AccessRequired),
131    InviteLinkPassword(String),
132    AnnouncementOnly(bool),
133}
134
135#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
136pub struct Timer {
137    pub duration: u32,
138}
139
140// Conversion from and to protobuf definitions
141
142impl TryFrom<i32> for Role {
143    type Error = GroupDecodingError;
144
145    fn try_from(value: i32) -> Result<Self, Self::Error> {
146        use crate::proto::member::Role::*;
147        match crate::proto::member::Role::try_from(value) {
148            Ok(Unknown) => Ok(Role::Unknown),
149            Ok(Default) => Ok(Role::Default),
150            Ok(Administrator) => Ok(Role::Administrator),
151            Err(_e) => Err(GroupDecodingError::WrongEnumValue),
152        }
153    }
154}
155
156impl From<Role> for i32 {
157    fn from(val: Role) -> Self {
158        use crate::proto::member::Role::*;
159        match val {
160            Role::Unknown => Unknown,
161            Role::Default => Default,
162            Role::Administrator => Administrator,
163        }
164        .into()
165    }
166}
167
168impl TryFrom<i32> for AccessRequired {
169    type Error = GroupDecodingError;
170
171    fn try_from(value: i32) -> Result<Self, Self::Error> {
172        use crate::proto::access_control::AccessRequired::*;
173        match crate::proto::access_control::AccessRequired::try_from(value) {
174            Ok(Unknown) => Ok(AccessRequired::Unknown),
175            Ok(Any) => Ok(AccessRequired::Any),
176            Ok(Member) => Ok(AccessRequired::Member),
177            Ok(Administrator) => Ok(AccessRequired::Administrator),
178            Ok(Unsatisfiable) => Ok(AccessRequired::Unsatisfiable),
179            Err(_e) => Err(GroupDecodingError::WrongEnumValue),
180        }
181    }
182}
183
184impl From<AccessRequired> for i32 {
185    fn from(val: AccessRequired) -> Self {
186        use crate::proto::access_control::AccessRequired::*;
187        match val {
188            AccessRequired::Unknown => Unknown,
189            AccessRequired::Any => Any,
190            AccessRequired::Member => Member,
191            AccessRequired::Administrator => Administrator,
192            AccessRequired::Unsatisfiable => Unsatisfiable,
193        }
194        .into()
195    }
196}
197
198impl TryFrom<crate::proto::AccessControl> for AccessControl {
199    type Error = GroupDecodingError;
200
201    fn try_from(
202        value: crate::proto::AccessControl,
203    ) -> Result<Self, Self::Error> {
204        Ok(Self {
205            attributes: value.attributes.try_into()?,
206            members: value.members.try_into()?,
207            add_from_invite_link: value.add_from_invite_link.try_into()?,
208        })
209    }
210}