--
-- This file is part of Challenger
-- Copyright (C) 2023 Taler Systems SA
--
-- Challenger is free software; you can redistribute it and/or modify it under the
-- terms of the GNU General Public License as published by the Free Software
-- Foundation; either version 3, or (at your option) any later version.
--
-- Challenger is distributed in the hope that it will be useful, but WITHOUT ANY
-- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
-- A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License along with
-- Challenger; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
--

-- Everything in one big transaction
BEGIN;

-- Check patch versioning is in place.
SELECT _v.register_patch('challenger-0001', NULL, NULL);

CREATE SCHEMA challenger;
COMMENT ON SCHEMA challenger IS 'challenger data';

SET search_path TO challenger;


CREATE TABLE IF NOT EXISTS clients
  (client_serial_id BIGINT UNIQUE GENERATED BY DEFAULT AS IDENTITY
  ,uri VARCHAR NOT NULL UNIQUE
  ,validation_counter INT8 NOT NULL DEFAULT(0)
  ,client_secret VARCHAR NOT NULL
  );
COMMENT ON TABLE clients
 IS 'Which clients are eligible to access the OAuth 2.0 client';
COMMENT ON COLUMN clients.client_serial_id
 IS 'Unique ID for the client';
COMMENT ON COLUMN clients.uri
 IS 'Client redirection URI of the clients, where we would redirect to for authorization';
COMMENT ON COLUMN clients.validation_counter
 IS 'How many validations were initiated on behalf of this client (for accounting)';
COMMENT ON COLUMN clients.client_secret
 IS 'Client secret, used by the client to authorize the /login request';
CREATE INDEX IF NOT EXISTS clients_serial
  ON clients (client_serial_id);

CREATE TABLE IF NOT EXISTS validations
  (validation_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY UNIQUE
  ,client_serial_id INT8 NOT NULL REFERENCES clients (client_serial_id)
  ,nonce BYTEA CHECK (length(nonce)=32) UNIQUE
  ,expiration_time INT8 NOT NULL
  ,last_tx_time INT8 NOT NULL DEFAULT (0)
  ,address_attempts_left INT4 DEFAULT(3)
  ,last_pin INT4
  ,pin_transmissions_left INT4 DEFAULT(3)
  ,auth_attempts_left INT4 DEFAULT(0)
  ,address VARCHAR
  ,client_scope VARCHAR
  ,client_state VARCHAR
  ,client_redirect_uri VARCHAR
 );

COMMENT ON TABLE validations
  IS 'Active validations where we send a challenge to an address of a user';
COMMENT ON COLUMN validations.client_serial_id
 IS 'Which client initiated this validation';
COMMENT ON COLUMN validations.nonce
  IS 'Unguessable validation identifier';
COMMENT ON COLUMN validations.client_scope
 IS 'Client-specific scope value identifying the requested scope';
COMMENT ON COLUMN validations.client_state
 IS 'Client-specific state value identifying the purpose of the validation';
COMMENT ON COLUMN validations.client_redirect_uri
 IS 'Client-specific URI where to redirect the user-agent back once access is granted (or denied)';
COMMENT ON COLUMN validations.address
  IS 'Address we are validating; provided by the user-agent; usually a phone number or e-mail address (depends on the client_scope)';
COMMENT ON COLUMN validations.last_pin
  IS 'Last PIN code send to the user';
COMMENT ON COLUMN validations.address_attempts_left
  IS 'How many more address changes is the user allowed to make (guard against DoS and brute-forcing)';
COMMENT ON COLUMN validations.pin_transmissions_left
  IS 'How many more PIN transmission attempts do we permit (guard against DoS and brute-forcing)';
COMMENT ON COLUMN validations.auth_attempts_left
  IS 'How many more authentication attempts do we permit (guard against brute-forcing)';
COMMENT ON COLUMN validations.last_tx_time
  IS 'When did we last sent the challenge (guard against DDoS)';
COMMENT ON COLUMN validations.expiration_time
  IS 'When will the challenge expire';

CREATE INDEX IF NOT EXISTS validations_serial
  ON validations (validation_serial_id);
CREATE INDEX IF NOT EXISTS validations_expiration
  ON validations (expiration_time);


CREATE TABLE IF NOT EXISTS tokens
  (grant_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY
  ,access_token BYTEA PRIMARY KEY CHECK (length(access_token)=32)
  ,address VARCHAR NOT NULL
  ,address_expiration_time INT8 NOT NULL
  ,token_expiration_time INT8 NOT NULL
  );

COMMENT ON TABLE tokens
  IS 'Active tokens where a client is authorized to access user data';
COMMENT ON COLUMN tokens.access_token
  IS 'Token that tokens access to the resource (the address)';
COMMENT ON COLUMN tokens.address
  IS 'Address of the user (the resource protected by the token)';
COMMENT ON COLUMN tokens.address_expiration_time
  IS 'Timestamp until when we consider the address to be valid';
COMMENT ON COLUMN tokens.token_expiration_time
  IS 'Time until when we consider the grant to be valid';

-- Complete transaction
COMMIT;
