mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
feat: encrypt collab update (#3215)
* feat: implement encrypt and decrypt * feat: encrypt and decrypt * feat: update user profile with encrypt * chore: store encryption sign * fix: login in setting menu * chore: show encryption account name * chore: fix test * ci: fix warnings * test: enable supabase test * chore: fix test and rename column * fix: update user profile after set the secret * fix: encryption with wrong secret * fix: don't save user data if the return value of did_sign_up is err * chore: encrypt snapshot data * chore: refactor snapshots interface * ci: add tests * chore: update collab rev
This commit is contained in:
@ -887,6 +887,6 @@ pub(crate) async fn get_snapshots_handler(
|
||||
) -> DataResult<RepeatedDatabaseSnapshotPB, FlowyError> {
|
||||
let manager = upgrade_manager(manager)?;
|
||||
let view_id = data.into_inner().value;
|
||||
let snapshots = manager.get_database_snapshots(&view_id).await?;
|
||||
let snapshots = manager.get_database_snapshots(&view_id, 10).await?;
|
||||
data_result_ok(RepeatedDatabaseSnapshotPB { items: snapshots })
|
||||
}
|
||||
|
@ -73,7 +73,7 @@ impl DatabaseManager {
|
||||
&self,
|
||||
uid: i64,
|
||||
_workspace_id: String,
|
||||
workspace_database_id: String,
|
||||
database_storage_id: String,
|
||||
) -> FlowyResult<()> {
|
||||
let collab_db = self.user.collab_db(uid)?;
|
||||
let collab_builder = UserDatabaseCollabServiceImpl {
|
||||
@ -84,28 +84,30 @@ impl DatabaseManager {
|
||||
let mut collab_raw_data = CollabRawData::default();
|
||||
|
||||
// If the workspace database not exist in disk, try to fetch from remote.
|
||||
if !self.is_collab_exist(uid, &collab_db, &workspace_database_id) {
|
||||
if !self.is_collab_exist(uid, &collab_db, &database_storage_id) {
|
||||
tracing::trace!("workspace database not exist, try to fetch from remote");
|
||||
match self
|
||||
.cloud_service
|
||||
.get_collab_update(&workspace_database_id, CollabType::WorkspaceDatabase)
|
||||
.get_collab_update(&database_storage_id, CollabType::WorkspaceDatabase)
|
||||
.await
|
||||
{
|
||||
Ok(updates) => collab_raw_data = updates,
|
||||
Ok(updates) => {
|
||||
collab_raw_data = updates;
|
||||
},
|
||||
Err(err) => {
|
||||
return Err(FlowyError::record_not_found().context(format!(
|
||||
"get workspace database :{} failed: {}",
|
||||
workspace_database_id, err,
|
||||
database_storage_id, err,
|
||||
)));
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Construct the workspace database.
|
||||
tracing::trace!("open workspace database: {}", &workspace_database_id);
|
||||
tracing::trace!("open workspace database: {}", &database_storage_id);
|
||||
let collab = collab_builder.build_collab_with_config(
|
||||
uid,
|
||||
&workspace_database_id,
|
||||
&database_storage_id,
|
||||
CollabType::WorkspaceDatabase,
|
||||
collab_db.clone(),
|
||||
collab_raw_data,
|
||||
@ -307,22 +309,21 @@ impl DatabaseManager {
|
||||
pub async fn get_database_snapshots(
|
||||
&self,
|
||||
view_id: &str,
|
||||
limit: usize,
|
||||
) -> FlowyResult<Vec<DatabaseSnapshotPB>> {
|
||||
let database_id = self.get_database_id_with_view_id(view_id).await?;
|
||||
let mut snapshots = vec![];
|
||||
if let Some(snapshot) = self
|
||||
let snapshots = self
|
||||
.cloud_service
|
||||
.get_collab_latest_snapshot(&database_id)
|
||||
.get_collab_snapshots(&database_id, limit)
|
||||
.await?
|
||||
.into_iter()
|
||||
.map(|snapshot| DatabaseSnapshotPB {
|
||||
snapshot_id: snapshot.snapshot_id,
|
||||
snapshot_desc: "".to_string(),
|
||||
created_at: snapshot.created_at,
|
||||
data: snapshot.data,
|
||||
})
|
||||
{
|
||||
snapshots.push(snapshot);
|
||||
}
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
Ok(snapshots)
|
||||
}
|
||||
|
@ -1,3 +1,19 @@
|
||||
use std::format;
|
||||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
|
||||
use chrono::{
|
||||
DateTime, Datelike, Days, Duration, Local, NaiveDate, NaiveDateTime, Offset, TimeZone,
|
||||
};
|
||||
use chrono_tz::Tz;
|
||||
use collab_database::database::timestamp;
|
||||
use collab_database::fields::Field;
|
||||
use collab_database::rows::{new_cell_builder, Cell, Cells, Row, RowDetail};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_repr::{Deserialize_repr, Serialize_repr};
|
||||
|
||||
use flowy_error::FlowyResult;
|
||||
|
||||
use crate::entities::{
|
||||
DateCellDataPB, FieldType, GroupPB, GroupRowsNotificationPB, InsertedGroupPB, InsertedRowPB,
|
||||
RowMetaPB,
|
||||
@ -12,19 +28,6 @@ use crate::services::group::controller::{
|
||||
use crate::services::group::{
|
||||
make_no_status_group, move_group_row, GeneratedGroupConfig, GeneratedGroups, Group,
|
||||
};
|
||||
use chrono::{
|
||||
DateTime, Datelike, Days, Duration, Local, NaiveDate, NaiveDateTime, Offset, TimeZone,
|
||||
};
|
||||
use chrono_tz::Tz;
|
||||
use collab_database::database::timestamp;
|
||||
use collab_database::fields::Field;
|
||||
use collab_database::rows::{new_cell_builder, Cell, Cells, Row, RowDetail};
|
||||
use flowy_error::FlowyResult;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_repr::{Deserialize_repr, Serialize_repr};
|
||||
use std::format;
|
||||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub trait GroupConfigurationContentSerde: Sized + Send + Sync {
|
||||
fn from_json(s: &str) -> Result<Self, serde_json::Error>;
|
||||
@ -46,9 +49,10 @@ impl GroupConfigurationContentSerde for DateGroupConfiguration {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize_repr, Deserialize_repr)]
|
||||
#[derive(Default, Serialize_repr, Deserialize_repr)]
|
||||
#[repr(u8)]
|
||||
pub enum DateCondition {
|
||||
#[default]
|
||||
Relative = 0,
|
||||
Day = 1,
|
||||
Week = 2,
|
||||
@ -56,12 +60,6 @@ pub enum DateCondition {
|
||||
Year = 4,
|
||||
}
|
||||
|
||||
impl std::default::Default for DateCondition {
|
||||
fn default() -> Self {
|
||||
DateCondition::Relative
|
||||
}
|
||||
}
|
||||
|
||||
pub type DateGroupController = BaseGroupController<
|
||||
DateGroupConfiguration,
|
||||
DateTypeOption,
|
||||
@ -245,7 +243,7 @@ impl GroupController for DateGroupController {
|
||||
match self.context.get_group(group_id) {
|
||||
None => tracing::warn!("Can not find the group: {}", group_id),
|
||||
Some((_, _)) => {
|
||||
let date = DateTime::parse_from_str(&group_id, GROUP_ID_DATE_FORMAT).unwrap();
|
||||
let date = DateTime::parse_from_str(group_id, GROUP_ID_DATE_FORMAT).unwrap();
|
||||
let cell = insert_date_cell(date.timestamp(), None, field);
|
||||
cells.insert(field.id.clone(), cell);
|
||||
},
|
||||
@ -299,7 +297,7 @@ impl GroupsBuilder for DateGroupGenerator {
|
||||
fn make_group_from_date_cell(
|
||||
cell_data: &DateCellData,
|
||||
type_option: Option<&DateTypeOption>,
|
||||
setting_content: &String,
|
||||
setting_content: &str,
|
||||
) -> Group {
|
||||
let group_id = group_id(cell_data, type_option, setting_content);
|
||||
Group::new(
|
||||
@ -308,12 +306,12 @@ fn make_group_from_date_cell(
|
||||
)
|
||||
}
|
||||
|
||||
const GROUP_ID_DATE_FORMAT: &'static str = "%Y/%m/%d";
|
||||
const GROUP_ID_DATE_FORMAT: &str = "%Y/%m/%d";
|
||||
|
||||
fn group_id(
|
||||
cell_data: &DateCellData,
|
||||
type_option: Option<&DateTypeOption>,
|
||||
setting_content: &String,
|
||||
setting_content: &str,
|
||||
) -> String {
|
||||
let binding = DateTypeOption::default();
|
||||
let type_option = type_option.unwrap_or(&binding);
|
||||
@ -343,11 +341,11 @@ fn group_id(
|
||||
now.checked_add_signed(Duration::days(-1))
|
||||
} else if diff == 1 {
|
||||
now.checked_add_signed(Duration::days(1))
|
||||
} else if diff >= -7 && diff < -1 {
|
||||
} else if (-7..-1).contains(&diff) {
|
||||
now.checked_add_signed(Duration::days(-7))
|
||||
} else if diff > 1 && diff <= 7 {
|
||||
now.checked_add_signed(Duration::days(2))
|
||||
} else if diff >= -30 && diff < -7 {
|
||||
} else if (-30..-7).contains(&diff) {
|
||||
now.checked_add_signed(Duration::days(-30))
|
||||
} else if diff > 7 && diff <= 30 {
|
||||
now.checked_add_signed(Duration::days(8))
|
||||
@ -374,9 +372,9 @@ fn group_id(
|
||||
}
|
||||
|
||||
fn group_name_from_id(
|
||||
group_id: &String,
|
||||
group_id: &str,
|
||||
type_option: Option<&DateTypeOption>,
|
||||
setting_content: &String,
|
||||
setting_content: &str,
|
||||
) -> String {
|
||||
let binding = DateTypeOption::default();
|
||||
let type_option = type_option.unwrap_or(&binding);
|
||||
@ -386,12 +384,7 @@ fn group_name_from_id(
|
||||
let tmp;
|
||||
match config.condition {
|
||||
DateCondition::Day => {
|
||||
tmp = format!(
|
||||
"{} {}, {}",
|
||||
date.format("%b").to_string(),
|
||||
date.day(),
|
||||
date.year(),
|
||||
);
|
||||
tmp = format!("{} {}, {}", date.format("%b"), date.day(), date.year(),);
|
||||
tmp
|
||||
},
|
||||
DateCondition::Week => {
|
||||
@ -406,15 +399,15 @@ fn group_name_from_id(
|
||||
|
||||
tmp = format!(
|
||||
"Week of {} {}-{} {}",
|
||||
date.format("%b").to_string(),
|
||||
begin_of_week.to_string(),
|
||||
end_of_week.to_string(),
|
||||
date.format("%b"),
|
||||
begin_of_week,
|
||||
end_of_week,
|
||||
date.year()
|
||||
);
|
||||
tmp
|
||||
},
|
||||
DateCondition::Month => {
|
||||
tmp = format!("{} {}", date.format("%b").to_string(), date.year(),);
|
||||
tmp = format!("{} {}", date.format("%b"), date.year(),);
|
||||
tmp
|
||||
},
|
||||
DateCondition::Year => date.year().to_string(),
|
||||
@ -431,7 +424,7 @@ fn group_name_from_id(
|
||||
-30 => "Last 30 days",
|
||||
8 => "Next 30 days",
|
||||
_ => {
|
||||
tmp = format!("{} {}", date.format("%b").to_string(), date.year(),);
|
||||
tmp = format!("{} {}", date.format("%b"), date.year(),);
|
||||
&tmp
|
||||
},
|
||||
};
|
||||
@ -441,7 +434,7 @@ fn group_name_from_id(
|
||||
}
|
||||
}
|
||||
|
||||
fn date_time_from_timestamp(timestamp: Option<i64>, timezone_id: &String) -> DateTime<Local> {
|
||||
fn date_time_from_timestamp(timestamp: Option<i64>, timezone_id: &str) -> DateTime<Local> {
|
||||
match timestamp {
|
||||
Some(timestamp) => {
|
||||
let naive = NaiveDateTime::from_timestamp_opt(timestamp, 0).unwrap();
|
||||
@ -458,14 +451,17 @@ fn date_time_from_timestamp(timestamp: Option<i64>, timezone_id: &String) -> Dat
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::vec;
|
||||
|
||||
use chrono::{offset, Days, Duration, NaiveDateTime};
|
||||
|
||||
use crate::entities::FieldType;
|
||||
use crate::services::{
|
||||
field::{date_type_option::DateTypeOption, DateCellData},
|
||||
group::controller_impls::date_controller::{
|
||||
group_id, group_name_from_id, GROUP_ID_DATE_FORMAT,
|
||||
},
|
||||
};
|
||||
use chrono::{offset, Days, Duration, NaiveDateTime};
|
||||
use std::vec;
|
||||
|
||||
#[test]
|
||||
fn group_id_name_test() {
|
||||
@ -485,9 +481,9 @@ mod tests {
|
||||
let today = offset::Local::now();
|
||||
let three_days_before = today.checked_add_signed(Duration::days(-3)).unwrap();
|
||||
|
||||
let mut local_date_type_option = DateTypeOption::default();
|
||||
let mut local_date_type_option = DateTypeOption::new(FieldType::DateTime);
|
||||
local_date_type_option.timezone_id = today.offset().to_string();
|
||||
let mut default_date_type_option = DateTypeOption::default();
|
||||
let mut default_date_type_option = DateTypeOption::new(FieldType::DateTime);
|
||||
default_date_type_option.timezone_id = "".to_string();
|
||||
|
||||
let tests = vec![
|
||||
@ -552,7 +548,7 @@ mod tests {
|
||||
exp_group_name: "Mar 2022".to_string(),
|
||||
},
|
||||
GroupIDTest {
|
||||
cell_data: mar_14_2022_cd.clone(),
|
||||
cell_data: mar_14_2022_cd,
|
||||
type_option: &local_date_type_option,
|
||||
setting_content: r#"{"condition": 4, "hide_empty": false}"#.to_string(),
|
||||
exp_group_id: "2022/01/01".to_string(),
|
||||
@ -588,7 +584,7 @@ mod tests {
|
||||
);
|
||||
assert_eq!(test.exp_group_id, group_id, "test {}", i);
|
||||
|
||||
if test.exp_group_name != "" {
|
||||
if !test.exp_group_name.is_empty() {
|
||||
let group_name =
|
||||
group_name_from_id(&group_id, Some(test.type_option), &test.setting_content);
|
||||
assert_eq!(test.exp_group_name, group_name, "test {}", i);
|
||||
|
@ -174,11 +174,9 @@ pub fn make_inserted_cell(group_id: &str, field: &Field) -> Option<Cell> {
|
||||
Some(cell)
|
||||
},
|
||||
FieldType::DateTime => {
|
||||
let date = NaiveDateTime::parse_from_str(
|
||||
&format!("{} 00:00:00", group_id).to_string(),
|
||||
"%Y/%m/%d %H:%M:%S",
|
||||
)
|
||||
.unwrap();
|
||||
let date =
|
||||
NaiveDateTime::parse_from_str(&format!("{} 00:00:00", group_id), "%Y/%m/%d %H:%M:%S")
|
||||
.unwrap();
|
||||
let cell = insert_date_cell(date.timestamp(), None, field);
|
||||
Some(cell)
|
||||
},
|
||||
|
Reference in New Issue
Block a user