feat: initialize database schema and implement core Radius entities, EF context, and account enforcement service.
Build and Push Docker Image to Gitea Container Registry / build-and-push (push) Successful in 1m12s

This commit is contained in:
Tygozwolle
2026-07-24 17:51:04 +02:00
parent 9c2cbfa7b9
commit 63b9a97cdf
5 changed files with 126 additions and 14 deletions
+55
View File
@@ -131,3 +131,58 @@ INSERT INTO system_settings (key, value) VALUES ('default_data_limit', '500') ON
-- System settings initialized on startup
-- Admin user is created by administrator during first startup via the web interface
-- Dedicated table for robust, per-user data tracking that survives AP counter resets
CREATE TABLE IF NOT EXISTS guest_data_usage (
username VARCHAR(64) PRIMARY KEY,
total_input_octets BIGINT NOT NULL DEFAULT 0,
total_output_octets BIGINT NOT NULL DEFAULT 0
);
-- Trigger function to safely accumulate data usage from radacct
CREATE OR REPLACE FUNCTION update_guest_data_usage()
RETURNS TRIGGER AS $$
DECLARE
delta_input BIGINT := 0;
delta_output BIGINT := 0;
BEGIN
-- Handle INSERT (new session)
IF (TG_OP = 'INSERT') THEN
delta_input := COALESCE(NEW.acctinputoctets, 0);
delta_output := COALESCE(NEW.acctoutputoctets, 0);
-- Handle UPDATE (interim updates)
ELSIF (TG_OP = 'UPDATE') THEN
-- Only add if the new value is greater than the old value (protects against counter resets)
IF (COALESCE(NEW.acctinputoctets, 0) > COALESCE(OLD.acctinputoctets, 0)) THEN
delta_input := NEW.acctinputoctets - COALESCE(OLD.acctinputoctets, 0);
ELSIF (COALESCE(NEW.acctinputoctets, 0) < COALESCE(OLD.acctinputoctets, 0)) THEN
-- Counter reset mid-session! Just add the new value as the delta.
delta_input := COALESCE(NEW.acctinputoctets, 0);
END IF;
IF (COALESCE(NEW.acctoutputoctets, 0) > COALESCE(OLD.acctoutputoctets, 0)) THEN
delta_output := NEW.acctoutputoctets - COALESCE(OLD.acctoutputoctets, 0);
ELSIF (COALESCE(NEW.acctoutputoctets, 0) < COALESCE(OLD.acctoutputoctets, 0)) THEN
-- Counter reset mid-session!
delta_output := COALESCE(NEW.acctoutputoctets, 0);
END IF;
END IF;
-- Upsert the calculated deltas into the usage table per-user
IF (delta_input > 0 OR delta_output > 0) THEN
INSERT INTO guest_data_usage (username, total_input_octets, total_output_octets)
VALUES (NEW.username, delta_input, delta_output)
ON CONFLICT (username) DO UPDATE
SET total_input_octets = guest_data_usage.total_input_octets + EXCLUDED.total_input_octets,
total_output_octets = guest_data_usage.total_output_octets + EXCLUDED.total_output_octets;
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- Attach trigger to radacct table
DROP TRIGGER IF EXISTS trg_update_guest_data_usage ON radacct;
CREATE TRIGGER trg_update_guest_data_usage
AFTER INSERT OR UPDATE OF acctinputoctets, acctoutputoctets ON radacct
FOR EACH ROW EXECUTE FUNCTION update_guest_data_usage();