ibs/sql_app/crud.py
HeshamTB 6a3d9d9e95 sql_app: Use more relations in database
Instead of using manual db lookup for access log,
	use device.access_list to fetch the data from
	access_log table. This does the SQL query underneath.

	To do so, instructions from SQLAlchemey were followed
	to to many-to-one relations for users and devices,
	respectevly.

Signed-off-by: HeshamTB <hishaminv@gmail.com>
2022-06-08 14:19:27 +03:00

195 lines
7.0 KiB
Python

# CRUD (Create, Read, Update, Delete) from db
from sqlalchemy import select, join
from sqlalchemy.orm import Session
from . import models, schemas, crypto, auth_helper
from datetime import datetime
from warnings import warn
# TODO: Data we can collect or log
# - Last user connection (link to user)
# - Last Iot Entity Connection (link to IotEntity)
# - Any open request (link to user)
# - Any polling from IotEntity? Maybe to much data
def get_user(db: Session, user_id: int) -> models.User:
return db.query(models.User).get(user_id)
def get_iot_entity(db: Session, id: int):
return db.query(models.IotEntity).get(id)
def get_iot_entity_by_description(db: Session, description: str):
return db.query(models.IotEntity).filter(models.IotEntity.description == description).first()
def get_iot_entity_by_bluetooth_mac(db: Session, bluetooth_mac: str) -> models.IotEntity:
return db.query(models.IotEntity).filter(models.IotEntity.bluetooth_mac == bluetooth_mac).first()
def get_user_by_email(db: Session, email: str) -> models.User:
return db.query(models.User).filter(models.User.email == email).first()
def get_user_by_username(db: Session, username: str) -> models.User:
return db.query(models.User).filter(models.User.username == username).first()
def get_users(db: Session, skip: int = 0, limit: int = 100):
return db.query(models.User).offset(skip).limit(limit).all()
def get_access_log_for_door_by_door_mac(db: Session, iot_id: str):
warn("Manual access log read is deprecated. Use device.access_log",
DeprecationWarning, stacklevel=2)
return db.query(models.DoorAccessLog)\
.filter(models.DoorAccessLog.iot_id == iot_id).all()
def get_access_log_for_user_by_id(db: Session, id : str):
return db.query(models.DoorAccessLog).filter(models.DoorAccessLog.user_id == id).all()
def get_room_data_now(db: Session) -> models.RoomSensorData:
return db.query(models.RoomSensorData)[-1]
def create_user(db: Session, user: schemas.UserCreate):
key = crypto.gen_new_key(user.password)
salt = key[1]
hashed_pass = key[0]
db_user = models.User(email=user.email,
username=user.username,
hashed_password=hashed_pass,
passwd_salt=salt)
db.add(db_user)
db.commit()
db.refresh(db_user)
return db_user
def update_user_password(db: Session, user: models.User, request: schemas.UserUpdatePassword):
key = crypto.gen_new_key(request.password)
salt = key[1]
hashed_pass = key[0]
user.passwd_salt = salt
user.hashed_password = hashed_pass
db.add(user)
db.commit()
db.refresh(user)
def get_iot_entities(db: Session, skip: int = 0, limit: int = 100):
return db.query(models.IotEntity).offset(skip).limit(limit).all()
def create_iot_entity(db: Session, iot_entity: schemas.IotEntityCreate):
db_item = models.IotEntity(bluetooth_mac=iot_entity.bluetooth_mac,
description=iot_entity.description)
db.add(db_item)
db.commit()
db.refresh(db_item)
return db_item
def create_user_link_to_iot(db: Session, user_id: int, iot_dev_id: int):
# Ensure link is not already present and it does not allow duplicates
link = db.query(models.UserAuthToIoTDev).filter(models.UserAuthToIoTDev.user_id == user_id).filter(models.UserAuthToIoTDev.iot_id == iot_dev_id).first()
if link: return True
new_link = models.UserAuthToIoTDev(user_id=user_id,
iot_id=iot_dev_id,
timestamp=datetime.now())
db.add(new_link)
db.commit()
db.refresh(new_link)
return True
def remove_user_link_to_iot(db: Session, user_id: int, iot_dev_id: int):
# Ensure link is not already present and it does not allow duplicates
link = (db.query(models.UserAuthToIoTDev)
.filter(models.UserAuthToIoTDev.user_id == user_id)
.filter(models.UserAuthToIoTDev.iot_id == iot_dev_id)
.first())
if not link: return True
db.delete(link)
db.flush()
db.commit()
#db.refresh(link)
return True
def set_open_door_request(db: Session, iot_entity_id: int, time_seconds : int):
device = get_iot_entity(db, iot_entity_id)
setattr(device, "open_request", True)
if time_seconds < 1:
time_seconds = 10 # Magic number move to global constant
setattr(device, "time_seconds", time_seconds)
db.add(device)
db.commit()
db.refresh(device)
return True
def set_close_door_request(db: Session, iot_id: int):
device : models.IotEntity = get_iot_entity(db, iot_id)
device.force_close = True
db.add(device)
db.commit()
db.refresh(device)
return True
def clear_close_door_request(db: Session, iot_id: int):
device : models.IotEntity = get_iot_entity(db, iot_id)
device.force_close = False
db.add(device)
db.commit()
def set_user_last_token(db: Session, username: str, token: str):
user : models.User = get_user_by_username(db, username)
user.last_token = token
db.add(user)
db.commit()
db.refresh(user)
return True
def set_door_state(db: Session, iot_device: models.IotEntity, state: bool):
iot_device.state = state
db.add(iot_device)
db.commit()
db.refresh(iot_device)
def get_user_last_token(db: Session, username: str):
user : models.User = get_user_by_username(db, username)
return user.last_token # This method is bad security practice.
def clear_open_door_request(db: Session, iot_entity_id: int):
device = get_iot_entity(db, iot_entity_id)
setattr(device, "open_request", False)
setattr(device, "time_seconds", 10)
db.add(device)
db.commit()
db.refresh(device)
return True
def record_door_access_log(db: Session, entry: schemas.DoorAccessLog):
db_item = models.DoorAccessLog(user_id=entry.user_id,
iot_id=entry.iot_id,
command=entry.command,
timestamp=entry.timestamp)
db.add(db_item)
db.commit()
db.refresh(db_item)
def record_room_sensor_data(db: Session, entry: schemas.IotMonitorRoomInfo):
db_item = models.RoomSensorData(humidity=entry.humidity,
people=entry.people,
temperature=entry.temperature,
smoke_sensor_reading=entry.smoke_sensor_reading,
timestamp=datetime.now())
db.add(db_item)
db.commit()
db.refresh(db_item)
def increment_door_access_list_counter(db: Session, iot_entity: models.IotEntity):
iot_entity.acces_list_counter = iot_entity.acces_list_counter + 1
db.add(iot_entity)
db.commit()
db.refresh(iot_entity)
def record_user_connection(db: Session, user: models.User, time: datetime):
entry = models.UserConnectionHistory(user_id=user.id, timestamp=time)
db.add(entry)
db.commit()
db.refresh(entry)
def get_sensor_data_for_room(db: Session, skip: int = 0, limit: int = 100):
data = db.query(models.RoomSensorData).offset(skip).limit(limit).all()
return data