Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
167 changes: 167 additions & 0 deletions backend/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
from flask import Flask, request, jsonify
from models import db, User, Device, SensorLog
import secrets

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///smart_workspace.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db.init_app(app)

with app.app_context():
db.create_all()


@app.route('/auth/register', methods=['POST'])
def register():
data = request.json
if User.query.filter_by(email=data.get('email')).first():
return jsonify({"error": "User already exists"}), 400

new_user = User(
full_name=data.get('fullName'),
email=data.get('email'),
password=data.get('password'),
department=data.get('department', 'Unknown')
)
db.session.add(new_user)
db.session.commit()
return jsonify({"message": "User registered successfully"}), 201

@app.route('/auth/login', methods=['POST'])
def login():
data = request.json
user = User.query.filter_by(email=data.get('email'), password=data.get('password')).first()

if user:
token = secrets.token_hex(20)
user.access_token = token
db.session.commit()
return jsonify({"token": token, "user": user.to_dict()}), 200

return jsonify({"error": "Invalid email or password"}), 401

@app.route('/auth/account', methods=['DELETE'])
def delete_account():
token = request.headers.get('Authorization')
user = User.query.filter_by(access_token=token).first()
if not user:
return jsonify({"error": "Unauthorized"}), 401

Device.query.filter_by(user_id=user.id).delete()
SensorLog.query.filter_by(user_id=user.id).delete()

db.session.delete(user)
db.session.commit()

return jsonify({"message": "Account, devices and logs deleted"}), 200


@app.route('/devices', methods=['GET'])
def get_devices():
token = request.headers.get('Authorization')
user = User.query.filter_by(access_token=token).first()
if not user:
return jsonify({"error": "Unauthorized"}), 401

devices = Device.query.filter_by(user_id=user.id).all()
return jsonify([device.to_dict() for device in devices]), 200

@app.route('/devices', methods=['POST'])
def add_device():
token = request.headers.get('Authorization')
user = User.query.filter_by(access_token=token).first()
if not user:
return jsonify({"error": "Unauthorized"}), 401

data = request.json
new_device = Device(
id=data.get('id'),
title=data.get('title'),
value=data.get('value', '--'),
status=data.get('status', 'Stable'),
icon_code=data.get('icon_code'),
color_hex=data.get('color_hex'),
user_id=user.id
)
db.session.add(new_device)
db.session.commit()
return jsonify(new_device.to_dict()), 201

@app.route('/devices/<device_id>', methods=['PUT'])
def update_device(device_id):
token = request.headers.get('Authorization')
user = User.query.filter_by(access_token=token).first()
if not user:
return jsonify({"error": "Unauthorized"}), 401

device = Device.query.filter_by(id=device_id, user_id=user.id).first()
if not device:
return jsonify({"error": "Device not found"}), 404

data = request.json
device.title = data.get('title', device.title)
device.value = data.get('value', device.value)
device.status = data.get('status', device.status)
device.icon_code = data.get('icon_code', device.icon_code)
device.color_hex = data.get('color_hex', device.color_hex)

db.session.commit()
return jsonify(device.to_dict()), 200

@app.route('/devices/<device_id>', methods=['DELETE'])
def delete_device(device_id):
token = request.headers.get('Authorization')
user = User.query.filter_by(access_token=token).first()
if not user:
return jsonify({"error": "Unauthorized"}), 401

device = Device.query.filter_by(id=device_id, user_id=user.id).first()
if not device:
return jsonify({"error": "Device not found"}), 404

db.session.delete(device)
db.session.commit()
return jsonify({"message": "Device deleted"}), 200


@app.route('/logs', methods=['POST'])
def save_log():
token = request.headers.get('Authorization')
user = User.query.filter_by(access_token=token).first()
if not user:
return jsonify({"error": "Unauthorized"}), 401

data = request.json
new_log = SensorLog(
sensor_id=data.get('sensor_id'),
value=str(data.get('value')),
user_id=user.id
)
db.session.add(new_log)
db.session.commit()

return jsonify(new_log.to_dict()), 201

@app.route('/auth/profile', methods=['PUT'])
def update_profile():
token = request.headers.get('Authorization')
user = User.query.filter_by(access_token=token).first()
if not user:
return jsonify({"error": "Unauthorized"}), 401

data = request.json

if 'email' in data and data['email'] != user.email:
if User.query.filter_by(email=data['email']).first():
return jsonify({"error": "Email already in use"}), 400

user.full_name = data.get('fullName', user.full_name)
user.email = data.get('email', user.email)
user.department = data.get('department', user.department)

db.session.commit()
return jsonify(user.to_dict()), 200


if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000, debug=True)
55 changes: 55 additions & 0 deletions backend/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
from flask_sqlalchemy import SQLAlchemy
from datetime import datetime
import uuid

db = SQLAlchemy()

class User(db.Model):
id = db.Column(db.String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
full_name = db.Column(db.String(100), nullable=False)
email = db.Column(db.String(100), unique=True, nullable=False)
password = db.Column(db.String(100), nullable=False)
department = db.Column(db.String(100))
access_token = db.Column(db.String(100), unique=True)

def to_dict(self):
return {
"id": self.id,
"fullName": self.full_name,
"email": self.email,
"department": self.department
}

class Device(db.Model):
id = db.Column(db.String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
title = db.Column(db.String(100), nullable=False)
value = db.Column(db.String(50))
status = db.Column(db.String(50), default="Stable")
icon_code = db.Column(db.Integer)
color_hex = db.Column(db.Integer)
user_id = db.Column(db.String(36), db.ForeignKey('user.id'))

def to_dict(self):
return {
"id": self.id,
"title": self.title,
"value": self.value,
"status": self.status,
"icon_code": self.icon_code,
"color_hex": self.color_hex
}

class SensorLog(db.Model):
id = db.Column(db.String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
sensor_id = db.Column(db.String(100), nullable=False)
value = db.Column(db.String(50), nullable=False)
timestamp = db.Column(db.DateTime, default=datetime.utcnow)
user_id = db.Column(db.String(36), db.ForeignKey('user.id'))

def to_dict(self):
return {
"id": self.id,
"sensor_id": self.sensor_id,
"value": self.value,
"timestamp": self.timestamp.isoformat()
}
Binary file added instance/smart_workspace.db
Binary file not shown.
25 changes: 25 additions & 0 deletions lib/models/device_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,29 @@ class DeviceModel {
color: Color(map['color'] as int),
);
}

factory DeviceModel.fromJson(Map<String, dynamic> json) {
return DeviceModel(
id: json['id']?.toString() ?? '',
title: json['title']?.toString() ?? 'Unknown Node',
value: json['value']?.toString() ?? '--',
status: json['status']?.toString() ?? 'Stable',
icon: IconData(
json['icon_code'] as int? ?? Icons.device_hub.codePoint,
fontFamily: 'MaterialIcons',
),
color: Color(json['color_hex'] as int? ?? 0xFF38BDF8),
);
}

Map<String, dynamic> toJson() {
return {
'id': id,
'title': title,
'value': value,
'status': status,
'icon_code': icon.codePoint,
'color_hex': color.toARGB32(),
};
}
}
8 changes: 4 additions & 4 deletions lib/models/user_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ class UserModel {

factory UserModel.fromJson(Map<String, dynamic> json) {
return UserModel(
fullName: json['fullName'] as String,
email: json['email'] as String,
password: json['password'] as String,
department: json['department'] as String,
fullName: json['fullName']?.toString() ?? 'Unknown User',
email: json['email']?.toString() ?? 'no-email@system.io',
password: json['password']?.toString() ?? '',
department: json['department']?.toString() ?? 'KSA',
);
}

Expand Down
Loading
Loading