\q
--
-- PostgreSQL database dump
--

-- Dumped from database version 15.13
-- Dumped by pg_dump version 15.13

SET statement_timeout = 0;
SET lock_timeout = 0;
SET idle_in_transaction_session_timeout = 0;
SET client_encoding = 'UTF8';
SET standard_conforming_strings = on;
SELECT pg_catalog.set_config('search_path', '', false);
SET check_function_bodies = false;
SET xmloption = content;
SET client_min_messages = warning;
SET row_security = off;

--
-- Name: reseller_gateway; Type: SCHEMA; Schema: -; Owner: postgres
--

CREATE SCHEMA reseller_gateway;


ALTER SCHEMA reseller_gateway OWNER TO postgres;

--
-- Name: balance.get(); Type: FUNCTION; Schema: reseller_gateway; Owner: postgres
--

CREATE FUNCTION reseller_gateway."balance.get"() RETURNS numeric
    LANGUAGE plpgsql SECURITY DEFINER
    AS $$
DECLARE
    balance NUMERIC;
    v_user_id TEXT := reseller_inner.authenticate();
BEGIN
    RAISE LOG 'balance.get called for user_id: %', v_user_id;
    SELECT traffic_amount FROM reseller_inner.resellers WHERE user_id::TEXT = v_user_id INTO balance;
    IF balance IS NULL THEN
        RAISE sqlstate 'PT500' USING message = 'Failed to get balance';
    ELSE
        RAISE LOG 'balance.get successful: balance=% for user_id: %', balance, v_user_id;
        RETURN balance;
    END IF;
EXCEPTION
    WHEN OTHERS THEN
        RAISE WARNING 'balance.get error: %', SQLERRM;
        RAISE sqlstate 'PT500' USING message = 'Unexpected exception';
END $$;


ALTER FUNCTION reseller_gateway."balance.get"() OWNER TO postgres;

--
-- Name: balance.get_full(); Type: FUNCTION; Schema: reseller_gateway; Owner: postgres
--

CREATE FUNCTION reseller_gateway."balance.get_full"() RETURNS jsonb
    LANGUAGE plpgsql SECURITY DEFINER
    AS $$
DECLARE
    balance NUMERIC;
    v_user_id TEXT := reseller_inner.authenticate();
BEGIN
    RAISE LOG 'balance.get called for user_id: %', v_user_id;
    SELECT traffic_amount FROM reseller_inner.resellers WHERE user_id::TEXT = v_user_id INTO balance;
    IF balance IS NULL THEN
        RAISE sqlstate 'PT500' USING message = 'Failed to get balance';
    ELSE
        RAISE LOG 'balance.get successful: balance=% for user_id: %', balance, v_user_id;
        RETURN jsonb_build_object(
            'bytes', balance,
            'gb', reseller_inner.bytes_to_gb(balance),
            'formatted', reseller_inner.bytes_to_gb(balance) || ' GB'
        );
    END IF;
EXCEPTION
    WHEN OTHERS THEN
        RAISE WARNING 'balance.get_full error: %', SQLERRM;
        RAISE sqlstate 'PT500' USING message = 'Unexpected exception';
END $$;


ALTER FUNCTION reseller_gateway."balance.get_full"() OWNER TO postgres;

--
-- Name: common.location(common.dataimpulsepool); Type: FUNCTION; Schema: reseller_gateway; Owner: postgres
--

CREATE FUNCTION reseller_gateway."common.location"(pool common.dataimpulsepool) RETURNS jsonb
    LANGUAGE plpgsql SECURITY DEFINER
    AS $$
DECLARE
    v_user_id TEXT := reseller_inner.authenticate();
BEGIN
    RAISE LOG 'common.location called for pool: %', pool;
    RETURN dataimpulse.common_locations(pool);
EXCEPTION
    WHEN OTHERS THEN
        RAISE WARNING 'common.location error: %', SQLERRM;
        RAISE sqlstate 'PT500' USING message = 'Unexpected exception';
END $$;


ALTER FUNCTION reseller_gateway."common.location"(pool common.dataimpulsepool) OWNER TO postgres;

--
-- Name: common.location.asn(common.dataimpulsepool, text[], text[], text[], text[], text); Type: FUNCTION; Schema: reseller_gateway; Owner: postgres
--

CREATE FUNCTION reseller_gateway."common.location.asn"(pool common.dataimpulsepool, countries text[], states text[] DEFAULT '{}'::text[], cities text[] DEFAULT '{}'::text[], zipcodes text[] DEFAULT '{}'::text[], order_by text DEFAULT 'name,asc'::text) RETURNS jsonb
    LANGUAGE plpgsql SECURITY DEFINER
    AS $$
DECLARE
    v_user_id TEXT := reseller_inner.authenticate();
BEGIN
    RAISE LOG 'common.location.asn called with pool=%, countries=%', pool, countries;
    RETURN dataimpulse.get_proxy_asns(pool, countries, states, cities, zipcodes, order_by);
EXCEPTION
    WHEN OTHERS THEN
        RAISE WARNING 'common.location.asn error: %', SQLERRM;
        RAISE sqlstate 'PT500' USING message = 'Unexpected exception';
END $$;


ALTER FUNCTION reseller_gateway."common.location.asn"(pool common.dataimpulsepool, countries text[], states text[], cities text[], zipcodes text[], order_by text) OWNER TO postgres;

--
-- Name: common.location.city(common.dataimpulsepool, text[], text[], text[], text[], text); Type: FUNCTION; Schema: reseller_gateway; Owner: postgres
--

CREATE FUNCTION reseller_gateway."common.location.city"(pool common.dataimpulsepool, countries text[], states text[] DEFAULT '{}'::text[], zipcodes text[] DEFAULT '{}'::text[], asns text[] DEFAULT '{}'::text[], order_by text DEFAULT 'name,asc'::text) RETURNS jsonb
    LANGUAGE plpgsql SECURITY DEFINER
    AS $$
DECLARE
    v_user_id TEXT := reseller_inner.authenticate();
BEGIN
    RAISE LOG 'common.location.city called with pool=%, countries=%', pool, countries;
    RETURN dataimpulse.get_proxy_cities(pool, countries, states, zipcodes, asns, order_by);
EXCEPTION
    WHEN OTHERS THEN
        RAISE WARNING 'common.location.city error: %', SQLERRM;
        RAISE sqlstate 'PT500' USING message = 'Unexpected exception';
END $$;


ALTER FUNCTION reseller_gateway."common.location.city"(pool common.dataimpulsepool, countries text[], states text[], zipcodes text[], asns text[], order_by text) OWNER TO postgres;

--
-- Name: common.location.country(common.dataimpulsepool, text); Type: FUNCTION; Schema: reseller_gateway; Owner: postgres
--

CREATE FUNCTION reseller_gateway."common.location.country"(pool common.dataimpulsepool, order_by text DEFAULT 'name,asc'::text) RETURNS jsonb
    LANGUAGE plpgsql SECURITY DEFINER
    AS $$
DECLARE
    v_user_id TEXT := reseller_inner.authenticate();
BEGIN
    RAISE LOG 'common.location.country called with pool=%', pool;
    RETURN dataimpulse.get_proxy_countries(pool, order_by);
EXCEPTION
    WHEN OTHERS THEN
        RAISE WARNING 'common.location.country error: %', SQLERRM;
        RAISE sqlstate 'PT500' USING message = 'Unexpected exception';
END $$;


ALTER FUNCTION reseller_gateway."common.location.country"(pool common.dataimpulsepool, order_by text) OWNER TO postgres;

--
-- Name: common.location.state(common.dataimpulsepool, text[], text[], text[], text[], text); Type: FUNCTION; Schema: reseller_gateway; Owner: postgres
--

CREATE FUNCTION reseller_gateway."common.location.state"(pool common.dataimpulsepool, countries text[], cities text[] DEFAULT '{}'::text[], zipcodes text[] DEFAULT '{}'::text[], asns text[] DEFAULT '{}'::text[], order_by text DEFAULT 'name,asc'::text) RETURNS jsonb
    LANGUAGE plpgsql SECURITY DEFINER
    AS $$
DECLARE
    v_user_id TEXT := reseller_inner.authenticate();
BEGIN
    RAISE LOG 'common.location.state called with pool=%, countries=%', pool, countries;
    RETURN dataimpulse.get_proxy_states(pool, countries, cities, zipcodes, asns, order_by);
EXCEPTION
    WHEN OTHERS THEN
        RAISE WARNING 'common.location.state error: %', SQLERRM;
        RAISE sqlstate 'PT500' USING message = 'Unexpected exception';
END $$;


ALTER FUNCTION reseller_gateway."common.location.state"(pool common.dataimpulsepool, countries text[], cities text[], zipcodes text[], asns text[], order_by text) OWNER TO postgres;

--
-- Name: common.location.zipcode(common.dataimpulsepool, text[], text[], text[], text); Type: FUNCTION; Schema: reseller_gateway; Owner: postgres
--

CREATE FUNCTION reseller_gateway."common.location.zipcode"(pool common.dataimpulsepool, countries text[], states text[] DEFAULT '{}'::text[], asns text[] DEFAULT '{}'::text[], order_by text DEFAULT 'name,asc'::text) RETURNS jsonb
    LANGUAGE plpgsql SECURITY DEFINER
    AS $$
DECLARE
    v_user_id TEXT := reseller_inner.authenticate();
BEGIN
    RAISE LOG 'common.location.zipcode called with pool=%, countries=%', pool, countries;
    RETURN dataimpulse.get_proxy_zipcodes(pool, countries, states, asns, order_by);
EXCEPTION
    WHEN OTHERS THEN
        RAISE WARNING 'common.location.zipcode error: %', SQLERRM;
        RAISE sqlstate 'PT500' USING message = 'Unexpected exception';
END $$;


ALTER FUNCTION reseller_gateway."common.location.zipcode"(pool common.dataimpulsepool, countries text[], states text[], asns text[], order_by text) OWNER TO postgres;

--
-- Name: common.pool_stat(common.dataimpulsepool); Type: FUNCTION; Schema: reseller_gateway; Owner: postgres
--

CREATE FUNCTION reseller_gateway."common.pool_stat"(pool common.dataimpulsepool) RETURNS jsonb
    LANGUAGE plpgsql SECURITY DEFINER
    AS $$
DECLARE
    v_user_id TEXT := reseller_inner.authenticate();
BEGIN
    RAISE LOG 'common.pool_stat called for pool: %', pool;
    RETURN dataimpulse.pool_stats(pool);
EXCEPTION
    WHEN OTHERS THEN
        RAISE WARNING 'common.pool_stat error: %', SQLERRM;
        RAISE sqlstate 'PT500' USING message = 'Unexpected exception';
END $$;


ALTER FUNCTION reseller_gateway."common.pool_stat"(pool common.dataimpulsepool) OWNER TO postgres;

--
-- Name: get-proxy(text, text, text, text, integer, integer, common.dataimpulsepool, integer, text[], text[], text[], text[], text[], text[], text); Type: FUNCTION; Schema: reseller_gateway; Owner: postgres
--

CREATE FUNCTION reseller_gateway."get-proxy"(anonymous text, type text, protocol text, format text, quantity integer, sessionttl integer, pool common.dataimpulsepool, subuser_id integer, countries text[] DEFAULT NULL::text[], excluded_asns text[] DEFAULT NULL::text[], included_asns text[] DEFAULT NULL::text[], cities text[] DEFAULT NULL::text[], states text[] DEFAULT NULL::text[], zipcodes text[] DEFAULT NULL::text[], connection_host text DEFAULT NULL::text) RETURNS vgate."text/plain"
    LANGUAGE plpgsql SECURITY DEFINER
    AS $$
DECLARE
    v_user_id TEXT := reseller_inner.authenticate();
    host_ip INET;
BEGIN
    RAISE LOG 'get-proxy called for subuser_id=% with type=% and protocol=% excluded_asns=% included_asns=%', subuser_id, type, protocol, excluded_asns, included_asns;
    PERFORM reseller_inner.ensure_subuser_exists(subuser_id);

    IF connection_host IS NOT NULL THEN
        SELECT ip
        FROM dataimpulse.host
        WHERE region::TEXT = connection_host
        LIMIT 1
        INTO host_ip;

        IF NOT FOUND THEN
            RAISE sqlstate 'PT404' USING
                message = 'Such connection host does not exist';
        END IF;
    ELSE
        SELECT ip
        FROM dataimpulse.host
        WHERE region::TEXT = 'auto'
        LIMIT 1
        INTO host_ip;
    END IF;

    RETURN dataimpulse.get_proxy(
        anonymous,
        type,
        protocol,
        format,
        quantity,
        sessionttl,
        pool,
        subuser_id::text,
        countries,
        cities,
        states,
        excluded_asns,
        included_asns,
        zipcodes,
        host_ip
    );
EXCEPTION
    WHEN sqlstate 'PT400' THEN
        RAISE;
    WHEN sqlstate 'PT422' THEN
        RAISE;
    WHEN sqlstate 'PT404' THEN
        RAISE;
    WHEN OTHERS THEN
        RAISE WARNING 'get-proxy error: %', SQLERRM;
        RAISE sqlstate 'PT500' USING message = 'Unexpected exception';
END $$;


ALTER FUNCTION reseller_gateway."get-proxy"(anonymous text, type text, protocol text, format text, quantity integer, sessionttl integer, pool common.dataimpulsepool, subuser_id integer, countries text[], excluded_asns text[], included_asns text[], cities text[], states text[], zipcodes text[], connection_host text) OWNER TO postgres;

--
-- Name: subuser.balance.add(integer, integer); Type: FUNCTION; Schema: reseller_gateway; Owner: postgres
--

CREATE FUNCTION reseller_gateway."subuser.balance.add"(subuser_id integer, gb integer) RETURNS void
    LANGUAGE plpgsql SECURITY DEFINER
    AS $$
DECLARE
    v_user_id TEXT := reseller_inner.authenticate();
    reseller_id INT;
    reseller_balance BIGINT;
    bytes_value BIGINT;
    result JSON;
    conversion_rate NUMERIC;
    _pool DATAIMPULSEPOOL;
BEGIN
    IF gb <= 0 THEN
        RAISE sqlstate 'PT400' USING message = 'Traffic addition must be a positive number';
    END IF;

    SELECT subuser_id, pool
      FROM reseller_inner.ensure_subuser_exists(subuser_id)
      INTO subuser_id, _pool;

    conversion_rate := reseller_inner.conversion_rate(_pool);

    SELECT id, traffic_amount
      FROM reseller_inner.resellers
      WHERE user_id::TEXT = v_user_id
      INTO reseller_id, reseller_balance;
      
    bytes_value := reseller_inner.gb_to_bytes(gb);
    IF reseller_balance < (bytes_value * conversion_rate) THEN
        RAISE LOG 'subuser.balance.add: insufficient reseller balance: reseller_balance=% (bytes: %), conversion_rate=%', reseller_balance, (bytes_value * conversion_rate), conversion_rate;
        RAISE sqlstate 'PT402' USING message = 'Insufficient reseller balance';
    END IF;
    
    RAISE LOG 'subuser.balance.add called for subuser_id=% (%), addition gb=% (bytes: %), conversion_rate=%', subuser_id, _pool, gb, bytes_value, conversion_rate;
    
    UPDATE reseller_inner.resellers
      SET traffic_amount = traffic_amount - (bytes_value * conversion_rate)
      WHERE id = reseller_id;
      
    result := dataimpulse.subuser_balance_add(subuser_id, gb);
    RAISE LOG 'subuser.balance.add successful for subuser_id=%, reduced reseller traffic by % bytes', subuser_id, (bytes_value * conversion_rate);
    RETURN;
EXCEPTION
    WHEN sqlstate 'PT404' THEN
        RAISE;
    WHEN sqlstate 'PT402' THEN
        RAISE;
    WHEN OTHERS THEN
        RAISE WARNING 'subuser.balance.add error: %', SQLERRM;
        RAISE sqlstate 'PT500' USING message = 'Unexpected exception';
END $$;


ALTER FUNCTION reseller_gateway."subuser.balance.add"(subuser_id integer, gb integer) OWNER TO postgres;

--
-- Name: subuser.balance.dec(integer, integer); Type: FUNCTION; Schema: reseller_gateway; Owner: postgres
--

CREATE FUNCTION reseller_gateway."subuser.balance.dec"(subuser_id integer, gb integer) RETURNS jsonb
    LANGUAGE plpgsql SECURITY DEFINER
    AS $$
DECLARE
    v_user_id TEXT := reseller_inner.authenticate();
    reseller_id INT;
    reseller_balance BIGINT;
    sub_balance BIGINT;
    bytes_value BIGINT;
    result JSON;
    conversion_rate NUMERIC;
    _pool DATAIMPULSEPOOL;
BEGIN
    IF gb <= 0 THEN
        RAISE sqlstate 'PT400' USING message = 'Traffic decrement must be a positive number';
    END IF;

    SELECT id, pool
      FROM reseller_inner.ensure_subuser_exists(subuser_id)
      INTO subuser_id, _pool;

    conversion_rate := reseller_inner.conversion_rate(_pool);

    SELECT id, traffic_amount
      INTO reseller_id, reseller_balance
      FROM reseller_inner.resellers
      WHERE user_id::TEXT = v_user_id;
      
    bytes_value := reseller_inner.gb_to_bytes(gb);
    RAISE LOG 'subuser.balance.dec called for subuser_id=% (%), decrement gb=% (bytes: %), conversion_rate=%', subuser_id, _pool, gb, bytes_value, conversion_rate;
    
    SELECT ((dataimpulse.subuser_balance_get(subuser_id))->>'balance')::BIGINT
      INTO sub_balance;
      
    IF sub_balance < bytes_value THEN
        RAISE sqlstate 'PT400' USING message = 'Insufficient subuser balance';
    END IF;
    
    -- Update reseller's traffic using conversion factor
    UPDATE reseller_inner.resellers
      SET traffic_amount = traffic_amount + (bytes_value * conversion_rate)
      WHERE id = reseller_id;
      
    result := dataimpulse.subuser_balance_add(subuser_id, gb * -1);
    RAISE LOG 'subuser.balance.dec successful for subuser_id=%, updated reseller traffic by % bytes', subuser_id, (bytes_value * conversion_rate);
    RETURN result;
EXCEPTION
    WHEN sqlstate 'PT404' THEN
        RAISE;
    WHEN sqlstate 'PT400' THEN
        RAISE;
    WHEN OTHERS THEN
        RAISE WARNING 'subuser.balance.dec error: %', SQLERRM;
        RAISE sqlstate 'PT500' USING message = 'Unexpected exception';
END $$;


ALTER FUNCTION reseller_gateway."subuser.balance.dec"(subuser_id integer, gb integer) OWNER TO postgres;

--
-- Name: subuser.balance.drop(integer); Type: FUNCTION; Schema: reseller_gateway; Owner: postgres
--

CREATE FUNCTION reseller_gateway."subuser.balance.drop"(subuser_id integer) RETURNS jsonb
    LANGUAGE plpgsql SECURITY DEFINER
    AS $$
DECLARE
    v_user_id TEXT := reseller_inner.authenticate();
    reseller_id INT;
    pre_balance NUMERIC;
    post_balance NUMERIC;
    diff NUMERIC;
    drop_result JSONB;
    conversion_rate NUMERIC;
    _pool DATAIMPULSEPOOL;
BEGIN
    SELECT id, pool
      FROM reseller_inner.ensure_subuser_exists(subuser_id)
      INTO subuser_id, _pool;

    conversion_rate := reseller_inner.conversion_rate(_pool);

    RAISE LOG 'subuser.balance.drop called for subuser_id=% (%)', subuser_id, _pool;

    SELECT id
      INTO reseller_id
      FROM reseller_inner.resellers
      WHERE user_id::TEXT = v_user_id;

    SELECT ((dataimpulse.subuser_balance_get(subuser_id))->>'balance')::NUMERIC
      INTO pre_balance;

    drop_result := dataimpulse.subuser_balance_drop(subuser_id);

    SELECT ((dataimpulse.subuser_balance_get(subuser_id))->>'balance')::NUMERIC
      INTO post_balance;

    diff := pre_balance - post_balance;

    IF diff > 0 THEN
        UPDATE reseller_inner.resellers
          SET traffic_amount = traffic_amount + (diff * conversion_rate)
          WHERE id = reseller_id;
        RAISE LOG 'subuser.balance.drop: traffic_amount adjusted by diff=% (after conversion: % bytes) for reseller_id=%', diff, (diff * conversion_rate), reseller_id;
    END IF;

    RAISE LOG 'subuser.balance.drop successful for subuser_id=%', subuser_id;
    RETURN drop_result;
EXCEPTION
    WHEN sqlstate 'PT404' THEN
        RAISE;
    WHEN sqlstate 'PT400' THEN
        RAISE;
    WHEN OTHERS THEN
        RAISE WARNING 'subuser.balance.drop error: %', SQLERRM;
        RAISE sqlstate 'PT500' USING message = 'Unexpected exception';
END $$;


ALTER FUNCTION reseller_gateway."subuser.balance.drop"(subuser_id integer) OWNER TO postgres;

--
-- Name: subuser.balance.get(integer); Type: FUNCTION; Schema: reseller_gateway; Owner: postgres
--

CREATE FUNCTION reseller_gateway."subuser.balance.get"(subuser_id integer) RETURNS jsonb
    LANGUAGE plpgsql SECURITY DEFINER
    AS $$
DECLARE
    v_user_id TEXT := reseller_inner.authenticate();
BEGIN
    RAISE LOG 'subuser.balance.get called for subuser_id=%', subuser_id;
    PERFORM reseller_inner.ensure_subuser_exists(subuser_id);
    RAISE LOG 'subuser.balance.get successful for subuser_id=%', subuser_id;
    RETURN dataimpulse.subuser_balance_get(subuser_id);
EXCEPTION
    WHEN sqlstate 'PT404' THEN
        RAISE;
    WHEN OTHERS THEN
        RAISE WARNING 'subuser.balance.get error: %', SQLERRM;
        RAISE sqlstate 'PT500' USING message = 'Unexpected exception';
END $$;


ALTER FUNCTION reseller_gateway."subuser.balance.get"(subuser_id integer) OWNER TO postgres;

--
-- Name: subuser.create(common.dataimpulsepool, jsonb, integer, inet[], jsonb); Type: FUNCTION; Schema: reseller_gateway; Owner: postgres
--

CREATE FUNCTION reseller_gateway."subuser.create"(pool_type common.dataimpulsepool DEFAULT 'residential'::common.dataimpulsepool, sticky_range jsonb DEFAULT NULL::jsonb, threads integer DEFAULT NULL::integer, allowed_ips inet[] DEFAULT NULL::inet[], default_pool_parameters jsonb DEFAULT NULL::jsonb) RETURNS integer
    LANGUAGE plpgsql SECURITY DEFINER
    AS $$
DECLARE
    v_user_id TEXT := reseller_inner.authenticate();
    reseller_id INT;
    subuser_id INT;
BEGIN
    reseller_id := (SELECT id FROM reseller_inner.resellers WHERE user_id = v_user_id);
    RAISE LOG 'subuser.create: retrieved reseller_id=% for user_id=%', reseller_id, v_user_id;

    IF default_pool_parameters IS NOT NULL THEN
        IF default_pool_parameters->>'rotation_interval' IS NOT NULL THEN
            -- TODO: validate rotation interval is number
            IF (default_pool_parameters->>'rotation_interval')::integer > 120 THEN
                RAISE sqlstate 'PT400' USING message = 'rotation_interval must be less than 120';
            END IF;
        END IF;
    END IF;

    SELECT (dataimpulse.create_subuser(
        label := 'r_' || reseller_id,
        sticky_range := sticky_range,
        threads := threads,
        allowed_ips := allowed_ips,
        pool_type := pool_type,
        default_pool_parameters := default_pool_parameters
    ))->>'id'
    INTO subuser_id;

    IF subuser_id IS NULL THEN
        RAISE sqlstate 'PT500' USING
            message = 'Failed to create subuser';
    ELSE
        INSERT INTO reseller_inner.reseller_subusers (id, reseller_id, pool)
        VALUES (subuser_id, reseller_id, pool_type);
        RAISE LOG 'subuser.create successful: subuser_id=% in % pool created for reseller_id=%', subuser_id, pool_type, reseller_id;
        RETURN subuser_id;
    END IF;
EXCEPTION
    WHEN sqlstate 'PT404' THEN
        RAISE;
    WHEN sqlstate 'PT400' THEN
        RAISE;
    WHEN sqlstate 'PT422' THEN
        RAISE;
    WHEN OTHERS THEN
        RAISE WARNING 'subuser.create error: %', SQLERRM;
        RAISE sqlstate 'PT500' USING message = 'Unexpected exception';
END $$;


ALTER FUNCTION reseller_gateway."subuser.create"(pool_type common.dataimpulsepool, sticky_range jsonb, threads integer, allowed_ips inet[], default_pool_parameters jsonb) OWNER TO postgres;

--
-- Name: subuser.delete(integer); Type: FUNCTION; Schema: reseller_gateway; Owner: postgres
--

CREATE FUNCTION reseller_gateway."subuser.delete"(subuser_id integer) RETURNS jsonb
    LANGUAGE plpgsql SECURITY DEFINER
    AS $$
DECLARE
    v_user_id TEXT := reseller_inner.authenticate();
BEGIN
    RAISE LOG 'subuser.delete called for subuser_id=%', subuser_id;
    PERFORM reseller_inner.ensure_subuser_exists(subuser_id);
    DELETE FROM reseller_inner.reseller_subusers
    WHERE id = subuser_id;
    RAISE LOG 'subuser.delete successful for subuser_id=%', subuser_id;
    RETURN dataimpulse.delete_subuser(subuser_id);
EXCEPTION
    WHEN sqlstate 'PT404' THEN
        RAISE;
    WHEN OTHERS THEN
        RAISE WARNING 'subuser.delete error: %', SQLERRM;
        RAISE sqlstate 'PT500' USING message = 'Unexpected exception';
END $$;


ALTER FUNCTION reseller_gateway."subuser.delete"(subuser_id integer) OWNER TO postgres;

--
-- Name: subuser.get(integer); Type: FUNCTION; Schema: reseller_gateway; Owner: postgres
--

CREATE FUNCTION reseller_gateway."subuser.get"(subuser_id integer) RETURNS jsonb
    LANGUAGE plpgsql SECURITY DEFINER
    AS $$
DECLARE
    v_user_id TEXT := reseller_inner.authenticate();
BEGIN
    RAISE LOG 'subuser.get called for subuser_id=%', subuser_id;
    PERFORM reseller_inner.ensure_subuser_exists(subuser_id);
    RAISE LOG 'subuser.get successful for subuser_id=%', subuser_id;
    RETURN dataimpulse.get_subuser(subuser_id);
EXCEPTION
    WHEN sqlstate 'PT404' THEN
        RAISE;
    WHEN OTHERS THEN
        RAISE WARNING 'subuser.get error: %', SQLERRM;
        RAISE sqlstate 'PT500' USING message = 'Unexpected exception';
END $$;


ALTER FUNCTION reseller_gateway."subuser.get"(subuser_id integer) OWNER TO postgres;

--
-- Name: subuser.list(bigint, bigint); Type: FUNCTION; Schema: reseller_gateway; Owner: postgres
--

CREATE FUNCTION reseller_gateway."subuser.list"("limit" bigint DEFAULT 1000, "offset" bigint DEFAULT 0) RETURNS jsonb
    LANGUAGE plpgsql SECURITY DEFINER
    AS $$
DECLARE
    v_user_id TEXT := reseller_inner.authenticate();
    v_reseller_id INT;
BEGIN
    IF "limit" < 0 THEN
        RAISE sqlstate 'PT400' USING message = 'limit cannot be negative';
    END IF;
    IF "limit" > 1000 THEN
        RAISE sqlstate 'PT400' USING message = 'limit maximum is 1000';
    END IF;
    IF "offset" > 1000 THEN
        RAISE sqlstate 'PT400' USING message = 'offset cannot be negative';
    END IF;
    v_reseller_id := (SELECT id FROM reseller_inner.resellers WHERE user_id = v_user_id);
    RAISE LOG 'subuser.list called for reseller_id=% with limit=% and offset=%', v_reseller_id, "limit", "offset";
    RETURN COALESCE(
        (SELECT jsonb_agg(subuser)
        FROM jsonb_array_elements(dataimpulse.subuser_list("limit", "offset")->'subusers') AS subuser
        WHERE EXISTS (
            SELECT 1
            FROM reseller_inner.reseller_subusers
            WHERE id::TEXT = (subuser::JSON)->>'id' AND reseller_id = v_reseller_id
        )),
        '[]'::jsonb
    );
EXCEPTION
    WHEN OTHERS THEN
        RAISE WARNING 'subuser.list error: %', SQLERRM;
        RAISE sqlstate 'PT500' USING message = 'Unexpected exception';
END $$;


ALTER FUNCTION reseller_gateway."subuser.list"("limit" bigint, "offset" bigint) OWNER TO postgres;

--
-- Name: subuser.pool.parameters(integer, jsonb); Type: FUNCTION; Schema: reseller_gateway; Owner: postgres
--

CREATE FUNCTION reseller_gateway."subuser.pool.parameters"(subuser_id integer, parameters jsonb) RETURNS jsonb
    LANGUAGE plpgsql SECURITY DEFINER
    AS $$
DECLARE
    v_user_id TEXT := reseller_inner.authenticate();
BEGIN
    IF parameters IS NOT NULL THEN
        IF parameters->>'rotation_interval' IS NOT NULL THEN
            -- TODO: validate rotation interval is number
            IF (parameters->>'rotation_interval')::integer > 120 THEN
                RAISE sqlstate 'PT400' USING message = 'rotation_interval must be less than 120';
            END IF;
        END IF;
    END IF;
    -- {
    --   countries: optional, array of strings,
    --   cities: optional, array of strings,
    --   states: optional, array of strings,
    --   zipcodes: optional, array of strings,
    --   asns: optional, array of strings,
    --   exclude_countries: optional, array of strings,
    --   exclude_asn: optional, array of numbers,
    --   anonymous_filter: boolean,
    --   rotation_interval: number
    -- }
    RAISE LOG 'subuser.pool.parameters called for subuser_id=%, parameters=%', subuser_id, parameters;
    PERFORM reseller_inner.ensure_subuser_exists(subuser_id);
    RETURN dataimpulse.subuser_set_default_pool_parameters(subuser_id, parameters);
EXCEPTION
    WHEN sqlstate 'PT404' THEN
        RAISE;
    WHEN sqlstate 'PT400' THEN
        RAISE;
    WHEN OTHERS THEN
        RAISE WARNING 'subuser.pool.parameters error: %', SQLERRM;
        RAISE sqlstate 'PT500' USING message = 'Unexpected exception';
END $$;


ALTER FUNCTION reseller_gateway."subuser.pool.parameters"(subuser_id integer, parameters jsonb) OWNER TO postgres;

--
-- Name: subuser.reset-password(integer); Type: FUNCTION; Schema: reseller_gateway; Owner: postgres
--

CREATE FUNCTION reseller_gateway."subuser.reset-password"(subuser_id integer) RETURNS jsonb
    LANGUAGE plpgsql SECURITY DEFINER
    AS $$
DECLARE
    v_user_id TEXT := reseller_inner.authenticate();
BEGIN
    RAISE LOG 'subuser.reset-password called for subuser_id=%', subuser_id;
    PERFORM reseller_inner.ensure_subuser_exists(subuser_id);
    RAISE LOG 'subuser.reset-password successful for subuser_id=%', subuser_id;
    RETURN dataimpulse.reset_subuser_password(subuser_id);
EXCEPTION
    WHEN sqlstate 'PT404' THEN
        RAISE;
    WHEN OTHERS THEN
        RAISE WARNING 'subuser.reset-password error: %', SQLERRM;
        RAISE sqlstate 'PT500' USING message = 'Unexpected exception';
END $$;


ALTER FUNCTION reseller_gateway."subuser.reset-password"(subuser_id integer) OWNER TO postgres;

--
-- Name: subuser.update(integer, jsonb, integer); Type: FUNCTION; Schema: reseller_gateway; Owner: postgres
--

CREATE FUNCTION reseller_gateway."subuser.update"(subuser_id integer, sticky_range jsonb DEFAULT NULL::jsonb, threads integer DEFAULT NULL::integer) RETURNS jsonb
    LANGUAGE plpgsql SECURITY DEFINER
    AS $$
DECLARE
    v_user_id TEXT := reseller_inner.authenticate();
    reseller_id INT;
    data jsonb;
BEGIN
    reseller_id := (SELECT id FROM reseller_inner.resellers WHERE user_id = v_user_id);
    RAISE LOG 'subuser.update called for subuser_id=% by reseller_id=%', subuser_id, reseller_id;
    PERFORM reseller_inner.ensure_subuser_exists(subuser_id);
    data := json_build_object(
        'subuser_id', subuser_id
    );
    RAISE LOG 'subuser.update: calling dataimpulse.update_subuser for subuser_id=%', subuser_id;
    RETURN dataimpulse.update_subuser(
        subuser_id,
        'r_' || reseller_id,
        sticky_range,
        threads
    );
EXCEPTION
    WHEN sqlstate 'PT404' THEN
        RAISE;
    WHEN OTHERS THEN
        RAISE WARNING 'subuser.update error: %', SQLERRM;
        RAISE sqlstate 'PT500' USING message = 'Unexpected exception';
END $$;


ALTER FUNCTION reseller_gateway."subuser.update"(subuser_id integer, sticky_range jsonb, threads integer) OWNER TO postgres;

--
-- Name: SCHEMA reseller_gateway; Type: ACL; Schema: -; Owner: postgres
--

GRANT USAGE ON SCHEMA reseller_gateway TO vgate_user;
GRANT USAGE ON SCHEMA reseller_gateway TO anon;


--
-- PostgreSQL database dump complete
--

