1
use std::collections::HashMap;
2

            
3
use log::error;
4

            
5
use sylvia_iot_corelib::{err::ErrResp, role::Role};
6

            
7
use super::super::State as AppState;
8
use crate::models::{
9
    application::{Application, QueryCond as ApplicationQueryCond},
10
    device::{Device, QueryCond as DeviceQueryCond},
11
    network::{Network, QueryCond as NetworkQueryCond},
12
    unit::{QueryCond as UnitQueryCond, Unit},
13
};
14

            
15
/// To check if the user ID can access the unit. Choose `only_owner` to check if the user is the
16
/// owner or one of members.
17
///
18
/// # Errors
19
///
20
/// Returns Ok if the unit is found or not. Otherwise errors will be returned.
21
1764
pub async fn check_unit(
22
1764
    fn_name: &str,
23
1764
    user_id: &str,
24
1764
    roles: &HashMap<String, bool>,
25
1764
    unit_id: &str,
26
1764
    only_owner: bool,
27
1764
    state: &AppState,
28
1764
) -> Result<Option<Unit>, ErrResp> {
29
1764
    let mut cond = UnitQueryCond {
30
1764
        unit_id: Some(unit_id),
31
1764
        ..Default::default()
32
1764
    };
33
1764
    if !Role::is_role(roles, Role::ADMIN) && !Role::is_role(roles, Role::MANAGER) {
34
1047
        if only_owner {
35
399
            cond.owner_id = Some(user_id);
36
648
        } else {
37
648
            cond.member_id = Some(user_id);
38
648
        }
39
717
    }
40
1764
    match state.model.unit().get(&cond).await {
41
        Err(e) => {
42
            error!("[{}] check unit error: {}", fn_name, e);
43
            return Err(ErrResp::ErrDb(Some(format!("check unit error: {}", e))));
44
        }
45
1764
        Ok(unit) => Ok(unit),
46
    }
47
1764
}
48

            
49
/// To check if the user ID can access the application. Choose `only_owner` to check if the user is
50
/// the unit owner or one of unit members.
51
///
52
/// # Errors
53
///
54
/// Returns Ok if the application is found or not. Otherwise errors will be returned.
55
321
pub async fn check_application(
56
321
    fn_name: &str,
57
321
    application_id: &str,
58
321
    user_id: &str,
59
321
    only_owner: bool, // to check if this `user_id` is the owner.
60
321
    roles: &HashMap<String, bool>,
61
321
    state: &AppState,
62
321
) -> Result<Option<Application>, ErrResp> {
63
321
    let cond = ApplicationQueryCond {
64
321
        application_id: Some(application_id),
65
321
        ..Default::default()
66
321
    };
67
321
    let application = match state.model.application().get(&cond).await {
68
        Err(e) => {
69
            error!("[{}] get error: {}", fn_name, e);
70
            return Err(ErrResp::ErrDb(Some(e.to_string())));
71
        }
72
321
        Ok(application) => match application {
73
33
            None => return Ok(None),
74
288
            Some(application) => application,
75
288
        },
76
288
    };
77
288
    if Role::is_role(roles, Role::ADMIN) || Role::is_role(roles, Role::MANAGER) {
78
165
        return Ok(Some(application));
79
123
    }
80
123
    let unit_id = application.unit_id.as_str();
81
123
    match check_unit(fn_name, user_id, &roles, unit_id, only_owner, &state).await? {
82
33
        None => Ok(None),
83
90
        Some(_) => Ok(Some(application)),
84
    }
85
321
}
86

            
87
/// To check if the user ID can access the network. Choose `only_owner` to check if the user is the
88
/// unit owner or one of unit members.
89
///
90
/// # Errors
91
///
92
/// Returns OK if the network is found or not. Otherwise errors will be returned.
93
267
pub async fn check_network(
94
267
    fn_name: &str,
95
267
    network_id: &str,
96
267
    user_id: &str,
97
267
    only_owner: bool, // to check if this `user_id` is the owner.
98
267
    roles: &HashMap<String, bool>,
99
267
    state: &AppState,
100
267
) -> Result<Option<Network>, ErrResp> {
101
267
    let cond = NetworkQueryCond {
102
267
        network_id: Some(network_id),
103
267
        ..Default::default()
104
267
    };
105
267
    let network = match state.model.network().get(&cond).await {
106
        Err(e) => {
107
            error!("[{}] get error: {}", fn_name, e);
108
            return Err(ErrResp::ErrDb(Some(e.to_string())));
109
        }
110
267
        Ok(network) => match network {
111
36
            None => return Ok(None),
112
231
            Some(network) => network,
113
231
        },
114
231
    };
115
231
    if Role::is_role(roles, Role::ADMIN) || Role::is_role(roles, Role::MANAGER) {
116
120
        return Ok(Some(network));
117
111
    }
118
111
    let unit_id = match network.unit_id.as_ref() {
119
24
        None => return Ok(None),
120
87
        Some(unit_id) => unit_id.as_str(),
121
87
    };
122
87
    match check_unit(fn_name, user_id, &roles, unit_id, only_owner, &state).await? {
123
18
        None => Ok(None),
124
69
        Some(_) => Ok(Some(network)),
125
    }
126
267
}
127

            
128
/// To check if the user ID can access the device. Choose `only_owner` to check if the user is the
129
/// unit owner or one of unit members.
130
///
131
/// # Errors
132
///
133
/// Returns OK if the device is found or not. Otherwise errors will be returned.
134
249
pub async fn check_device(
135
249
    fn_name: &str,
136
249
    device_id: &str,
137
249
    user_id: &str,
138
249
    only_owner: bool, // to check if this `user_id` is the owner.
139
249
    roles: &HashMap<String, bool>,
140
249
    state: &AppState,
141
249
) -> Result<Option<Device>, ErrResp> {
142
249
    let cond = DeviceQueryCond {
143
249
        device_id: Some(device_id),
144
249
        ..Default::default()
145
249
    };
146
249
    let device = match state.model.device().get(&cond).await {
147
        Err(e) => {
148
            error!("[{}] get error: {}", fn_name, e);
149
            return Err(ErrResp::ErrDb(Some(e.to_string())));
150
        }
151
249
        Ok(device) => match device {
152
15
            None => return Ok(None),
153
234
            Some(device) => device,
154
234
        },
155
234
    };
156
234
    let unit_id = device.unit_id.as_str();
157
234
    match check_unit(fn_name, user_id, roles, unit_id, only_owner, state).await? {
158
54
        None => Ok(None),
159
180
        Some(_) => Ok(Some(device)),
160
    }
161
249
}
162

            
163
/// To generate a key for managing managers. Empty unit for public networks.
164
406
pub fn gen_mgr_key(unit: &str, name: &str) -> String {
165
406
    format!("{}.{}", unit, name)
166
406
}