Skip to main content

A lightweight Flask utility library providing validation, authentication decorators, and database helpers.

Project description

Ol_Utills Logo

๐Ÿ› ๏ธ Ol_Utills

A lightweight Flask utility library for validation, authentication, security, and database helpers.

PyPI Version Python Versions License


โœจ Features

  • Input Validation โ€” Password, email, and phone number validation using battle-tested regex patterns.
  • Auth Decorators โ€” Drop-in @login_required and @admin_required decorators for Flask routes.
  • Response Helpers โ€” Standardized success_response and error_response for consistent API output.
  • Security โ€” Rate limiting (Redis-backed), input/file sanitization, bcrypt password hashing & verification.
  • Database Helpers โ€” Quick-connect utilities for SQLite, PostgreSQL, and Redis.
  • Zero Config โ€” Works out of the box with any Flask app.

๐Ÿ—๏ธ Architecture Overview

graph LR
    A["๐Ÿ› ๏ธ Ol_Utills"] --> B["๐Ÿ”’ val"]
    A --> C["๐Ÿ›ก๏ธ req"]
    A --> D["๐Ÿ“ฆ res"]
    A --> E["๐Ÿ—„๏ธ Connections"]
    A --> F["๐Ÿ” security"]

    B --> B1["chk_p โ€” Password"]
    B --> B2["chk_e โ€” Email"]
    B --> B3["chk_ph โ€” Phone"]

    C --> C1["@login_required"]
    C --> C2["@admin_required"]

    D --> D1["success_response"]
    D --> D2["error_response"]

    E --> E1["SQLite"]
    E --> E2["PostgreSQL"]
    E --> E3["Redis"]

    F --> F1["@rate_limit"]
    F --> F2["Sanitizes"]
    F --> F3["hash"]
    F --> F4["verify"]

    style A fill:#4f46e5,stroke:#4338ca,color:#fff
    style B fill:#0891b2,stroke:#0e7490,color:#fff
    style C fill:#059669,stroke:#047857,color:#fff
    style D fill:#d97706,stroke:#b45309,color:#fff
    style E fill:#7c3aed,stroke:#6d28d9,color:#fff
    style F fill:#e11d48,stroke:#be123c,color:#fff

๐Ÿ“ฆ Installation

pip install ol-utills flask

Requirements

Dependency Purpose
flask Session management & JSON responses
psycopg2 PostgreSQL connectivity
redis Redis connectivity & rate limiting
bcrypt Secure password hashing

Note: sqlite3 and re are part of the Python standard library and do not need to be installed.

Supported Python Versions

  • Python 3.8 and above

๐Ÿš€ Quick Start

from Ol_Utills import val, req, res, Connections, security

# Validate an email
if val.chk_e("user@example.com"):
    print("Valid email!")

# Connect to a SQLite database
conn, db = Connections.sqlite("app.db")
db.execute("SELECT * FROM users")

# Hash a password
hashed = security.hash("MySecureP@ss1")
print(security.verify("MySecureP@ss1", hashed))  # True

๐Ÿ“– Detailed Documentation

Table of Contents

  1. val โ€” Validation
  2. req โ€” Authentication Decorators
  3. res โ€” Response Helpers
  4. Connections โ€” Database Connections
  5. security โ€” Security Utilities
  6. Full Flask App Example

val โ€” Validation

The val class provides static methods for validating common user inputs using regular expressions. All methods return True on success and None on failure, making them easy to use in conditional checks.

flowchart LR
    Input["๐Ÿ“ฅ User Input"] --> Val{"val method"}
    Val -->|"chk_p"| P["Password Regex"]
    Val -->|"chk_e"| E["Email Regex"]
    Val -->|"chk_ph"| Ph["Phone Regex"]
    P --> Result{"Match?"}
    E --> Result
    Ph --> Result
    Result -->|"โœ… Yes"| True["Returns True"]
    Result -->|"โŒ No"| None["Returns None"]

    style Input fill:#f8fafc,stroke:#94a3b8,color:#334155
    style True fill:#22c55e,stroke:#16a34a,color:#fff
    style None fill:#ef4444,stroke:#dc2626,color:#fff

val.chk_p(password)

Validates password strength against a robust regex pattern.

Details
Parameter password (str) โ€” The password string to validate
Returns True if valid, None if invalid

Password Rules:

The password must satisfy all of the following criteria:

  • โœ… Minimum 7 characters long (6 + 1 trailing non-whitespace)
  • โœ… At least 1 uppercase letter (A-Z)
  • โœ… At least 1 lowercase letter (a-z)
  • โœ… At least 1 digit (0-9)
  • โœ… Must not contain whitespace
  • โœ… The last character must be a non-whitespace character

Note: Special characters (e.g. @, #, !) are allowed but not required.

Examples:

from Ol_Utills import val

# โœ… Valid passwords
val.chk_p("MyP@ss1234")    # True โ€” uppercase, lowercase, digit, special char
val.chk_p("Hello1x")        # True โ€” meets all minimum criteria
val.chk_p("Abcdef1")        # True โ€” exactly 7 chars, has upper, lower, digit

# โŒ Invalid passwords
val.chk_p("weak")            # None โ€” too short, no uppercase, no digit
val.chk_p("alllowercase1")  # None โ€” no uppercase letter
val.chk_p("ALLUPPERCASE1")  # None โ€” no lowercase letter
val.chk_p("NoDigits!")       # None โ€” no digit
val.chk_p("Ab1")             # None โ€” too short

Usage in a Flask route:

from flask import Flask, request, jsonify
from Ol_Utills import val

app = Flask(__name__)

@app.route('/register', methods=['POST'])
def register():
    password = request.form.get('password')

    if not val.chk_p(password):
        return jsonify({
            "error": "Password must be 7+ chars with at least 1 uppercase, 1 lowercase, and 1 digit."
        }), 400

    # Proceed with registration...
    return jsonify({"message": "Registration successful"}), 201

val.chk_e(email)

Validates an email address against the RFC 2822 specification using a comprehensive regex pattern.

Details
Parameter email (str) โ€” The email address string to validate
Returns True if valid, None if invalid

Validation Covers:

  • โœ… Standard emails: user@example.com
  • โœ… Subdomains: user@mail.example.com
  • โœ… Plus addressing: user+tag@example.com
  • โœ… Dots in local part: first.last@example.com
  • โœ… Quoted strings: "unusual@chars"@example.com
  • โŒ Missing @ symbol
  • โŒ Missing domain
  • โŒ Spaces in unquoted local parts
  • โŒ Control characters

Examples:

from Ol_Utills import val

# โœ… Valid emails
val.chk_e("user@example.com")          # True
val.chk_e("first.last@company.co.uk")  # True
val.chk_e("user+filter@gmail.com")     # True
val.chk_e("admin@192.168.1.1")         # True

# โŒ Invalid emails
val.chk_e("not-an-email")              # None โ€” no @ symbol
val.chk_e("@missing-local.com")        # None โ€” no local part
val.chk_e("spaces in@email.com")       # None โ€” spaces not allowed
val.chk_e("")                           # None โ€” empty string

val.chk_ph(phone)

Validates international phone numbers.

Details
Parameter phone (str) โ€” The phone number string to validate
Returns True if valid, None if invalid

Supported Formats:

  • โœ… International: +1-555-555-5555
  • โœ… With parentheses: (555) 555-5555
  • โœ… With dots: 555.555.5555
  • โœ… With spaces: +44 20 7946 0958
  • โœ… Plain digits: 5555555555

Examples:

from Ol_Utills import val

val.chk_ph("+1-800-555-0199")    # True
val.chk_ph("(555) 123-4567")     # True
val.chk_ph("+44 20 7946 0958")   # True

req โ€” Authentication Decorators

The req class provides Flask route decorators for session-based authentication. These decorators wrap your view functions and check the Flask session object before allowing access.

How It Works:

flowchart TD
    A["๐ŸŒ Client Request"] --> B["Flask Route"]
    B --> C{"Decorator Check"}

    C -->|"@login_required"| D{"session logged == True?"}
    C -->|"@admin_required"| E{"session admin == True?"}

    D -->|"โœ… Yes"| F["โœ… Execute View Function"]
    D -->|"โŒ No"| G["๐Ÿšซ Return 401 error_response"]

    E -->|"โœ… Yes"| F
    E -->|"โŒ No"| G

    F --> H["๐Ÿ“ค Return Response to Client"]
    G --> H

    style A fill:#f8fafc,stroke:#94a3b8,color:#334155
    style F fill:#22c55e,stroke:#16a34a,color:#fff
    style G fill:#ef4444,stroke:#dc2626,color:#fff
    style H fill:#3b82f6,stroke:#2563eb,color:#fff

@req.login_required

Restricts a Flask route to authenticated (logged-in) users only.

Details
Session Key session['logged']
Required Value True (boolean)
On Success Executes the decorated view function normally
On Failure Returns res.error_response('Unauthorized', 401)

Prerequisites:

You must set session['logged'] = True somewhere in your login logic (e.g., after verifying credentials).

Example:

from flask import Flask, session, request, jsonify
from Ol_Utills import req

app = Flask(__name__)
app.secret_key = 'your-secret-key'

# Login route โ€” sets session
@app.route('/login', methods=['POST'])
def login():
    username = request.form.get('username')
    password = request.form.get('password')

    # ... verify credentials against database ...

    session['logged'] = True         # โ† Required for @login_required
    session['username'] = username   # โ† Optional: store user info
    return jsonify({"message": "Logged in successfully"})

# Protected route โ€” requires login
@app.route('/dashboard')
@req.login_required
def dashboard():
    return jsonify({"message": "Welcome to your dashboard"})

# Logout route โ€” clears session
@app.route('/logout')
def logout():
    session.pop('logged', None)
    return jsonify({"message": "Logged out"})

Behavior:

Scenario session['logged'] Result
User is logged in True View function runs normally
User is not logged in Missing or False Returns error_response('Unauthorized', 401)
Session expired Missing Returns error_response('Unauthorized', 401)

@req.admin_required

Restricts a Flask route to admin users only. Works the same as @login_required but checks a different session key.

Details
Session Key session['admin']
Required Value True (boolean)
On Success Executes the decorated view function normally
On Failure Returns res.error_response('Unauthorized', 401)

Example:

# Admin login โ€” sets admin session
@app.route('/admin/login', methods=['POST'])
def admin_login():
    # ... verify admin credentials ...

    session['logged'] = True    # for general auth
    session['admin'] = True     # โ† Required for @admin_required
    return jsonify({"message": "Admin logged in"})

# Admin-only route
@app.route('/admin/users')
@req.admin_required
def manage_users():
    return jsonify({"users": ["user1", "user2", "user3"]})

Stacking Decorators:

You can combine both decorators for routes that require login and admin access:

@app.route('/admin/settings')
@req.login_required
@req.admin_required
def admin_settings():
    return jsonify({"settings": "..."})

Tip: When stacking, @req.login_required should be the outermost decorator (listed first) so the login check runs before the admin check.


res โ€” Response Helpers

The res class provides utilities for building standardized JSON API responses, ensuring a consistent format across all your endpoints.


res.success_response(data)

Returns a standardized success JSON response with HTTP status 200.

Details
Parameter data (any) โ€” The data payload to include
Returns (jsonify({'data': data}), 200) โ€” Flask response tuple

Example:

from Ol_Utills import res

# In a Flask route
@app.route('/users')
def get_users():
    users = [{"id": 1, "name": "Alice"}, {"id": 2, "name": "Bob"}]
    return res.success_response(users)
    # Response: {"data": [{"id": 1, "name": "Alice"}, {"id": 2, "name": "Bob"}]}, 200

res.error_response(message, code)

Returns a standardized error JSON response with a custom HTTP status code.

Details
Parameters message (str) โ€” Error message to return
code (int) โ€” HTTP status code (e.g. 400, 404, 500)
Returns (jsonify({'error': message}), code) โ€” Flask response tuple

Example:

from Ol_Utills import res

@app.route('/users/<int:user_id>')
def get_user(user_id):
    user = find_user(user_id)
    if not user:
        return res.error_response("User not found", 404)
        # Response: {"error": "User not found"}, 404
    return res.success_response(user)

Connections โ€” Database Connections

The Connections class provides quick-connect helper functions for database setup. Each method opens a connection and returns a (connection, cursor) tuple.

flowchart LR
    App["๐Ÿ Flask App"] --> DB{"Connections helper"}

    DB -->|".sqlite"| SQ["๐Ÿ“ SQLite File"]
    DB -->|".postgresql"| PG["๐Ÿ˜ PostgreSQL Server"]
    DB -->|".C_redis"| RD["๐Ÿ”ด Redis Server"]

    SQ --> SQC["sqlite3.connect"]
    PG --> PGC["psycopg2.connect"]
    RD --> RDC["redis.Redis"]

    SQC --> Tuple["๐Ÿ“‹ (conn, cursor)"]
    PGC --> Tuple
    RDC --> Client["๐Ÿ“‹ Redis client"]

    Tuple --> Ops["execute / fetchall / fetchone / commit"]
    Client --> ROps["get / set / incr / expire"]

    style App fill:#f8fafc,stroke:#94a3b8,color:#334155
    style SQ fill:#0891b2,stroke:#0e7490,color:#fff
    style PG fill:#4f46e5,stroke:#4338ca,color:#fff
    style RD fill:#dc2626,stroke:#b91c1c,color:#fff
    style Tuple fill:#22c55e,stroke:#16a34a,color:#fff
    style Client fill:#22c55e,stroke:#16a34a,color:#fff

Important: Connections.sqlite() and Connections.postgresql() now return a (connection, cursor) tuple instead of just a cursor. Use conn for commit() / close(), and db for queries.


Connections.sqlite(database)

Opens a connection to a SQLite database file and returns a (connection, cursor) tuple.

Details
Parameter database (str) โ€” Path to the SQLite database file. If the file doesn't exist, SQLite will create it automatically.
Returns (sqlite3.Connection, sqlite3.Cursor) โ€” A tuple of connection and cursor objects

Examples:

from Ol_Utills import Connections

# Connect to (or create) a database
conn, db = Connections.sqlite("app.db")

# Create a table
db.execute("""
    CREATE TABLE IF NOT EXISTS users (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        username TEXT NOT NULL UNIQUE,
        email TEXT NOT NULL,
        created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
    )
""")
conn.commit()  # Use conn for commit

# Insert a record
db.execute(
    "INSERT INTO users (username, email) VALUES (?, ?)",
    ("john_doe", "john@example.com")
)
conn.commit()

# Query records
db.execute("SELECT * FROM users")
users = db.fetchall()
for user in users:
    print(user)

# Close when done
conn.close()

Connections.postgresql(database, user, password, host)

Opens a connection to a PostgreSQL database and returns a (connection, cursor) tuple.

Details
Parameters
database (str) Name of the PostgreSQL database
user (str) Database username
password (str) Database password
host (str) Database host address (e.g. "localhost", "db.example.com")
Returns (psycopg2.Connection, psycopg2.Cursor) โ€” A tuple of connection and cursor objects
Requires psycopg2 package (pip install psycopg2-binary)

Examples:

from Ol_Utills import Connections

# Connect to PostgreSQL
conn, db = Connections.postgresql(
    database="myapp",
    user="admin",
    password="secure_password",
    host="localhost"
)

# Create a table
db.execute("""
    CREATE TABLE IF NOT EXISTS products (
        id SERIAL PRIMARY KEY,
        name VARCHAR(100) NOT NULL,
        price DECIMAL(10, 2),
        in_stock BOOLEAN DEFAULT TRUE
    )
""")
conn.commit()

# Insert a record
db.execute(
    "INSERT INTO products (name, price) VALUES (%s, %s)",
    ("Widget", 19.99)
)
conn.commit()

# Query records
db.execute("SELECT * FROM products WHERE in_stock = %s", (True,))
products = db.fetchall()

Important: PostgreSQL uses %s for parameter placeholders, while SQLite uses ?.


Connections.C_redis(host, port, password, socket_timeout)

Creates a connection to a Redis server and returns a Redis client instance.

Details
Parameters
host (str) Redis server host (default: "localhost")
port (int) Redis server port (default: 6379)
password (str or None) Redis password (default: None)
socket_timeout (int) Connection timeout in seconds (default: 5)
Returns redis.Redis client instance (with decode_responses=True)
Requires redis package (pip install redis)

Examples:

from Ol_Utills import Connections

# Connect to Redis with defaults
r = Connections.C_redis()

# Connect with custom settings
r = Connections.C_redis(
    host="redis.example.com",
    port=6380,
    password="my_redis_pass",
    socket_timeout=10
)

# Use the Redis client
r.set("greeting", "hello")
print(r.get("greeting"))  # "hello"

r.incr("counter")
print(r.get("counter"))   # "1"

security โ€” Security Utilities

The security class provides essential security tools: Redis-backed rate limiting, input/file sanitization, and bcrypt password hashing with verification.

graph LR
    S["๐Ÿ” security"] --> RL["@rate_limit"]
    S --> SN["Sanitizes"]
    S --> HS["hash"]
    S --> VR["verify"]

    RL --> RL1["Redis-backed"]
    RL --> RL2["Per-IP tracking"]
    RL --> RL3["429 on exceed"]

    SN --> SN1["File sanitization"]
    SN --> SN2["Text sanitization"]

    HS --> HS1["bcrypt hashing"]
    VR --> VR1["bcrypt verification"]

    style S fill:#e11d48,stroke:#be123c,color:#fff
    style RL fill:#f97316,stroke:#ea580c,color:#fff
    style SN fill:#8b5cf6,stroke:#7c3aed,color:#fff
    style HS fill:#0891b2,stroke:#0e7490,color:#fff
    style VR fill:#059669,stroke:#047857,color:#fff

@security.rate_limit(max_requests, window_seconds, r)

A decorator that adds Redis-backed rate limiting to Flask routes. Tracks requests per client IP address.

Details
Parameters
max_requests (int) Maximum allowed requests per window (default: 20)
window_seconds (int) Time window in seconds (default: 60)
r (Redis client or None) Optional Redis client; auto-connects via Connections.C_redis() if None
On Limit Exceeded Returns 429 Too Many Requests JSON response
Requires A running Redis server

Example:

from flask import Flask
from Ol_Utills import security, Connections

app = Flask(__name__)

# Using default settings (20 requests per 60 seconds, auto Redis connection)
@app.route('/api/data')
@security.rate_limit()
def get_data():
    return {"data": "some data"}

# Custom limits with explicit Redis connection
r = Connections.C_redis(host="redis.example.com")

@app.route('/api/sensitive')
@security.rate_limit(max_requests=5, window_seconds=30, r=r)
def sensitive_endpoint():
    return {"data": "sensitive data"}

How It Works:

Step Action
1 Client IP is extracted from the request
2 A Redis counter for that IP is incremented
3 On first request, a TTL (time-to-live) is set on the key
4 If the counter exceeds max_requests, a 429 response is returned
5 After the window expires, the counter resets automatically

Note: If Redis is unavailable, the decorator gracefully falls through and allows the request.


security.Sanitizes(type, file, text)

Strips HTML tags from files or text input to prevent XSS and injection attacks.

Details
Parameters
type (str) "file" to sanitize a file, or any other value for text sanitization
file (str or None) File path to sanitize (required when type="file")
text (str) Text input to sanitize (default: "text")
Returns File path (str) if file mode, sanitized text (str) if text mode

Examples:

from Ol_Utills import security

# Sanitize text input
clean = security.Sanitizes('text', text='Hello <script>alert("xss")</script> World')
print(clean)  # "Hello alert("xss") World"

# Sanitize a file in-place
security.Sanitizes('file', file='user_upload.csv')
# Removes all HTML tags from the file content and rewrites it

security.hash(password)

Hashes a password using bcrypt with an auto-generated salt.

Details
Parameter password (str) โ€” The plaintext password to hash
Returns bytes โ€” The bcrypt hashed password
Requires bcrypt package (pip install bcrypt)

Example:

from Ol_Utills import security

hashed = security.hash("MySecureP@ss1")
print(hashed)  # b'$2b$12$...'

# Store `hashed` in your database

security.verify(password, hashed)

Verifies a plaintext password against a bcrypt hash.

Details
Parameters password (str) โ€” The plaintext password to check
hashed (bytes) โ€” The bcrypt hash to compare against
Returns True if the password matches, False otherwise
Requires bcrypt package (pip install bcrypt)

Example:

from Ol_Utills import security

hashed = security.hash("MySecureP@ss1")

# โœ… Correct password
security.verify("MySecureP@ss1", hashed)    # True

# โŒ Wrong password
security.verify("WrongPassword1", hashed)   # False

Full Registration/Login Flow:

from flask import Flask, request, jsonify
from Ol_Utills import security, Connections, val

app = Flask(__name__)
conn, db = Connections.sqlite("app.db")

@app.route('/register', methods=['POST'])
def register():
    password = request.form.get('password')

    if not val.chk_p(password):
        return jsonify({"error": "Weak password"}), 400

    hashed = security.hash(password)
    db.execute("INSERT INTO users (password) VALUES (?)", (hashed,))
    conn.commit()
    return jsonify({"message": "Registered"}), 201

@app.route('/login', methods=['POST'])
def login():
    password = request.form.get('password')
    db.execute("SELECT password FROM users WHERE id = 1")
    stored_hash = db.fetchone()[0]

    if security.verify(password, stored_hash):
        return jsonify({"message": "Login successful"})
    return jsonify({"error": "Invalid credentials"}), 401

๐Ÿ”ง Full Flask App Example

A complete example showing all library features working together:

sequenceDiagram
    participant C as ๐ŸŒ Client
    participant F as ๐Ÿ Flask App
    participant V as ๐Ÿ”’ val
    participant D as ๐Ÿ—„๏ธ Connections
    participant S as ๐Ÿ›ก๏ธ session
    participant R as ๐Ÿ”ด Redis
    participant B as ๐Ÿ” bcrypt

    Note over C,B: Registration Flow
    C->>F: POST /register
    F->>V: val.chk_e(email)
    V-->>F: True / None
    F->>V: val.chk_p(password)
    V-->>F: True / None
    F->>B: security.hash(password)
    B-->>F: hashed password
    F->>D: Connections.sqlite("app.db")
    D-->>F: (conn, cursor)
    F->>D: INSERT INTO users
    F-->>C: 201 Created

    Note over C,B: Login Flow
    C->>F: POST /login
    F->>R: rate_limit check
    R-->>F: allowed โœ…
    F->>D: SELECT FROM users
    D-->>F: user record
    F->>B: security.verify(password, hash)
    B-->>F: True โœ…
    F->>S: session["logged"] = True
    F-->>C: Login successful

    Note over C,B: Protected Route
    C->>F: GET /dashboard
    F->>R: rate_limit check
    R-->>F: allowed โœ…
    F->>S: Check session["logged"]
    S-->>F: True โœ…
    F-->>C: Dashboard data
from flask import Flask, session, request, jsonify
from Ol_Utills import val, req, res, Connections, security

app = Flask(__name__)
app.secret_key = 'your-secret-key-here'

# Initialize database
conn, db = Connections.sqlite("app.db")
db.execute("""
    CREATE TABLE IF NOT EXISTS users (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        username TEXT UNIQUE,
        email TEXT,
        password BLOB,
        is_admin BOOLEAN DEFAULT 0
    )
""")
conn.commit()


@app.route('/register', methods=['POST'])
def register():
    email = request.form.get('email')
    password = request.form.get('password')
    username = request.form.get('username')

    # Validate email
    if not val.chk_e(email):
        return res.error_response("Invalid email format", 400)

    # Validate password strength
    if not val.chk_p(password):
        return res.error_response(
            "Password must be 7+ chars with uppercase, lowercase, and a digit", 400
        )

    # Hash password before storing
    hashed = security.hash(password)

    # Insert user into database
    try:
        db.execute(
            "INSERT INTO users (username, email, password) VALUES (?, ?, ?)",
            (username, email, hashed)
        )
        conn.commit()
    except Exception as e:
        return res.error_response(str(e), 500)

    return res.success_response({"message": "User registered successfully"})


@app.route('/login', methods=['POST'])
@security.rate_limit(max_requests=10, window_seconds=60)
def login():
    username = request.form.get('username')
    password = request.form.get('password')

    db.execute("SELECT * FROM users WHERE username = ?", (username,))
    user = db.fetchone()

    if user and security.verify(password, user[3]):
        session['logged'] = True
        session['username'] = username
        if user[4]:  # is_admin column
            session['admin'] = True
        return res.success_response({"message": "Login successful"})

    return res.error_response("Invalid credentials", 401)


@app.route('/dashboard')
@req.login_required
def dashboard():
    return res.success_response({
        "message": f"Welcome, {session.get('username')}!",
        "role": "admin" if session.get('admin') else "user"
    })


@app.route('/admin/panel')
@req.admin_required
def admin_panel():
    db.execute("SELECT id, username, email FROM users")
    users = db.fetchall()
    return res.success_response({"users": users})


@app.route('/logout')
def logout():
    session.clear()
    return res.success_response({"message": "Logged out"})


if __name__ == '__main__':
    app.run(debug=True)

๐Ÿงช Running Tests

cd tests
python test.py

๐Ÿค Contributing

Contributions are welcome! Here's how to get started:

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

๐Ÿ“„ License

Distributed under the MIT License. See LICENSE for more information.


Made with โค๏ธ by OverLimit (OL)

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ol_utills-0.7.1.tar.gz (28.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ol_utills-0.7.1-py3-none-any.whl (13.2 kB view details)

Uploaded Python 3

File details

Details for the file ol_utills-0.7.1.tar.gz.

File metadata

  • Download URL: ol_utills-0.7.1.tar.gz
  • Upload date:
  • Size: 28.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for ol_utills-0.7.1.tar.gz
Algorithm Hash digest
SHA256 0b01677a8c52f4af4e3fbb63343df35c24c63d411575dc94f4a02736cd0d9a7e
MD5 45ec52afce2b7e5df789d47bd2559672
BLAKE2b-256 2166d469c7dd81141abaeff2b1219846f7175fc1912c837b4562278b28864dca

See more details on using hashes here.

Provenance

The following attestation bundles were made for ol_utills-0.7.1.tar.gz:

Publisher: publish.yml on OverLimit-OL/Ol_Utills

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ol_utills-0.7.1-py3-none-any.whl.

File metadata

  • Download URL: ol_utills-0.7.1-py3-none-any.whl
  • Upload date:
  • Size: 13.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for ol_utills-0.7.1-py3-none-any.whl
Algorithm Hash digest
SHA256 cba5f43ac95cd39bed61ad7e7efac2bea4a7cca3df973ef60cc02f1e28228998
MD5 1ba216aeeb71e920ddbcd7169ad6b33f
BLAKE2b-256 3d53f1e21c0cdc81a5c76d7bc4368a4adb5db8adae772bb15752da0650168c5a

See more details on using hashes here.

Provenance

The following attestation bundles were made for ol_utills-0.7.1-py3-none-any.whl:

Publisher: publish.yml on OverLimit-OL/Ol_Utills

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page