| 179 | } |
| 180 | |
| 181 | pub async fn add_device(relay_dev_eui: EUI64, device_dev_eui: EUI64) -> Result<(), Error> { |
| 182 | let mut c = get_async_db_conn().await?; |
| 183 | c.transaction::<(), Error, _>(async |c| { |
| 184 | let query = device::dsl::device.find(&relay_dev_eui); |
| 185 | // We lock the relay device to avoid race-conditions in the validation. |
| 186 | #[cfg(feature = "postgres")] |
| 187 | let query = query.for_update(); |
| 188 | let rd: Device = query |
| 189 | .get_result(c) |
| 190 | .await |
| 191 | .map_err(|e| Error::from_diesel(e, relay_dev_eui.to_string()))?; |
| 192 | |
| 193 | // Is the given relay_dev_eui a Relay? |
| 194 | let rdp: super::device_profile::DeviceProfile = device_profile::dsl::device_profile |
| 195 | .find(&rd.device_profile_id) |
| 196 | .get_result(c) |
| 197 | .await |
| 198 | .map_err(|e| Error::from_diesel(e, rd.device_profile_id.to_string()))?; |
| 199 | |
| 200 | if !rdp |
| 201 | .relay_params |
| 202 | .as_ref() |
| 203 | .map(|v| v.is_relay) |
| 204 | .unwrap_or_default() |
| 205 | { |
| 206 | return Err(Error::Validation("Device is not a relay".to_string())); |
| 207 | } |
| 208 | |
| 209 | // Validate that relay and device are under the same application. |
| 210 | let d: Device = device::dsl::device |
| 211 | .find(&device_dev_eui) |
| 212 | .get_result(c) |
| 213 | .await |
| 214 | .map_err(|e| Error::from_diesel(e, device_dev_eui.to_string()))?; |
| 215 | |
| 216 | if rd.application_id != d.application_id { |
| 217 | return Err(Error::Validation( |
| 218 | "Relay and device must be under the same application".into(), |
| 219 | )); |
| 220 | } |
| 221 | |
| 222 | // Validate that the relay and device are under the same region. |
| 223 | let dp: super::device_profile::DeviceProfile = device_profile::dsl::device_profile |
| 224 | .find(&d.device_profile_id) |
| 225 | .get_result(c) |
| 226 | .await |
| 227 | .map_err(|e| Error::from_diesel(e, d.device_profile_id.to_string()))?; |
| 228 | if rdp.region != dp.region { |
| 229 | return Err(Error::Validation( |
| 230 | "Relay and device must be under the same region".into(), |
| 231 | )); |
| 232 | } |
| 233 | |
| 234 | // Validate that the device is not a relay. |
| 235 | if let Some(relay_params) = &dp.relay_params |
| 236 | && relay_params.is_relay |
| 237 | { |
| 238 | return Err(Error::Validation("Can not add relay to a relay".into())); |