Skip to content

Commit 0036471

Browse files
committed
Refactor Sends table
1 parent 9f7fcc0 commit 0036471

9 files changed

Lines changed: 105 additions & 49 deletions

File tree

migrations/mysql/2026-06-18-120000_add_sends_emails/up.sql

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,41 @@ CREATE TABLE sends_otp (
1111

1212
PRIMARY KEY(send_uuid, email)
1313
);
14+
15+
16+
DELETE FROM sends where user_uuid IS NULL;
17+
UPDATE sends SET hide_email = false WHERE hide_email IS NULL;
18+
19+
SELECT if (
20+
EXISTS(
21+
SELECT CONSTRAINT_NAME FROM information_schema.table_constraints
22+
WHERE TABLE_SCHEMA = DATABASE()
23+
AND TABLE_NAME = 'sends'
24+
AND CONSTRAINT_TYPE = 'FOREIGN KEY'
25+
AND CONSTRAINT_NAME = 'sends_ibfk_2'
26+
)
27+
,'ALTER TABLE sends DROP FOREIGN KEY `sends_ibfk_2`'
28+
,'SELECT "info: FK sends_ibfk_2 does not exist."'
29+
) INTO @drop_stmt;
30+
PREPARE drop_stmt FROM @drop_stmt;
31+
EXECUTE drop_stmt;
32+
33+
SELECT if (
34+
EXISTS(
35+
SELECT CONSTRAINT_NAME FROM information_schema.table_constraints
36+
WHERE TABLE_SCHEMA = DATABASE()
37+
AND TABLE_NAME = 'sends'
38+
AND CONSTRAINT_TYPE = 'FOREIGN KEY'
39+
AND CONSTRAINT_NAME = '2'
40+
)
41+
,'ALTER TABLE sends DROP FOREIGN KEY `2`'
42+
,'SELECT "info: FK sends 2 does not exist."'
43+
) INTO @drop_stmt;
44+
PREPARE drop_stmt FROM @drop_stmt;
45+
EXECUTE drop_stmt;
46+
47+
DEALLOCATE PREPARE drop_stmt;
48+
49+
ALTER TABLE sends DROP COLUMN organization_uuid;
50+
ALTER TABLE sends MODIFY user_uuid CHAR(36) NOT NULL;
51+
ALTER TABLE sends MODIFY hide_email BOOLEAN NOT NULL;

migrations/postgresql/2026-06-18-120000_add_sends_emails/up.sql

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,10 @@ CREATE TABLE sends_otp (
1111

1212
PRIMARY KEY(send_uuid, email)
1313
);
14+
15+
16+
DELETE FROM sends where user_uuid IS NULL;
17+
UPDATE sends SET hide_email = false WHERE hide_email IS NULL;
18+
ALTER TABLE sends DROP COLUMN organization_uuid;
19+
ALTER TABLE sends ALTER COLUMN user_uuid SET NOT NULL;
20+
ALTER TABLE sends ALTER COLUMN hide_email SET NOT NULL;
Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +0,0 @@
1-
ALTER TABLE sends DROP COLUMN emails;
2-
DROP TABLE sends_otp;

migrations/sqlite/2026-06-18-120000_add_sends_emails/up.sql

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,43 @@
1-
ALTER TABLE sends ADD COLUMN emails TEXT;
1+
ALTER TABLE sends RENAME TO sends_old;
2+
3+
CREATE TABLE sends (
4+
uuid TEXT NOT NULL PRIMARY KEY,
5+
user_uuid TEXT NOT NULL REFERENCES users (uuid),
6+
7+
name TEXT NOT NULL,
8+
notes TEXT,
9+
10+
atype INTEGER NOT NULL,
11+
data TEXT NOT NULL,
12+
akey TEXT NOT NULL,
13+
password_hash BLOB,
14+
password_salt BLOB,
15+
password_iter INTEGER,
16+
emails TEXT,
17+
18+
max_access_count INTEGER,
19+
access_count INTEGER NOT NULL,
20+
21+
creation_date DATETIME NOT NULL,
22+
revision_date DATETIME NOT NULL,
23+
expiration_date DATETIME,
24+
deletion_date DATETIME NOT NULL,
25+
26+
disabled BOOLEAN NOT NULL,
27+
hide_email BOOLEAN NOT NULL
28+
);
29+
30+
INSERT INTO sends(
31+
uuid, user_uuid, name, notes, atype, data, akey, password_hash, password_salt, password_iter,
32+
max_access_count, access_count, creation_date, revision_date, expiration_date, deletion_date,
33+
disabled, hide_email
34+
) SELECT uuid, user_uuid, name, notes, atype, data, akey, password_hash, password_salt, password_iter,
35+
max_access_count, access_count, creation_date, revision_date, expiration_date, deletion_date,
36+
disabled,
37+
CASE WHEN hide_email IS NOT NULL THEN hide_email ELSE false END
38+
FROM sends_old WHERE user_uuid IS NOT NULL;
39+
40+
DROP TABLE sends_old;
241

342
CREATE TABLE sends_otp (
443
send_uuid TEXT NOT NULL REFERENCES sends(uuid) ON DELETE CASCADE ON UPDATE CASCADE,

src/api/core/sends.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ fn create_send(data: SendData, user_id: UserId) -> ApiResult<Send> {
172172
data.expiration_date.map(|d| d.naive_utc()),
173173
data.deletion_date.naive_utc(),
174174
data.disabled,
175-
data.hide_email,
175+
data.hide_email.unwrap_or(false),
176176
);
177177

178178
send.set_password(data.password.as_deref());
@@ -665,7 +665,7 @@ pub async fn update_send_from_data(
665665
nt: &Notify<'_>,
666666
ut: UpdateType,
667667
) -> EmptyResult {
668-
if send.user_uuid.as_ref() != Some(&headers.user.uuid) {
668+
if send.user_uuid != headers.user.uuid {
669669
err!("Send is not owned by user")
670670
}
671671

@@ -700,7 +700,7 @@ pub async fn update_send_from_data(
700700
_ => None,
701701
};
702702
send.expiration_date = data.expiration_date.map(|d| d.naive_utc());
703-
send.hide_email = data.hide_email;
703+
send.hide_email = data.hide_email.unwrap_or(false);
704704
send.disabled = data.disabled;
705705
send.emails = data.emails.map(|e| e.to_lowercase());
706706

src/api/notifications.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -465,12 +465,11 @@ impl WebSocketUsers {
465465
if *NOTIFICATIONS_DISABLED {
466466
return;
467467
}
468-
let user_id = convert_option(send.user_uuid.as_deref());
469468

470469
let data = create_update(
471470
vec![
472471
("Id".into(), send.uuid.to_string().into()),
473-
("UserId".into(), user_id),
472+
("UserId".into(), send.user_uuid.to_string().into()),
474473
("RevisionDate".into(), serialize_date(send.revision_date)),
475474
],
476475
ut,

src/api/push.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -244,9 +244,7 @@ pub async fn push_folder_update(ut: UpdateType, folder: &Folder, device: &Device
244244
}
245245

246246
pub async fn push_send_update(ut: UpdateType, send: &Send, device: &Device, conn: &DbConn) {
247-
if let Some(s) = &send.user_uuid
248-
&& Device::check_user_has_push_device(s, conn).await
249-
{
247+
if Device::check_user_has_push_device(&send.user_uuid, conn).await {
250248
tokio::task::spawn(send_to_push_relay(json!({
251249
"userId": send.user_uuid,
252250
"organizationId": null,

src/db/models/send.rs

Lines changed: 13 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use crate::{
2020
util::{LowerCase, NumberOrString, format_date},
2121
};
2222

23-
use super::{OrganizationId, User, UserId};
23+
use super::{User, UserId};
2424

2525
#[derive(Identifiable, Queryable, Insertable, AsChangeset, Selectable)]
2626
#[diesel(table_name = sends)]
@@ -29,8 +29,7 @@ use super::{OrganizationId, User, UserId};
2929
pub struct Send {
3030
pub uuid: SendId,
3131

32-
pub user_uuid: Option<UserId>,
33-
pub organization_uuid: Option<OrganizationId>,
32+
pub user_uuid: UserId,
3433

3534
pub name: String,
3635
pub notes: Option<String>,
@@ -52,7 +51,7 @@ pub struct Send {
5251
pub deletion_date: NaiveDateTime,
5352

5453
pub disabled: bool,
55-
pub hide_email: Option<bool>,
54+
pub hide_email: bool,
5655
}
5756

5857
#[derive(Copy, Clone, PartialEq, Eq, num_derive::FromPrimitive)]
@@ -85,14 +84,13 @@ impl Send {
8584
expiration_date: Option<NaiveDateTime>,
8685
deletion_date: NaiveDateTime,
8786
disabled: bool,
88-
hide_email: Option<bool>,
87+
hide_email: bool,
8988
) -> Self {
9089
let now = Utc::now().naive_utc();
9190

9291
Self {
9392
uuid: SendId::from(crate::util::get_uuid()),
94-
user_uuid: Some(user_uuid),
95-
organization_uuid: None,
93+
user_uuid,
9694
name,
9795
notes,
9896
atype,
@@ -142,19 +140,13 @@ impl Send {
142140
}
143141

144142
pub async fn creator_identifier(&self, conn: &DbConn) -> Option<String> {
145-
if let Some(hide_email) = self.hide_email
146-
&& hide_email
143+
if !self.hide_email
144+
&& let Some(user) = User::find_by_uuid(&self.user_uuid, conn).await
147145
{
148-
return None;
149-
}
150-
151-
if let Some(user_uuid) = &self.user_uuid
152-
&& let Some(user) = User::find_by_uuid(user_uuid, conn).await
153-
{
154-
return Some(user.email);
146+
Some(user.email)
147+
} else {
148+
None
155149
}
156-
157-
None
158150
}
159151

160152
pub fn to_json(&self) -> Value {
@@ -181,7 +173,7 @@ impl Send {
181173
"password": self.password_hash.as_deref().map(|h| BASE64URL_NOPAD.encode(h)),
182174
"authType": if self.password_hash.is_some() { SendAuthType::Password } else if self.emails.is_some() { SendAuthType::Email } else { SendAuthType::None } as i32,
183175
"disabled": self.disabled,
184-
"hideEmail": self.hide_email.unwrap_or(false),
176+
"hideEmail": self.hide_email,
185177
"emails": self.emails,
186178

187179
"revisionDate": format_date(&self.revision_date),
@@ -263,14 +255,8 @@ impl Send {
263255
}
264256

265257
pub async fn update_users_revision(&self, conn: &DbConn) -> Vec<UserId> {
266-
let mut user_uuids = Vec::new();
267-
if let Some(user_uuid) = &self.user_uuid {
268-
User::update_uuid_revision(user_uuid, conn).await;
269-
user_uuids.push(user_uuid.clone());
270-
} else {
271-
// Belongs to Organization, not implemented
272-
}
273-
user_uuids
258+
User::update_uuid_revision(&self.user_uuid, conn).await;
259+
vec![self.user_uuid.clone()]
274260
}
275261

276262
pub async fn delete_all_by_user(user_uuid: &UserId, conn: &DbConn) -> EmptyResult {
@@ -332,13 +318,6 @@ impl Send {
332318
Some(total)
333319
}
334320

335-
pub async fn find_by_org(org_uuid: &OrganizationId, conn: &DbConn) -> Vec<Self> {
336-
conn.run(move |conn| {
337-
sends::table.filter(sends::organization_uuid.eq(org_uuid)).load::<Self>(conn).expect("Error loading sends")
338-
})
339-
.await
340-
}
341-
342321
pub async fn find_by_past_deletion_date(conn: &DbConn) -> Vec<Self> {
343322
let now = Utc::now().naive_utc();
344323
conn.run(move |conn| {

src/db/schema.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -132,8 +132,7 @@ table! {
132132
table! {
133133
sends (uuid) {
134134
uuid -> Text,
135-
user_uuid -> Nullable<Text>,
136-
organization_uuid -> Nullable<Text>,
135+
user_uuid -> Text,
137136
name -> Text,
138137
notes -> Nullable<Text>,
139138
atype -> Integer,
@@ -150,7 +149,7 @@ table! {
150149
expiration_date -> Nullable<Timestamp>,
151150
deletion_date -> Timestamp,
152151
disabled -> Bool,
153-
hide_email -> Nullable<Bool>,
152+
hide_email -> Bool,
154153
}
155154
}
156155

@@ -376,7 +375,6 @@ joinable!(folders -> users (user_uuid));
376375
joinable!(folders_ciphers -> ciphers (cipher_uuid));
377376
joinable!(folders_ciphers -> folders (folder_uuid));
378377
joinable!(org_policies -> organizations (org_uuid));
379-
joinable!(sends -> organizations (organization_uuid));
380378
joinable!(sends -> users (user_uuid));
381379
joinable!(sends_otp -> sends (send_uuid));
382380
joinable!(twofactor -> users (user_uuid));

0 commit comments

Comments
 (0)