diff --git a/app.py b/app.py index bd441ec..478483d 100644 --- a/app.py +++ b/app.py @@ -4,17 +4,17 @@ from flask_caching import Cache import requests.auth import os from lib.datetime import filter_accounts_current_month -from lib.reqs import get_urls, get_user_accounts, add_user_account, delete_user_account +from lib.reqs import get_urls, get_user_accounts, add_user_account, delete_user_account, get_user_accounts_count from flask import send_from_directory import requests import base64 from flask import Flask -from config import DevelopmentConfig # or ProductionConfig +from config import DevelopmentConfig app = Flask(__name__) app.config.from_object( DevelopmentConfig -) # Use DevelopmentConfig or ProductionConfig as needed +) cache = Cache(app, config={"CACHE_TYPE": "SimpleCache"}) @@ -44,7 +44,7 @@ def home(): return render_template( "home.html", username=session["username"], - accounts=get_user_accounts(base_url, session["auth_credentials"]), + accounts=get_user_accounts_count(base_url, session["auth_credentials"]), current_month_accounts=current_month_accounts, ) diff --git a/backend/app.py b/backend/app.py new file mode 100644 index 0000000..5328312 --- /dev/null +++ b/backend/app.py @@ -0,0 +1,19 @@ +from flask import Flask, jsonify +from config import DevelopmentConfig +from lib.mysql import execute_query + +app = Flask(__name__) +app.config.from_object(DevelopmentConfig) + +@app.route('/getUserAccounts', methods=['GET']) +def get_user_accounts(): + # Use the execute_query function to get user accounts + + data = execute_query("SELECT COUNT(*) AS account_count FROM userAccounts WHERE userID = %s;", (1,)) + if data is None: + return jsonify({"error": "Database query failed"}), 500 + return jsonify(data), 200 + +# Run the app +if __name__ == '__main__': + app.run(debug=app.config["DEBUG"], port=app.config["PORT"]) diff --git a/backend/lib/mysql.py b/backend/lib/mysql.py new file mode 100644 index 0000000..7450411 --- /dev/null +++ b/backend/lib/mysql.py @@ -0,0 +1,37 @@ +import mysql.connector +from flask import current_app + +def execute_query(query, params=None, fetch_one=False): + """Execute a SQL query and optionally fetch results.""" + try: + # Get database configuration from the current app context + db_config = { + "host": current_app.config['DBHOST'], + "user": current_app.config['DBUSER'], + "password": current_app.config['DBPASS'], + "database": current_app.config['DATABASE'], + } + + # Establish database connection + connection = mysql.connector.connect(**db_config) + cursor = connection.cursor(dictionary=True) + + # Execute the query with optional parameters + cursor.execute(query, params) + + # Fetch results if it's a SELECT query + if query.strip().upper().startswith("SELECT"): + result = cursor.fetchone() if fetch_one else cursor.fetchall() + else: + # Commit changes for INSERT, UPDATE, DELETE + connection.commit() + result = cursor.rowcount # Number of affected rows + + # Close the database connection + cursor.close() + connection.close() + + return result + except mysql.connector.Error as err: + print("Error: ", err) + return None diff --git a/lib/reqs.py b/lib/reqs.py index 14943d1..69514b4 100644 --- a/lib/reqs.py +++ b/lib/reqs.py @@ -1,11 +1,20 @@ import requests import json from datetime import datetime +from typing import List, Dict, Any -def get_urls(base_url, auth: str) -> list: +def get_urls(base_url: str, auth: str) -> List[Dict[str, Any]]: + """Retrieve user account streams from the specified base URL. + + Args: + base_url (str): The base URL of the API. + auth (str): The authorization token for accessing the API. + + Returns: + List[Dict[str, Any]]: A list of user account streams. + """ url = f"{base_url}/getUserAccounts/streams" - payload = {} headers = {"Authorization": f"Basic {auth}"} @@ -13,67 +22,86 @@ def get_urls(base_url, auth: str) -> list: return json.loads(response.text) -def get_user_accounts(base_url, auth: str) -> list: - url = f"{base_url}/getUserAccounts" +def get_user_accounts(base_url: str, auth: str) -> List[Dict[str, Any]]: + """Retrieve user accounts from the specified base URL. + Args: + base_url (str): The base URL of the API. + auth (str): The authorization token for accessing the API. + + Returns: + List[Dict[str, Any]]: A list of user accounts with their expiration dates rendered. + """ + url = f"{base_url}/getUserAccounts" payload = {} headers = {"Authorization": f"Basic {auth}"} response = requests.request("GET", url, headers=headers, data=payload) res_json = json.loads(response.text) + for account in res_json: account["expiaryDate_rendered"] = datetime.utcfromtimestamp( account["expiaryDate"] ).strftime("%d/%m/%Y") + return res_json -def delete_user_account(base_url: str, auth: str, stream:str, username:str) -> bool: - """_summary_ +def delete_user_account(base_url: str, auth: str, stream: str, username: str) -> bool: + """Delete a user account from the specified base URL. Args: - base_url (str): _description_ - auth (str): _description_ - stream (str): _description_ - username (str): _description_ + base_url (str): The base URL of the API. + auth (str): The authorization token for accessing the API. + stream (str): The name of the stream associated with the user account. + username (str): The username of the account to delete. Returns: - bool: _description_ - """ + bool: True if the account was deleted successfully, False otherwise. + """ url = f"{base_url}/deleteAccount" - payload = {"stream": stream, "user": username} - headers = {"Authorization": f"Basic {auth}"} response = requests.request("POST", url, headers=headers, data=payload) - if "Deleted" in response.text: - return True - else: - return False + return "Deleted" in response.text - -def add_user_account(base_url: str, auth: str, username:str, password:str, stream:str,) -> bool: - """_summary_ +def add_user_account(base_url: str, auth: str, username: str, password: str, stream: str) -> bool: + """Add a user account to the specified base URL. Args: - base_url (str): _description_ - auth (str): _description_ - stream (str): _description_ - username (str): _description_ + base_url (str): The base URL of the API. + auth (str): The authorization token for accessing the API. + username (str): The username of the account to add. + password (str): The password of the account to add. + stream (str): The name of the stream associated with the user account. Returns: - bool: _description_ - """ + bool: True if the account was added successfully, False otherwise. + """ url = f"{base_url}/addAccount" - payload = {"username": username, "password": password, "stream": stream} - headers = {"Authorization": f"Basic {auth}"} response = requests.request("POST", url, headers=headers, data=payload) - if "Added successfully" in response.text: - return True - else: - return False \ No newline at end of file + return "Added successfully" in response.text + + +def get_user_accounts_count(base_url: str, auth: str) -> int: + """Get the count of user accounts from the specified base URL. + + Args: + base_url (str): The base URL of the API. + auth (str): The authorization token for accessing the API. + + Returns: + int: The count of user accounts. + """ + url = f"{base_url}/getUserAccounts/count" + payload = {} + headers = {"Authorization": f"Basic {auth}"} + + response = requests.request("GET", url, headers=headers, data=payload) + res_json = json.loads(response.text) + return res_json['count'] diff --git a/templates/home.html b/templates/home.html index f59e688..3540b0d 100644 --- a/templates/home.html +++ b/templates/home.html @@ -34,7 +34,7 @@

Welcome {{ username }}!


-

You have {{ accounts|length }} active accounts

+

You have {{ accounts }} active accounts


{% if current_month_accounts %} diff --git a/templates/user_accounts.html b/templates/user_accounts.html index b88babf..dca0729 100644 --- a/templates/user_accounts.html +++ b/templates/user_accounts.html @@ -45,7 +45,7 @@ - + @@ -57,7 +57,7 @@ {% for account in user_accounts %} - + @@ -100,17 +100,19 @@ return data; // return as is if the format is unexpected }; - // Initialize DataTable with custom sorting + // Initialize DataTable with custom sorting and default ordering by Expiry Date $('#accountsTable').DataTable({ "searching": true, "ordering": true, "responsive": true, + "order": [[3, 'asc']], // Default order by Expiry Date column in ascending order "columnDefs": [ - { "type": "date-eu", "targets": 4 } // Use custom date-eu type for the date column + { "type": "date-eu", "targets": 3 } // Use custom date-eu type for the date column ] }); }); +
# Username Stream Stream URL
{{ loop.index }} {{ account.username }} {{ account.stream }} {{ account.streamURL }}