Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a9dfbb423f |
No files matched your search
@@ -1,3 +0,0 @@
|
||||
pub const STUDENT_PROVIDER_POOL_ID: &str = "us-east-1_Lfjuy5zaM";
|
||||
pub const PROVIDER_GROUP: &str = "ScholarshipProviders";
|
||||
pub const STUDENT_GROUP: &str = "ScholarshipStudents";
|
||||
@@ -4,7 +4,6 @@ use aws_config::BehaviorVersion;
|
||||
use serde::{Serialize, Deserialize};
|
||||
use std::collections::HashMap;
|
||||
use aws_sdk_cognitoidentityprovider::error::ProvideErrorMetadata;
|
||||
use crate::constants::{PROVIDER_GROUP, STUDENT_GROUP, STUDENT_PROVIDER_POOL_ID};
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
@@ -44,7 +43,7 @@ async fn add_user_to_group(provider: Client, user_id: String, group_name: impl I
|
||||
println!("Adding user {} to group {}", user_id, group_name);
|
||||
match provider
|
||||
.admin_add_user_to_group()
|
||||
.user_pool_id(STUDENT_PROVIDER_POOL_ID)
|
||||
.user_pool_id("us-east-1_Lfjuy5zaM")
|
||||
.username(user_id)
|
||||
.group_name(group_name)
|
||||
.send()
|
||||
@@ -64,8 +63,8 @@ pub(crate) async fn handler(event: LambdaEvent<PostConfirmationEvent>) -> Result
|
||||
|
||||
// Check the client ID of the request to assign the user to the correct location.
|
||||
let res = match event.payload.caller_context.client_id.as_str() {
|
||||
"10jr2h3vtpu9n7gj46pvg5qo2q" => add_user_to_group(client, user_id, STUDENT_GROUP).await,
|
||||
"56c2bqvl021rv8d5mq36blt7jv" => add_user_to_group(client, user_id, PROVIDER_GROUP).await,
|
||||
"10jr2h3vtpu9n7gj46pvg5qo2q" => add_user_to_group(client, user_id, "ScholarshipStudents").await,
|
||||
"56c2bqvl021rv8d5mq36blt7jv" => add_user_to_group(client, user_id, "ScholarshipProviders").await,
|
||||
_ => Err("Invalid client ID, denying all user access.".to_string()),
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
use lambda_runtime::{run, service_fn, tracing, Error};
|
||||
mod constants;
|
||||
mod handler;
|
||||
|
||||
use handler::handler as function_handler;
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
pub const STUDENT_PROVIDER_POOL_ID: &str = "us-east-1_Lfjuy5zaM";
|
||||
pub const ADMIN_POOL_ID: &str = "us-east-1_rvCU4Xy4j";
|
||||
pub const COGNITO_REGION: &str = "us-east-1";
|
||||
pub const PROVIDER_GROUP: &str = "ScholarshipProviders";
|
||||
pub const STUDENT_GROUP: &str = "ScholarshipStudents";
|
||||
+1
-2
@@ -9,9 +9,8 @@ mod value_type;
|
||||
pub mod animations;
|
||||
mod tab_info;
|
||||
mod schema_node;
|
||||
mod constants;
|
||||
|
||||
pub use self::{
|
||||
comparison::*, date_info::*, expandable_info::*, form_params::*, form_schema::*,
|
||||
submit_status::*, user::*, value_type::*, tab_info::*, schema_node::*, constants::*,
|
||||
submit_status::*, user::*, value_type::*, tab_info::*, schema_node::*,
|
||||
};
|
||||
@@ -1,12 +1,11 @@
|
||||
use crate::common::{ADMIN_POOL_ID, COGNITO_REGION};
|
||||
use crate::components::login::setup::provide_auth_context;
|
||||
use crate::components::login::setup::provide_auth_context;
|
||||
use leptos::prelude::*;
|
||||
|
||||
#[component]
|
||||
pub fn AdminLoginContext(children: Children) -> impl IntoView {
|
||||
provide_auth_context(
|
||||
crate::utils::use_origin(),
|
||||
format!("https://cognito-idp.{COGNITO_REGION}.amazonaws.com/{ADMIN_POOL_ID}"),
|
||||
"https://cognito-idp.us-east-1.amazonaws.com/us-east-1_rvCU4Xy4j",
|
||||
"1vh1q994rid6cgi6tjf58r9jp4",
|
||||
"/admin/callback",
|
||||
);
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
use leptos::prelude::*;
|
||||
use leptos_router::components::Outlet;
|
||||
use super::setup::provide_auth_context;
|
||||
use crate::common::{COGNITO_REGION, STUDENT_PROVIDER_POOL_ID};
|
||||
|
||||
///# Provider Login Context Component
|
||||
///
|
||||
@@ -20,7 +19,7 @@ use crate::common::{COGNITO_REGION, STUDENT_PROVIDER_POOL_ID};
|
||||
pub fn ProviderLoginContext() -> impl IntoView {
|
||||
provide_auth_context(
|
||||
crate::utils::use_origin(),
|
||||
format!("https://cognito-idp.{COGNITO_REGION}.amazonaws.com/{STUDENT_PROVIDER_POOL_ID}"),
|
||||
"https://cognito-idp.us-east-1.amazonaws.com/us-east-1_Lfjuy5zaM",
|
||||
"56c2bqvl021rv8d5mq36blt7jv",
|
||||
"/providers/callback"
|
||||
);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
use leptos::prelude::*;
|
||||
use super::setup::provide_auth_context;
|
||||
use crate::common::{COGNITO_REGION, STUDENT_PROVIDER_POOL_ID};
|
||||
|
||||
///# Student Login Context Component
|
||||
///
|
||||
@@ -21,7 +20,7 @@ pub fn StudentLoginContext(
|
||||
) -> impl IntoView {
|
||||
provide_auth_context(
|
||||
crate::utils::use_origin(),
|
||||
format!("https://cognito-idp.{COGNITO_REGION}.amazonaws.com/{STUDENT_PROVIDER_POOL_ID}"),
|
||||
"https://cognito-idp.us-east-1.amazonaws.com/us-east-1_Lfjuy5zaM",
|
||||
"10jr2h3vtpu9n7gj46pvg5qo2q",
|
||||
"/students/callback"
|
||||
);
|
||||
|
||||
@@ -63,11 +63,10 @@ fn AdminApplicantsScholarshipList() -> impl IntoView {
|
||||
async fn admin_get_provider_scholarships(
|
||||
access_token: String,
|
||||
) -> Result<Vec<ExpandableInfo>, ServerFnError> {
|
||||
use crate::common::{ADMIN_POOL_ID, COGNITO_REGION};
|
||||
use crate::pages::api::SCHOLARSHIPS_TABLE;
|
||||
use crate::pages::api::tokens::validate_and_get_token_info;
|
||||
|
||||
let claims = validate_and_get_token_info(access_token, ADMIN_POOL_ID, COGNITO_REGION).await?;
|
||||
let claims = validate_and_get_token_info(access_token, "us-east-1_rvCU4Xy4j", "us-east-1").await?;
|
||||
|
||||
// Get the information from the database.
|
||||
let client = crate::utils::server::create_dynamo_client().await;
|
||||
|
||||
@@ -6,7 +6,6 @@ use server_fn::codec::{MultipartData, MultipartFormData};
|
||||
#[cfg(feature = "ssr")]
|
||||
mod imports {
|
||||
pub use super::super::{MAIN_TABLE_NAME, S3_BUCKET_NAME};
|
||||
pub use crate::common::{COGNITO_REGION, STUDENT_PROVIDER_POOL_ID};
|
||||
pub use crate::pages::api::tokens::validate_and_get_token_info;
|
||||
pub use crate::utils::server::create_aws_config;
|
||||
pub use aws_sdk_dynamodb::{
|
||||
@@ -67,7 +66,7 @@ pub async fn upload_file(data: MultipartData) -> Result<String, ServerFnError> {
|
||||
return Err(ServerFnError::new("Missing file contents"));
|
||||
}
|
||||
|
||||
let user_claims = validate_and_get_token_info(access_token, STUDENT_PROVIDER_POOL_ID, COGNITO_REGION).await?;
|
||||
let user_claims = validate_and_get_token_info(access_token, "us-east-1_Lfjuy5zaM", "us-east-1").await?;
|
||||
let subject = user_claims.subject;
|
||||
|
||||
let key = format!("{form_id}/{subject}/{input_name}/{file_name}");
|
||||
@@ -158,7 +157,7 @@ pub async fn delete_file(
|
||||
) -> Result<String, ServerFnError> {
|
||||
use imports::*;
|
||||
|
||||
let user_claims = validate_and_get_token_info(access_token, STUDENT_PROVIDER_POOL_ID, COGNITO_REGION).await?;
|
||||
let user_claims = validate_and_get_token_info(access_token, "us-east-1_Lfjuy5zaM", "us-east-1").await?;
|
||||
let subject = user_claims.subject;
|
||||
|
||||
let entry_hk = format!("STUDENT#{subject}");
|
||||
@@ -227,7 +226,7 @@ pub async fn list_files(
|
||||
) -> Result<Vec<String>, ServerFnError> {
|
||||
use imports::*;
|
||||
|
||||
let user_claims = validate_and_get_token_info(access_token, STUDENT_PROVIDER_POOL_ID, COGNITO_REGION).await?;
|
||||
let user_claims = validate_and_get_token_info(access_token, "us-east-1_Lfjuy5zaM", "us-east-1").await?;
|
||||
let subject = user_claims.subject;
|
||||
|
||||
let entry_hk = format!("STUDENT#{subject}");
|
||||
|
||||
+15
-15
@@ -7,7 +7,7 @@ use std::process::Stdio;
|
||||
#[cfg(feature = "ssr")]
|
||||
mod imports {
|
||||
pub use super::super::MAIN_TABLE_NAME;
|
||||
pub use crate::common::{ADMIN_POOL_ID, COGNITO_REGION, PROVIDER_GROUP, STUDENT_PROVIDER_POOL_ID, ValueType};
|
||||
pub use crate::common::ValueType;
|
||||
pub use crate::pages::api::tokens::validate_and_get_token_info;
|
||||
pub use crate::utils::server::*;
|
||||
pub use aws_sdk_dynamodb::error::ProvideErrorMetadata;
|
||||
@@ -148,11 +148,11 @@ pub async fn provider_get_completed_students(
|
||||
use imports::*;
|
||||
|
||||
let claims =
|
||||
validate_and_get_token_info(access_token, STUDENT_PROVIDER_POOL_ID, COGNITO_REGION).await?;
|
||||
if !claims.groups.contains(&PROVIDER_GROUP.to_string()) {
|
||||
return Err(ServerFnError::new(format!(
|
||||
"User is not in the {PROVIDER_GROUP} group",
|
||||
)));
|
||||
validate_and_get_token_info(access_token, "us-east-1_Lfjuy5zaM", "us-east-1").await?;
|
||||
if !claims.groups.contains(&"ScholarshipProviders".to_string()) {
|
||||
return Err(ServerFnError::new(
|
||||
"User is not in the ScholarshipProviders group",
|
||||
));
|
||||
}
|
||||
|
||||
get_completed_students().await
|
||||
@@ -164,7 +164,7 @@ pub async fn admin_get_completed_students(
|
||||
) -> Result<HashMap<String, HashMap<String, crate::common::ValueType>>, ServerFnError> {
|
||||
use imports::*;
|
||||
|
||||
let _ = validate_and_get_token_info(access_token, ADMIN_POOL_ID, COGNITO_REGION).await?;
|
||||
let _ = validate_and_get_token_info(access_token, "us-east-1_rvCU4Xy4j", "us-east-1").await?;
|
||||
|
||||
get_completed_students().await
|
||||
}
|
||||
@@ -254,7 +254,7 @@ pub async fn get_file_by_key(
|
||||
use imports::*;
|
||||
|
||||
let user_claims =
|
||||
validate_and_get_token_info(access_token, STUDENT_PROVIDER_POOL_ID, COGNITO_REGION).await?;
|
||||
validate_and_get_token_info(access_token, "us-east-1_Lfjuy5zaM", "us-east-1").await?;
|
||||
|
||||
// Check if the user's subject is contained in the file_key (since all files are keyed by the
|
||||
// user's subject)
|
||||
@@ -262,7 +262,7 @@ pub async fn get_file_by_key(
|
||||
// Check that the user is a provider.
|
||||
if !user_claims
|
||||
.groups
|
||||
.contains(&PROVIDER_GROUP.to_string())
|
||||
.contains(&"ScholarshipProviders".to_string())
|
||||
{
|
||||
return Err(ServerFnError::new(
|
||||
"Access denied: user is not the student or a provider",
|
||||
@@ -304,16 +304,16 @@ pub async fn get_student_files(
|
||||
) -> Result<(String, Vec<u8>), ServerFnError> {
|
||||
use imports::*;
|
||||
|
||||
match validate_and_get_token_info(access_token.clone(), STUDENT_PROVIDER_POOL_ID, COGNITO_REGION)
|
||||
match validate_and_get_token_info(access_token.clone(), "us-east-1_Lfjuy5zaM", "us-east-1")
|
||||
.await
|
||||
{
|
||||
Ok(claims) => {
|
||||
if !claims.groups.contains(&PROVIDER_GROUP.to_string()) {
|
||||
if !claims.groups.contains(&"ScholarshipProviders".to_string()) {
|
||||
return Err(ServerFnError::new("Access denied: user is not a provider"));
|
||||
}
|
||||
}
|
||||
Err(_) => {
|
||||
let _ = validate_and_get_token_info(access_token, ADMIN_POOL_ID, COGNITO_REGION)
|
||||
let _ = validate_and_get_token_info(access_token, "us-east-1_rvCU4Xy4j", "us-east-1")
|
||||
.await?;
|
||||
}
|
||||
};
|
||||
@@ -507,7 +507,7 @@ pub async fn admin_get_all_input_files(
|
||||
) -> Result<HashMap<String, Vec<String>>, ServerFnError> {
|
||||
use imports::*;
|
||||
|
||||
let _ = validate_and_get_token_info(access_token, ADMIN_POOL_ID, COGNITO_REGION).await?;
|
||||
let _ = validate_and_get_token_info(access_token, "us-east-1_rvCU4Xy4j", "us-east-1").await?;
|
||||
|
||||
get_all_input_files(form_name, input_name).await
|
||||
}
|
||||
@@ -521,8 +521,8 @@ pub async fn provider_get_all_input_files(
|
||||
use imports::*;
|
||||
|
||||
let claims =
|
||||
validate_and_get_token_info(access_token, STUDENT_PROVIDER_POOL_ID, COGNITO_REGION).await?;
|
||||
if !claims.groups.contains(&PROVIDER_GROUP.to_string()) {
|
||||
validate_and_get_token_info(access_token, "us-east-1_Lfjuy5zaM", "us-east-1").await?;
|
||||
if !claims.groups.contains(&"ScholarshipProviders".to_string()) {
|
||||
return Err(ServerFnError::new("Access denied: user is not a provider"));
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ pub async fn validate_and_get_token_info(
|
||||
|
||||
leptos::logging::debug_log!("Validating token using group {}", pool_id);
|
||||
|
||||
// let jwks = fetch_jwks("us-east-1_Lfjuy5zaM".into(), "us-east-1".into()).await?;
|
||||
let jwks = fetch_jwks(pool_id, pool_region.into()).await?;
|
||||
|
||||
let validation = Validation::new(Algorithm::RS256);
|
||||
|
||||
@@ -75,14 +75,13 @@ fn ApplicantsScholarshipList() -> impl IntoView {
|
||||
async fn get_provider_scholarships(
|
||||
access_token: String,
|
||||
) -> Result<Vec<ExpandableInfo>, ServerFnError> {
|
||||
use crate::common::{COGNITO_REGION, STUDENT_PROVIDER_POOL_ID};
|
||||
use crate::pages::api::SCHOLARSHIPS_TABLE;
|
||||
use crate::pages::api::tokens::validate_and_get_token_info;
|
||||
|
||||
let claims = validate_and_get_token_info(
|
||||
access_token,
|
||||
STUDENT_PROVIDER_POOL_ID.to_string(),
|
||||
COGNITO_REGION.to_string(),
|
||||
"us-east-1_Lfjuy5zaM".to_string(),
|
||||
"us-east-1".to_string(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
|
||||
Generated
-7
@@ -1,7 +0,0 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "traits"
|
||||
version = "0.1.0"
|
||||
@@ -1,6 +0,0 @@
|
||||
[package]
|
||||
name = "traits"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
@@ -1,3 +0,0 @@
|
||||
pub mod reactive;
|
||||
|
||||
pub use reactive::*;
|
||||
@@ -1,82 +0,0 @@
|
||||
/// Trait that ensures a reactive struct can be created from a non-reactive struct.
|
||||
///
|
||||
/// For example:
|
||||
///
|
||||
/// ```rust
|
||||
/// struct User {
|
||||
/// id: i32,
|
||||
/// name: String
|
||||
/// }
|
||||
///
|
||||
/// struct UserReactive {
|
||||
/// id: RwSignal<i32>,
|
||||
/// name: RwSignal<String>
|
||||
/// }
|
||||
///
|
||||
/// impl ReactiveCapture for UserReactive {
|
||||
/// // implement - required for ReactiveType.
|
||||
/// }
|
||||
///
|
||||
/// impl AsReactive for User {
|
||||
/// type ReactiveType = UserReactive;
|
||||
/// fn as_reactive(self) -> UserReactive {
|
||||
/// UserReactive {
|
||||
/// id: RwSignal::new(self.id),
|
||||
/// name: RwSignal::new(self.name)
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
pub trait AsReactive {
|
||||
/// The type of the reactive struct. It must implement `ReactiveCapture`.
|
||||
type ReactiveType: ReactiveCapture;
|
||||
|
||||
/// Wraps all fields of the struct into an `RwSignal`, returning a new
|
||||
/// "reactive" struct.
|
||||
///
|
||||
/// Note that this method consumes the original struct and returns a new
|
||||
/// reactive struct.
|
||||
fn as_reactive(self) -> Self::ReactiveType;
|
||||
}
|
||||
|
||||
/// Trait that ensures a reactive struct can be captured into a non-reactive struct.
|
||||
/// The "captured" struct does not contain *any* reactive fields, meaning that it is not
|
||||
/// wrapped in an `RwSignal`.
|
||||
///
|
||||
/// The captured struct should simply collect all the values from the reactive fields at
|
||||
/// that point in time.
|
||||
///
|
||||
/// For example:
|
||||
///
|
||||
/// ```rust
|
||||
/// struct User {
|
||||
/// id: i32,
|
||||
/// name: String
|
||||
/// }
|
||||
///
|
||||
/// struct UserReactive {
|
||||
/// id: RwSignal<i32>,
|
||||
/// name: RwSignal<String>
|
||||
/// }
|
||||
///
|
||||
/// impl AsReactive for User {
|
||||
/// // implement - required for CaptureType.
|
||||
/// }
|
||||
///
|
||||
/// impl ReactiveCapture for UserReactive {
|
||||
/// type CaptureType = User;
|
||||
/// fn capture(&self) -> User {
|
||||
/// User {
|
||||
/// id: self.id.get(),
|
||||
/// name: self.name.get()
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
pub trait ReactiveCapture {
|
||||
/// The type of the captured struct. It must implement `AsReactive`.
|
||||
type CaptureType: AsReactive;
|
||||
|
||||
/// Captures the current state of the reactive struct into a non-reactive struct.
|
||||
fn capture(&self) -> Self::CaptureType;
|
||||
}
|
||||
Reference in new issue
Block a user