mirror of
https://github.com/Arcadia-Solutions/arcadia.git
synced 2025-12-21 09:19:33 -06:00
Merge branch 'main' of https://github.com/Arcadia-Solutions/arcadia
This commit is contained in:
@@ -1,12 +1,13 @@
|
||||
use crate::Arcadia;
|
||||
use actix_web::{
|
||||
web::{Data, Json},
|
||||
HttpResponse,
|
||||
HttpRequest, HttpResponse,
|
||||
};
|
||||
use arcadia_common::error::Result;
|
||||
use arcadia_storage::{
|
||||
models::user_application::{UserApplication, UserCreatedUserApplication},
|
||||
redis::RedisPoolInterface,
|
||||
sqlx::types::ipnetwork::IpNetwork,
|
||||
};
|
||||
|
||||
#[utoipa::path(
|
||||
@@ -20,11 +21,18 @@ use arcadia_storage::{
|
||||
)]
|
||||
pub async fn exec<R: RedisPoolInterface + 'static>(
|
||||
arc: Data<Arcadia<R>>,
|
||||
req: HttpRequest,
|
||||
application: Json<UserCreatedUserApplication>,
|
||||
) -> Result<HttpResponse> {
|
||||
let client_ip = req
|
||||
.connection_info()
|
||||
.realip_remote_addr()
|
||||
.and_then(|ip| ip.parse::<IpNetwork>().ok())
|
||||
.unwrap();
|
||||
|
||||
let created_application = arc
|
||||
.pool
|
||||
.create_user_application(&application.into_inner())
|
||||
.create_user_application(&application.into_inner(), client_ip)
|
||||
.await?;
|
||||
|
||||
Ok(HttpResponse::Created().json(created_application))
|
||||
|
||||
@@ -451,8 +451,14 @@ async fn test_non_owner_cannot_edit_thread(pool: PgPool) {
|
||||
let pool = Arc::new(ConnectionPool::with_pg_pool(pool));
|
||||
|
||||
// First, login as staff user (101) and create a thread owned by them
|
||||
let (service, staff_user) =
|
||||
create_test_app_and_login(pool.clone(), MockRedisPool::default(), 100, 100, TestUser::Staff).await;
|
||||
let (service, staff_user) = create_test_app_and_login(
|
||||
pool.clone(),
|
||||
MockRedisPool::default(),
|
||||
100,
|
||||
100,
|
||||
TestUser::Staff,
|
||||
)
|
||||
.await;
|
||||
|
||||
let create_body = UserCreatedForumThread {
|
||||
forum_sub_category_id: 100,
|
||||
@@ -475,7 +481,8 @@ async fn test_non_owner_cannot_edit_thread(pool: PgPool) {
|
||||
|
||||
// Now login as a different non-staff user (100) and try to edit the staff user's thread
|
||||
let (service2, standard_user) =
|
||||
create_test_app_and_login(pool, MockRedisPool::default(), 100, 100, TestUser::Standard).await;
|
||||
create_test_app_and_login(pool, MockRedisPool::default(), 100, 100, TestUser::Standard)
|
||||
.await;
|
||||
|
||||
let edit_body = EditedForumThread {
|
||||
id: thread.id, // Thread owned by user 101 (staff)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "\n INSERT INTO user_applications (body, referral, email, staff_note, status)\n VALUES ($1, $2, $3, '', 'pending')\n RETURNING id, created_at, body, email, referral, staff_note,\n status as \"status: UserApplicationStatus\"\n ",
|
||||
"query": "\n INSERT INTO user_applications (body, referral, email, applied_from_ip, staff_note, status)\n VALUES ($1, $2, $3, $4, '', 'pending')\n RETURNING id, created_at, body, email, referral,\n applied_from_ip as \"applied_from_ip: IpNetwork\",\n staff_note, status as \"status: UserApplicationStatus\"\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
@@ -30,11 +30,16 @@
|
||||
},
|
||||
{
|
||||
"ordinal": 5,
|
||||
"name": "applied_from_ip: IpNetwork",
|
||||
"type_info": "Inet"
|
||||
},
|
||||
{
|
||||
"ordinal": 6,
|
||||
"name": "staff_note",
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"ordinal": 6,
|
||||
"ordinal": 7,
|
||||
"name": "status: UserApplicationStatus",
|
||||
"type_info": {
|
||||
"Custom": {
|
||||
@@ -54,7 +59,8 @@
|
||||
"Left": [
|
||||
"Text",
|
||||
"Text",
|
||||
"Text"
|
||||
"Text",
|
||||
"Inet"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
@@ -64,8 +70,9 @@
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "1f6d24cb5529ad67db890fedb4e722bd7395bc3beacfd770acaac11ea389bb5f"
|
||||
"hash": "c26a5cd31c8ba876b555639c3e77d3ec99a052e7f28920a8802c096f3e687c6a"
|
||||
}
|
||||
@@ -98,6 +98,7 @@ CREATE TABLE user_applications (
|
||||
body TEXT NOT NULL,
|
||||
referral TEXT NOT NULL,
|
||||
email TEXT NOT NULL,
|
||||
applied_from_ip INET NOT NULL,
|
||||
staff_note TEXT NOT NULL DEFAULT '',
|
||||
status user_application_status_enum NOT NULL DEFAULT 'pending'
|
||||
);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use chrono::{DateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sqlx::prelude::FromRow;
|
||||
use sqlx::{prelude::FromRow, types::ipnetwork::IpNetwork};
|
||||
use strum::Display;
|
||||
use utoipa::ToSchema;
|
||||
|
||||
@@ -23,6 +23,8 @@ pub struct UserApplication {
|
||||
pub body: String,
|
||||
pub email: String,
|
||||
pub referral: String,
|
||||
#[schema(value_type = String)]
|
||||
pub applied_from_ip: IpNetwork,
|
||||
pub staff_note: String,
|
||||
pub status: UserApplicationStatus,
|
||||
}
|
||||
|
||||
@@ -5,24 +5,28 @@ use crate::{
|
||||
},
|
||||
};
|
||||
use arcadia_common::error::{Error, Result};
|
||||
use sqlx::types::ipnetwork::IpNetwork;
|
||||
use std::borrow::Borrow;
|
||||
|
||||
impl ConnectionPool {
|
||||
pub async fn create_user_application(
|
||||
&self,
|
||||
application: &UserCreatedUserApplication,
|
||||
from_ip: IpNetwork,
|
||||
) -> Result<UserApplication> {
|
||||
let created_application = sqlx::query_as!(
|
||||
UserApplication,
|
||||
r#"
|
||||
INSERT INTO user_applications (body, referral, email, staff_note, status)
|
||||
VALUES ($1, $2, $3, '', 'pending')
|
||||
RETURNING id, created_at, body, email, referral, staff_note,
|
||||
status as "status: UserApplicationStatus"
|
||||
INSERT INTO user_applications (body, referral, email, applied_from_ip, staff_note, status)
|
||||
VALUES ($1, $2, $3, $4, '', 'pending')
|
||||
RETURNING id, created_at, body, email, referral,
|
||||
applied_from_ip as "applied_from_ip: IpNetwork",
|
||||
staff_note, status as "status: UserApplicationStatus"
|
||||
"#,
|
||||
application.body,
|
||||
application.referral,
|
||||
application.email
|
||||
application.email,
|
||||
from_ip
|
||||
)
|
||||
.fetch_one(self.borrow())
|
||||
.await
|
||||
@@ -39,7 +43,7 @@ impl ConnectionPool {
|
||||
) -> Result<Vec<UserApplication>> {
|
||||
let query = format!(
|
||||
r#"
|
||||
SELECT id, created_at, body, email, referral, staff_note,
|
||||
SELECT id, created_at, body, email, referral, applied_from_ip, staff_note,
|
||||
status::user_application_status_enum as status
|
||||
FROM user_applications ua
|
||||
WHERE $1 IS NULL OR ua.status = $1::user_application_status_enum
|
||||
@@ -69,7 +73,7 @@ impl ConnectionPool {
|
||||
UPDATE user_applications
|
||||
SET status = $2::user_application_status_enum
|
||||
WHERE id = $1
|
||||
RETURNING id, created_at, body, email, referral, staff_note,
|
||||
RETURNING id, created_at, body, email, referral, applied_from_ip, staff_note,
|
||||
status::user_application_status_enum as status
|
||||
"#,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user