1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
use crate::az_impl::az_lmdb::LmdbAzContext;
use crate::onto::individual::Individual;
use crate::onto::parser::parse_raw;
use crate::storage::common::{Storage, StorageId};
use crate::storage::lmdb_storage::LMDBStorage;
use crate::v_api::obj::ResultCode;
use crate::v_authorization::common::{Access, AuthorizationContext, Trace};
use futures::lock::Mutex;
use rusty_tarantool::tarantool::{Client, IteratorType};
use std::io;
use std::io::{Error, ErrorKind};

pub const INDIVIDUALS_SPACE_ID: i32 = 512;
pub const TICKETS_SPACE_ID: i32 = 513;

pub struct AStorage {
    pub tt: Option<Client>,
    pub lmdb: Option<Mutex<LMDBStorage>>,
}

pub async fn check_indv_access_read(mut indv: Individual, uri: &str, user_uri: &str, az: Option<&Mutex<LmdbAzContext>>) -> io::Result<(Individual, ResultCode)> {
    if indv.get_id().is_empty() {
        return Ok((indv, ResultCode::NotFound));
    }

    if let Some(a) = az {
        if a.lock().await.authorize(uri, user_uri, Access::CanRead as u8, false).unwrap_or(0) != Access::CanRead as u8 {
            return Ok((indv, ResultCode::NotAuthorized));
        }
    }

    indv.parse_all();
    Ok((indv, ResultCode::Ok))
}

pub async fn check_user_in_group(user_id: &str, group_id: &str, az: Option<&Mutex<LmdbAzContext>>) -> io::Result<bool> {
    if let Some(a) = az {
        let mut tr = Trace {
            acl: &mut "".to_string(),
            is_acl: false,
            group: &mut String::new(),
            is_group: true,
            info: &mut "".to_string(),
            is_info: false,
            str_num: 0,
        };
        if a.lock().await.authorize_and_trace(user_id, user_id, 0xF, false, &mut tr).is_ok() {
            for gr in tr.group.split('\n') {
                if gr == group_id {
                    return Ok(true);
                }
            }
        } else {
            return Err(Error::new(ErrorKind::Other, "fail authorize_and_trace"));
        }
    }

    Ok(false)
}

pub async fn get_individual_from_db(uri: &str, user_uri: &str, db: &AStorage, az: Option<&Mutex<LmdbAzContext>>) -> io::Result<(Individual, ResultCode)> {
    get_individual_use_storage_id(StorageId::Individuals, uri, user_uri, db, az).await
}

pub async fn get_individual_use_storage_id(
    storage_id: StorageId,
    uri: &str,
    user_uri: &str,
    db: &AStorage,
    az: Option<&Mutex<LmdbAzContext>>,
) -> io::Result<(Individual, ResultCode)> {
    if let Some(tt) = &db.tt {
        let space_id = match storage_id {
            StorageId::Tickets => TICKETS_SPACE_ID,
            StorageId::Individuals => INDIVIDUALS_SPACE_ID,
            StorageId::Az => 514,
        };

        let response = tt.select(space_id, 0, &(uri,), 0, 100, IteratorType::EQ).await?;

        let mut iraw = Individual::default();
        iraw.set_raw(&response.data[5..]);
        if parse_raw(&mut iraw).is_ok() {
            return check_indv_access_read(iraw, uri, user_uri, az).await;
        }
        return Ok((iraw, ResultCode::UnprocessableEntity));
    }
    if let Some(lmdb) = &db.lmdb {
        let mut iraw = Individual::default();
        match lmdb.lock().await.get_individual_from_db(storage_id, uri, &mut iraw) {
            Ok(()) => {
                return check_indv_access_read(iraw, uri, user_uri, az).await;
            },
            Err(r) => {
                if r == ResultCode::NotFound {
                    return Ok((Individual::default(), ResultCode::NotFound));
                }
            },
        }
    }

    Ok((Individual::default(), ResultCode::UnprocessableEntity))
}