CREATE EXTENSION IF NOT EXISTS pgcrypto;



CREATE TABLE person_account(
	person_id int NOT NULL UNIQUE REFERENCES person,
	login varchar(60) NOT NULL,
	password varchar NOT NULL,
	CONSTRAINT empty_login CHECK (trim(login) <> '')
);

CREATE OR REPLACE FUNCTION check_password(_password varchar(60))
RETURNS void AS
$BODY$
BEGIN
	IF (trim(_password) = '')
	THEN
		RAISE EXCEPTION 'Пароль не может быть пустым!';
	END IF;

	IF (trim(_password) <> _password)
	THEN
		RAISE EXCEPTION 'Пароль должен быть без пробелов!';
	END IF;

	IF (length(_password) < 8)
	THEN
		RAISE EXCEPTION 'Пароль должен иметь больше 8 знаков!';
	END IF;

	IF (lower(_password) = _password OR _password !~ '[0-9]')
	THEN
		RAISE EXCEPTION 'Пароль должен иметь прописные и заглавные буквы, а также цифры!';
	END IF;

	IF ((SELECT COUNT(*) AS letter_count
		FROM ( SELECT regexp_split_to_table(_password, '') AS letter) AS letters
		GROUP BY letter
		ORDER BY letter
		LIMIT 1) >= length(_password)/2)
	THEN
		RAISE EXCEPTION 'Пароль не должен иметь больше половины одинаковых символов!';
	END IF;
END
$BODY$
LANGUAGE plpgsql VOLATILE;

CREATE OR REPLACE FUNCTION create_person_account()
RETURNS TRIGGER AS $$
DECLARE
	role int;
BEGIN
    PERFORM check_password(NEW.password);
    NEW.password := crypt(NEW.password, gen_salt('bf'));
	
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

-- Создаем триггер
CREATE TRIGGER trigger_create_account
BEFORE INSERT ON person_account
FOR EACH ROW
EXECUTE FUNCTION create_person_account();

CREATE OR REPLACE FUNCTION check_enter_in_person_account(_login varchar, _password varchar)
RETURNS int AS $$
DECLARE
	_hash_password varchar := null;
    _person_id int;
BEGIN
    -- Получаем person_id и проверяем авторизацию
    SELECT pa.person_id, pa.password
    INTO _person_id, _hash_password
    FROM person_account pa
    WHERE pa.login = _login
    AND pa.password = crypt(_password, pa.password);

    -- Если запись не найдена
    IF _person_id IS NULL THEN
        RAISE EXCEPTION 'Неверный логин или пароль!';
    END IF;
	
	RETURN _person_id;
END;
$$ LANGUAGE plpgsql;

INSERT INTO person_account (person_id, login, password)
VALUES (1, 'Иванов Н.В.', 'Иванов123'),
	(2, 'Сидоров В.А.', 'Сидоров123'),
	(3, 'Кузнецов П.С.', 'Кузнецов123'),
	(4, 'Петров И.В.', 'Петров123'),
	(5, 'Иванов Н.А.', 'Иванов123'),
	(6, 'Иванов Е.С.', 'Иванов123');