Skip to content

Commit

Permalink
fix: using a share level bigger than max share level now returns perm…
Browse files Browse the repository at this point in the history
…ission denied.
  • Loading branch information
zrll12 committed Mar 27, 2024
1 parent 9851767 commit 8ae5f5d
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 58 deletions.
8 changes: 6 additions & 2 deletions src/service/share/create.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,12 @@ pub async fn create_share(headers: HeaderMap, Json(body): Json<CreateShareReques
let raw: Vec<i64> = serde_json::from_str(&e).unwrap();
LevelInfo::try_from(raw).unwrap_or_else(|_| LevelInfo::get_free_level())
}).max().unwrap_or_else(|| LevelInfo::get_free_level());
let max_level = level.get_max_share_level();
let share_level = min(max_level as u8, body.mode as u8);
let max_level = level.level.get_max_share_level();
let share_level = body.mode as u8;

if share_level > max_level as u8 {
return Err(ErrorMessage::PermissionDenied);
}
let password = match body.password {
None => { None }
Some(a) => { Some(generate_password_hash(&a)) }
Expand Down
114 changes: 58 additions & 56 deletions src/service/user/level.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crate::model::prelude::User;

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct LevelInfo {
level: Level,
pub level: Level,
start: DateTime<Utc>,
end: DateTime<Utc>,
}
Expand All @@ -20,22 +20,46 @@ impl LevelInfo {
self.start < now && self.end > now
}

pub fn get_max_share_level(&self) -> ShareLevel {
match self.level {
Level::Free => ShareLevel::Watermarked,
Level::Started => ShareLevel::Compressed,
Level::Advanced => ShareLevel::Compressed,
Level::Professional => ShareLevel::Original,
}
}

pub fn get_free_level() -> Self {
LevelInfo {
level: Level::Free,
start: Utc.timestamp_opt(0, 0).unwrap(),
end: Utc.timestamp_opt(0, 0).unwrap(),
}
}

pub fn remove_invalid_levels(levels: Vec<Self>) -> Vec<Self> {
levels.into_iter().filter(|level| level.is_valid()).collect()
}
}

impl TryFrom<Vec<i64>> for LevelInfo {
type Error = std::io::Error;

fn try_from(value: Vec<i64>) -> Result<Self, Self::Error> {
if value.len() != 3 {
return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "Invalid data length"));
}
if value[0] > 3 || value[0] < 0 {
return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "Invalid level"));
}

Ok(LevelInfo {
level: Level::from(value[0] as u8),
start: Utc.timestamp_opt(value[1], 0).unwrap(),
end: Utc.timestamp_opt(value[2], 0).unwrap(),
})
}
}

impl From<LevelInfo> for Vec<i64> {
fn from(value: LevelInfo) -> Self {
vec![
value.level as i64,
value.start.timestamp(),
value.end.timestamp(),
]
}
}

impl Eq for LevelInfo {}
Expand All @@ -62,9 +86,6 @@ impl Ord for LevelInfo {
}


pub fn remove_invalid_levels(levels: Vec<LevelInfo>) -> Vec<LevelInfo> {
levels.into_iter().filter(|level| level.is_valid()).collect()
}

#[derive(Clone, Debug, Serialize, Deserialize, Ord, PartialOrd, Eq, PartialEq)]
pub enum Level {
Expand All @@ -74,6 +95,26 @@ pub enum Level {
Professional,
}

impl Level {
pub fn get_price(&self) -> i32 {
match self {
Level::Free => 0,
Level::Started => 3000,
Level::Advanced => 5000,
Level::Professional => 15000,
}
}

pub fn get_max_share_level(&self) -> ShareLevel {
match self {
Level::Free => ShareLevel::Watermarked,
Level::Started => ShareLevel::Compressed,
Level::Advanced => ShareLevel::Compressed,
Level::Professional => ShareLevel::Original,
}
}
}

impl Display for Level {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Expand All @@ -98,16 +139,6 @@ impl From<u8> for Level {
}


impl Level {
pub fn get_price(&self) -> i32 {
match self {
Level::Free => 0,
Level::Started => 3000,
Level::Advanced => 5000,
Level::Professional => 15000,
}
}
}

#[derive(Clone, Debug, Serialize, Deserialize, Ord, PartialOrd, Eq, PartialEq)]
pub enum ShareLevel {
Expand All @@ -116,26 +147,6 @@ pub enum ShareLevel {
Watermarked,
}


impl TryFrom<Vec<i64>> for LevelInfo {
type Error = std::io::Error;

fn try_from(value: Vec<i64>) -> Result<Self, Self::Error> {
if value.len() != 3 {
return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "Invalid data length"));
}
if value[0] > 3 || value[0] < 0 {
return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "Invalid level"));
}

Ok(LevelInfo {
level: Level::from(value[0] as u8),
start: Utc.timestamp_opt(value[1], 0).unwrap(),
end: Utc.timestamp_opt(value[2], 0).unwrap(),
})
}
}

impl TryFrom<i16> for ShareLevel {
type Error = std::io::Error;

Expand All @@ -149,22 +160,13 @@ impl TryFrom<i16> for ShareLevel {
}
}

impl From<LevelInfo> for Vec<i64> {
fn from(value: LevelInfo) -> Self {
vec![
value.level as i64,
value.start.timestamp(),
value.end.timestamp(),
]
}
}

pub async fn add_level_to_user(user_id: i64, level: Level, period: i16, start_time: DateTime<Utc>) -> Result<(), String> {
let level_info = LevelInfo {
let level_info: Vec<i64> = LevelInfo {
level,
start: start_time,
end: start_time.checked_add_months(Months::new(period as u32)).unwrap(),
};
}.into();
let user = User::find_by_id(user_id).one(&*crate::DATABASE).await.unwrap().ok_or("Cannot fond user".to_string())?;
let mut levels = user.level.clone();
levels.push(serde_json::to_string(&level_info).unwrap());
Expand All @@ -178,7 +180,7 @@ pub async fn add_level_to_user(user_id: i64, level: Level, period: i16, start_ti

#[test]
fn test_level_serialize() {
let level_str = r#"{"level":"Started","start":"2024-02-20T07:57:52Z","end":"2024-02-27T07:57:52Z"}"#;
let level_str = r#"{"level":"Started","start":"2024-02-20T07:57:52Z","end":"2025-02-27T07:57:52Z"}"#;
let level_info: LevelInfo = serde_json::from_str(level_str).unwrap();

assert_eq!(serde_json::to_string(&level_info).unwrap(), level_str);
Expand All @@ -187,7 +189,7 @@ fn test_level_serialize() {
let level_array: Vec<i64> = serde_json::from_str(level_array_str).unwrap();
let level_info2 = LevelInfo::try_from(level_array).unwrap();

println!("level: {}", serde_json::to_string(&level_info2).unwrap());
println!("level: {}", serde_json::to_string::<Vec<i64>>(&level_info2.clone().into()).unwrap());

assert_eq!(level_info2, level_info);
}

0 comments on commit 8ae5f5d

Please sign in to comment.