DO $$
DECLARE r record;
BEGIN
  FOR r IN
    SELECT p.oid::regprocedure AS sig
    FROM pg_proc p JOIN pg_namespace n ON n.oid = p.pronamespace
    WHERE n.nspname = 'public'
  LOOP
    EXECUTE format('REVOKE ALL ON FUNCTION %s FROM anon, PUBLIC', r.sig);
  END LOOP;
END $$;

CREATE OR REPLACE FUNCTION public.next_number(_key text)
RETURNS text
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = public
AS $$
DECLARE
  _next integer;
  _prefix text;
BEGIN
  IF auth.uid() IS NULL THEN
    RAISE EXCEPTION 'Not authorised';
  END IF;

  UPDATE public.number_sequences
     SET next_value = next_value + 1
   WHERE key = _key
  RETURNING next_value - 1, prefix INTO _next, _prefix;

  IF _next IS NULL THEN
    RAISE EXCEPTION 'Unknown number sequence: %', _key;
  END IF;

  RETURN _prefix || lpad(_next::text, 5, '0');
END;
$$;

REVOKE ALL ON FUNCTION public.next_number(text) FROM anon, PUBLIC;
GRANT EXECUTE ON FUNCTION public.next_number(text) TO authenticated, service_role;