Commit a1ab21b5 authored by jan.koester's avatar jan.koester
Browse files

deb



Co-authored-by: default avatarCopilot <copilot@github.com>
parent cbe6d73d
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
mediadb (20260424+73) unstable; urgency=medium

  * Performance: use authdb ConnectionPool for is_authorized(), check_gpo(),
    repopulate_session() and list_groups — eliminates TCP connection setup
    per request.
  * Performance: session lookups now validate TTL inline, preventing stale
    sessions from being treated as valid.
  * Performance: add domain_label_index_ for O(1) find_domain_by_label()
    instead of linear scan across all stores.

 -- Jan Koester <jan.koester@tuxist.de>  Thu, 24 Apr 2026 00:00:00 +0200

mediadb (20260423+72) unstable; urgency=medium

  * Preview: flush FFmpeg decoder after read loop so codecs that buffer
+41 −22
Original line number Diff line number Diff line
@@ -200,7 +200,10 @@ std::string App::get_session_username(const HttpRequest& req) const {
    const std::string token = value.substr(prefix.size());
    std::lock_guard<std::mutex> lk(session_mutex_);
    auto sit = sessions_.find(token);
    return sit != sessions_.end() ? sit->second.username : std::string{};
    if (sit == sessions_.end()) return {};
    if (std::chrono::steady_clock::now() - sit->second.created_at > std::chrono::seconds(SESSION_TTL_SECONDS))
        return {};
    return sit->second.username;
}

std::string App::get_session_domain(const HttpRequest& req) const {
@@ -212,7 +215,10 @@ std::string App::get_session_domain(const HttpRequest& req) const {
    const std::string token = value.substr(prefix.size());
    std::lock_guard<std::mutex> lk(session_mutex_);
    auto sit = sessions_.find(token);
    return sit != sessions_.end() ? sit->second.domain_label : std::string{};
    if (sit == sessions_.end()) return {};
    if (std::chrono::steady_clock::now() - sit->second.created_at > std::chrono::seconds(SESSION_TTL_SECONDS))
        return {};
    return sit->second.domain_label;
}

std::vector<std::string> App::get_session_groups(const HttpRequest& req) const {
@@ -224,7 +230,10 @@ std::vector<std::string> App::get_session_groups(const HttpRequest& req) const {
    const std::string token = value.substr(prefix.size());
    std::lock_guard<std::mutex> lk(session_mutex_);
    auto sit = sessions_.find(token);
    return sit != sessions_.end() ? sit->second.group_ids : std::vector<std::string>{};
    if (sit == sessions_.end()) return {};
    if (std::chrono::steady_clock::now() - sit->second.created_at > std::chrono::seconds(SESSION_TTL_SECONDS))
        return {};
    return sit->second.group_ids;
}

std::vector<std::string> App::resolve_session_groups(authdb::client::Client& client) {
@@ -255,17 +264,13 @@ void App::repopulate_session(const HttpRequest& req) {
    const std::string token = value.substr(prefix.size());
    try {
        uuid::uuid session_id(token);
        authdb::client::ClientConnection con;
        con.setUrl(auth_.url());
        con.setClientName(auth_.client_name());
        con.setClientSecret(auth_.client_secret());
        con.setSessionID(session_id);
        authdb::client::Client client(con);
        if (!client.ClientAuth()) return;
        auto pooled = auth_.pool().acquire();
        pooled.setSessionID(session_id);
        if (!pooled.client().ClientAuth()) return;
        authdb::SessionData sdat;
        client.SessionInfo(sdat);
        pooled.client().SessionInfo(sdat);
        std::string username = sdat.getUsername() ? sdat.getUsername() : "";
        auto grps = resolve_session_groups(client);
        auto grps = resolve_session_groups(pooled.client());
        store_session(token, username, {}, grps);
    } catch (...) {
        store_session(token, "");
@@ -280,7 +285,11 @@ bool App::is_session_known(const HttpRequest& req) const {
    if (value.size() <= prefix.size() || value.compare(0, prefix.size(), prefix) != 0) return false;
    const std::string token = value.substr(prefix.size());
    std::lock_guard<std::mutex> lk(session_mutex_);
    return sessions_.find(token) != sessions_.end();
    auto sit = sessions_.find(token);
    if (sit == sessions_.end()) return false;
    if (std::chrono::steady_clock::now() - sit->second.created_at > std::chrono::seconds(SESSION_TTL_SECONDS))
        return false;
    return true;
}

bool App::is_any_authorized(const HttpRequest& req) {
@@ -1260,25 +1269,35 @@ HttpResponse App::handle_list_groups(const HttpRequest& req) {
    const std::string domain = get_session_domain(req);

    try {
        authdb::client::ClientConnection con;

        if (!domain.empty()) {
            auto dom = db_.find_domain_by_label(domain);
            if (!dom) return error_json(404, "unknown domain: " + domain);
            // Domain-specific connection — not pooled
            authdb::client::ClientConnection con;
            con.setUrl(dom->url);
            con.setClientName(dom->client_name);
            con.setClientSecret(dom->client_secret);
        } else {
            con.setUrl(auth_.url());
            con.setClientName(auth_.client_name());
            con.setClientSecret(auth_.client_secret());
        }

            authdb::client::Client client(con);
            if (!client.ClientAuth())
                return error_json(500, "client authentication failed");

            auto groups = client.listGroups();
            json_object* arr = json_object_new_array();
            for (const auto& g : groups) {
                json_object* jgrp = json_object_new_object();
                json_object_object_add(jgrp, "gid", json_object_new_string(g.gid.c_str()));
                json_object_object_add(jgrp, "name", json_object_new_string(g.name.c_str()));
                json_object_array_add(arr, jgrp);
            }
            json_object* wrap = json_object_new_object();
            json_object_object_add(wrap, "groups", arr);
            return HttpResponse::json(200, wrap);
        }

        auto pooled = auth_.pool().acquire();
        if (!pooled.client().ClientAuth())
            return error_json(500, "client authentication failed");

        auto groups = pooled.client().listGroups();

        json_object* arr = json_object_new_array();
        for (const auto& g : groups) {
+9 −30
Original line number Diff line number Diff line
@@ -10,7 +10,8 @@ AuthService::AuthService(const std::string& authdb_url,
                         const std::string& client_secret)
    : authdb_url_(authdb_url),
      client_name_(client_name),
      client_secret_(client_secret) {}
      client_secret_(client_secret),
      pool_(authdb_url, client_name, client_secret) {}

void AuthService::try_init_policies(authdb::client::Client& client, const std::string& domain_key) {
    {
@@ -93,21 +94,10 @@ bool AuthService::is_authorized(const HttpRequest& req) const {
    try {
        uuid::uuid session_id(token);

        authdb::client::ClientConnection con;
        con.setUrl(authdb_url_);
        con.setClientName(client_name_);
        con.setClientSecret(client_secret_);
        con.setSessionID(session_id);
        auto pooled = pool_.acquire();
        pooled.setSessionID(session_id);

        std::unique_ptr<authdb::client::Client> client;
        try {
            client = std::make_unique<authdb::client::Client>(con);
        } catch (...) {
            con.reConnect();
            client = std::make_unique<authdb::client::Client>(con);
        }

        bool ok = client->ClientAuth();
        bool ok = pooled.client().ClientAuth();
        if (ok) cache_token(token);
        return ok;
    } catch (const authdb::AuthBackendError&) {
@@ -133,22 +123,11 @@ bool AuthService::check_gpo(const HttpRequest& req, const char* gpo_id) const {
        uuid::uuid session_id(token);
        uuid::uuid gpoid(gpo_id);

        authdb::client::ClientConnection con;
        con.setUrl(authdb_url_);
        con.setClientName(client_name_);
        con.setClientSecret(client_secret_);
        con.setSessionID(session_id);

        std::unique_ptr<authdb::client::Client> client;
        try {
            client = std::make_unique<authdb::client::Client>(con);
        } catch (...) {
            con.reConnect();
            client = std::make_unique<authdb::client::Client>(con);
        }
        auto pooled = pool_.acquire();
        pooled.setSessionID(session_id);

        if (!client->ClientAuth()) return false;
        return client->GPOcheck(gpoid);
        if (!pooled.client().ClientAuth()) return false;
        return pooled.client().GPOcheck(gpoid);
    } catch (...) {
        return false;
    }
+2 −0
Original line number Diff line number Diff line
@@ -59,6 +59,7 @@ public:
    const std::string& url() const { return authdb_url_; }
    const std::string& client_name() const { return client_name_; }
    const std::string& client_secret() const { return client_secret_; }
    authdb::client::ConnectionPool& pool() const { return pool_; }

private:
    std::string authdb_url_;
@@ -66,6 +67,7 @@ private:
    std::string client_secret_;
    mutable std::mutex gpo_mutex_;
    std::set<std::string> gpo_initialized_domains_;
    mutable authdb::client::ConnectionPool pool_;

    // Session cache: token -> expiry time
    static constexpr int CACHE_TTL_SECONDS = 300; // 5 minutes
+24 −4
Original line number Diff line number Diff line
@@ -101,6 +101,9 @@ bool BinDb::delete_store(const std::string& id) {
        std::unique_lock lock(mutex_);
        auto it = stores_.find(id);
        if (it == stores_.end()) return false;
        for (const auto& d : it->second.auth_domains) {
            domain_label_index_.erase(d.label);
        }
        for (const auto& aid : it->second.album_ids) {
            auto ait = albums_.find(aid);
            if (ait != albums_.end()) {
@@ -140,6 +143,7 @@ std::string BinDb::add_store_domain(const std::string& store_id, AuthDomain doma
        if (it == stores_.end()) return {};
        domain.id = make_uuid();
        did = domain.id;
        domain_label_index_[domain.label] = {store_id, domain.id};
        it->second.auth_domains.push_back(std::move(domain));
        save_index_locked();
    }
@@ -155,6 +159,7 @@ bool BinDb::remove_store_domain(const std::string& store_id, const std::string&
        auto dit = std::find_if(domains.begin(), domains.end(),
                                [&](const AuthDomain& d) { return d.id == domain_id; });
        if (dit == domains.end()) return false;
        domain_label_index_.erase(dit->label);
        domains.erase(dit);
        save_index_locked();
    }
@@ -170,10 +175,12 @@ std::vector<AuthDomain> BinDb::list_store_domains(const std::string& store_id) c

std::optional<AuthDomain> BinDb::find_domain_by_label(const std::string& label) const {
    std::shared_lock lock(mutex_);
    for (const auto& [sid, store] : stores_) {
        for (const auto& d : store.auth_domains) {
            if (d.label == label) return d;
        }
    auto it = domain_label_index_.find(label);
    if (it == domain_label_index_.end()) return std::nullopt;
    auto sit = stores_.find(it->second.first);
    if (sit == stores_.end()) return std::nullopt;
    for (const auto& d : sit->second.auth_domains) {
        if (d.id == it->second.second) return d;
    }
    return std::nullopt;
}
@@ -1621,10 +1628,12 @@ void BinDb::reload() {
    albums_.clear();
    media_.clear();
    mmaps_.clear();
    domain_label_index_.clear();
    load_index();
    for (auto& [sid, store] : stores_) {
        load_store(sid, store);
    }
    rebuild_domain_label_index_locked();
    mmap_all_stores();
}

@@ -1652,9 +1661,19 @@ void BinDb::load() {
    for (auto& [sid, store] : stores_) {
        load_store(sid, store);
    }
    rebuild_domain_label_index_locked();
    mmap_all_stores();
}

void BinDb::rebuild_domain_label_index_locked() {
    domain_label_index_.clear();
    for (const auto& [sid, store] : stores_) {
        for (const auto& d : store.auth_domains) {
            domain_label_index_[d.label] = {sid, d.id};
        }
    }
}

void BinDb::load_index() {
    std::ifstream in(index_file(), std::ios::binary);
    if (!in.is_open()) return;
@@ -2267,6 +2286,7 @@ void BinDb::load_index_from_buffer(const std::vector<std::uint8_t>& data) {
    // Deletes propagate explicitly via delete_store() + cluster_.remove();
    // removing here would wipe out recently-created local stores when the
    // synced index is stale (same merge-only approach as authdb).
    rebuild_domain_label_index_locked();
}

std::vector<std::uint8_t> BinDb::save_store_to_buffer(const std::string& store_id) {
Loading