scar-chat/DATABASE.md

6.6 KiB

SCAR Chat - Database Documentation

Overview

The SCAR Chat server now includes a SQLite3 database system for user authentication and management. All passwords are securely stored using SHA256 hashing with per-user salt values.

Database Schema

Users Table

CREATE TABLE users(
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    username TEXT UNIQUE NOT NULL,
    password_hash TEXT NOT NULL,
    salt TEXT NOT NULL,
    email TEXT,
    role TEXT DEFAULT 'user',
    is_active BOOLEAN DEFAULT 1,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

Fields:

  • id: Unique user identifier
  • username: Unique username (required, no spaces allowed)
  • password_hash: SHA256(password + salt) in hexadecimal format
  • salt: 16-character random salt unique to each user
  • email: Optional email address
  • role: User role - user, admin, or moderator
  • is_active: Boolean flag for account status (0=inactive, 1=active)
  • created_at: Account creation timestamp
  • updated_at: Last update timestamp

Security Features

Password Hashing

Passwords are hashed using SHA256 with a unique salt for each user:

hash = SHA256(password + salt)

Why this approach?

  • SHA256 is widely tested and cryptographically secure
  • Per-user salt prevents rainbow table attacks
  • Even if database is compromised, passwords are not recoverable

Security Note: In production, consider using bcrypt or Argon2 for additional computational cost and timing attack resistance.

Minimum Requirements

  • Username: Unique, required
  • Password: Minimum 8 characters (enforced in code)
  • Email: Optional but recommended for account recovery

Database Manager Tool

The dbmanager executable provides command-line user management.

Building

cd build
make dbmanager

Commands

Register a New User

./dbmanager register <username> <password> [email] [role]

Examples:

# Register regular user
./dbmanager register john password123 john@example.com user

# Register admin
./dbmanager register admin SecureP@ss123 admin@scar.local admin

# Register moderator
./dbmanager register moderator ModPass456 mod@scar.local moderator

Authenticate User

./dbmanager authenticate <username> <password>

Example:

./dbmanager authenticate john password123

List All Users

./dbmanager list

Output:

================================================================================
Username        Email                   Role            Status
================================================================================
admin           admin@scar.local        admin           Active
john            john@example.com        user            Active
moderator       mod@scar.local          moderator       Active
================================================================================

List Users by Role

./dbmanager list-role <role>

Example:

./dbmanager list-role admin

Update User Role

./dbmanager setrole <username> <role>

Example:

./dbmanager setrole john admin

Deactivate User

./dbmanager deactivate <username>

Example:

./dbmanager deactivate john

Activate User

./dbmanager activate <username>

Example:

./dbmanager activate john

Using Database in Server Code

Initialize Database

#include "database.h"

Database db("scar_chat.db");
if (!db.initialize()) {
    std::cerr << "Failed to initialize database" << std::endl;
    return 1;
}

Register User

if (db.register_user("alice", "password123", "alice@example.com", "user")) {
    std::cout << "User registered successfully" << std::endl;
}

Authenticate User

if (db.authenticate_user("alice", "password123")) {
    std::cout << "Authentication successful" << std::endl;
} else {
    std::cout << "Authentication failed" << std::endl;
}

Get User Information

User user = db.get_user("alice");
if (!user.username.empty()) {
    std::cout << "Found user: " << user.username << " (role: " << user.role << ")" << std::endl;
}

Get All Users

std::vector<User> users = db.get_all_users();
for (const auto &user : users) {
    std::cout << user.username << " - " << user.role << std::endl;
}

Get Users by Role

std::vector<User> admins = db.get_users_by_role("admin");
for (const auto &admin : admins) {
    std::cout << admin.username << std::endl;
}

Update User Role

if (db.update_user_role("bob", "moderator")) {
    std::cout << "User role updated" << std::endl;
}

Deactivate/Activate User

db.deactivate_user("bob");  // Disable account
db.activate_user("bob");    // Re-enable account

Database File Location

By default, the database is created as scar_chat.db in the current working directory.

To use a custom location:

Database db("/path/to/custom/scar_chat.db");
db.initialize();

Integration with Server

The database module is now compiled into chat_server. To integrate authentication:

  1. Initialize database on server startup
  2. Handle LOGIN:username:password messages from clients
  3. Validate credentials using authenticate_user()
  4. Store authenticated username with client session
  5. Validate user permissions for actions (based on role)

Troubleshooting

Database File Already Exists

  • The initialize() function checks for existing tables
  • Existing data is preserved; tables are only created if they don't exist

Password Too Short

  • Minimum 8 characters required
  • Error: "Password must be at least 8 characters long"

User Already Exists

  • Usernames are unique
  • Error: "User already exists"

Authentication Failed

  • Check username spelling (case-sensitive)
  • Verify password is correct
  • Confirm user account is active (not deactivated)

Database Cleanup

To reset the database (delete all data):

rm scar_chat.db

The next run of the database tool or server will create a fresh database with the schema.

Performance Considerations

  • SQLite3 is optimized for local file-based storage
  • Suitable for small to medium deployments (< 10K concurrent users)
  • For larger deployments, consider migrating to PostgreSQL or MySQL
  • Database operations are fast (typical query < 1ms)

Future Enhancements

  • Session tokens and JWT authentication
  • Password reset functionality
  • User profile customization
  • Activity logging and audit trails
  • Rate limiting per user
  • Two-factor authentication