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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
use crate::az_impl::az_lmdb::LmdbAzContext;
use crate::module::ticket::Ticket;
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};
use futures::lock::Mutex;
use rusty_tarantool::tarantool::{Client, IteratorType};
use std::io;
use std::sync::Arc;
pub(crate) const INDIVIDUALS_SPACE_ID: i32 = 512;
pub(crate) const TICKETS_SPACE_ID: i32 = 513;
pub struct AStorage {
pub tt: Option<Client>,
pub lmdb: Option<Mutex<LMDBStorage>>,
}
pub struct TicketCache {
pub read: evmap::ReadHandle<String, Ticket>,
pub write: Arc<Mutex<evmap::WriteHandle<String, Ticket>>>,
}
async fn check_indv_access_read(mut indv: Individual, uri: &str, user_uri: &str, az: Option<&Mutex<LmdbAzContext>>) -> io::Result<(Individual, ResultCode)> {
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));
}
}
if indv.get_id().is_empty() {
return Ok((indv, ResultCode::NotFound));
}
indv.parse_all();
Ok((indv, ResultCode::Ok))
}
pub async fn get_individual_from_db(uri: &str, user_uri: &str, db: &AStorage, az: Option<&Mutex<LmdbAzContext>>) -> io::Result<(Individual, ResultCode)> {
if let Some(tt) = &db.tt {
let response = tt.select(INDIVIDUALS_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();
if lmdb.lock().await.get_individual_from_db(StorageId::Individuals, uri, &mut iraw) {
return check_indv_access_read(iraw, uri, user_uri, az).await;
} else {
return Ok((Individual::default(), ResultCode::NotFound));
}
}
Ok((Individual::default(), ResultCode::UnprocessableEntity))
}
pub async fn check_ticket(w_ticket_id: &Option<String>, ticket_cache: &TicketCache, db: &AStorage) -> io::Result<(ResultCode, Option<String>)> {
if w_ticket_id.is_none() {
return Ok((ResultCode::Ok, Some("cfg:Guest".to_owned())));
}
let ticket_id = w_ticket_id.as_ref().unwrap();
if ticket_id.is_empty() || ticket_id == "systicket" {
return Ok((ResultCode::Ok, Some("cfg:Guest".to_owned())));
}
if let Some(cached_ticket) = ticket_cache.read.get(&ticket_id.to_owned()) {
if let Some(t) = cached_ticket.get_one() {
if t.is_ticket_valid() != ResultCode::Ok {
return Ok((ResultCode::TicketNotFound, None));
}
Ok((ResultCode::Ok, Some(t.user_uri.clone())))
} else {
Ok((ResultCode::TicketNotFound, None))
}
} else {
let mut ticket_obj = Ticket::default();
if let Some(tt) = &db.tt {
let response = tt.select(TICKETS_SPACE_ID, 0, &(&ticket_id,), 0, 100, IteratorType::EQ).await?;
let mut to = Individual::default();
to.set_raw(&response.data[5..]);
if parse_raw(&mut to).is_ok() {
ticket_obj.update_from_individual(&mut to);
ticket_obj.result = ResultCode::Ok;
}
}
if let Some(lmdb) = &db.lmdb {
let mut to = Individual::default();
if lmdb.lock().await.get_individual_from_db(StorageId::Tickets, ticket_id, &mut to) {
ticket_obj.update_from_individual(&mut to);
ticket_obj.result = ResultCode::Ok;
}
}
if ticket_obj.result != ResultCode::Ok {
return Ok((ResultCode::TicketNotFound, None));
}
if ticket_obj.is_ticket_valid() != ResultCode::Ok {
return Ok((ResultCode::TicketNotFound, None));
}
let user_uri = ticket_obj.user_uri.clone();
let mut t = ticket_cache.write.lock().await;
t.insert(ticket_id.to_owned(), ticket_obj);
t.refresh();
Ok((ResultCode::Ok, Some(user_uri)))
}
}