2025-08-03 21:53:15 -04:00
|
|
|
#pragma once
|
|
|
|
|
#include <string>
|
2025-08-10 07:55:39 -04:00
|
|
|
#include <functional>
|
2025-08-03 21:53:15 -04:00
|
|
|
#include <memory>
|
2026-01-05 22:54:27 -05:00
|
|
|
#include <optional>
|
2025-08-10 07:55:39 -04:00
|
|
|
#include <jwt-cpp/jwt.h>
|
|
|
|
|
#include <bcrypt/BCrypt.hpp>
|
2025-08-03 21:53:15 -04:00
|
|
|
|
|
|
|
|
struct UserInfo {
|
2025-08-10 07:55:39 -04:00
|
|
|
int64_t id = 0;
|
2025-08-03 21:53:15 -04:00
|
|
|
std::string username;
|
2025-08-10 07:55:39 -04:00
|
|
|
bool isAdmin = false;
|
2026-01-05 22:54:27 -05:00
|
|
|
bool isModerator = false; // Site-wide moderator role
|
2025-08-10 07:55:39 -04:00
|
|
|
bool isStreamer = false;
|
2026-01-05 22:54:27 -05:00
|
|
|
bool isRestreamer = false;
|
|
|
|
|
bool isBot = false;
|
|
|
|
|
bool isTexter = false;
|
2025-08-10 07:55:39 -04:00
|
|
|
bool isPgpOnly = false;
|
2026-01-05 22:54:27 -05:00
|
|
|
bool isDisabled = false; // SECURITY FIX #26: Track disabled status
|
2025-08-03 21:53:15 -04:00
|
|
|
std::string bio;
|
|
|
|
|
std::string avatarUrl;
|
2026-01-05 22:54:27 -05:00
|
|
|
std::string bannerUrl;
|
|
|
|
|
int bannerPosition = 50; // Y position percentage (0-100) for object-position
|
|
|
|
|
int bannerZoom = 100; // Zoom percentage (100-200)
|
|
|
|
|
int bannerPositionX = 50; // X position percentage (0-100) for object-position
|
|
|
|
|
std::string graffitiUrl;
|
2025-08-03 21:53:15 -04:00
|
|
|
std::string pgpOnlyEnabledAt;
|
2025-08-10 07:55:39 -04:00
|
|
|
std::string colorCode;
|
2026-01-05 22:54:27 -05:00
|
|
|
double ubercoinBalance = 0.0; // Übercoin balance (3 decimal places)
|
|
|
|
|
std::string createdAt; // Account creation date (for burn rate calculation)
|
|
|
|
|
int tokenVersion = 1; // SECURITY FIX #10: Token version for revocation
|
|
|
|
|
};
|
|
|
|
|
|
2026-01-07 02:14:34 -05:00
|
|
|
// Result structure for refresh token operations
|
|
|
|
|
struct RefreshTokenResult {
|
|
|
|
|
bool success = false;
|
|
|
|
|
std::string error;
|
|
|
|
|
std::string accessToken;
|
|
|
|
|
std::string refreshToken;
|
|
|
|
|
std::string familyId;
|
|
|
|
|
UserInfo user;
|
|
|
|
|
};
|
|
|
|
|
|
2026-01-05 22:54:27 -05:00
|
|
|
// Chat service compatibility struct
|
|
|
|
|
struct UserClaims {
|
|
|
|
|
std::string userId;
|
|
|
|
|
std::string username;
|
|
|
|
|
std::string userColor;
|
|
|
|
|
bool isAdmin;
|
|
|
|
|
bool isModerator; // Site-wide moderator role
|
|
|
|
|
bool isStreamer;
|
|
|
|
|
bool isRestreamer;
|
|
|
|
|
|
|
|
|
|
UserClaims() : isAdmin(false), isModerator(false), isStreamer(false), isRestreamer(false) {}
|
2025-08-03 21:53:15 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class AuthService {
|
|
|
|
|
public:
|
|
|
|
|
static AuthService& getInstance() {
|
|
|
|
|
static AuthService instance;
|
|
|
|
|
return instance;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void registerUser(const std::string& username, const std::string& password,
|
|
|
|
|
const std::string& publicKey, const std::string& fingerprint,
|
2025-08-10 07:55:39 -04:00
|
|
|
std::function<void(bool, const std::string&, int64_t)> callback);
|
2025-08-03 21:53:15 -04:00
|
|
|
|
|
|
|
|
void loginUser(const std::string& username, const std::string& password,
|
2025-08-10 07:55:39 -04:00
|
|
|
std::function<void(bool, const std::string&, const UserInfo&)> callback);
|
2025-08-03 21:53:15 -04:00
|
|
|
|
|
|
|
|
void initiatePgpLogin(const std::string& username,
|
2025-08-10 07:55:39 -04:00
|
|
|
std::function<void(bool, const std::string&, const std::string&)> callback);
|
2025-08-03 21:53:15 -04:00
|
|
|
|
2025-08-10 07:55:39 -04:00
|
|
|
void verifyPgpLogin(const std::string& username, const std::string& signature,
|
|
|
|
|
const std::string& challenge,
|
|
|
|
|
std::function<void(bool, const std::string&, const UserInfo&)> callback);
|
2025-08-03 21:53:15 -04:00
|
|
|
|
2025-08-10 07:55:39 -04:00
|
|
|
std::string generateToken(const UserInfo& user);
|
2025-08-03 21:53:15 -04:00
|
|
|
bool validateToken(const std::string& token, UserInfo& userInfo);
|
2026-01-05 22:54:27 -05:00
|
|
|
|
|
|
|
|
// Chat service compatibility method
|
|
|
|
|
std::optional<UserClaims> verifyToken(const std::string& token);
|
|
|
|
|
|
2026-01-07 02:14:34 -05:00
|
|
|
// Refresh token methods
|
|
|
|
|
void createRefreshTokenFamily(int64_t userId,
|
|
|
|
|
std::function<void(bool success, const std::string& refreshToken,
|
|
|
|
|
const std::string& familyId)> callback);
|
|
|
|
|
|
|
|
|
|
void validateAndRotateRefreshToken(const std::string& refreshToken,
|
|
|
|
|
std::function<void(RefreshTokenResult)> callback);
|
|
|
|
|
|
|
|
|
|
void revokeTokenFamily(const std::string& familyId,
|
|
|
|
|
std::function<void(bool success)> callback);
|
|
|
|
|
|
|
|
|
|
void revokeAllUserTokenFamilies(int64_t userId,
|
|
|
|
|
std::function<void(bool success)> callback);
|
|
|
|
|
|
2025-08-10 07:55:39 -04:00
|
|
|
// New method to fetch complete user info including color
|
|
|
|
|
void fetchUserInfo(int64_t userId, std::function<void(bool, const UserInfo&)> callback);
|
2025-08-03 21:53:15 -04:00
|
|
|
|
2025-08-10 07:55:39 -04:00
|
|
|
void updatePassword(int64_t userId, const std::string& oldPassword,
|
|
|
|
|
const std::string& newPassword,
|
|
|
|
|
std::function<void(bool, const std::string&)> callback);
|
2025-08-03 21:53:15 -04:00
|
|
|
|
2025-08-10 07:55:39 -04:00
|
|
|
void updateUserColor(int64_t userId, const std::string& newColor,
|
|
|
|
|
std::function<void(bool, const std::string&, const std::string&)> callback);
|
|
|
|
|
|
|
|
|
|
void generateUniqueColor(std::function<void(const std::string& color)> callback);
|
2025-08-03 21:53:15 -04:00
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
AuthService() = default;
|
|
|
|
|
std::string jwtSecret_;
|
2026-01-05 22:54:27 -05:00
|
|
|
|
2025-08-10 07:55:39 -04:00
|
|
|
bool validatePassword(const std::string& password, std::string& error);
|
2026-01-05 22:54:27 -05:00
|
|
|
void validateAndLoadJwtSecret(); // SECURITY FIX #5
|
2026-01-07 02:14:34 -05:00
|
|
|
|
|
|
|
|
// Refresh token helpers
|
|
|
|
|
std::string generateRefreshToken(); // Generates random 256-bit token
|
|
|
|
|
std::string hashToken(const std::string& token); // SHA256 hash for storage
|
|
|
|
|
std::string generateUUID(); // Generate UUID for family_id
|
|
|
|
|
|
|
|
|
|
static constexpr int ACCESS_TOKEN_EXPIRY_MINUTES = 150; // 2.5 hours (gives buffer for 2-hour refresh)
|
|
|
|
|
static constexpr int REFRESH_TOKEN_EXPIRY_DAYS = 90;
|
2025-08-03 21:53:15 -04:00
|
|
|
};
|