Skip to content

Commit

Permalink
Merge branch 'main' into web-worker
Browse files Browse the repository at this point in the history
  • Loading branch information
giggity-hub authored Jul 26, 2023
2 parents c82d133 + 75fb11a commit 291d5fb
Show file tree
Hide file tree
Showing 35 changed files with 1,868 additions and 2,689 deletions.
5 changes: 0 additions & 5 deletions .env

This file was deleted.

14 changes: 14 additions & 0 deletions .example.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Posgres
PGUSER=postgres
PGPASSWORD=example
PGPORT=5432
PGHOST=127.0.0.1

# Authentication Providers
GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=

GITHUB_CLIENT_ID=
GITHUB_CLIENT_SECRET=

AUTH_SECRET=
7 changes: 7 additions & 0 deletions .github/workflows/e2e-tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ jobs:
run-e2e-tests:
timeout-minutes: 60
runs-on: ubuntu-latest
env:
AUTH_SECRET: ${{ secrets.AUTH_SECRET }}
NEXTAUTH_SECRET: ${{ secrets.NEXTAUTH_SECRET }}
GOOGLE_CLIENT_ID: ${{ secrets.GOOGLE_CLIENT_ID }}
GOOGLE_CLIENT_SECRET: ${{ secrets.GOOGLE_CLIENT_SECRET }}
defaults:
run:
working-directory: ./backend
Expand All @@ -31,6 +36,8 @@ jobs:
path: ~/.npm
key: npm-${{ hashFiles('package-lock.json') }}
restore-keys: npm-
# - name: Setup tmate session
# uses: mxschmitt/action-tmate@v3
- name: Install dependencies
working-directory: ./frontend-svelte
run: npm ci
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,8 @@ hypothesis_example/.hypothesis/**
.ipynb_checkpoints
.venv


frontend-svelte/node_modules
node_modules

.env
11 changes: 10 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
build:
cd backend && $(MAKE) build
cd database && $(MAKE) new
cd database && $(MAKE) new

cleanup:
docker rm dataframetrainer-db-1
docker rm dataframetrainer-backend-1
docker rm dataframetrainer-adminer-1
docker rm dataframetrainer-db-fill-or-update-tables-1
docker image rm -f dataframetrainer-db-fill-or-update-tables
docker image rm -f dataframetrainer-backend
docker volume rm -f dataframetrainer_sql
10 changes: 5 additions & 5 deletions database/fill_or_update_tables.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import time

DEFAULT_ELO = 700
TABLE_ORDER = ["users", "sessions", "challenges", "user_challenges", "challenge_elo"]
TABLE_ORDER = ["users", "accounts", "sessions", "verification_tokens", "challenges", "user_challenges", "challenge_elo"]
ROLES = ["roles"]
FUNCTIONS = ["authentication_functions"]

Expand Down Expand Up @@ -43,14 +43,14 @@ def run(port, dbname, password, user, host):
with open(f"sql/{role}.sql") as f:
cursor.execute(f.read())

for table in TABLE_ORDER:
with open(f"sql/{table}.sql") as f:
cursor.execute(f.read())

for function in FUNCTIONS:
with open(f"sql/{function}.sql") as f:
cursor.execute(f.read())

for table in TABLE_ORDER:
with open(f"sql/{table}.sql") as f:
cursor.execute(f.read())

for challenge in os.listdir("challenges"):
# ignore files that are not challenges
if not challenge[0].isupper():
Expand Down
17 changes: 17 additions & 0 deletions database/sql/accounts.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
CREATE TABLE public.accounts (
id uuid DEFAULT public.uuid_generate_v4() NOT NULL,
user_id uuid NOT NULL,
type character varying NOT NULL,
provider character varying NOT NULL,
provider_account_id character varying NOT NULL,
refresh_token character varying,
access_token character varying,
expires_at bigint,
token_type character varying,
scope character varying,
id_token character varying,
session_state character varying,

CONSTRAINT "accounts_pkey" PRIMARY KEY (id),
CONSTRAINT "accounts_fkey" FOREIGN KEY (user_id) REFERENCES public.users(id)
);
235 changes: 59 additions & 176 deletions database/sql/authentication_functions.sql
Original file line number Diff line number Diff line change
@@ -1,176 +1,59 @@
CREATE EXTENSION IF NOT EXISTS pgcrypto;
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";

CREATE OR REPLACE FUNCTION authenticate(
input json,
OUT response json)
RETURNS json
LANGUAGE 'plpgsql'
COST 100
VOLATILE PARALLEL UNSAFE
AS $BODY$
DECLARE
input_email varchar(80) := LOWER(TRIM((input->>'email')::varchar));
input_password varchar(80) := (input->>'password')::varchar;
BEGIN
IF input_email IS NULL OR input_password IS NULL THEN
response := json_build_object('statusCode', 400, 'status', 'Please provide an email address and password to authenticate.', 'user', NULL);
RETURN;
END IF;

WITH user_authenticated AS (
SELECT id, role, user_name
FROM users
WHERE email = input_email AND password = crypt(input_password, password) LIMIT 1
)
SELECT json_build_object(
'statusCode', CASE WHEN (SELECT COUNT(*) FROM user_authenticated) > 0 THEN 200 ELSE 401 END,
'status', CASE WHEN (SELECT COUNT(*) FROM user_authenticated) > 0
THEN 'Login successful.'
ELSE 'Invalid username/password combination.'
END,
'user', CASE WHEN (SELECT COUNT(*) FROM user_authenticated) > 0
THEN (SELECT json_build_object(
'id', user_authenticated.id,
'role', user_authenticated.role,
'email', input_email,
'name', user_authenticated.user_name)
FROM user_authenticated)
ELSE NULL
END,
'sessionId', (SELECT create_session(user_authenticated.id) FROM user_authenticated)
) INTO response;
END;
$BODY$;





CREATE OR REPLACE FUNCTION create_session(
input_user_id TEXT)
RETURNS uuid
LANGUAGE 'sql'
COST 100
VOLATILE PARALLEL UNSAFE
AS $BODY$
DELETE FROM sessions WHERE user_id = input_user_id;
INSERT INTO sessions(user_id) VALUES (input_user_id) RETURNING sessions.id;
$BODY$;





CREATE OR REPLACE FUNCTION get_session(input_session_id uuid)
RETURNS json
LANGUAGE 'sql'
AS $BODY$
SELECT json_build_object(
'id', sessions.user_id,
'role', users.role,
'email', users.email,
'name', users.user_name,
'expires', sessions.expires
) AS users
FROM sessions
INNER JOIN users ON sessions.user_id = users.id
WHERE sessions.id = input_session_id AND expires > CURRENT_TIMESTAMP LIMIT 1;
$BODY$;





CREATE OR REPLACE FUNCTION register(
input json,
OUT user_session json)
RETURNS json
LANGUAGE 'plpgsql'
COST 100
VOLATILE PARALLEL UNSAFE
AS $BODY$
DECLARE
input_email varchar(80) := LOWER(TRIM((input->>'email')::varchar));
input_name varchar(20) := TRIM((input->>'name')::varchar);
input_password varchar(80) := (input->>'password')::varchar;
BEGIN
PERFORM id FROM users WHERE email = input_email;
IF NOT FOUND THEN
INSERT INTO users(role, password, email, user_name)
VALUES('user', crypt(input_password, gen_salt('bf', 8)), input_email, input_name)
RETURNING
json_build_object(
'sessionId', create_session(users.id),
'user', json_build_object('id', users.id, 'role', 'user', 'email', input_email, 'name', input_name, 'optOut', false)
) INTO user_session;
ELSE -- user is registering account that already exists so set sessionId and user to null so client can let them know
SELECT authenticate(input) INTO user_session;
END IF;
END;
$BODY$;





CREATE PROCEDURE delete_session(input_id TEXT)
LANGUAGE sql
AS $$
DELETE FROM sessions WHERE user_id = input_id;
$$;





CREATE OR REPLACE PROCEDURE upsert_user(input json)
LANGUAGE plpgsql
AS $BODY$
DECLARE
input_id text := (input->>'id')::text;
input_role roles := COALESCE((input->>'role')::roles, 'user');
input_email varchar(80) := LOWER(TRIM((input->>'email')::varchar));
input_password varchar(80) := COALESCE((input->>'password')::varchar, '');
input_name varchar(20) := TRIM((input->>'name')::varchar);
BEGIN
INSERT INTO users (id, role, email, password, user_name)
VALUES (
input_id,
input_role, input_email, crypt(input_password, gen_salt('bf', 8)), input_name)
ON CONFLICT (id) DO
UPDATE SET
role = input_role,
email = input_email,
password = CASE WHEN input_password = ''
THEN users.password -- leave as is (we are updating fields other than the password)
ELSE crypt(input_password, gen_salt('bf', 8))
END,
user_name = input_name
WHERE users.id = input_id;
END;
$BODY$;


CREATE OR REPLACE PROCEDURE update_user(input_id integer, input json)
LANGUAGE plpgsql
AS $BODY$
DECLARE
input_email varchar(80) := LOWER(TRIM((input->>'email')::varchar));
input_password varchar(80) := COALESCE((input->>'password')::varchar, '');
input_name varchar(20) := TRIM((input->>'name')::varchar);
BEGIN
UPDATE users SET
email = input_email,
password = CASE WHEN input_password = ''
THEN password -- leave as is (we are updating fields other than the password)
ELSE crypt(input_password, gen_salt('bf', 8))
END,
user_name = input__name
WHERE id = input_id;
END;
$BODY$;



CALL upsert_user('{"id":"someid", "role":"user", "email":"exampleuser@gmail.com", "password":"supersecurepassword123", "name":"nicerusername420"}'::json)
CREATE OR REPLACE FUNCTION public.uuid_nil()
RETURNS uuid
LANGUAGE c
IMMUTABLE PARALLEL SAFE STRICT
AS '$libdir/uuid-ossp', $function$uuid_nil$function$;

CREATE OR REPLACE FUNCTION public.uuid_ns_dns()
RETURNS uuid
LANGUAGE c
IMMUTABLE PARALLEL SAFE STRICT
AS '$libdir/uuid-ossp', $function$uuid_ns_dns$function$;

CREATE OR REPLACE FUNCTION public.uuid_ns_url()
RETURNS uuid
LANGUAGE c
IMMUTABLE PARALLEL SAFE STRICT
AS '$libdir/uuid-ossp', $function$uuid_ns_url$function$;

CREATE OR REPLACE FUNCTION public.uuid_ns_oid()
RETURNS uuid
LANGUAGE c
IMMUTABLE PARALLEL SAFE STRICT
AS '$libdir/uuid-ossp', $function$uuid_ns_oid$function$;

CREATE OR REPLACE FUNCTION public.uuid_ns_x500()
RETURNS uuid
LANGUAGE c
IMMUTABLE PARALLEL SAFE STRICT
AS '$libdir/uuid-ossp', $function$uuid_ns_x500$function$;

CREATE OR REPLACE FUNCTION public.uuid_generate_v1()
RETURNS uuid
LANGUAGE c
PARALLEL SAFE STRICT
AS '$libdir/uuid-ossp', $function$uuid_generate_v1$function$;

CREATE OR REPLACE FUNCTION public.uuid_generate_v1mc()
RETURNS uuid
LANGUAGE c
PARALLEL SAFE STRICT
AS '$libdir/uuid-ossp', $function$uuid_generate_v1mc$function$;

CREATE OR REPLACE FUNCTION public.uuid_generate_v3(namespace uuid, name text)
RETURNS uuid
LANGUAGE c
IMMUTABLE PARALLEL SAFE STRICT
AS '$libdir/uuid-ossp', $function$uuid_generate_v3$function$;

CREATE OR REPLACE FUNCTION public.uuid_generate_v4()
RETURNS uuid
LANGUAGE c
PARALLEL SAFE STRICT
AS '$libdir/uuid-ossp', $function$uuid_generate_v4$function$;

CREATE OR REPLACE FUNCTION public.uuid_generate_v5(namespace uuid, name text)
RETURNS uuid
LANGUAGE c
IMMUTABLE PARALLEL SAFE STRICT
AS '$libdir/uuid-ossp', $function$uuid_generate_v5$function$;
22 changes: 9 additions & 13 deletions database/sql/sessions.sql
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
CREATE EXTENSION IF NOT EXISTS pgcrypto;
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE TABLE IF NOT EXISTS public.sessions (
id uuid DEFAULT public.uuid_generate_v4() NOT NULL,
session_token character varying NOT NULL,
user_id uuid NOT NULL,
expires character varying NOT NULL,

CREATE TABLE IF NOT EXISTS "sessions" (
id uuid NOT NULL DEFAULT uuid_generate_v4(),
user_id TEXT NOT NULL,
expires timestamp with time zone DEFAULT (CURRENT_TIMESTAMP + '02:00:00'::interval),
CONSTRAINT sessions_pkey PRIMARY KEY (id),
CONSTRAINT sessions_user_fkey FOREIGN KEY (user_id)
REFERENCES users (id) MATCH SIMPLE
ON UPDATE NO ACTION
ON DELETE CASCADE
NOT VALID
) TABLESPACE pg_default;
CONSTRAINT "sessions_pkey" PRIMARY KEY (id),
CONSTRAINT "sessions_unique_session_token" UNIQUE (session_token),
CONSTRAINT "sessions_fkey" FOREIGN KEY (user_id) REFERENCES public.users(id)
);
2 changes: 1 addition & 1 deletion database/sql/user_challenges.sql
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
CREATE TABLE IF NOT EXISTS "user_challenges" (
"user_id" TEXT NOT NULL,
"user_id" UUID NOT NULL,
"challenge_id" TEXT,
"session_id" TEXT,
"timestamp" TIMESTAMP NOT NULL,
Expand Down
Loading

0 comments on commit 291d5fb

Please sign in to comment.