coven_database/
members.rs1use crate::{sqlite::DatabaseConnection, store_state::DeviceState, DbError};
5use coven_format::admin::{MemberPublicKeys, MemberRole};
6use coven_foundation::id_source::{CircleId, DeviceId, MemberId};
7
8#[derive(Clone, Debug, PartialEq, Eq)]
10pub struct MemberInfo {
11 pub id: MemberId,
13 pub keys: MemberPublicKeys,
15 pub role: MemberRole,
17 pub access: coven_format::MemberAccess,
20 pub devices: Vec<DeviceInfo>,
22 pub is_self: bool,
24}
25
26#[derive(Clone, Debug, PartialEq, Eq)]
28pub struct DeviceInfo {
29 pub id: DeviceId,
31 pub name: String,
33 pub state: DeviceState,
35 pub is_self: bool,
37}
38
39#[derive(Clone, Debug, PartialEq, Eq)]
41pub struct Circle {
42 pub id: CircleId,
44 pub name: String,
46}
47
48#[derive(Clone, Debug, PartialEq, Eq)]
50pub struct CircleMemberInfo {
51 pub member: MemberId,
53 pub is_self: bool,
55}
56
57use crate::store_state_tables::{circle, device_member, member};
58
59pub(crate) fn members(
60 db: &DatabaseConnection,
61 device: DeviceId,
62) -> Result<Vec<MemberInfo>, DbError> {
63 let me = device_member(db, device)?;
64 let members = db.query(
65 "SELECT member,signing,sealing,role,removed,access FROM _coven_members WHERE removed=0
66 ORDER BY member",
67 [],
68 crate::store_state_tables::stored_member,
69 )?;
70 members
71 .into_iter()
72 .map(|(id, crate::StoreMember { keys, access, role, .. })| {
73 let devices = db.query(
74 "SELECT device,name,state FROM _coven_devices WHERE member=?1 ORDER BY device",
75 [id],
76 |r| {
77 let id = r.get::<_, DeviceId>(0)?;
78 Ok(DeviceInfo {
79 id,
80 is_self: id == device,
81 name: r.get(1)?,
82 state: crate::store_state_tables::device_state(r, 2)?,
83 })
84 },
85 )?;
86 Ok(MemberInfo { is_self: me.as_ref() == Some(&id), keys, id, role, access, devices })
87 })
88 .collect()
89}
90
91pub(crate) fn circles(db: &DatabaseConnection, device: DeviceId) -> Result<Vec<Circle>, DbError> {
92 let Some(me) = device_member(db, device)? else {
93 return Ok(Vec::new());
94 };
95 let circles = db.query(
98 "SELECT c.circle,c.name FROM _coven_circle_members m JOIN _coven_circles c ON c.circle=m.circle
99 WHERE m.member=?1 AND NOT EXISTS(SELECT 1 FROM _coven_circle_deletions d WHERE d.circle=c.circle)
100 ORDER BY m.circle",
101 [me],
102 |r| {
103 Ok(Circle {
104 id: circle(r, 0)?,
105 name: r.get(1)?,
106 })
107 },
108 )?;
109 Ok(circles)
110}
111
112pub(crate) fn circle_members(
114 db: &DatabaseConnection,
115 device: DeviceId,
116 circle: CircleId,
117) -> Result<Vec<CircleMemberInfo>, DbError> {
118 let me = device_member(db, device)?;
119 let members = db.query(
120 "SELECT m.member FROM _coven_circle_members m JOIN _coven_members s ON s.member=m.member
121 WHERE m.circle=?1 AND s.removed=0
122 AND NOT EXISTS(SELECT 1 FROM _coven_circle_deletions d WHERE d.circle=m.circle)
123 ORDER BY m.member",
124 [circle],
125 |r| member(r, 0),
126 )?;
127 Ok(members
128 .into_iter()
129 .map(|member| CircleMemberInfo { is_self: me.as_ref() == Some(&member), member })
130 .collect())
131}
132
133#[cfg(test)]
134#[path = "members_tests.rs"]
135mod tests;