some change of locations
This commit is contained in:
216
server/src/server_api.py
Normal file
216
server/src/server_api.py
Normal file
@@ -0,0 +1,216 @@
|
||||
from flask import Flask, request, jsonify
|
||||
from flask_sqlalchemy import SQLAlchemy
|
||||
from flask_cors import CORS
|
||||
import datetime
|
||||
import os
|
||||
import json
|
||||
|
||||
# Flask app instance
|
||||
app = Flask(__name__)
|
||||
CORS(app)
|
||||
# Flask app should allow the necessary HTTP methods in CORS.
|
||||
CORS(
|
||||
app,
|
||||
resources={r"/*": {"origins": "*"}},
|
||||
allow_headers=["Content-Type", "Authorization"]
|
||||
)
|
||||
|
||||
|
||||
# Configuration for SQLAlchemy
|
||||
app.config[
|
||||
'SQLALCHEMY_DATABASE_URI'
|
||||
] = os.environ.get(
|
||||
"SQLALCHEMY_DATABASE_URI"
|
||||
)
|
||||
db = SQLAlchemy(app)
|
||||
|
||||
# Database Model for Records
|
||||
class Record(db.Model):
|
||||
__tablename__ = 'records'
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
timestamp = db.Column(db.String(255), nullable=False)
|
||||
description = db.Column(db.String(255), nullable=False)
|
||||
|
||||
# Parse a timestamp string into a datetime object
|
||||
def parse_timestamp(timestamp_str):
|
||||
try:
|
||||
return datetime.strptime(timestamp_str, '%Y-%m-%d %H:%M:%S')
|
||||
except ValueError:
|
||||
return None
|
||||
|
||||
# Function to validate API keys based on their values and access level
|
||||
def validate_api_key(api_key, required_access_level):
|
||||
api_keys_json = os.environ.get('API_KEYS_JSON', '{}')
|
||||
api_keys_dict = json.loads(api_keys_json)
|
||||
|
||||
if api_key in api_keys_dict:
|
||||
access_level = api_keys_dict[api_key].get("access_level")
|
||||
return access_level == required_access_level
|
||||
|
||||
return False
|
||||
|
||||
# API key authentication
|
||||
@app.before_request
|
||||
def authenticate():
|
||||
# Check if the API key provided in the request headers is valid
|
||||
api_key = request.headers.get("Authorization")
|
||||
|
||||
# Allow all requests with RW keys
|
||||
if validate_api_key(api_key, "RW"):
|
||||
return None # Allow the request to proceed
|
||||
|
||||
# Allow GET requests with RO keys
|
||||
if request.method == "GET" and validate_api_key(api_key, "RO"):
|
||||
return None # Allow the request to proceed
|
||||
|
||||
# Return a 401 Unauthorized response for invalid API keys or access levels
|
||||
return jsonify({'error': 'Invalid API key or access level'}), 401
|
||||
|
||||
|
||||
|
||||
# Route to add a new record
|
||||
@app.route(
|
||||
'/add_record',
|
||||
methods=['POST']
|
||||
)
|
||||
def add_record():
|
||||
try:
|
||||
data = request.get_json()
|
||||
timestamp = data['timestamp']
|
||||
description = data['description']
|
||||
|
||||
# Create a new record with provided data and add it to the db
|
||||
new_record = Record(
|
||||
timestamp=timestamp, description=description
|
||||
)
|
||||
db.session.add(new_record)
|
||||
db.session.commit()
|
||||
|
||||
return jsonify({'message': 'Record added successfully'}), 201
|
||||
except Exception as e:
|
||||
# Return a 500 Internal Server Error response if an exception occurs
|
||||
return jsonify({'error': 'An error occurred: {}'.format(e)}), 500
|
||||
|
||||
|
||||
# Route to get the last recorded entry
|
||||
@app.route(
|
||||
'/get_last_record',
|
||||
methods=['GET']
|
||||
)
|
||||
def get_last_record():
|
||||
# Retrieve the last record from the database based on its ID
|
||||
last_record = Record.query.order_by(Record.id.desc()).first()
|
||||
if last_record:
|
||||
# Return the data of the last record as JSON
|
||||
return jsonify({
|
||||
'id': last_record.id,
|
||||
'timestamp': last_record.timestamp,
|
||||
'description': last_record.description
|
||||
})
|
||||
else:
|
||||
# Return a 404 Not Found response if no records are found
|
||||
return jsonify({'message': 'No records found'}), 404
|
||||
|
||||
# Route to get all records
|
||||
@app.route(
|
||||
'/get_all_records',
|
||||
methods=['GET']
|
||||
)
|
||||
def get_all_records():
|
||||
# Retrieve all records from the database
|
||||
# and format them into a list of dictionaries
|
||||
records = Record.query.order_by(Record.id.desc()).all()
|
||||
records_list = []
|
||||
for record in records:
|
||||
record_data = {
|
||||
'id': record.id,
|
||||
'timestamp': record.timestamp,
|
||||
'description': record.description
|
||||
}
|
||||
records_list.append(record_data)
|
||||
# Return the list of records as JSON
|
||||
return jsonify(records_list)
|
||||
|
||||
# Route to get records since a given timestamp
|
||||
@app.route(
|
||||
'/get_records_since/<timestamp_str>',
|
||||
methods=['GET']
|
||||
)
|
||||
def get_records_since(timestamp_str):
|
||||
timestamp = parse_timestamp(timestamp_str)
|
||||
if timestamp is None:
|
||||
return jsonify({'error': 'Invalid timestamp format'}), 400
|
||||
|
||||
# Retrieve records from the database where
|
||||
# the timestamp is greater than or equal to the provided timestamp
|
||||
records = Record.query.filter(
|
||||
Record.timestamp >= timestamp
|
||||
).order_by(Record.id.desc()).all()
|
||||
|
||||
records_list = []
|
||||
for record in records:
|
||||
record_data = {
|
||||
'id': record.id,
|
||||
'timestamp': record.timestamp,
|
||||
'description': record.description
|
||||
}
|
||||
records_list.append(record_data)
|
||||
|
||||
# Return the list of matching records as JSON
|
||||
return jsonify(records_list)
|
||||
|
||||
# Route to get records between two timestamps
|
||||
@app.route(
|
||||
'/get_records_between/'
|
||||
'<start_timestamp_str>/<end_timestamp_str>',
|
||||
methods=['GET']
|
||||
)
|
||||
def get_records_between(start_timestamp_str, end_timestamp_str):
|
||||
# Parse the provided start and end timestamps into datetime objects
|
||||
start_timestamp = parse_timestamp(start_timestamp_str)
|
||||
end_timestamp = parse_timestamp(end_timestamp_str)
|
||||
if start_timestamp is None or end_timestamp is None:
|
||||
return jsonify({'error': 'Invalid timestamp format'}), 400
|
||||
|
||||
# Retrieve records from the database
|
||||
# that fall within the provided timestamp range
|
||||
records = Record.query.filter(
|
||||
Record.timestamp.between(start_timestamp, end_timestamp)
|
||||
).order_by(Record.id.desc()).all()
|
||||
records_list = []
|
||||
for record in records:
|
||||
record_data = {
|
||||
'id': record.id,
|
||||
'timestamp': record.timestamp,
|
||||
'description': record.description
|
||||
}
|
||||
records_list.append(record_data)
|
||||
|
||||
return jsonify(records_list)
|
||||
|
||||
# Route to get records until a given timestamp
|
||||
@app.route('/get_records_until/<timestamp_str>', methods=['GET'])
|
||||
def get_records_until(timestamp_str):
|
||||
timestamp = parse_timestamp(timestamp_str)
|
||||
if timestamp is None:
|
||||
return jsonify({'error': 'Invalid timestamp format'}), 400
|
||||
|
||||
records = Record.query.filter(
|
||||
Record.timestamp <= timestamp
|
||||
).order_by(Record.id.desc()).all()
|
||||
|
||||
records_list = []
|
||||
for record in records:
|
||||
record_data = {
|
||||
'id': record.id,
|
||||
'timestamp': record.timestamp,
|
||||
'description': record.description
|
||||
}
|
||||
records_list.append(record_data)
|
||||
|
||||
return jsonify(records_list)
|
||||
|
||||
|
||||
# Run the Flask app
|
||||
if __name__ == '__main__':
|
||||
app.run(host='0.0.0.0', port=5000)
|
||||
Reference in New Issue
Block a user