This commit is contained in:
louiscklaw
2025-01-31 19:15:17 +08:00
parent 09adae8c8e
commit 6c60a73f30
1546 changed files with 286918 additions and 0 deletions

View File

@@ -0,0 +1,893 @@
{
"firstName": [
"John",
"William",
"James",
"Charles",
"George",
"Frank",
"Joseph",
"Thomas",
"Henry",
"Robert",
"Edward",
"Harry",
"Walter",
"Arthur",
"Fred",
"Albert",
"Samuel",
"David",
"Louis",
"Joe",
"Charlie",
"Clarence",
"Richard",
"Andrew",
"Daniel",
"Ernest",
"Will",
"Jesse",
"Oscar",
"Lewis",
"Peter",
"Benjamin",
"Frederick",
"Willie",
"Alfred",
"Sam",
"Roy",
"Herbert",
"Jacob",
"Tom",
"Elmer",
"Carl",
"Lee",
"Howard",
"Martin",
"Michael",
"Bert",
"Herman",
"Jim",
"Francis",
"Harvey",
"Earl",
"Eugene",
"Ralph",
"Ed",
"Claude",
"Edwin",
"Ben",
"Charley",
"Paul",
"Edgar",
"Isaac",
"Otto",
"Luther",
"Lawrence",
"Ira",
"Patrick",
"Guy",
"Oliver",
"Theodore",
"Hugh",
"Clyde",
"Alexander",
"August",
"Floyd",
"Homer",
"Jack",
"Leonard",
"Horace",
"Marion",
"Philip",
"Allen",
"Archie",
"Stephen",
"Chester",
"Willis",
"Raymond",
"Mary",
"Anna",
"Emma",
"Elizabeth",
"Minnie",
"Margaret",
"Ida",
"Alice",
"Bertha",
"Sarah",
"Annie",
"Clara",
"Ella",
"Florence",
"Cora",
"Martha",
"Laura",
"Nellie",
"Grace",
"Carrie",
"Maude",
"Mabel",
"Bessie",
"Jennie",
"Gertrude",
"Julia",
"Hattie",
"Edith",
"Mattie",
"Rose",
"Catherine",
"Lillian",
"Ada",
"Lillie",
"Helen",
"Jessie",
"Louise",
"Ethel",
"Lula",
"Myrtle",
"Eva",
"Frances",
"Lena",
"Lucy",
"Edna",
"Maggie",
"Pearl",
"Daisy",
"Fannie",
"Josephine",
"Dora",
"Rosa",
"Katherine",
"Agnes",
"Marie",
"Nora",
"May",
"Mamie",
"Blanche",
"Stella",
"Ellen",
"Nancy",
"Effie",
"Sallie",
"Nettie",
"Della",
"Lizzie",
"Flora",
"Susie",
"Maud",
"Mae",
"Etta",
"Harriet",
"Sadie",
"Caroline",
"Katie",
"Lydia",
"Elsie",
"Kate",
"Susan",
"Mollie",
"Alma",
"Addie",
"Georgia",
"Eliza",
"Lulu",
"Nannie",
"Lottie",
"Amanda",
"Belle",
"Charlotte"
],
"lastName": [
"Smith",
"Johnson",
"Williams",
"Brown",
"Jones",
"Miller",
"Davis",
"Garcia",
"Rodriguez",
"Wilson",
"Martinez",
"Anderson",
"Taylor",
"Thomas",
"Hernandez",
"Moore",
"Martin",
"Jackson",
"Thompson",
"White",
"Lopez",
"Lee",
"Gonzalez",
"Harris",
"Clark",
"Lewis",
"Robinson",
"Walker",
"Perez",
"Hall",
"Young",
"Allen",
"Sanchez",
"Wright",
"King",
"Scott",
"Green",
"Baker",
"Adams",
"Nelson",
"Hill",
"Ramirez",
"Campbell",
"Mitchell",
"Roberts",
"Carter",
"Phillips",
"Evans",
"Turner",
"Torres",
"Parker",
"Collins",
"Edwards",
"Stewart",
"Flores",
"Morris",
"Nguyen",
"Murphy",
"Rivera",
"Cook",
"Rogers",
"Morgan",
"Peterson",
"Cooper",
"Reed",
"Bailey",
"Bell",
"Gomez",
"Kelly",
"Howard",
"Ward",
"Cox",
"Diaz",
"Richardson",
"Wood",
"Watson",
"Brooks",
"Bennett",
"Gray",
"James",
"Reyes",
"Cruz",
"Hughes",
"Price",
"Myers",
"Long",
"Foster",
"Sanders",
"Ross",
"Morales",
"Powell",
"Sullivan",
"Russell",
"Ortiz",
"Jenkins",
"Gutierrez",
"Perry",
"Butler",
"Barnes",
"Fisher",
"Henderson",
"Coleman",
"Simmons",
"Patterson",
"Jordan",
"Reynolds",
"Hamilton",
"Graham",
"Kim",
"Gonzales",
"Alexander",
"Ramos",
"Wallace",
"Griffin",
"West",
"Cole",
"Hayes",
"Chavez",
"Gibson",
"Bryant",
"Ellis",
"Stevens",
"Murray",
"Ford",
"Marshall",
"Owens",
"Mcdonald",
"Harrison",
"Ruiz",
"Kennedy",
"Wells",
"Alvarez",
"Woods",
"Mendoza",
"Castillo",
"Olson",
"Webb",
"Washington",
"Tucker",
"Freeman",
"Burns",
"Henry",
"Vasquez",
"Snyder",
"Simpson",
"Crawford",
"Jimenez",
"Porter",
"Mason",
"Shaw",
"Gordon",
"Wagner",
"Hunter",
"Romero",
"Hicks",
"Dixon",
"Hunt",
"Palmer",
"Robertson",
"Black",
"Holmes",
"Stone",
"Meyer",
"Boyd",
"Mills",
"Warren",
"Fox",
"Rose",
"Rice",
"Moreno",
"Schmidt",
"Patel",
"Ferguson",
"Nichols",
"Herrera",
"Medina",
"Ryan",
"Fernandez",
"Weaver",
"Daniels",
"Stephens",
"Gardner"
],
"emailHost": ["hotmail.com", "gmail.com", "yahoo.com"],
"phoneAreaCode": ["905", "807", "705", "647", "613", "519", "416", "343", "289", "226"],
"partyReason": [
"Birthday",
"Surprise",
"Garden",
"Cocktail",
"Tea",
"Dance",
"Costume",
"Pool",
"Singles",
"Fundraising",
"Graduation",
"Dating",
"Housewarming",
"Welcome",
"Farewell",
"Drinking",
"Poker"
],
"streetName": [
"Lane S College W Gladstone",
"Lane E Glenside S Walpole",
"Corona Street",
"Durant Avenue",
"Dana Avenue",
"Drumheller Road",
"Distin Avenue",
"Dixington Crescent",
"Corylus Court",
"Dickens Street",
"Courton Drive",
"Denny Court",
"Delburn Drive",
"Delaware Avenue North",
"Connie Street",
"Diesel Drive",
"Delverton Place",
"Court Square",
"Courage Avenue",
"Donald Avenue",
"Dolan Gate",
"Delisle Avenue",
"Coltman Crescent",
"Dinnick Crescent",
"Dewhurst Boulevard North",
"Cosburn Avenue",
"Delemere Avenue",
"Commons Drive",
"Conroy Avenue",
"Constellation Court",
"Cranborne Avenue",
"Dobbin Road",
"Crestview Road",
"Doctor O Lane",
"Cooper Street",
"Coyote Crescent",
"Crete Court",
"Dekoven Mews",
"Mcglashan Court",
"Delroy Drive",
"Owen Boulevard",
"Dittmer Crescent",
"Lane S Dundas E Hamilton Street",
"Doncrest Road",
"Nagel Road",
"Donna Shaw Lane",
"Neston Avenue",
"Denison Square",
"Cherrydale Court",
"Coules Court",
"Leader Lane",
"Ridgevale Drive",
"Royalavon Crescent",
"Christine Crescent",
"Conference Boulevard",
"Donnybrook Lane",
"Redbird Gate",
"Coronation Drive",
"Dewbourne Avenue",
"Redcar Avenue",
"Cawthra Square",
"Devondale Avenue",
"Tompkins Mews",
"Elgin Avenue",
"Carey Road",
"Rosita Crescent",
"St Columba Place",
"Castlemere Crescent",
"Redland Crescent East",
"Dixon Avenue",
"Dumbarton Road",
"Rosedale Valley Road",
"Redstone Path",
"Dunboyne Court",
"Charlotte Street",
"Peelar Mews",
"Dorine Crescent",
"Duncannon Drive",
"Rosemarie Drive",
"Endicott Avenue",
"Skyridge Road",
"Sackville Street",
"Emmott Avenue",
"Dellbrook Crescent",
"Redfern Avenue",
"Carus Avenue",
"St Helens Avenue",
"Rathnelly Avenue",
"Chestnut Street",
"Duggan Avenue",
"Casebridge Court",
"Dusay Place",
"Rooksnest Trail",
"Sheila Court",
"Peregrine Way",
"Royal Doulton Drive",
"Reindeer Drive",
"Conamore Crescent",
"Caroline Avenue",
"Dunsany Crescent",
"Springmount Avenue",
"Edith Drive",
"Dufflaw Road",
"Relmar Road",
"Pepper Vineway",
"Rock Fernway",
"Elmview Drive",
"Rintella Court",
"Condor Avenue",
"Dundas Square",
"Cascaden Street",
"Chimes Lane",
"Carmichael Avenue",
"Dunvegan Road",
"Rooksgrove Place",
"Craighurst Avenue",
"Emmeline Crescent",
"Paulvale Crescent",
"Dunfield Avenue",
"Emcarr Drive",
"Delahaye Street",
"Raymond Avenue",
"Silversted Drive",
"Cora Crescent",
"Rutland Street",
"Cornwall Street",
"Chipping Road",
"Chetta Place",
"Shawford Crescent",
"Charles H Hiscott Bridge",
"Delaware Avenue",
"Squirewood Road",
"Dorval Road",
"Silverton Avenue",
"Donwoods Lane",
"Cotillion Court",
"Pastrano Court",
"Sherway Gardens Road",
"Chevron Crescent",
"Delsing Drive",
"Peard Road",
"Saddle Ridge Drive",
"Dunkirk Road",
"Raybould Street",
"Charnwood Road",
"Lane N Chapman E Royal York",
"Sawmill Road",
"Peach Willoway",
"Falcon Lane",
"Pinoak Street",
"Photography Drive",
"St Andrews Boulevard",
"Rideau Avenue",
"Lane E Nairn N Rogers",
"Spring Forest Square",
"Ronan Avenue",
"Connolly Street",
"Cheritan Avenue",
"Rossdean Drive",
"Shockley Drive",
"Chipper Crescent",
"Sapling Court",
"Thistle Down Terrace",
"Lane E Ossington S Acores",
"Deep Dene Drive",
"Saunders Avenue",
"Gunns Road",
"Lane S Morningside W Lavinia",
"Hemford Crescent",
"Chestnut Hills Parkway",
"Rawlinson Avenue",
"Madonna Gardens",
"Sheppard Street",
"Lesmill Road",
"Lane W Laing N Sears",
"Lane S Carlton E Sackville Street",
"Civic Road",
"Tillbrook Court",
"Lane W York S Richmond",
"Lane W Montrose S Cinder",
"Hillborn Avenue",
"Lane W Alhambra S Indian Trail",
"Lane S Eglinton W Rostrevor",
"Niantic Crescent",
"Lane E Lount Street S Torbrick",
"Grenview Boulevard South",
"Pine Ridge Drive",
"Donmore Avenue",
"Van Allan Road",
"Lane S Davenport E Salem Avenue",
"Glencrest Boulevard",
"Lane E South Kingsway N Ormskirk Court",
"Thornbury Crescent",
"Lane S College E Beatrice",
"Lane W Yonge N Woburn",
"Lane E Runnymede S Maher",
"Pintail Crescent",
"Vanauley Court",
"Feldbar Court",
"Denison Road West",
"Cather Crescent",
"Mystic Avenue",
"St Clair Avenue East",
"Gretna Avenue",
"Casemore Road",
"Lane W Macdonell N Garden",
"Newbridge Road",
"Grenadier Road",
"Thurodale Avenue",
"Lane S Davenport E Bathurst",
"Ketchum Place",
"Valerie Road",
"Leading Road",
"Saranac Boulevard",
"Nesbitt Drive",
"Lane E Melita Crescent N Wycrest",
"Cranston Manor Court",
"Chestnut Lane",
"Duern Street",
"Horfield Avenue",
"Kentish Crescent",
"Lane E Shaw N Yarmouth",
"Leander Court",
"Lane W Carroll S Thompson",
"Markham Street",
"Hocken Avenue",
"Leroy Avenue",
"Lane E Sunnyside N Galley",
"Crestridge Heights Road",
"Lane S Carlton W Dermott Place",
"Claremont Place",
"Geary Avenue",
"Sherman Court",
"Connaught Avenue",
"Peyton Lane",
"Lane E Sibley S Dentonia Park",
"St Andrews Road",
"Langbourne Place",
"Delaney Crescent",
"Coltbridge Court",
"Hillcrest Drive",
"Vanellan Court",
"Rayward Court",
"Paulander Avenue",
"Newmill Gate",
"Lane 1 W Sorauren N Fern",
"Lane W Wineva S Violet",
"Lackman Court",
"Gennela Square",
"Marathon Crescent",
"Ebonywood Gate",
"Eastdale Avenue",
"Nicholas Avenue",
"Grey Road",
"Tromley Drive",
"Gilroy Drive",
"Lane S Queen W Glen Manor",
"Lane E River N Labatt",
"Manor Road East",
"Hullen Crescent",
"Lambton Avenue",
"Hodge Lane",
"Thistlewaite Crescent",
"Nightingale Place",
"Lane 1 S Carlton W Parliament",
"Farmhill Court",
"Coolhurst Drive",
"Markburn Court",
"Maple Bush Avenue",
"Elba Avenue",
"Ringwood Crescent",
"Emmett Avenue",
"Lethbridge Avenue",
"Nearctic Drive",
"Ravenhill Road",
"Kylemore Crescent",
"Lane S Cook W Haynes",
"Don Roadway",
"Satterly Road",
"Felicity Drive",
"Phenix Drive",
"Duval Drive",
"Vanley Crescent",
"Lunness Road",
"Lane 1 N Foxley W Grove",
"Trinity Street",
"Gerigs Street",
"Latimer Avenue",
"Thornhill Avenue",
"Church Street",
"Thorold Gate",
"Paynter Drive",
"Dewey Drive",
"Reddick Court",
"Lane S Queen W Pape",
"Littles Road",
"Lane S Kingston W Glen Manor Road",
"Thursfield Crescent",
"Cleadon Road",
"Twin Circle Court",
"Munster Avenue",
"Community Circle",
"Thorndale Crescent",
"Bruton Road",
"Safari Street",
"Nettlecreek Crescent",
"Pine Hill Road",
"Marianfeld Avenue",
"Rollins Place",
"Ladysmith Avenue",
"Gypsy Roseway",
"Taylor Road",
"Upper Humber Drive",
"Archgate Lane",
"Ferrand Drive",
"Ameer Avenue",
"Holita Road",
"Lane S Davenport W Walmer",
"Lane 1 N Bloor E Bathurst",
"Leswyn Road",
"Braddock Road",
"Centrepark Drive",
"Lane E Spadina N Harbord",
"Lane W Avon S Avon",
"Evans Lane",
"Lane S The Queensway W Dayton",
"Leslie Street",
"Lane S Gerrard W Parliament",
"Leavenworth Crescent",
"St Albans Road",
"Anola Place",
"Bartlett Avenue",
"Hallmark Avenue",
"Lane W Pape S Cosburn",
"Furnival Road",
"Reno Drive",
"Lane S Ascot W Nairn",
"Lane W Indian Road S Annette",
"Lane 1 E Yonge S Charles",
"Lyall Avenue",
"Simcoe Street",
"Larabee Crescent",
"Deakin Avenue",
"Lane E Brock N Brockton",
"Dora Avenue",
"Harvest Moon Drive",
"Homeview Avenue",
"Lane E Melita Crescent S Lambertlodge",
"Harnworth Drive",
"Muir Drive",
"Rensburg Drive",
"Lane E Ohara N Maple Grove",
"Muir Avenue",
"Hasbrooke Drive",
"Ranstone Gardens",
"Eglinton E St Dennis Ramp",
"Eglinton W 27 N Ramp",
"Avalon Avenue",
"Sunburst Square",
"Guildpark Pathway",
"Fermanagh Avenue",
"Bexhill Court",
"Benlark Court",
"Penny Lane",
"Lane E Pape N Harcourt",
"Atlee Avenue",
"Berkindale Crescent",
"Triton Road",
"Anvil Millway",
"Lane S Lake Shore E 10th",
"Lane S Rogers W Nairn",
"Pepper Tree Drive",
"Parsonage Drive",
"Bevdale Road",
"Lane S Davenport W Osler",
"Hardwick Court",
"Hillwood Court",
"Lane E Spadina N Lonsdale",
"Marsh Grassway",
"Marrakesh Drive",
"Comrie Terrace",
"Thornbush Crescent",
"Lane S Yorkminster W Fairmeadow",
"Maresfield Drive",
"Springbank Avenue",
"Mainshep Road",
"Lane 3 N Bloor W Bartlett",
"Purpledusk Trail",
"Lane E Grace N Plymouth",
"Genessee Avenue",
"Benedict Road",
"Prue Avenue",
"Lane W Jarvis S Shuter",
"Lane S Hepbourne W Ossington",
"Evans W West Mall Ramp",
"Netheravon Road",
"Lindylou Road",
"Lane E Bernice S Eileen",
"Charlesworth Lane",
"Haddon Avenue",
"Lane W Arlington S St Clair",
"Tilden Crescent",
"Garrybrook Drive",
"Silbury Drive",
"Benbow Road",
"Signal Hill Avenue",
"Lormar Drive",
"Cherryhill Avenue",
"Mulvey Avenue",
"Dynevor Road",
"Lane 1 W Airley S 4 Oaks",
"Lane E Earlscourt N Rogers",
"Pumfrey Crescent",
"Lakeshore W Browns Line Ramp",
"Lane W Greensides S Benson",
"Lane S Argyle E Northcote",
"Lane W Symington N Kingsley",
"Lane E Hazelton S Scollard",
"Garrison Road",
"Lane S Yarmouth W Miles Place",
"Needham Drive",
"Lane E Broadview N Dundas",
"Macgregor Avenue",
"Lane W Shaw N Harbord",
"Pettibone Square",
"Lane S Helena E Wychwood",
"Nina Street",
"Lane S Bloor E Grace",
"Lane W Evans N Ardagh",
"Gillard Avenue",
"Dunsdale Square",
"Lane E Ossington N Acores",
"Regency Square",
"Pear Tree Mews",
"Stonegate Road",
"Ladner Drive",
"Thorny Vineway",
"Farley Crescent",
"Gatesview Avenue",
"Lane E Burrard N Hadrian",
"Lane 1 N Gerrard W Hastings",
"Lane S Eglinton E Northcliffe",
"Guildwood Parkway",
"Pont Lane",
"Amarillo Drive",
"Lane S College W Beatrice",
"Atomic Avenue",
"Sunshine Street",
"Munson Crescent",
"Hillock Place",
"Lane 1 N Newport W Byng",
"Mansewood Gardens",
"Newbold Avenue",
"Salem Avenue North",
"Lane E Mcroberts S Rogers",
"Lane E Broadview N Gerrard",
"Ellendale Drive",
"Cliff Street",
"Lane S Dundas W St Clarens",
"Lane S Howard Park W Lynd",
"Thyme Court",
"Southlawn Drive",
"Leafy Woodway",
"Donna Court",
"Council Crescent",
"Trio Avenue",
"Denewood Crescent",
"St Emilion Way",
"Don Mount Court",
"Lane S Liberty E Jefferson",
"York Avenue",
"Bernard Avenue",
"Court Street",
"Lane E Carling S Irene Avenue",
"Dunedin Drive",
"Chestnut Park",
"Lane S Dundas E Cordova",
"Munford Crescent",
"Niven Street",
"Benlight Crescent",
"Landry Avenue",
"Oakley Boulevard",
"Hopedale Avenue",
"Lane 2 S Eastern E Logan",
"Denton Avenue",
"Grenadine Court",
"Vanderhoof Avenue",
"Suraty Avenue",
"Penrose Road",
"Degrey Court",
"Hopecrest Crescent",
"Lane S Eastern W Knox",
"Major Street",
"Elgin Road",
"Lane W Yonge N Wellesley",
"Severn Road",
"Beta Street",
"Murmouth Road",
"Lapsley Road",
"Lane S Bloor W Lothian"
],
"food": ["apples", "oranges", "bananas", "pineapples", "strawberry"],
"drink": ["coke", "milk", "coffee", "tea", "juice"],
"decoration": ["flowers", "stickers", "balloons", "pumpkins", "tapes"],
"other": ["pens", "table cloth", "straws", "cups", "chopsticks"]
}

View File

@@ -0,0 +1,560 @@
import pg from "pg";
import dotenv from "dotenv";
import jsonfile from "jsonfile";
import path from "path";
import crypto from "crypto";
import { hashPassword } from "../functions/hash";
import { DataParts, Users } from "../models";
import { format } from "date-fns";
import { logger } from "../logger";
function randomDate(start: Date, days: number): Date {
const startTime = start.getTime();
const minusTime = startTime - days * 86_400_000;
const plusTime = startTime + days * 86_400_000;
return new Date(minusTime + Math.random() * (plusTime - minusTime));
}
function randomIntFromInterval(min: number, max: number): number {
return Math.floor(Math.random() * (max - min + 1) + min);
}
export async function clearDB() {
dotenv.config();
const client = new pg.Client({
host: process.env.DB_HOST,
database: process.env.DB_NAME,
user: process.env.DB_USERNAME,
password: process.env.DB_PASSWORD,
});
await client.connect();
await client.query(`
DROP TABLE event_date_time_votes;
DROP TABLE event_date_time;
DROP TABLE event_venues_votes;
DROP TABLE event_venues;
DROP TABLE comments;
DROP TABLE time_block_item;
DROP TABLE time_blocks;
DROP TABLE items;
DROP TABLE participants;
DROP TABLE events;
DROP TABLE users;
`);
await client.end();
}
export async function initDB() {
dotenv.config();
const client = new pg.Client({
host: process.env.DB_HOST,
database: process.env.DB_NAME,
user: process.env.DB_USERNAME,
password: process.env.DB_PASSWORD,
});
await client.connect();
await client.query(`CREATE TABLE users (
id SERIAL primary key,
first_name varchar not NULL,
last_name varchar not NULL,
email varchar not NULL,
phone varchar not NULL,
password varchar not NULL,
created_at timestamp not NULL,
updated_at timestamp not NULL
);
CREATE TABLE events (
id SERIAL primary key,
name varchar not NULL,
venue varchar,
start_datetime timestamptz,
end_datetime timestamptz,
creator_id int not NULL,
invitation_token varchar not NULL,
deleted boolean not NULL,
date_poll_created boolean not NULL,
date_poll_terminated boolean not NULL,
venue_poll_created boolean not NULL,
venue_poll_terminated boolean not NULL,
created_at timestamp not NULL,
updated_at timestamp not NULL,
FOREIGN KEY (creator_id) REFERENCES users(id)
);
CREATE TABLE participants (
id SERIAL primary key,
event_id int not NULL,
user_id int not NULL,
created_at timestamp not NULL,
updated_at timestamp not NULL,
FOREIGN KEY (event_id) REFERENCES events(id),
FOREIGN KEY (user_id) REFERENCES users(id)
);
CREATE TABLE items (
id SERIAL primary key,
name varchar not NULL,
purchased boolean not NULL,
type_name varchar not NULL,
event_id int not NULL,
user_id int not NULL,
quantity int,
price int,
created_at timestamp not NULL,
updated_at timestamp not NULL,
FOREIGN KEY (event_id) REFERENCES events(id),
FOREIGN KEY (user_id) REFERENCES users(id)
);
CREATE TABLE time_blocks (
id SERIAL primary key,
title varchar not NULL,
description varchar,
event_id int not NULL,
user_id int not NULL,
date varchar,
start_time time not NULL,
end_time time not NULL,
color varchar,
remark varchar,
remark_2 varchar,
remark_3 varchar,
created_at timestamp not NULL,
updated_at timestamp not NULL,
FOREIGN KEY (event_id) REFERENCES events(id),
FOREIGN KEY (user_id) REFERENCES users(id)
);
CREATE TABLE time_block_item (
id SERIAL primary key,
item_id int not NULL,
time_block_id int not NULL,
quantity int,
created_at timestamp not NULL,
updated_at timestamp not NULL,
FOREIGN KEY (item_id) REFERENCES items(id),
FOREIGN KEY (time_block_id) REFERENCES time_blocks(id)
);
CREATE TABLE comments (
id SERIAL primary key,
user_id int not NULL,
event_id int not NULL,
category varchar not NULL,
content varchar not NULL,
anonymous boolean not NULL,
read boolean not NULL DEFAULT 'false',
created_at timestamp not NULL,
updated_at timestamp not NULL,
FOREIGN KEY (user_id) REFERENCES users(id),
FOREIGN KEY (event_id) REFERENCES events(id)
);
CREATE TABLE event_venues (
id SERIAL primary key,
address varchar not NULL,
event_id int not NULL,
created_at timestamp not NULL,
updated_at timestamp not NULL,
FOREIGN KEY (event_id) REFERENCES events(id)
);
CREATE TABLE event_venues_votes (
id SERIAL primary key,
event_venues_id int not NULL,
user_id int not NULL,
created_at timestamp not NULL,
updated_at timestamp not NULL,
FOREIGN KEY (event_venues_id) REFERENCES event_venues(id),
FOREIGN KEY (user_id) REFERENCES users(id)
);
CREATE TABLE event_date_time (
id SERIAL primary key,
start_datetime timestamptz not NULL,
end_datetime timestamptz not NULL,
event_id int not NULL,
created_at timestamp not NULL,
updated_at timestamp not NULL,
FOREIGN KEY (event_id) REFERENCES events(id)
);
CREATE TABLE event_date_time_votes (
id SERIAL primary key,
event_date_time_id int not NULL,
user_id int not NULL,
created_at timestamp not NULL,
updated_at timestamp not NULL,
FOREIGN KEY (event_date_time_id) REFERENCES event_date_time(id),
FOREIGN KEY (user_id) REFERENCES users(id)
);`);
client.end();
}
export async function regUsers(newUsersAmount: number) {
dotenv.config();
const client = new pg.Client({
host: process.env.DB_HOST,
database: process.env.DB_NAME,
user: process.env.DB_USERNAME,
password: process.env.DB_PASSWORD,
});
await client.connect();
// Insert test user when DB is empty
const [usersDB] = (await client.query(`SELECT * FROM users WHERE id = -1;`)).rows;
if (!usersDB) {
const first_name = "Gordon";
const last_name = "Lau";
const email = "gordonlau@tecky.io";
const phone = "647-111-1111";
const testPassword = await hashPassword("test");
await client.query(
`INSERT INTO users
(id,first_name,last_name,email,phone,password,created_at,updated_at)
VALUES (-1,$1,$2,$3,$4,$5,CURRENT_TIMESTAMP,CURRENT_TIMESTAMP);`,
[first_name, last_name, email, phone, testPassword]
);
}
// Read random data parts for data assembling
let parts: DataParts = await jsonfile.readFile(path.join(__dirname, "/data/dataParts.json"));
let counter = 0;
while (counter < newUsersAmount) {
// Names
const first_name: string = parts["firstName"][Math.floor(Math.random() * parts["firstName"].length)];
const last_name: string = parts["lastName"][Math.floor(Math.random() * parts["lastName"].length)];
// Email
const emailHost: string = parts["emailHost"][Math.floor(Math.random() * parts["emailHost"].length)];
const email: string = `${first_name.toLowerCase()}${last_name.toLowerCase()}@${emailHost}`;
// Phone
const phoneAreaCode: string = parts["phoneAreaCode"][Math.floor(Math.random() * parts["phoneAreaCode"].length)];
const phone: string = `${phoneAreaCode}-${Math.random()
.toString()
.concat("0".repeat(3))
.substring(2, 3)}-${Math.random().toString().concat("0".repeat(3)).substring(2, 4)}`;
// Password
const password: string = "test";
const hashedPassword = await hashPassword(password);
const [checkUsers] = (await client.query(`SELECT * FROM users WHERE email = $1 OR phone = $2;`, [email, phone]))
.rows;
if (!checkUsers) {
await client.query(
`INSERT INTO users
(first_name,last_name,email,phone,password,created_at,updated_at)
VALUES ($1,$2,$3,$4,$5,CURRENT_TIMESTAMP,CURRENT_TIMESTAMP);`,
[first_name, last_name, email, phone, hashedPassword]
);
counter++;
}
}
client.end();
}
export async function createEvents(eventNumbers: number) {
dotenv.config();
const client = new pg.Client({
host: process.env.DB_HOST,
database: process.env.DB_NAME,
user: process.env.DB_USERNAME,
password: process.env.DB_PASSWORD,
});
await client.connect();
// Read random data parts for data assembling
let parts: DataParts = await jsonfile.readFile(path.join(__dirname, "/data/dataParts.json"));
// Obtain users info for event creation for each user
let users: Users[] = (await client.query(`SELECT * FROM users;`)).rows;
for (let i = 0; i < eventNumbers; i++) {
for (const user of users) {
// Party name
const partyReason: string = parts["partyReason"][Math.floor(Math.random() * parts["partyReason"].length)];
const name: string = `${user.first_name}'s ${partyReason} Party`;
// Party venue
const venue: string = `${Math.floor(Math.random() * 999) + 1} ${
parts["streetName"][Math.floor(Math.random() * parts["streetName"].length)]
}`;
// Date
const date: string = format(randomDate(new Date(), 100), "yyyy/MM/dd");
const userDetail = (await client.query(`SELECT * FROM users WHERE email = $1;`, [user.email])).rows[0];
// Time
const start_time: string = `${randomIntFromInterval(12, 17)}:${Math.random() > 0.5 ? "00" : "30"}`;
const end_time: string = `${randomIntFromInterval(18, 23)}:${Math.random() > 0.5 ? "00" : "30"}`;
// DateTime
const start_datetime: string = new Date(`${date} ${start_time}`).toISOString();
const end_datetime: string = new Date(`${date} ${end_time}`).toISOString();
// Creator id
const creator_id: number = userDetail.id;
// Invitation Token
const invitation_token = crypto.randomBytes(64).toString("hex");
await client.query(
`INSERT INTO events
(name,venue,start_datetime,end_datetime,
creator_id,invitation_token,deleted,
date_poll_created,
date_poll_terminated,
venue_poll_created,
venue_poll_terminated,
created_at,updated_at)
VALUES ($1,$2,$3,$4,$5,$6,FALSE,FALSE,FALSE,FALSE,FALSE,
CURRENT_TIMESTAMP,CURRENT_TIMESTAMP);`,
[name, venue, start_datetime, end_datetime, creator_id, invitation_token]
);
}
}
client.end();
}
export async function joinEvents(eventsJoinedPerUser: number) {
dotenv.config();
const client = new pg.Client({
host: process.env.DB_HOST,
database: process.env.DB_NAME,
user: process.env.DB_USERNAME,
password: process.env.DB_PASSWORD,
});
await client.connect();
const eventsParticipantsRelations = (
await client.query(
`SELECT DISTINCT events.id as event_id,
events.creator_id,
participants.user_id as participants_id
FROM events
LEFT JOIN participants ON events.id = participants.event_id
ORDER BY events.id, participants.user_id;
`
)
).rows;
let usersOfEventsList:
| {
(keys: number): {
creator_id: number;
participants_id: number[] | null[];
};
}
| {} = {};
for (let relation of eventsParticipantsRelations) {
if (!(relation.event_id in usersOfEventsList)) {
usersOfEventsList[relation.event_id] = {
creator_id: relation.creator_id,
participants_id: relation.participants_id ? [relation.participants_id] : [],
};
} else {
usersOfEventsList[relation.event_id]["participants_id"].push(relation.participants_id);
}
}
let usersIdList = (await client.query(`SELECT id FROM users;`)).rows;
for (let userId of usersIdList) {
let eventsJoined = 0;
for (const eventId in usersOfEventsList) {
const usersInfoInEvent = usersOfEventsList[eventId];
if (usersInfoInEvent.creator_id !== userId.id && !usersInfoInEvent.participants_id.includes(userId.id)) {
await client.query(
`
INSERT INTO participants (event_id, user_id, created_at, updated_at)
VALUES ($1, $2, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP);
`,
[eventId, userId.id]
);
eventsJoined++;
}
if (eventsJoined === eventsJoinedPerUser) {
break;
}
}
}
client.end();
}
export async function addParticipants(eventId: number, participantsAmount: number) {
dotenv.config();
const client = new pg.Client({
host: process.env.DB_HOST,
database: process.env.DB_NAME,
user: process.env.DB_USERNAME,
password: process.env.DB_PASSWORD,
});
await client.connect();
try {
// Get creator ID of the event (need to exclude)
const [creatorUserObj] = (
await client.query(
`
SELECT creator_id FROM events WHERE id = $1;
`,
[eventId]
)
).rows;
if (!creatorUserObj) {
throw new Error(`No such event (event id: ${eventId})!`);
}
const creatorUser: number = creatorUserObj.creator_id;
// Get participant ID of the event (need to exclude)
const participantsObj: { [key: string]: number }[] = (
await client.query(
`
SELECT user_id FROM participants
WHERE event_id = $1;
`,
[eventId]
)
).rows;
const participants = participantsObj.map((each) => {
return each.user_id;
});
// Obtain users info for event creation for each user (excluding creator)
const userIdListRawObj: { [key: string]: number }[] = (
await client.query(
`
SELECT id FROM users
WHERE id != $1;
`,
[creatorUser]
)
).rows;
const userIdListRaw: number[] = userIdListRawObj.map((each) => {
return each.id;
});
const participantsSet = new Set(participants);
const userIdList = userIdListRaw.filter((userId) => {
return !participantsSet.has(userId);
});
const loopTimes: number = Math.min(userIdList.length, participantsAmount);
for (let i = 0; i < loopTimes; i++) {
const usersIndex: number = Math.floor(Math.random() * userIdList.length);
const [userId] = userIdList.splice(usersIndex, 1);
await client.query(
`INSERT INTO participants
(event_id,user_id,created_at,updated_at)
VALUES ($1,$2,CURRENT_TIMESTAMP,CURRENT_TIMESTAMP);`,
[eventId, userId]
);
}
} catch (e) {
logger.error(e);
}
client.end();
}
export async function addItems(eventId: number) {
dotenv.config();
const client = new pg.Client({
host: process.env.DB_HOST,
database: process.env.DB_NAME,
user: process.env.DB_USERNAME,
password: process.env.DB_PASSWORD,
});
await client.connect();
try {
// Read random data parts for data assembling
let parts: DataParts = await jsonfile.readFile(path.join(__dirname, "/data/dataParts.json"));
// Get participant ID of the event (need to exclude)
const participantsObj: { [key: string]: number }[] = (
await client.query(
`
SELECT user_id FROM participants
WHERE event_id = $1;
`,
[eventId]
)
).rows;
const participants = participantsObj.map((each) => {
return each.user_id;
});
// addItems
let types = ["food", "drink", "decoration", "other"];
for (let type of types) {
for (let i = 0; i < parts[type].length; i++) {
await client.query(
`
INSERT INTO items
(name, purchased, type_name, event_id, user_id, quantity, price, created_at, updated_at)
VALUES ($1, $2 ,$3, $4, $5, $6, $7, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP);
`,
[
parts[type][i],
Math.random() > 0.5,
type,
eventId,
participants.splice(0, 1)[0],
Math.floor(Math.random() * 20),
Math.floor(Math.random() * 1000),
]
);
}
}
} catch (e) {
logger.error(e);
}
client.end();
}
export async function truncateDB() {
dotenv.config();
const client = new pg.Client({
host: process.env.DB_HOST,
database: process.env.DB_NAME,
user: process.env.DB_USERNAME,
password: process.env.DB_PASSWORD,
});
await client.connect();
await client.query(`
DELETE FROM event_date_time_votes;
DELETE FROM event_date_time;
DELETE FROM event_venues_votes;
DELETE FROM event_venues;
DELETE FROM comments;
DELETE FROM time_block_item;
DELETE FROM time_blocks;
DELETE FROM items;
DELETE FROM participants;
DELETE FROM events;
DELETE FROM users;
`);
client.end();
jsonfile.writeFile(path.join(__dirname, "/data/users.json"), []);
}

View File

@@ -0,0 +1,4 @@
import { addItems } from '../dbSetupFunctions';
const eventId = 1;
addItems(eventId);

View File

@@ -0,0 +1,5 @@
import { addParticipants } from '../dbSetupFunctions';
const eventId = 1;
const participantsAmount = 100;
addParticipants(eventId, participantsAmount);

View File

@@ -0,0 +1,3 @@
import { clearDB } from '../dbSetupFunctions';
clearDB();

View File

@@ -0,0 +1,4 @@
import { createEvents } from '../dbSetupFunctions';
const eventNumbers = 50;
createEvents(eventNumbers);

View File

@@ -0,0 +1,3 @@
import { initDB } from "../dbSetupFunctions";
initDB();

View File

@@ -0,0 +1,4 @@
import { joinEvents } from '../dbSetupFunctions';
const eventsJoinedPerUser = 50;
joinEvents(eventsJoinedPerUser);

View File

@@ -0,0 +1,46 @@
import pg from "pg";
import dotenv from "dotenv";
import { addItems, addParticipants, clearDB, createEvents, initDB, regUsers } from "../dbSetupFunctions";
const newUsersNumber: number = 100;
const createEventsAmountPerUser: number = 1;
const eventId: number = 1;
const participantAmount: number = 100;
lazy();
async function lazy() {
dotenv.config();
const client = new pg.Client({
host: process.env.DB_HOST,
database: process.env.DB_NAME,
user: process.env.DB_USERNAME,
password: process.env.DB_PASSWORD,
});
await client.connect();
const [tableCount] = (
await client.query(`
select count(*)
from information_schema.tables
where table_schema = 'public';
`)
).rows;
console.log(tableCount);
await client.end();
if (parseInt(tableCount.count)) {
await clearDB();
}
await initDB();
await regUsers(newUsersNumber);
await createEvents(createEventsAmountPerUser);
await addParticipants(eventId, participantAmount);
await addItems(eventId);
}

View File

@@ -0,0 +1,4 @@
import { regUsers } from '../dbSetupFunctions';
const newUsersAmount = 10;
regUsers(newUsersAmount);

View File

@@ -0,0 +1,3 @@
import { truncateDB } from '../dbSetupFunctions';
truncateDB();

View File

@@ -0,0 +1,13 @@
import * as bcrypt from 'bcryptjs';
const SALT_ROUNDS = 10;
export async function hashPassword(plainPassword: string) {
const hash = await bcrypt.hash(plainPassword, SALT_ROUNDS);
return hash;
}
export async function checkPassword(plainPassword: string, hashPassword: string) {
const match = await bcrypt.compare(plainPassword, hashPassword);
return match;
}

View File

@@ -0,0 +1,3 @@
export function onlyNumbers(str: string): boolean {
return /^[0-9]+$/.test(str);
}

View File

@@ -0,0 +1,29 @@
import express from 'express';
export const isLoggedIn = (req: express.Request, res: express.Response, next: express.NextFunction) => {
if (req.session?.user) {
next();
} else {
res.status(404).redirect('/landingPage.html');
}
};
export const isLoggedInAPI = (req: express.Request, res: express.Response, next: express.NextFunction) => {
if (req.session?.user) {
next();
} else {
// redirect to 404 page
res.status(400).json({ error: "You don't have the permission" });
}
};
export const isLoggedInInvitation = (req: express.Request, res: express.Response, next: express.NextFunction) => {
if (req.session?.user) {
next();
} else {
res.json({
status: false,
login: false
});
}
};

View File

@@ -0,0 +1,12 @@
import winston from 'winston';
const logFormat = winston.format.printf(function (info) {
let date = new Date().toISOString();
return `${date}[${info.level}]: ${info.message}\n`;
});
export const logger = winston.createLogger({
level: 'info',
format: winston.format.combine(winston.format.colorize(), logFormat),
transports: [new winston.transports.Console()]
});

View File

@@ -0,0 +1,60 @@
export interface Events {
id: number;
name: string;
venue: string | null;
start_datetime: string | null;
end_datetime: string | null;
creator_id: number;
invitation_token: string;
deleted: boolean;
created_at: string;
updated_at: string;
status?: string;
}
export interface Users {
id: number;
first_name: string;
last_name: string;
email: string;
phone: string | null;
password: string;
created_at: string;
updated_at: string;
}
export type UsersInput = Omit<Users, 'id' | 'created_at' | 'updated_at'>;
export type UserPickedInput = Pick<Users, 'id' | 'created_at' | 'updated_at'>;
export interface Participants {
id: number;
event_id: number;
user_id: number;
created_at: string;
updated_at: string;
}
export interface DataParts {
firstName: string[];
lastName: string[];
emailHost: string[];
phoneAreaCode: string[];
partyReason: string[];
streetName: string[];
food: string[];
drink: string[];
decoration: string[];
other: string[];
}
export interface Items {
event_id: number;
user_id: number;
name: string;
type_name: string;
quantity: number;
price: number | null;
created_at: string;
updated_at: string;
}