mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
chore: save workspace member info to disk (#5536)
* chore: save workspace member info to disk * chore: fix clippy
This commit is contained in:
parent
785597f53e
commit
27899ee993
@ -2,6 +2,7 @@ import 'package:appflowy/generated/flowy_svgs.g.dart';
|
|||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/plugins/database/application/row/row_service.dart';
|
import 'package:appflowy/plugins/database/application/row/row_service.dart';
|
||||||
import 'package:appflowy/plugins/database/grid/presentation/layout/sizes.dart';
|
import 'package:appflowy/plugins/database/grid/presentation/layout/sizes.dart';
|
||||||
|
import 'package:appflowy/workspace/presentation/widgets/dialogs.dart';
|
||||||
import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
|
import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
|
||||||
import 'package:appflowy_popover/appflowy_popover.dart';
|
import 'package:appflowy_popover/appflowy_popover.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
@ -52,7 +53,17 @@ class RowActionMenu extends StatelessWidget {
|
|||||||
child: FlowyButton(
|
child: FlowyButton(
|
||||||
text: FlowyText.medium(action.text, overflow: TextOverflow.ellipsis),
|
text: FlowyText.medium(action.text, overflow: TextOverflow.ellipsis),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
action.performAction(context, viewId, rowId);
|
if (action == RowAction.delete) {
|
||||||
|
NavigatorOkCancelDialog(
|
||||||
|
message: LocaleKeys.grid_row_deleteRowPrompt.tr(),
|
||||||
|
onOkPressed: () {
|
||||||
|
action.performAction(context, viewId, rowId);
|
||||||
|
},
|
||||||
|
).show(context);
|
||||||
|
} else {
|
||||||
|
action.performAction(context, viewId, rowId);
|
||||||
|
}
|
||||||
|
|
||||||
PopoverContainer.of(context).close();
|
PopoverContainer.of(context).close();
|
||||||
},
|
},
|
||||||
leftIcon: icon,
|
leftIcon: icon,
|
||||||
|
@ -1087,6 +1087,7 @@
|
|||||||
"action": "Action",
|
"action": "Action",
|
||||||
"add": "Click add to below",
|
"add": "Click add to below",
|
||||||
"drag": "Drag to move",
|
"drag": "Drag to move",
|
||||||
|
"deleteRowPrompt": "Are you sure you want to delete this row? This action cannot be undone",
|
||||||
"dragAndClick": "Drag to move, click to open menu",
|
"dragAndClick": "Drag to move, click to open menu",
|
||||||
"insertRecordAbove": "Insert record above",
|
"insertRecordAbove": "Insert record above",
|
||||||
"insertRecordBelow": "Insert record below",
|
"insertRecordBelow": "Insert record below",
|
||||||
@ -1915,4 +1916,4 @@
|
|||||||
"title": "Spaces",
|
"title": "Spaces",
|
||||||
"defaultSpaceName": "General"
|
"defaultSpaceName": "General"
|
||||||
}
|
}
|
||||||
}
|
}
|
22
frontend/rust-lib/Cargo.lock
generated
22
frontend/rust-lib/Cargo.lock
generated
@ -1165,7 +1165,7 @@ dependencies = [
|
|||||||
"cssparser-macros",
|
"cssparser-macros",
|
||||||
"dtoa-short",
|
"dtoa-short",
|
||||||
"itoa",
|
"itoa",
|
||||||
"phf 0.8.0",
|
"phf 0.11.2",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -3790,7 +3790,7 @@ version = "0.8.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12"
|
checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"phf_macros",
|
"phf_macros 0.8.0",
|
||||||
"phf_shared 0.8.0",
|
"phf_shared 0.8.0",
|
||||||
"proc-macro-hack",
|
"proc-macro-hack",
|
||||||
]
|
]
|
||||||
@ -3810,6 +3810,7 @@ version = "0.11.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc"
|
checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"phf_macros 0.11.2",
|
||||||
"phf_shared 0.11.2",
|
"phf_shared 0.11.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -3877,6 +3878,19 @@ dependencies = [
|
|||||||
"syn 1.0.109",
|
"syn 1.0.109",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "phf_macros"
|
||||||
|
version = "0.11.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b"
|
||||||
|
dependencies = [
|
||||||
|
"phf_generator 0.11.2",
|
||||||
|
"phf_shared 0.11.2",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.47",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "phf_shared"
|
name = "phf_shared"
|
||||||
version = "0.8.0"
|
version = "0.8.0"
|
||||||
@ -4080,7 +4094,7 @@ checksum = "c55e02e35260070b6f716a2423c2ff1c3bb1642ddca6f99e1f26d06268a0e2d2"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"heck 0.4.1",
|
"heck 0.4.1",
|
||||||
"itertools 0.10.5",
|
"itertools 0.11.0",
|
||||||
"log",
|
"log",
|
||||||
"multimap",
|
"multimap",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
@ -4101,7 +4115,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e"
|
checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"itertools 0.10.5",
|
"itertools 0.11.0",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.47",
|
"syn 2.0.47",
|
||||||
|
@ -88,6 +88,7 @@ collab-database = { version = "0.2" }
|
|||||||
collab-plugins = { version = "0.2" }
|
collab-plugins = { version = "0.2" }
|
||||||
collab-user = { version = "0.2" }
|
collab-user = { version = "0.2" }
|
||||||
yrs = "0.18.8"
|
yrs = "0.18.8"
|
||||||
|
validator = { version = "0.16.1", features = ["derive"] }
|
||||||
|
|
||||||
# Please using the following command to update the revision id
|
# Please using the following command to update the revision id
|
||||||
# Current directory: frontend
|
# Current directory: frontend
|
||||||
|
@ -18,7 +18,7 @@ uuid.workspace = true
|
|||||||
strum_macros = "0.21"
|
strum_macros = "0.21"
|
||||||
protobuf.workspace = true
|
protobuf.workspace = true
|
||||||
bytes.workspace = true
|
bytes.workspace = true
|
||||||
validator = { version = "0.16.0", features = ["derive"] }
|
validator = { workspace = true, features = ["derive"] }
|
||||||
lib-infra = { workspace = true, features = ["isolate_flutter"] }
|
lib-infra = { workspace = true, features = ["isolate_flutter"] }
|
||||||
flowy-chat-pub.workspace = true
|
flowy-chat-pub.workspace = true
|
||||||
dashmap = "5.5"
|
dashmap = "5.5"
|
||||||
|
@ -47,7 +47,7 @@ chrono-tz = "0.8.2"
|
|||||||
csv = "1.1.6"
|
csv = "1.1.6"
|
||||||
strum = "0.25"
|
strum = "0.25"
|
||||||
strum_macros = "0.25"
|
strum_macros = "0.25"
|
||||||
validator = { version = "0.16.0", features = ["derive"] }
|
validator = { workspace = true, features = ["derive"] }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
event-integration-test = { path = "../event-integration-test", default-features = false }
|
event-integration-test = { path = "../event-integration-test", default-features = false }
|
||||||
|
@ -13,7 +13,7 @@ protobuf.workspace = true
|
|||||||
bytes.workspace = true
|
bytes.workspace = true
|
||||||
anyhow.workspace = true
|
anyhow.workspace = true
|
||||||
thiserror = "1.0"
|
thiserror = "1.0"
|
||||||
validator = "0.16.0"
|
validator.workspace = true
|
||||||
tokio = { workspace = true, features = ["sync", "rt"] }
|
tokio = { workspace = true, features = ["sync", "rt"] }
|
||||||
|
|
||||||
fancy-regex = { version = "0.11.0" }
|
fancy-regex = { version = "0.11.0" }
|
||||||
|
@ -35,9 +35,9 @@ strum_macros = "0.21"
|
|||||||
protobuf.workspace = true
|
protobuf.workspace = true
|
||||||
uuid.workspace = true
|
uuid.workspace = true
|
||||||
tokio-stream = { workspace = true, features = ["sync"] }
|
tokio-stream = { workspace = true, features = ["sync"] }
|
||||||
serde = { workspace = true, features = ["derive"]}
|
serde = { workspace = true, features = ["derive"] }
|
||||||
serde_json.workspace = true
|
serde_json.workspace = true
|
||||||
validator = "0.16.0"
|
validator.workspace = true
|
||||||
async-trait.workspace = true
|
async-trait.workspace = true
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
-- This file should undo anything in `up.sql`
|
@ -0,0 +1,11 @@
|
|||||||
|
-- Your SQL goes here
|
||||||
|
CREATE TABLE workspace_members_table (
|
||||||
|
email TEXT KEY NOT NULL,
|
||||||
|
role INTEGER NOT NULL,
|
||||||
|
name TEXT NOT NULL,
|
||||||
|
avatar_url TEXT,
|
||||||
|
uid BIGINT NOT NULL,
|
||||||
|
workspace_id TEXT NOT NULL,
|
||||||
|
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
PRIMARY KEY (email, workspace_id)
|
||||||
|
);
|
@ -67,6 +67,18 @@ diesel::table! {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
diesel::table! {
|
||||||
|
workspace_members_table (email, workspace_id) {
|
||||||
|
email -> Text,
|
||||||
|
role -> Integer,
|
||||||
|
name -> Text,
|
||||||
|
avatar_url -> Nullable<Text>,
|
||||||
|
uid -> BigInt,
|
||||||
|
workspace_id -> Text,
|
||||||
|
updated_at -> Timestamp,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
diesel::allow_tables_to_appear_in_same_query!(
|
diesel::allow_tables_to_appear_in_same_query!(
|
||||||
chat_message_table,
|
chat_message_table,
|
||||||
chat_table,
|
chat_table,
|
||||||
@ -74,4 +86,5 @@ diesel::allow_tables_to_appear_in_same_query!(
|
|||||||
user_data_migration_records,
|
user_data_migration_records,
|
||||||
user_table,
|
user_table,
|
||||||
user_workspace_table,
|
user_workspace_table,
|
||||||
|
workspace_members_table,
|
||||||
);
|
);
|
||||||
|
@ -384,11 +384,33 @@ pub enum UserTokenState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Workspace Role
|
// Workspace Role
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug, Serialize_repr, Deserialize_repr)]
|
||||||
|
#[repr(u8)]
|
||||||
pub enum Role {
|
pub enum Role {
|
||||||
Owner,
|
Owner = 0,
|
||||||
Member,
|
Member = 1,
|
||||||
Guest,
|
Guest = 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<i32> for Role {
|
||||||
|
fn from(value: i32) -> Self {
|
||||||
|
match value {
|
||||||
|
0 => Role::Owner,
|
||||||
|
1 => Role::Member,
|
||||||
|
2 => Role::Guest,
|
||||||
|
_ => Role::Guest,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Role> for i32 {
|
||||||
|
fn from(value: Role) -> Self {
|
||||||
|
match value {
|
||||||
|
Role::Owner => 0,
|
||||||
|
Role::Member => 1,
|
||||||
|
Role::Guest => 2,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct WorkspaceMember {
|
pub struct WorkspaceMember {
|
||||||
|
@ -9,7 +9,7 @@ edition = "2018"
|
|||||||
flowy-derive.workspace = true
|
flowy-derive.workspace = true
|
||||||
flowy-sqlite = { workspace = true }
|
flowy-sqlite = { workspace = true }
|
||||||
flowy-encrypt = { workspace = true }
|
flowy-encrypt = { workspace = true }
|
||||||
flowy-error = { workspace = true, features = ["impl_from_dispatch_error", "impl_from_sqlite", "impl_from_collab_folder", "impl_from_collab_persistence"] }
|
flowy-error = { workspace = true, features = ["impl_from_dispatch_error", "impl_from_sqlite", "impl_from_collab_folder", "impl_from_collab_persistence", "impl_from_collab_document"] }
|
||||||
flowy-folder-pub = { workspace = true }
|
flowy-folder-pub = { workspace = true }
|
||||||
lib-infra = { workspace = true }
|
lib-infra = { workspace = true }
|
||||||
flowy-notification = { workspace = true }
|
flowy-notification = { workspace = true }
|
||||||
@ -39,7 +39,6 @@ parking_lot.workspace = true
|
|||||||
strum = "0.25"
|
strum = "0.25"
|
||||||
strum_macros = "0.25.2"
|
strum_macros = "0.25.2"
|
||||||
tokio = { workspace = true, features = ["rt"] }
|
tokio = { workspace = true, features = ["rt"] }
|
||||||
validator = "0.16.0"
|
|
||||||
unicode-segmentation = "1.10"
|
unicode-segmentation = "1.10"
|
||||||
fancy-regex = "0.11.0"
|
fancy-regex = "0.11.0"
|
||||||
uuid.workspace = true
|
uuid.workspace = true
|
||||||
@ -47,6 +46,7 @@ chrono = { workspace = true, default-features = false, features = ["clock"] }
|
|||||||
base64 = "^0.21"
|
base64 = "^0.21"
|
||||||
tokio-stream = "0.1.14"
|
tokio-stream = "0.1.14"
|
||||||
semver = "1.0.22"
|
semver = "1.0.22"
|
||||||
|
validator = { workspace = true, features = ["derive"] }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
nanoid = "0.4.0"
|
nanoid = "0.4.0"
|
||||||
|
@ -0,0 +1,52 @@
|
|||||||
|
use diesel::{insert_into, RunQueryDsl};
|
||||||
|
use flowy_error::FlowyResult;
|
||||||
|
|
||||||
|
use flowy_sqlite::schema::workspace_members_table;
|
||||||
|
|
||||||
|
use flowy_sqlite::schema::workspace_members_table::dsl;
|
||||||
|
use flowy_sqlite::{query_dsl::*, DBConnection, ExpressionMethods};
|
||||||
|
|
||||||
|
#[derive(Queryable, Insertable, AsChangeset, Debug)]
|
||||||
|
#[diesel(table_name = workspace_members_table)]
|
||||||
|
#[diesel(primary_key(email, workspace_id))]
|
||||||
|
pub struct WorkspaceMemberTable {
|
||||||
|
pub email: String,
|
||||||
|
pub role: i32,
|
||||||
|
pub name: String,
|
||||||
|
pub avatar_url: Option<String>,
|
||||||
|
pub uid: i64,
|
||||||
|
pub workspace_id: String,
|
||||||
|
pub updated_at: chrono::NaiveDateTime,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn upsert_workspace_member<T: Into<WorkspaceMemberTable>>(
|
||||||
|
mut conn: DBConnection,
|
||||||
|
member: T,
|
||||||
|
) -> FlowyResult<()> {
|
||||||
|
let member = member.into();
|
||||||
|
|
||||||
|
insert_into(workspace_members_table::table)
|
||||||
|
.values(&member)
|
||||||
|
.on_conflict((
|
||||||
|
workspace_members_table::email,
|
||||||
|
workspace_members_table::workspace_id,
|
||||||
|
))
|
||||||
|
.do_update()
|
||||||
|
.set(&member)
|
||||||
|
.execute(&mut conn)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn select_workspace_member(
|
||||||
|
mut conn: DBConnection,
|
||||||
|
workspace_id: &str,
|
||||||
|
uid: i64,
|
||||||
|
) -> FlowyResult<WorkspaceMemberTable> {
|
||||||
|
let member = dsl::workspace_members_table
|
||||||
|
.filter(workspace_members_table::workspace_id.eq(workspace_id))
|
||||||
|
.filter(workspace_members_table::uid.eq(uid))
|
||||||
|
.first::<WorkspaceMemberTable>(&mut conn)?;
|
||||||
|
|
||||||
|
Ok(member)
|
||||||
|
}
|
@ -1,2 +1,3 @@
|
|||||||
|
pub(crate) mod member_sql;
|
||||||
pub(crate) mod user_sql;
|
pub(crate) mod user_sql;
|
||||||
pub(crate) mod workspace_sql;
|
pub(crate) mod workspace_sql;
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
|
use chrono::{Duration, NaiveDateTime, Utc};
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use collab_entity::{CollabObject, CollabType};
|
use collab_entity::{CollabObject, CollabType};
|
||||||
use collab_integrate::CollabKVDB;
|
use collab_integrate::CollabKVDB;
|
||||||
use tracing::{error, info, instrument, warn};
|
use tracing::{error, info, instrument, trace, warn};
|
||||||
|
|
||||||
use flowy_error::{ErrorCode, FlowyError, FlowyResult};
|
use flowy_error::{ErrorCode, FlowyError, FlowyResult};
|
||||||
use flowy_folder_pub::entities::{AppFlowyData, ImportData};
|
use flowy_folder_pub::entities::{AppFlowyData, ImportData};
|
||||||
@ -23,6 +24,9 @@ use crate::notification::{send_notification, UserNotification};
|
|||||||
use crate::services::data_import::{
|
use crate::services::data_import::{
|
||||||
generate_import_data, upload_collab_objects_data, ImportedFolder, ImportedSource,
|
generate_import_data, upload_collab_objects_data, ImportedFolder, ImportedSource,
|
||||||
};
|
};
|
||||||
|
use crate::services::sqlite_sql::member_sql::{
|
||||||
|
select_workspace_member, upsert_workspace_member, WorkspaceMemberTable,
|
||||||
|
};
|
||||||
use crate::services::sqlite_sql::workspace_sql::{
|
use crate::services::sqlite_sql::workspace_sql::{
|
||||||
get_all_user_workspace_op, get_user_workspace_op, insert_new_workspaces_op, UserWorkspaceTable,
|
get_all_user_workspace_op, get_user_workspace_op, insert_new_workspaces_op, UserWorkspaceTable,
|
||||||
};
|
};
|
||||||
@ -483,11 +487,54 @@ impl UserManager {
|
|||||||
#[instrument(level = "debug", skip(self), err)]
|
#[instrument(level = "debug", skip(self), err)]
|
||||||
pub async fn get_workspace_member_info(&self, uid: i64) -> FlowyResult<WorkspaceMember> {
|
pub async fn get_workspace_member_info(&self, uid: i64) -> FlowyResult<WorkspaceMember> {
|
||||||
let workspace_id = self.get_session()?.user_workspace.id.clone();
|
let workspace_id = self.get_session()?.user_workspace.id.clone();
|
||||||
|
let db = self.authenticate_user.get_sqlite_connection(uid)?;
|
||||||
|
// Can opt in using memory cache
|
||||||
|
if let Ok(member_record) = select_workspace_member(db, &workspace_id, uid) {
|
||||||
|
if is_older_than_n_minutes(member_record.updated_at, 10) {
|
||||||
|
self
|
||||||
|
.get_workspace_member_info_from_remote(&workspace_id, uid)
|
||||||
|
.await?;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok(WorkspaceMember {
|
||||||
|
email: member_record.email,
|
||||||
|
role: member_record.role.into(),
|
||||||
|
name: member_record.name,
|
||||||
|
avatar_url: member_record.avatar_url,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let member = self
|
||||||
|
.get_workspace_member_info_from_remote(&workspace_id, uid)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(member)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_workspace_member_info_from_remote(
|
||||||
|
&self,
|
||||||
|
workspace_id: &str,
|
||||||
|
uid: i64,
|
||||||
|
) -> FlowyResult<WorkspaceMember> {
|
||||||
|
trace!("get workspace member info from remote: {}", workspace_id);
|
||||||
let member = self
|
let member = self
|
||||||
.cloud_services
|
.cloud_services
|
||||||
.get_user_service()?
|
.get_user_service()?
|
||||||
.get_workspace_member_info(&workspace_id, uid)
|
.get_workspace_member_info(&workspace_id, uid)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
let record = WorkspaceMemberTable {
|
||||||
|
email: member.email.clone(),
|
||||||
|
role: member.role.clone().into(),
|
||||||
|
name: member.name.clone(),
|
||||||
|
avatar_url: member.avatar_url.clone(),
|
||||||
|
uid,
|
||||||
|
workspace_id: workspace_id.to_string(),
|
||||||
|
updated_at: Utc::now().naive_utc(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let db = self.authenticate_user.get_sqlite_connection(uid)?;
|
||||||
|
upsert_workspace_member(db, record)?;
|
||||||
Ok(member)
|
Ok(member)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -599,3 +646,11 @@ pub fn delete_user_workspaces(mut conn: DBConnection, workspace_id: &str) -> Flo
|
|||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_older_than_n_minutes(updated_at: NaiveDateTime, minutes: i64) -> bool {
|
||||||
|
let current_time: NaiveDateTime = Utc::now().naive_utc();
|
||||||
|
match current_time.checked_sub_signed(Duration::minutes(minutes)) {
|
||||||
|
Some(five_minutes_ago) => updated_at < five_minutes_ago,
|
||||||
|
None => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -13,8 +13,7 @@ futures-core = { version = "0.3", default-features = false }
|
|||||||
futures-channel = "0.3.26"
|
futures-channel = "0.3.26"
|
||||||
futures.workspace = true
|
futures.workspace = true
|
||||||
futures-util = "0.3.26"
|
futures-util = "0.3.26"
|
||||||
bytes = {version = "1.4", features = ["serde"]}
|
bytes = { version = "1.4", features = ["serde"] }
|
||||||
tokio = { workspace = true, features = ["rt", "sync"] }
|
|
||||||
nanoid = "0.4.0"
|
nanoid = "0.4.0"
|
||||||
|
|
||||||
dyn-clone = "1.0"
|
dyn-clone = "1.0"
|
||||||
@ -25,16 +24,18 @@ serde_repr = { workspace = true, optional = true }
|
|||||||
validator = "0.16.1"
|
validator = "0.16.1"
|
||||||
tracing.workspace = true
|
tracing.workspace = true
|
||||||
parking_lot = "0.12"
|
parking_lot = "0.12"
|
||||||
bincode = { version = "1.3", optional = true}
|
bincode = { version = "1.3", optional = true }
|
||||||
protobuf = { workspace = true, optional = true }
|
protobuf = { workspace = true, optional = true }
|
||||||
|
|
||||||
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
||||||
thread-id = "3.3.0"
|
thread-id = "3.3.0"
|
||||||
|
tokio = { workspace = true, features = ["full", "rt-multi-thread"] }
|
||||||
|
|
||||||
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
||||||
getrandom = { version = "0.2", features = ["js"]}
|
getrandom = { version = "0.2", features = ["js"] }
|
||||||
wasm-bindgen = { version = "0.2.89" }
|
wasm-bindgen = { version = "0.2.89" }
|
||||||
wasm-bindgen-futures = "0.4"
|
wasm-bindgen-futures = "0.4"
|
||||||
|
tokio = { workspace = true, features = ["rt", "sync"] }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
tokio = { workspace = true, features = ["rt"] }
|
tokio = { workspace = true, features = ["rt"] }
|
||||||
@ -43,7 +44,7 @@ futures-util = "0.3.26"
|
|||||||
[features]
|
[features]
|
||||||
default = ["use_protobuf"]
|
default = ["use_protobuf"]
|
||||||
use_serde = ["bincode", "serde_json", "serde", "serde_repr"]
|
use_serde = ["bincode", "serde_json", "serde", "serde_repr"]
|
||||||
use_protobuf= ["protobuf"]
|
use_protobuf = ["protobuf"]
|
||||||
local_set = []
|
local_set = []
|
||||||
|
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ md5 = "0.7.0"
|
|||||||
anyhow.workspace = true
|
anyhow.workspace = true
|
||||||
walkdir = "2.4.0"
|
walkdir = "2.4.0"
|
||||||
tempfile = "3.8.1"
|
tempfile = "3.8.1"
|
||||||
validator = "0.16.0"
|
validator = { version = "0.16.1", features = ["derive"] }
|
||||||
tracing.workspace = true
|
tracing.workspace = true
|
||||||
atomic_refcell = "0.1"
|
atomic_refcell = "0.1"
|
||||||
allo-isolate = { version = "^0.1", features = ["catch-unwind"], optional = true }
|
allo-isolate = { version = "^0.1", features = ["catch-unwind"], optional = true }
|
||||||
|
Loading…
Reference in New Issue
Block a user