188 lines
6.8 KiB
Rust
188 lines
6.8 KiB
Rust
use rocket::State;
|
|
use crate::helper::settings::Settings;
|
|
use crate::database::controller::events::get_eu_position;
|
|
use crate::modules::api::member_management::controller::parser::parse_uuid_string;
|
|
use serde_json::{Value, Map};
|
|
use std::fmt;
|
|
use crate::database::controller::member_licenses::check_license_for_member;
|
|
use crate::database::model::member_licenses::MemberDrivePermission;
|
|
use diesel::result::Error;
|
|
use crate::database::controller::member_qualifications::check_qualification_for_member;
|
|
use uuid::Uuid;
|
|
use crate::modules::api::model::api_outcome::ApiErrorWrapper;
|
|
use rocket::serde::json::Json;
|
|
|
|
pub fn check_position_requirements(settings: &State<Settings>, position_id: uuid::Uuid, member_id: uuid::Uuid) -> Result<bool, RequirementParserError>{
|
|
let position = match get_eu_position(settings, position_id){
|
|
Ok(pos) => pos,
|
|
Err(e) => return Err(RequirementParserError::from(e))
|
|
};
|
|
match position.requirements{
|
|
Some(req) => parse_requirements(req, settings, member_id),
|
|
None => Ok(true)
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
|
pub enum Operator {
|
|
AND,
|
|
OR
|
|
}
|
|
|
|
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
|
pub enum RequirementParserErrorKind {
|
|
InvalidJsonStart,
|
|
UnknownOperator,
|
|
UnknownConditionType,
|
|
UnexpectedType,
|
|
InvalidUUID,
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub enum RequirementParserError {
|
|
Database(diesel::result::Error),
|
|
Parser(RequirementParserErrorKind),
|
|
}
|
|
|
|
impl RequirementParserErrorKind {
|
|
pub fn as_str(&self) -> &str {
|
|
match *self {
|
|
RequirementParserErrorKind::InvalidJsonStart => "requirements didn't start with conditions",
|
|
RequirementParserErrorKind::UnknownOperator => "operator not known",
|
|
RequirementParserErrorKind::UnknownConditionType => "condition not known",
|
|
RequirementParserErrorKind::UnexpectedType => "type unexpected",
|
|
RequirementParserErrorKind::InvalidUUID => "invalid, unparsable uuid",
|
|
}
|
|
}
|
|
}
|
|
|
|
impl fmt::Display for RequirementParserError {
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
match *self {
|
|
RequirementParserError::Parser(ref err) => write!(f, "JSON parsing error: {:?}", err),
|
|
RequirementParserError::Database(ref err) => err.fmt(f),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<diesel::result::Error> for RequirementParserError {
|
|
fn from(err: diesel::result::Error) -> RequirementParserError {
|
|
RequirementParserError::Database(err)
|
|
}
|
|
}
|
|
|
|
fn parse_requirements(req: serde_json::Value, settings: &State<Settings>, member_id: uuid::Uuid) -> Result<bool, RequirementParserError> {
|
|
match &req["conditions"]{
|
|
Value::Array(a) => parse_condition_group(a, settings, member_id),
|
|
_ => Err(RequirementParserError::Parser(RequirementParserErrorKind::InvalidJsonStart))
|
|
}
|
|
}
|
|
|
|
fn parse_condition_group(array: &Vec<Value>, settings: &State<Settings>, member_id: uuid::Uuid) -> Result<bool, RequirementParserError>{
|
|
let operator : Operator;
|
|
|
|
if array.len() >= 2 {
|
|
//Parse operator (first array item)
|
|
match &array[0]{
|
|
Value::String(o) => match parse_operator(o){
|
|
Ok(op) => operator = op,
|
|
Err(e) => return Err(e)
|
|
}
|
|
_ => return Err(RequirementParserError::Parser(RequirementParserErrorKind::InvalidJsonStart))
|
|
}
|
|
|
|
for i in 1..array.len(){
|
|
match &array[i]{
|
|
Value::Array(a) => match parse_condition_group(a, settings, member_id){
|
|
Ok(res) => {
|
|
if operator == Operator::AND{
|
|
if !res{
|
|
return Ok(false)
|
|
}
|
|
}else if operator == Operator::OR{
|
|
if res{
|
|
return Ok(true)
|
|
}
|
|
}
|
|
},
|
|
Err(e) => return Err(e)
|
|
},
|
|
Value::Object(o) => {
|
|
match parse_condition(o, settings, member_id){
|
|
Ok(res) => {
|
|
if operator == Operator::AND{
|
|
if !res{
|
|
return Ok(false)
|
|
}
|
|
}else if operator == Operator::OR{
|
|
if res{
|
|
return Ok(true)
|
|
}
|
|
}
|
|
},
|
|
Err(e) => return Err(e)
|
|
}
|
|
},
|
|
_ => return Err(RequirementParserError::Parser(RequirementParserErrorKind::UnexpectedType))
|
|
}
|
|
}
|
|
|
|
if operator == Operator::AND {
|
|
Ok(true)
|
|
}else{
|
|
Ok(false)
|
|
}
|
|
}else{
|
|
Ok(true)
|
|
}
|
|
}
|
|
|
|
fn parse_condition(condition: &Map<String, Value>, settings: &State<Settings>, member_id: uuid::Uuid) -> Result<bool, RequirementParserError>{
|
|
if condition.contains_key("license"){
|
|
let val = match condition.get("license").unwrap(){
|
|
Value::String(v) => v,
|
|
_ => return Err(RequirementParserError::Parser(RequirementParserErrorKind::UnexpectedType))
|
|
};
|
|
match check_member_license(settings, member_id, val.clone()){
|
|
Ok(res) => Ok(res),
|
|
Err(e) => Err(RequirementParserError::from(e))
|
|
}
|
|
}else if condition.contains_key("qualification"){
|
|
let val = match condition.get("qualification").unwrap(){
|
|
Value::String(v) => v,
|
|
_ => return Err(RequirementParserError::Parser(RequirementParserErrorKind::UnexpectedType))
|
|
};
|
|
let val = match parse_uuid_string(val.clone()){
|
|
Ok(val) => val,
|
|
Err(_) => return Err(RequirementParserError::Parser(RequirementParserErrorKind::InvalidUUID))
|
|
};
|
|
match check_qualification_for_member(settings, val,member_id){
|
|
Ok(res) => Ok(res),
|
|
Err(e) => Err(RequirementParserError::from(e))
|
|
}
|
|
}else{
|
|
Err(RequirementParserError::Parser(RequirementParserErrorKind::UnknownConditionType))
|
|
}
|
|
}
|
|
|
|
fn parse_operator(operator: &String) -> Result<Operator, RequirementParserError>{
|
|
if operator == "AND"{
|
|
Ok(Operator::AND)
|
|
}else if operator == "OR"{
|
|
Ok(Operator::OR)
|
|
}else{
|
|
Err(RequirementParserError::Parser(RequirementParserErrorKind::UnknownOperator))
|
|
}
|
|
}
|
|
|
|
fn check_member_license(settings: &State<Settings>, member_id: uuid::Uuid, license_id: String) -> Result<bool, diesel::result::Error>{
|
|
match check_license_for_member(settings, license_id, member_id){
|
|
Ok(res) => {
|
|
match res{
|
|
Some(_) => Ok(true),
|
|
None => Ok(false)
|
|
}
|
|
}
|
|
Err(e) => Err(e)
|
|
}
|
|
} |