mirror of
https://github.com/hubHarmony/servii-backend.git
synced 2024-11-18 05:50:31 +00:00
[+] Added basic firebase authentication checks, and added firestore basic functions.
Signed-off-by: Charles Le Maux <charles.le-maux@epitech.eu>
This commit is contained in:
parent
acd72ffa8a
commit
9ccef01999
19
api.py
19
api.py
@ -4,6 +4,7 @@ import inspect
|
|||||||
from flask import Flask, Response, jsonify, request
|
from flask import Flask, Response, jsonify, request
|
||||||
from flask_cors import CORS
|
from flask_cors import CORS
|
||||||
|
|
||||||
|
import firebase_manager
|
||||||
import generic_executor
|
import generic_executor
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
@ -44,6 +45,19 @@ def parse_and_validate_request(parameters: [str]) -> list[str]:
|
|||||||
data = request.get_json()
|
data = request.get_json()
|
||||||
if not data:
|
if not data:
|
||||||
raise Exception("Empty request body.")
|
raise Exception("Empty request body.")
|
||||||
|
if 'jwt' not in data:
|
||||||
|
raise Exception("Missing 'token' in request body. The API doesn't support anonymous access anymore.")
|
||||||
|
else:
|
||||||
|
valid, user_id = firebase_manager.verify_jwt_token(data['jwt'])
|
||||||
|
if not valid:
|
||||||
|
raise Exception("Invalid JWT token.")
|
||||||
|
else:
|
||||||
|
user = firebase_manager.get_user_from_id(user_id)
|
||||||
|
if not user:
|
||||||
|
raise Exception("User not found.")
|
||||||
|
if not user.email_verified:
|
||||||
|
raise Exception("Your google account isn't verified yet.")
|
||||||
|
pass
|
||||||
for name in parameters:
|
for name in parameters:
|
||||||
if name not in data:
|
if name not in data:
|
||||||
raise Exception(f"Missing parameter {name}")
|
raise Exception(f"Missing parameter {name}")
|
||||||
@ -73,13 +87,14 @@ def dynamic_route_handler(path):
|
|||||||
route_fn = route_handlers[path]
|
route_fn = route_handlers[path]
|
||||||
parameters = []
|
parameters = []
|
||||||
sig = inspect.signature(route_fn)
|
sig = inspect.signature(route_fn)
|
||||||
|
|
||||||
for param in sig.parameters.values():
|
for param in sig.parameters.values():
|
||||||
parameters.append(param.name)
|
parameters.append(param.name)
|
||||||
|
try :
|
||||||
mapped_parameters = parse_and_validate_request(parameters)
|
mapped_parameters = parse_and_validate_request(parameters)
|
||||||
status: http.HTTPStatus = route_fn(*mapped_parameters)
|
status: http.HTTPStatus = route_fn(*mapped_parameters)
|
||||||
return generic_response_maker(status)
|
return generic_response_maker(status)
|
||||||
|
except Exception as e:
|
||||||
|
return generic_response_maker(http.HTTPStatus.BAD_REQUEST, str(e))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
@ -42,6 +42,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
button.addEventListener('click', async event => {
|
button.addEventListener('click', async event => {
|
||||||
const form = event.target.closest('form');
|
const form = event.target.closest('form');
|
||||||
const action = button.dataset.action;
|
const action = button.dataset.action;
|
||||||
|
const jwt = "0";
|
||||||
const email = document.getElementById('accountEmail').value;
|
const email = document.getElementById('accountEmail').value;
|
||||||
const port = document.getElementById('accountPort').value;
|
const port = document.getElementById('accountPort').value;
|
||||||
const name = document.getElementById('serverName').value;
|
const name = document.getElementById('serverName').value;
|
||||||
@ -52,28 +53,28 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
var data = {}
|
var data = {}
|
||||||
switch(action) {
|
switch(action) {
|
||||||
case 'AccountCreate':
|
case 'AccountCreate':
|
||||||
data = {email, port}
|
data = {email, port, jwt}
|
||||||
break;
|
break;
|
||||||
case 'AccountDelete':
|
case 'AccountDelete':
|
||||||
data = {email, port}
|
data = {email, port, jwt}
|
||||||
break;
|
break;
|
||||||
case 'ServerCreate':
|
case 'ServerCreate':
|
||||||
data = {port, name, version}
|
data = {port, name, version, jwt}
|
||||||
break;
|
break;
|
||||||
case 'ServerDelete':
|
case 'ServerDelete':
|
||||||
data = {port, name}
|
data = {port, name, jwt}
|
||||||
break;
|
break;
|
||||||
case 'ServerRun':
|
case 'ServerRun':
|
||||||
data = {port, name}
|
data = {port, name, jwt}
|
||||||
break;
|
break;
|
||||||
case 'ServerStop':
|
case 'ServerStop':
|
||||||
data = {port, name}
|
data = {port, name, jwt}
|
||||||
break;
|
break;
|
||||||
case 'UpdateProperty':
|
case 'UpdateProperty':
|
||||||
data = {port, name, prop, value}
|
data = {port, name, prop, value, jwt}
|
||||||
break;
|
break;
|
||||||
case 'Command':
|
case 'Command':
|
||||||
data = {port, name, command}
|
data = {port, name, command, jwt}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
sendRequest(action, data)
|
sendRequest(action, data)
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
|
from datetime import datetime
|
||||||
|
|
||||||
import jwt
|
import jwt
|
||||||
import firebase_admin
|
import firebase_admin
|
||||||
from firebase_admin import credentials, auth
|
from firebase_admin import credentials, auth, firestore
|
||||||
|
from google.api_core.exceptions import NotFound, PermissionDenied, Aborted, ResourceExhausted, OutOfRange, DataLoss
|
||||||
|
|
||||||
cred = credentials.Certificate('servii.json')
|
cred = credentials.Certificate('servii.json')
|
||||||
firebase_admin.initialize_app(cred)
|
firebase_admin.initialize_app(cred)
|
||||||
|
firestore_database = firestore.client()
|
||||||
|
|
||||||
'''
|
'''
|
||||||
TODO
|
TODO
|
||||||
@ -15,6 +18,7 @@ Tell the database they have now stopped running.
|
|||||||
Also ensure the program can add an additional argument to avoid this checking for scalability.
|
Also ensure the program can add an additional argument to avoid this checking for scalability.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
|
||||||
def get_user_from_id(user_id):
|
def get_user_from_id(user_id):
|
||||||
return auth.get_user(user_id)
|
return auth.get_user(user_id)
|
||||||
|
|
||||||
@ -28,3 +32,44 @@ def verify_jwt_token(token):
|
|||||||
return False, None
|
return False, None
|
||||||
except jwt.InvalidTokenError:
|
except jwt.InvalidTokenError:
|
||||||
return False, None
|
return False, None
|
||||||
|
|
||||||
|
|
||||||
|
def create_firestore(user_id: str, data: dict) -> bool:
|
||||||
|
doc_ref = firestore_database.collection('users').document(user_id)
|
||||||
|
try:
|
||||||
|
doc_ref.create(data)
|
||||||
|
return True
|
||||||
|
except (NotFound, PermissionDenied, Aborted, ResourceExhausted,
|
||||||
|
OutOfRange, DataLoss, TypeError, Exception, ValueError) as e:
|
||||||
|
log_exception_to_firestore(e, user_id, data)
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def update_firestore(user_id: str, data: dict) -> bool:
|
||||||
|
doc_ref = firestore_database.collection('users').document(user_id)
|
||||||
|
try:
|
||||||
|
doc_ref.update(data)
|
||||||
|
return True
|
||||||
|
except (NotFound, PermissionDenied, Aborted, ResourceExhausted,
|
||||||
|
OutOfRange, DataLoss, TypeError, Exception, ValueError) as e:
|
||||||
|
log_exception_to_firestore(e, user_id, data)
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def log_exception_to_firestore(exception: Exception = None, user_id: str = None, data: dict = None):
|
||||||
|
new_id: str = datetime.now().strftime('%Y-%m-%d %H:%M:%S %Z%z')
|
||||||
|
log_entry = {
|
||||||
|
'exception_name': str(type(exception).__name__),
|
||||||
|
'exception': str(exception) if exception else 'No exception',
|
||||||
|
'user_id': str(user_id) if user_id else 'No user_id',
|
||||||
|
'data': str(data) if data else 'No data provided',
|
||||||
|
}
|
||||||
|
try:
|
||||||
|
firestore_database.collection('firebase.logs').document(new_id).create(log_entry)
|
||||||
|
print("Log entry added successfully.")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Failed to add log entry: {e}")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
pass
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
from server_mc_manager import MinecraftServerManager
|
from server_mc_manager import MinecraftServerManager
|
||||||
from http import HTTPStatus
|
from http import HTTPStatus
|
||||||
|
|
||||||
import file_manager
|
import file_manager
|
||||||
|
|
||||||
mc_manager: MinecraftServerManager = MinecraftServerManager()
|
mc_manager: MinecraftServerManager = MinecraftServerManager()
|
||||||
@ -90,3 +91,6 @@ def run_command(port: str, command: str) -> HTTPStatus:
|
|||||||
print(f"Error executing command: {e}")
|
print(f"Error executing command: {e}")
|
||||||
return HTTPStatus.INTERNAL_SERVER_ERROR
|
return HTTPStatus.INTERNAL_SERVER_ERROR
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
pass
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
|
firebase_admin==6.5.0
|
||||||
Flask==3.0.3
|
Flask==3.0.3
|
||||||
Flask_Cors==4.0.1
|
Flask_Cors==4.0.1
|
||||||
plotly==5.22.0
|
PyJWT==2.8.0
|
||||||
psutil==5.9.8
|
|
||||||
|
Loading…
Reference in New Issue
Block a user