mirror of
				https://gitlab.com/comunic/comunicapiv3
				synced 2025-11-04 09:34:04 +00:00 
			
		
		
		
	Save reports in the database
This commit is contained in:
		@@ -307,10 +307,11 @@ CREATE TABLE `comunic_admin_log` (
 | 
				
			|||||||
  PRIMARY KEY (`id`));
 | 
					  PRIMARY KEY (`id`));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CREATE TABLE `comunic_reports` (
 | 
					CREATE TABLE `comunic_reports` (
 | 
				
			||||||
  `id` INT NOT NULL,
 | 
					  `id` INT NOT NULL AUTO_INCREMENT,
 | 
				
			||||||
  `user_id` INT NOT NULL,
 | 
					  `user_id` INT NOT NULL,
 | 
				
			||||||
  `target` VARCHAR(25) NOT NULL,
 | 
					  `target_type` VARCHAR(25) NOT NULL,
 | 
				
			||||||
  `target_id` INT NOT NULL,
 | 
					  `target_id` INT NOT NULL,
 | 
				
			||||||
  `time` INT NOT NULL,
 | 
					  `time` INT NOT NULL,
 | 
				
			||||||
 | 
					  `cause` VARCHAR(20) NOT NULL,
 | 
				
			||||||
  `comment` TEXT NULL,
 | 
					  `comment` TEXT NULL,
 | 
				
			||||||
  PRIMARY KEY (`id`));
 | 
					  PRIMARY KEY (`id`));
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,9 +1,10 @@
 | 
				
			|||||||
-- Create report table
 | 
					-- Create report table
 | 
				
			||||||
CREATE TABLE `comunic_reports` (
 | 
					CREATE TABLE `comunic_reports` (
 | 
				
			||||||
  `id` INT NOT NULL,
 | 
					  `id` INT NOT NULL AUTO_INCREMENT,
 | 
				
			||||||
  `user_id` INT NOT NULL,
 | 
					  `user_id` INT NOT NULL,
 | 
				
			||||||
  `target` VARCHAR(25) NOT NULL,
 | 
					  `target_type` VARCHAR(25) NOT NULL,
 | 
				
			||||||
  `target_id` INT NOT NULL,
 | 
					  `target_id` INT NOT NULL,
 | 
				
			||||||
  `time` INT NOT NULL,
 | 
					  `time` INT NOT NULL,
 | 
				
			||||||
 | 
					  `cause` VARCHAR(20) NOT NULL,
 | 
				
			||||||
  `comment` TEXT NULL,
 | 
					  `comment` TEXT NULL,
 | 
				
			||||||
  PRIMARY KEY (`id`));
 | 
					  PRIMARY KEY (`id`));
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -73,3 +73,4 @@ pub mod user_is_writing_message_in_conversation;
 | 
				
			|||||||
pub mod res_create_conversation_for_group;
 | 
					pub mod res_create_conversation_for_group;
 | 
				
			||||||
pub mod notification_settings_api;
 | 
					pub mod notification_settings_api;
 | 
				
			||||||
pub mod push_notifications_status_api;
 | 
					pub mod push_notifications_status_api;
 | 
				
			||||||
 | 
					pub mod submit_report_result_api;
 | 
				
			||||||
							
								
								
									
										12
									
								
								src/api_data/submit_report_result_api.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/api_data/submit_report_result_api.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					use crate::data::report::ReportID;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(serde::Serialize)]
 | 
				
			||||||
 | 
					pub struct SubmitReportResultApi {
 | 
				
			||||||
 | 
					    report_id: u64,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl SubmitReportResultApi {
 | 
				
			||||||
 | 
					    pub fn new(r: ReportID) -> Self {
 | 
				
			||||||
 | 
					        Self { report_id: r.0 }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -58,6 +58,9 @@ pub mod database_tables_names {
 | 
				
			|||||||
    /// Notifications table
 | 
					    /// Notifications table
 | 
				
			||||||
    pub const NOTIFICATIONS_TABLE: &str = "comunic_notifications";
 | 
					    pub const NOTIFICATIONS_TABLE: &str = "comunic_notifications";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Reports table
 | 
				
			||||||
 | 
					    pub const REPORTS_TABLE: &str = "comunic_reports";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Forez presence table
 | 
					    /// Forez presence table
 | 
				
			||||||
    pub const FOREZ_PRESENCE_TABLE: &str = "forez_presence";
 | 
					    pub const FOREZ_PRESENCE_TABLE: &str = "forez_presence";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,15 @@
 | 
				
			|||||||
 | 
					use crate::api_data::http_error::HttpError;
 | 
				
			||||||
 | 
					use crate::api_data::submit_report_result_api::SubmitReportResultApi;
 | 
				
			||||||
 | 
					use crate::constants::reports;
 | 
				
			||||||
use crate::data::base_request_handler::BaseRequestHandler;
 | 
					use crate::data::base_request_handler::BaseRequestHandler;
 | 
				
			||||||
use crate::data::config::conf;
 | 
					use crate::data::config::conf;
 | 
				
			||||||
 | 
					use crate::data::group::GroupAccessLevel;
 | 
				
			||||||
use crate::data::http_request_handler::HttpRequestHandler;
 | 
					use crate::data::http_request_handler::HttpRequestHandler;
 | 
				
			||||||
 | 
					use crate::data::post::PostAccessLevel;
 | 
				
			||||||
 | 
					use crate::data::report::{Report, REPORT_CAUSES, ReportID, ReportTarget};
 | 
				
			||||||
 | 
					use crate::helpers::reports_helper;
 | 
				
			||||||
use crate::routes::RequestResult;
 | 
					use crate::routes::RequestResult;
 | 
				
			||||||
 | 
					use crate::utils::date_utils::time;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Submit a new report
 | 
					/// Submit a new report
 | 
				
			||||||
pub async fn report(r: &mut HttpRequestHandler) -> RequestResult {
 | 
					pub async fn report(r: &mut HttpRequestHandler) -> RequestResult {
 | 
				
			||||||
@@ -9,7 +17,66 @@ pub async fn report(r: &mut HttpRequestHandler) -> RequestResult {
 | 
				
			|||||||
        r.bad_request("Reporting is disabled!".to_string())?;
 | 
					        r.bad_request("Reporting is disabled!".to_string())?;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // TODO : continue
 | 
					    let comment = r.post_string_without_html_opt("comment", 0)?;
 | 
				
			||||||
 | 
					    if comment.as_ref().map(String::len).unwrap_or(0) as u32 > reports::MAX_COMMENT_LENGTH {
 | 
				
			||||||
 | 
					        r.bad_request("Report comment is too long!".to_string())?;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    r.success("go on")
 | 
					    let cause_id = r.post_string("cause")?;
 | 
				
			||||||
 | 
					    let cause = r.some_or_bad_request(
 | 
				
			||||||
 | 
					        REPORT_CAUSES.iter().find(|c| c.id().id().eq(&cause_id)),
 | 
				
			||||||
 | 
					        "No valid report cause was given in the request!",
 | 
				
			||||||
 | 
					    )?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let target = match r.post_string("target_type")?.as_str() {
 | 
				
			||||||
 | 
					        "post" =>
 | 
				
			||||||
 | 
					            ReportTarget::Post(
 | 
				
			||||||
 | 
					                r.post_post_with_access("target_id", PostAccessLevel::BASIC_ACCESS)?.id
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        "comment" => ReportTarget::Comment(
 | 
				
			||||||
 | 
					            r.post_comment_with_access("target_id")?.id
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        "conversation" => ReportTarget::Conversation(
 | 
				
			||||||
 | 
					            r.post_conv("target_id")?.conv_id
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        "conversation_message" => ReportTarget::ConversationMessage(
 | 
				
			||||||
 | 
					            r.post_conv_message_id("target_id")?.id
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        "user" => ReportTarget::User(
 | 
				
			||||||
 | 
					            r.post_user_id("target_id")?
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        "group" => ReportTarget::Group(
 | 
				
			||||||
 | 
					            r.post_group_id_with_access("target_id", GroupAccessLevel::LIMITED_ACCESS)?
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        _ => {
 | 
				
			||||||
 | 
					            r.bad_request("Unknown target type!".to_string())?;
 | 
				
			||||||
 | 
					            unreachable!();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let report = Report {
 | 
				
			||||||
 | 
					        id: ReportID(0),
 | 
				
			||||||
 | 
					        user_id: r.user_id()?,
 | 
				
			||||||
 | 
					        target,
 | 
				
			||||||
 | 
					        time: time(),
 | 
				
			||||||
 | 
					        cause,
 | 
				
			||||||
 | 
					        comment,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Check for duplicate
 | 
				
			||||||
 | 
					    if reports_helper::already_exists(&report)? {
 | 
				
			||||||
 | 
					        r.set_error(HttpError::new(409, "You have already submitted a report for this resource!"));
 | 
				
			||||||
 | 
					        return Ok(());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Save report
 | 
				
			||||||
 | 
					    let report_id = reports_helper::save_report(report)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    r.set_response(SubmitReportResultApi::new(report_id))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -18,6 +18,7 @@ use crate::data::admin::AdminID;
 | 
				
			|||||||
use crate::data::comment::Comment;
 | 
					use crate::data::comment::Comment;
 | 
				
			||||||
use crate::data::config::conf;
 | 
					use crate::data::config::conf;
 | 
				
			||||||
use crate::data::conversation::{ConversationMember, ConvID};
 | 
					use crate::data::conversation::{ConversationMember, ConvID};
 | 
				
			||||||
 | 
					use crate::data::conversation_message::ConversationMessage;
 | 
				
			||||||
use crate::data::custom_emoji::CustomEmoji;
 | 
					use crate::data::custom_emoji::CustomEmoji;
 | 
				
			||||||
use crate::data::error::{ExecError, Res, ResultBoxError};
 | 
					use crate::data::error::{ExecError, Res, ResultBoxError};
 | 
				
			||||||
use crate::data::group::GroupAccessLevel;
 | 
					use crate::data::group::GroupAccessLevel;
 | 
				
			||||||
@@ -695,6 +696,23 @@ pub trait BaseRequestHandler {
 | 
				
			|||||||
        Ok(conv)
 | 
					        Ok(conv)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Get & return information about a conversation message. The user must be a member of the
 | 
				
			||||||
 | 
					    /// conversation
 | 
				
			||||||
 | 
					    fn post_conv_message_id(&mut self, name: &str) -> Res<ConversationMessage> {
 | 
				
			||||||
 | 
					        let msg_id = self.post_u64(name)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let conv_message = self.ok_or_not_found(
 | 
				
			||||||
 | 
					            conversations_helper::get_single_message(msg_id),
 | 
				
			||||||
 | 
					            "Requested conversation message was not found!",
 | 
				
			||||||
 | 
					        )?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if conversations_helper::get_user_membership(&self.user_id()?, conv_message.conv_id).is_err() {
 | 
				
			||||||
 | 
					            self.forbidden("You do not belong to the conversation attached to this message!".to_string())?;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Ok(conv_message)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Get the ID
 | 
					    /// Get the ID
 | 
				
			||||||
    fn post_group_id(&mut self, name: &str) -> ResultBoxError<GroupID> {
 | 
					    fn post_group_id(&mut self, name: &str) -> ResultBoxError<GroupID> {
 | 
				
			||||||
        let group_id = GroupID::new(self.post_u64(name)?);
 | 
					        let group_id = GroupID::new(self.post_u64(name)?);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,6 +14,19 @@ pub enum ReportTarget {
 | 
				
			|||||||
    Group(GroupID),
 | 
					    Group(GroupID),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl ReportTarget {
 | 
				
			||||||
 | 
					    pub fn to_db(&self) -> (&'static str, u64) {
 | 
				
			||||||
 | 
					        match self {
 | 
				
			||||||
 | 
					            ReportTarget::Post(i) => ("post", *i),
 | 
				
			||||||
 | 
					            ReportTarget::Comment(i) => ("comment", *i),
 | 
				
			||||||
 | 
					            ReportTarget::Conversation(i) => ("conversation", i.id()),
 | 
				
			||||||
 | 
					            ReportTarget::ConversationMessage(i) => ("conv_msg", *i),
 | 
				
			||||||
 | 
					            ReportTarget::User(i) => ("user", i.id()),
 | 
				
			||||||
 | 
					            ReportTarget::Group(i) => ("group", i.id()),
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Eq, PartialEq, Copy, Clone)]
 | 
					#[derive(Eq, PartialEq, Copy, Clone)]
 | 
				
			||||||
pub struct ReportCauseId(&'static str);
 | 
					pub struct ReportCauseId(&'static str);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -71,5 +84,6 @@ pub struct Report {
 | 
				
			|||||||
    pub user_id: UserID,
 | 
					    pub user_id: UserID,
 | 
				
			||||||
    pub target: ReportTarget,
 | 
					    pub target: ReportTarget,
 | 
				
			||||||
    pub time: u64,
 | 
					    pub time: u64,
 | 
				
			||||||
 | 
					    pub cause: &'static ReportCause,
 | 
				
			||||||
    pub comment: Option<String>,
 | 
					    pub comment: Option<String>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -21,7 +21,9 @@ pub mod calls_helper;
 | 
				
			|||||||
pub mod push_notifications_helper;
 | 
					pub mod push_notifications_helper;
 | 
				
			||||||
pub mod independent_push_notifications_service_helper;
 | 
					pub mod independent_push_notifications_service_helper;
 | 
				
			||||||
pub mod firebase_notifications_helper;
 | 
					pub mod firebase_notifications_helper;
 | 
				
			||||||
 | 
					pub mod reports_helper;
 | 
				
			||||||
pub mod forez_presence_helper;
 | 
					pub mod forez_presence_helper;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub mod admin_account_helper;
 | 
					pub mod admin_account_helper;
 | 
				
			||||||
pub mod admin_account_key_helper;
 | 
					pub mod admin_account_key_helper;
 | 
				
			||||||
pub mod admin_access_token_helper;
 | 
					pub mod admin_access_token_helper;
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										30
									
								
								src/helpers/reports_helper.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								src/helpers/reports_helper.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,30 @@
 | 
				
			|||||||
 | 
					use crate::constants::database_tables_names::REPORTS_TABLE;
 | 
				
			||||||
 | 
					use crate::data::error::Res;
 | 
				
			||||||
 | 
					use crate::data::report::{Report, ReportID};
 | 
				
			||||||
 | 
					use crate::helpers::database;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Check if a report has already been saved by the same user on the same resource
 | 
				
			||||||
 | 
					pub fn already_exists(r: &Report) -> Res<bool> {
 | 
				
			||||||
 | 
					    let (target_type, target_id) = r.target.to_db();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    database::QueryInfo::new(REPORTS_TABLE)
 | 
				
			||||||
 | 
					        .cond_user_id("user_id", &r.user_id)
 | 
				
			||||||
 | 
					        .cond("target_type", target_type)
 | 
				
			||||||
 | 
					        .cond_u64("target_id", target_id)
 | 
				
			||||||
 | 
					        .exec_count_has_at_least_one_result()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Save a new report in the database
 | 
				
			||||||
 | 
					pub fn save_report(r: Report) -> Res<ReportID> {
 | 
				
			||||||
 | 
					    let (target_type, target_id) = r.target.to_db();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    database::InsertQuery::new(REPORTS_TABLE)
 | 
				
			||||||
 | 
					        .add_user_id("user_id", &r.user_id)
 | 
				
			||||||
 | 
					        .add_str("target_type", target_type)
 | 
				
			||||||
 | 
					        .add_u64("target_id", target_id)
 | 
				
			||||||
 | 
					        .add_u64("time", r.time)
 | 
				
			||||||
 | 
					        .add_str("cause", r.cause.id().id())
 | 
				
			||||||
 | 
					        .add_opt_str("comment", r.comment.as_ref())
 | 
				
			||||||
 | 
					        .insert_expect_result()
 | 
				
			||||||
 | 
					        .map(|i| ReportID(i))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user