---
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
node_modules
|
||||
deploy.sh
|
||||
@@ -0,0 +1,9 @@
|
||||
root = true
|
||||
[*]
|
||||
quote_type = single
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = false
|
||||
insert_final_newline = false
|
||||
@@ -0,0 +1,32 @@
|
||||
DB_USERNAME=
|
||||
DB_PASSWORD=
|
||||
DB_HOST=
|
||||
DB_PORT=
|
||||
DB_DATABASE=
|
||||
REDIS_URL=
|
||||
REDIS_SECRET=
|
||||
API_PORT=
|
||||
FRONTEND_ORIGIN=
|
||||
BACKEND_ORIGIN=
|
||||
DOMAIN_SUFFIX=
|
||||
NON_API_ERROR_PREFIX=
|
||||
NON_API_ERROR_SUFFIX=
|
||||
AWS_REGION=
|
||||
AWS_ACCOUNT_ID=
|
||||
AWS_ACCESS_KEY_ID=
|
||||
AWS_SECRET_ACCESS_KEY=
|
||||
S3_BUCKET=
|
||||
QUICKSIGHT_DASHBOARD_ID=
|
||||
FIREBASE_ADMIN_TYPE=
|
||||
FIREBASE_ADMIN_PROJECT_ID=
|
||||
FIREBASE_ADMIN_PRIVATE_KEY_ID=
|
||||
FIREBASE_ADMIN_PRIVATE_KEY=
|
||||
FIREBASE_ADMIN_CLIENT_EMAIL=
|
||||
FIREBASE_ADMIN_CLIENT_ID=
|
||||
FIREBASE_ADMIN_AUTH_URI=
|
||||
FIREBASE_TOKEN_URI=
|
||||
FIREBASE_ADMIN_AUTH_PROVIDER_X509_CERT_URL=
|
||||
FIREBASE_ADMIN_CLIENT_X509_CERT_URL=
|
||||
SMTP_HOST=
|
||||
SMTP_PORT=
|
||||
SMTP_SECURE=
|
||||
@@ -0,0 +1,5 @@
|
||||
node_modules
|
||||
.env
|
||||
.env.development
|
||||
.env.production
|
||||
deploy.sh
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
FROM node:latest
|
||||
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
COPY package.json .
|
||||
COPY package-lock.json .
|
||||
RUN npm install
|
||||
|
||||
COPY . .
|
||||
COPY .env.production .env
|
||||
ENV NODE_ENV production
|
||||
|
||||
EXPOSE 4000
|
||||
|
||||
CMD ["npm", "run", "start"]
|
||||
@@ -0,0 +1,42 @@
|
||||
declare global {
|
||||
namespace NodeJS {
|
||||
interface ProcessEnv {
|
||||
DB_USERNAME: string;
|
||||
DB_PASSWORD: string;
|
||||
DB_HOST: string;
|
||||
DB_PORT: string;
|
||||
DB_DATABASE: string;
|
||||
REDIS_URL: string;
|
||||
REDIS_SECRET: string;
|
||||
API_PORT: string;
|
||||
FRONTEND_ORIGIN: string;
|
||||
BACKEND_ORIGIN: string;
|
||||
DOMAIN_SUFFIX: string;
|
||||
NON_API_ERROR_PREFIX: string;
|
||||
NON_API_ERROR_SUFFIX: string;
|
||||
AWS_REGION: string;
|
||||
AWS_ACCOUNT_ID: string;
|
||||
AWS_ACCESS_KEY_ID: string;
|
||||
AWS_SECRET_ACCESS_KEY: string;
|
||||
S3_BUCKET: string;
|
||||
QUICKSIGHT_DASHBOARD_ID: string;
|
||||
FIREBASE_ADMIN_TYPE: string;
|
||||
FIREBASE_ADMIN_PROJECT_ID: string;
|
||||
FIREBASE_ADMIN_PRIVATE_KEY_ID: string;
|
||||
FIREBASE_ADMIN_PRIVATE_KEY: string;
|
||||
FIREBASE_ADMIN_CLIENT_EMAIL: string;
|
||||
FIREBASE_ADMIN_CLIENT_ID: string;
|
||||
FIREBASE_ADMIN_AUTH_URI: string;
|
||||
FIREBASE_TOKEN_URI: string;
|
||||
FIREBASE_ADMIN_AUTH_PROVIDER_X509_CERT_URL: string;
|
||||
FIREBASE_ADMIN_CLIENT_X509_CERT_URL: string;
|
||||
SMTP_HOST: string;
|
||||
SMTP_PORT: string;
|
||||
SMTP_SECURE: string;
|
||||
SMTP_USER: string;
|
||||
SMTP_PASS: string;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export {}
|
||||
Generated
+6944
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,62 @@
|
||||
{
|
||||
"name": "comroots-backend",
|
||||
"version": "1.0.0",
|
||||
"description": "Backend for Comroots. Uses PostgreSQL, Redis, and ExpressJS. Hosted as a Docker container using Dokku.",
|
||||
"main": "index.js",
|
||||
"type": "commonjs",
|
||||
"scripts": {
|
||||
"dev": "nodemon --watch . src/index.ts",
|
||||
"start": "ts-node src/index.ts",
|
||||
"env:generate": "gen-env-types .env -o env.d.ts -e .",
|
||||
"typeorm": "ts-node ./node_modules/typeorm/cli.js",
|
||||
"migration:initial": "run typeorm migration:generate -d src/type-orm.source.ts src/migrations/Initial",
|
||||
"migration:entities-update": "run typeorm migration:generate -d src/type-orm.source.ts src/migrations/EntitiesUpdate",
|
||||
"migration:new": "run typeorm migration:create"
|
||||
},
|
||||
"dependencies": {
|
||||
"@faker-js/faker": "^7.4.0",
|
||||
"@types/graphql-upload": "^8.0.11",
|
||||
"apollo-server-core": "^3.8.2",
|
||||
"apollo-server-errors": "^3.3.1",
|
||||
"apollo-server-express": "^3.8.2",
|
||||
"argon2": "^0.28.5",
|
||||
"aws-sdk": "^2.1172.0",
|
||||
"connect-redis": "^6.1.3",
|
||||
"dataloader": "^2.1.0",
|
||||
"dotenv-safe": "^8.2.0",
|
||||
"express": "^4.18.1",
|
||||
"express-session": "^1.17.3",
|
||||
"firebase-admin": "^11.0.0",
|
||||
"fireorm": "^0.23.3",
|
||||
"graphql": "^15.3.0",
|
||||
"graphql-upload": "13.0.0",
|
||||
"ioredis": "^5.1.0",
|
||||
"lodash": "^4.17.21",
|
||||
"nodemailer": "^6.7.5",
|
||||
"pg": "^8.7.3",
|
||||
"redis-session": "^0.1.0",
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"type-graphql": "^1.1.1",
|
||||
"typeorm": "^0.3.7",
|
||||
"uuid": "^8.3.2",
|
||||
"@swc/core": "^1.2.213",
|
||||
"@swc/helpers": "^0.4.3",
|
||||
"ts-node": "^10.8.2",
|
||||
"tsconfig-paths": "^4.0.0",
|
||||
"regenerator-runtime": "^0.13.9"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/connect-redis": "^0.0.18",
|
||||
"@types/dotenv-safe": "^8.1.2",
|
||||
"@types/express": "^4.17.13",
|
||||
"@types/express-session": "^1.17.4",
|
||||
"@types/ioredis": "^4.28.10",
|
||||
"@types/lodash": "^4.14.182",
|
||||
"@types/node": "^17.0.41",
|
||||
"@types/nodemailer": "^6.4.4",
|
||||
"@types/uuid": "^8.3.4",
|
||||
"gen-env-types": "^1.3.4",
|
||||
"nodemon": "^2.0.16",
|
||||
"typescript": "^4.7.3"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
import { Collection, getRepository, ISubCollection, SubCollection } from 'fireorm'
|
||||
import { Field, Int, ObjectType } from 'type-graphql'
|
||||
|
||||
@ObjectType()
|
||||
export class Message {
|
||||
@Field()
|
||||
id: string
|
||||
|
||||
@Field(() => String)
|
||||
createdAt: Date
|
||||
|
||||
@Field(() => String)
|
||||
updatedAt: Date
|
||||
|
||||
@Field(() => String)
|
||||
type: 'text' | 'image' | 'video' | 'audio' | 'file'
|
||||
|
||||
@Field(() => String)
|
||||
content: string
|
||||
|
||||
@Field(() => Int)
|
||||
senderId: number
|
||||
}
|
||||
|
||||
@ObjectType()
|
||||
@Collection('conversations')
|
||||
export class ConversationInFirestore {
|
||||
@Field()
|
||||
id: string
|
||||
|
||||
@SubCollection(Message, 'messages')
|
||||
messages: ISubCollection<Message>
|
||||
}
|
||||
|
||||
export const ConversationCol = getRepository(ConversationInFirestore)
|
||||
@@ -0,0 +1,17 @@
|
||||
import { Collection, getRepository } from 'fireorm'
|
||||
import { ObjectType, Field, Int } from 'type-graphql'
|
||||
|
||||
@ObjectType()
|
||||
@Collection('inboxes')
|
||||
export class Inbox {
|
||||
@Field()
|
||||
id: string
|
||||
|
||||
@Field(() => Int)
|
||||
userId: number
|
||||
|
||||
@Field(() => [String])
|
||||
conversationIds: string[]
|
||||
}
|
||||
|
||||
export const InboxCol = getRepository(Inbox)
|
||||
@@ -0,0 +1,2 @@
|
||||
export * from './Conversation'
|
||||
export * from './Inbox'
|
||||
@@ -0,0 +1,12 @@
|
||||
import AWS from 'aws-sdk'
|
||||
|
||||
AWS.config.update({
|
||||
region: process.env.AWS_REGION,
|
||||
credentials: {
|
||||
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
|
||||
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY
|
||||
}
|
||||
})
|
||||
|
||||
export const s3 = new AWS.S3({ apiVersion: '2006-03-01' })
|
||||
export const quicksight = new AWS.QuickSight()
|
||||
@@ -0,0 +1,14 @@
|
||||
import admin from 'firebase-admin'
|
||||
import { getFirestore } from 'firebase-admin/firestore'
|
||||
import * as fireorm from 'fireorm'
|
||||
|
||||
const app = admin.initializeApp({
|
||||
credential: admin.credential.cert({
|
||||
clientEmail: process.env.FIREBASE_ADMIN_CLIENT_EMAIL,
|
||||
privateKey: process.env.FIREBASE_ADMIN_PRIVATE_KEY,
|
||||
projectId: process.env.FIREBASE_ADMIN_PROJECT_ID
|
||||
})
|
||||
})
|
||||
|
||||
export const firestore = getFirestore(app)
|
||||
fireorm.initialize(firestore)
|
||||
@@ -0,0 +1,3 @@
|
||||
export * from './aws.config'
|
||||
export * from './type-orm.config'
|
||||
export * from './firebase.config'
|
||||
@@ -0,0 +1,39 @@
|
||||
import { Comment, CommentVote, Conversation, CV, EducationItem, Experience, Offer, OfferApplication, Page, PageFollow, Post, Qualification, Space, SpaceSubscription, Tag, Vote, User, UserFollow } from '@entities'
|
||||
import path from 'path'
|
||||
import { DataSource } from 'typeorm'
|
||||
|
||||
export const typeORMConfig = {
|
||||
type: 'postgres',
|
||||
username: process.env.DB_USERNAME,
|
||||
password: process.env.DB_PASSWORD,
|
||||
host: process.env.DB_HOST,
|
||||
port: parseInt(process.env.DB_PORT),
|
||||
database: process.env.DB_DATABASE,
|
||||
logging: true,
|
||||
synchronize: false,
|
||||
entities: [
|
||||
User,
|
||||
Post,
|
||||
Vote,
|
||||
Space,
|
||||
SpaceSubscription,
|
||||
Comment,
|
||||
CommentVote,
|
||||
Offer,
|
||||
OfferApplication,
|
||||
Tag,
|
||||
Conversation,
|
||||
Page,
|
||||
PageFollow,
|
||||
UserFollow,
|
||||
EducationItem,
|
||||
Experience,
|
||||
Qualification,
|
||||
CV
|
||||
],
|
||||
migrationsTableName: 'type_orm_migrations',
|
||||
migrations: [path.join(__dirname, '../migrations/*')],
|
||||
cli: {
|
||||
migrationsDir: 'migrations'
|
||||
}
|
||||
} as ConstructorParameters<typeof DataSource>[0]
|
||||
@@ -0,0 +1,4 @@
|
||||
// export const __prod__ = process.env.NODE_ENV === 'production'
|
||||
export const __prod__ = false
|
||||
export const COOKIE_NAME = 'qid'
|
||||
export const FORGET_PASSWORD_PREFIX = 'forget-password:'
|
||||
@@ -0,0 +1,30 @@
|
||||
import { Field, Int, ObjectType } from 'type-graphql'
|
||||
import { BaseEntity, Column, Entity, ManyToOne, PrimaryGeneratedColumn } from 'typeorm'
|
||||
import { User } from './User'
|
||||
|
||||
@ObjectType()
|
||||
@Entity()
|
||||
export class CV extends BaseEntity {
|
||||
@Field(() => Int)
|
||||
@PrimaryGeneratedColumn()
|
||||
id!: number
|
||||
|
||||
@Field()
|
||||
@Column()
|
||||
filename?: string
|
||||
|
||||
@Field()
|
||||
@Column()
|
||||
key?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
url?: string
|
||||
|
||||
@Field(() => Int, { nullable: true })
|
||||
@Column({ nullable: true })
|
||||
userId?: number
|
||||
|
||||
@Field(() => User, { nullable: true })
|
||||
@ManyToOne(() => User, user => user.cvs, { onDelete: 'CASCADE' })
|
||||
user?: User
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
import { Field, Int, ObjectType } from 'type-graphql'
|
||||
import { BaseEntity, Column, CreateDateColumn, Entity, ManyToOne, OneToMany, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm'
|
||||
import { CommentVote, Post, User, Page } from '@entities'
|
||||
|
||||
@ObjectType()
|
||||
@Entity()
|
||||
export class Comment extends BaseEntity {
|
||||
@Field(() => Int)
|
||||
@PrimaryGeneratedColumn()
|
||||
id!: number
|
||||
|
||||
@Field(() => String, { nullable: true })
|
||||
@CreateDateColumn()
|
||||
createdAt?: Date
|
||||
|
||||
@Field(() => String, { nullable: true })
|
||||
@UpdateDateColumn()
|
||||
updatedAt?: Date
|
||||
|
||||
@Field()
|
||||
@Column()
|
||||
text!: string
|
||||
|
||||
@Field(() => String)
|
||||
@Column({ default: 'user' })
|
||||
creatorType?: 'page' | 'user'
|
||||
|
||||
@Field(() => Int, { nullable: true })
|
||||
@Column({ nullable: true })
|
||||
creatorId?: number
|
||||
|
||||
@Field(() => User, { nullable: true })
|
||||
@ManyToOne(() => User, user => user.comments, { onDelete: 'CASCADE' })
|
||||
creator?: User
|
||||
|
||||
@Field(() => Int, { nullable: true })
|
||||
@Column({ nullable: true })
|
||||
pageCreatorId?: number
|
||||
|
||||
@Field(() => Page, { nullable: true })
|
||||
@ManyToOne(() => Page, page => page.posts, { onDelete: 'CASCADE' })
|
||||
pageCreator?: Page
|
||||
|
||||
@Field(() => Int, { nullable: true })
|
||||
@Column({ nullable: false })
|
||||
postId?: number
|
||||
|
||||
@ManyToOne(() => Post, post => post.comments, { onDelete: 'CASCADE' })
|
||||
post?: Post
|
||||
|
||||
@OneToMany(() => CommentVote, commentVote => commentVote.comment)
|
||||
votes?: CommentVote[]
|
||||
|
||||
@Field(() => Int)
|
||||
@Column({ type: 'int', default: 0 })
|
||||
points!: number
|
||||
|
||||
@Field(() => Int, { nullable: true })
|
||||
voteStatus?: number
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
import { Comment, User } from '@entities'
|
||||
import { Field, Int, ObjectType } from 'type-graphql'
|
||||
import { BaseEntity, Column, Entity, ManyToOne, PrimaryColumn } from 'typeorm'
|
||||
|
||||
@ObjectType()
|
||||
@Entity()
|
||||
export class CommentVote extends BaseEntity {
|
||||
@Field(() => Int)
|
||||
@Column({ type: 'int' })
|
||||
value!: number
|
||||
|
||||
@Field(() => Int)
|
||||
@PrimaryColumn()
|
||||
userId!: number
|
||||
|
||||
@Field(() => User)
|
||||
@ManyToOne(() => User, user => user.commentVotes, { onDelete: 'CASCADE' })
|
||||
user?: User
|
||||
|
||||
@Field(() => Int)
|
||||
@PrimaryColumn()
|
||||
commentId!: number
|
||||
|
||||
@Field(() => Comment)
|
||||
@ManyToOne(() => Comment, comment => comment.votes, { onDelete: 'CASCADE' })
|
||||
comment?: Comment
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import { Field, Int, ObjectType } from 'type-graphql'
|
||||
import { BaseEntity, Column, Entity, PrimaryGeneratedColumn } from 'typeorm'
|
||||
|
||||
@ObjectType()
|
||||
@Entity()
|
||||
export class Conversation extends BaseEntity {
|
||||
@Field(() => Int)
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number
|
||||
|
||||
@Field(() => [Int])
|
||||
@Column('int', { array: true })
|
||||
participants: number[]
|
||||
|
||||
@Field()
|
||||
@Column()
|
||||
firestoreCollectionId: string
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
import { Field, Int, ObjectType } from 'type-graphql'
|
||||
import { BaseEntity, Column, Entity, ManyToOne, PrimaryGeneratedColumn } from 'typeorm'
|
||||
import { User } from './User'
|
||||
|
||||
@ObjectType()
|
||||
@Entity()
|
||||
export class EducationItem extends BaseEntity {
|
||||
@Field(() => Int)
|
||||
@PrimaryGeneratedColumn()
|
||||
id!: number
|
||||
|
||||
@Field()
|
||||
@Column()
|
||||
school?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
@Column({ nullable: true })
|
||||
status?: string
|
||||
|
||||
@Field(() => Date, { nullable: true })
|
||||
@Column({ nullable: true, type: 'timestamptz' })
|
||||
startDate?: Date
|
||||
|
||||
@Field(() => Date, { nullable: true })
|
||||
@Column({ nullable: true, type: 'timestamptz' })
|
||||
endDate?: Date
|
||||
|
||||
@Field(() => Int, { nullable: true })
|
||||
@Column({ nullable: true })
|
||||
userId?: number
|
||||
|
||||
@Field(() => User, { nullable: true })
|
||||
@ManyToOne(() => User, user => user.educationItems, { onDelete: 'CASCADE' })
|
||||
user?: User
|
||||
|
||||
@Field({ nullable: true })
|
||||
@Column({ nullable: true })
|
||||
photo?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
photoUrl?: string
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
import { Field, Int, ObjectType } from 'type-graphql'
|
||||
import { BaseEntity, Column, Entity, ManyToOne, PrimaryGeneratedColumn } from 'typeorm'
|
||||
import { User } from './User'
|
||||
|
||||
@ObjectType()
|
||||
@Entity()
|
||||
export class Experience extends BaseEntity {
|
||||
@Field(() => Int)
|
||||
@PrimaryGeneratedColumn()
|
||||
id!: number
|
||||
|
||||
@Field()
|
||||
@Column()
|
||||
title?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
@Column({ nullable: true })
|
||||
workplace?: string
|
||||
|
||||
@Field(() => Date, { nullable: true })
|
||||
@Column({ nullable: true, type: 'timestamptz' })
|
||||
startDate?: Date
|
||||
|
||||
@Field(() => Date, { nullable: true })
|
||||
@Column({ nullable: true, type: 'timestamptz' })
|
||||
endDate?: Date
|
||||
|
||||
@Field(() => Int, { nullable: true })
|
||||
@Column({ nullable: true })
|
||||
userId?: number
|
||||
|
||||
@Field(() => User, { nullable: true })
|
||||
@ManyToOne(() => User, user => user.experiences, { onDelete: 'CASCADE' })
|
||||
user?: User
|
||||
|
||||
@Field({ nullable: true })
|
||||
@Column({ nullable: true })
|
||||
photo?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
photoUrl?: string
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
import { OfferApplication, Page, Space, User } from '@entities'
|
||||
import { Field, Int, ObjectType } from 'type-graphql'
|
||||
import { BaseEntity, Column, CreateDateColumn, Entity, ManyToOne, OneToMany, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm'
|
||||
|
||||
@ObjectType()
|
||||
@Entity()
|
||||
export class Offer extends BaseEntity {
|
||||
@Field(() => Int)
|
||||
@PrimaryGeneratedColumn()
|
||||
id!: number
|
||||
|
||||
@Field(() => String)
|
||||
@CreateDateColumn()
|
||||
createdAt?: Date
|
||||
|
||||
@Field(() => String)
|
||||
@UpdateDateColumn()
|
||||
updatedAt?: Date
|
||||
|
||||
@Field(() => String, { nullable: true })
|
||||
@Column({ default: 'user' })
|
||||
creatorType?: 'page' | 'user'
|
||||
|
||||
@Field(() => Int, { nullable: true })
|
||||
@Column({ nullable: true })
|
||||
creatorId!: number
|
||||
|
||||
@Field(() => User, { nullable: true })
|
||||
@ManyToOne(() => User, user => user.offers, { onDelete: 'CASCADE' })
|
||||
creator?: User
|
||||
|
||||
@Field(() => Int, { nullable: true })
|
||||
@Column({ nullable: true })
|
||||
pageCreatorId?: number
|
||||
|
||||
@Field(() => Page, { nullable: true })
|
||||
@ManyToOne(() => Page, page => page.offers, { onDelete: 'CASCADE' })
|
||||
pageCreator?: Page
|
||||
|
||||
@Field(() => Int)
|
||||
@Column()
|
||||
spaceId!: number
|
||||
|
||||
@Field(() => Space, { nullable: true })
|
||||
@ManyToOne(() => Space, space => space.posts, { onDelete: 'CASCADE' })
|
||||
space?: Space
|
||||
|
||||
@Field()
|
||||
@Column()
|
||||
title: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
@Column({ nullable: true })
|
||||
workplace?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
@Column({ nullable: true })
|
||||
address?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
@Column({ nullable: false, default: false })
|
||||
recruiting?: boolean
|
||||
|
||||
@Field(() => [OfferApplication], { nullable: true })
|
||||
@OneToMany(() => OfferApplication, offerApplication => offerApplication.offer)
|
||||
applications: OfferApplication[]
|
||||
|
||||
@Field({ nullable: true })
|
||||
@Column({ nullable: true })
|
||||
employmentType?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
@Column({ nullable: true })
|
||||
salaryRange?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
@Column({ nullable: true })
|
||||
department?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
@Column({ nullable: true })
|
||||
requirements?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
@Column({ nullable: true })
|
||||
benefits?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
@Column({ nullable: true })
|
||||
description?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
@Column({ nullable: true })
|
||||
photo?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
photoUrl?: string
|
||||
|
||||
@Field(() => Int, { nullable: true })
|
||||
applicationsNo?: number
|
||||
|
||||
@Field(() => String, { nullable: true })
|
||||
applicationStatus?: 'applied' | 'accepted' | 'rejected'
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
import { Field, Int, ObjectType } from 'type-graphql'
|
||||
import { BaseEntity, Column, Entity, ManyToOne, PrimaryColumn, PrimaryGeneratedColumn } from 'typeorm'
|
||||
import { User, Offer } from '@entities'
|
||||
|
||||
@ObjectType()
|
||||
@Entity()
|
||||
export class OfferApplication extends BaseEntity {
|
||||
@Field(() => Int)
|
||||
@PrimaryGeneratedColumn()
|
||||
id!: number
|
||||
|
||||
@Field(() => Int)
|
||||
@Column()
|
||||
userId!: number
|
||||
|
||||
@Field(() => User)
|
||||
@ManyToOne(() => User, user => user.applications, { onDelete: 'CASCADE', cascade: true })
|
||||
user?: User
|
||||
|
||||
@Field(() => Int)
|
||||
@Column()
|
||||
offerId!: number
|
||||
|
||||
@Field(() => Offer)
|
||||
@ManyToOne(() => Offer, offer => offer.applications, { onDelete: 'CASCADE', cascade: true })
|
||||
offer?: Offer
|
||||
|
||||
@Field()
|
||||
@Column({ default: 'applied' })
|
||||
status!: 'applied' | 'accepted' | 'rejected'
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
import { Comment, Offer, Post, User, PageFollow } from '@entities'
|
||||
import { Field, Int, ObjectType } from 'type-graphql'
|
||||
import { BaseEntity, Column, CreateDateColumn, Entity, JoinTable, ManyToMany, OneToMany, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm'
|
||||
|
||||
@ObjectType()
|
||||
@Entity()
|
||||
export class Page extends BaseEntity {
|
||||
@Field(() => Int)
|
||||
@PrimaryGeneratedColumn()
|
||||
id!: number
|
||||
|
||||
@Field(() => String, { nullable: true })
|
||||
@CreateDateColumn()
|
||||
createdAt?: Date
|
||||
|
||||
@Field(() => String, { nullable: true })
|
||||
@UpdateDateColumn()
|
||||
updatedAt?: Date
|
||||
|
||||
@Field(() => [User], { nullable: true })
|
||||
@ManyToMany(() => User, { cascade: true })
|
||||
@JoinTable()
|
||||
owners?: User[]
|
||||
|
||||
@Field(() => Boolean, { nullable: true })
|
||||
ownerStatus?: boolean
|
||||
|
||||
@OneToMany(() => PageFollow, pageFollow => pageFollow.page)
|
||||
pageFollows?: PageFollow[]
|
||||
|
||||
@Field(() => Boolean, { nullable: true })
|
||||
followStatus?: boolean
|
||||
|
||||
@Field(() => Int)
|
||||
followerNumber?: number
|
||||
|
||||
@Field()
|
||||
@Column({ unique: true, nullable: false })
|
||||
pageName?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
@Column({ unique: true, nullable: true })
|
||||
email?: string
|
||||
|
||||
@OneToMany(() => Post, post => post.pageCreator)
|
||||
posts?: Post[]
|
||||
|
||||
@OneToMany(() => Offer, offer => offer.pageCreator)
|
||||
offers?: Offer[]
|
||||
|
||||
@Field(() => [Comment], { nullable: true })
|
||||
@OneToMany(() => Comment, comment => comment.creator)
|
||||
comments?: Comment[]
|
||||
|
||||
@Field({ nullable: true })
|
||||
@Column({ nullable: true })
|
||||
avatar?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
avatarUrl?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
@Column({ nullable: true })
|
||||
coverPhoto?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
coverPhotoUrl?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
@Column({ nullable: true })
|
||||
fullPageName?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
@Column({ nullable: true })
|
||||
headline?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
@Column({ nullable: true })
|
||||
address?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
@Column({ nullable: true })
|
||||
about?: string
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import { Field, Int, ObjectType } from 'type-graphql'
|
||||
import { BaseEntity, Entity, ManyToOne, PrimaryColumn } from 'typeorm'
|
||||
import { Page } from './Page'
|
||||
import { User } from './User'
|
||||
|
||||
@ObjectType()
|
||||
@Entity()
|
||||
export class PageFollow extends BaseEntity {
|
||||
@Field(() => Int)
|
||||
@PrimaryColumn()
|
||||
userId!: number
|
||||
|
||||
@Field(() => User)
|
||||
@ManyToOne(() => User, user => user.pageFollows, { onDelete: 'CASCADE' })
|
||||
user?: User
|
||||
|
||||
@Field(() => Int)
|
||||
@PrimaryColumn()
|
||||
pageId!: number
|
||||
|
||||
@Field(() => Page)
|
||||
@ManyToOne(() => Page, page => page.pageFollows, { onDelete: 'CASCADE' })
|
||||
page?: Page
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
import { Field, Int, ObjectType } from 'type-graphql'
|
||||
import { BaseEntity, Column, CreateDateColumn, Entity, JoinTable, ManyToMany, ManyToOne, OneToMany, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm'
|
||||
import { Vote, User, Space, Comment, Tag, Page } from '@entities'
|
||||
|
||||
@ObjectType()
|
||||
@Entity()
|
||||
export class Post extends BaseEntity {
|
||||
@Field(() => Int)
|
||||
@PrimaryGeneratedColumn()
|
||||
id!: number
|
||||
|
||||
@Field(() => String)
|
||||
@CreateDateColumn()
|
||||
createdAt?: Date
|
||||
|
||||
@Field(() => String)
|
||||
@UpdateDateColumn()
|
||||
updatedAt?: Date
|
||||
|
||||
@Field()
|
||||
@Column()
|
||||
title!: string
|
||||
|
||||
@Field()
|
||||
@Column()
|
||||
text!: string
|
||||
|
||||
@Field(() => String)
|
||||
@Column({ default: 'user' })
|
||||
creatorType?: 'page' | 'user'
|
||||
|
||||
@Field(() => Int, { nullable: true })
|
||||
@Column({ nullable: true })
|
||||
creatorId?: number
|
||||
|
||||
@Field(() => User, { nullable: true })
|
||||
@ManyToOne(() => User, user => user.posts, { onDelete: 'CASCADE' })
|
||||
creator?: User
|
||||
|
||||
@Field(() => Int, { nullable: true })
|
||||
@Column({ nullable: true })
|
||||
pageCreatorId?: number
|
||||
|
||||
@Field(() => Page, { nullable: true })
|
||||
@ManyToOne(() => Page, page => page.posts, { onDelete: 'CASCADE' })
|
||||
pageCreator?: Page
|
||||
|
||||
@OneToMany(() => Vote, vote => vote.post)
|
||||
votes?: Vote[]
|
||||
|
||||
@Field(() => Int)
|
||||
@Column({ type: 'int', default: 0 })
|
||||
points!: number
|
||||
|
||||
@Field(() => Int, { nullable: true })
|
||||
voteStatus?: number
|
||||
|
||||
@Field(() => Int)
|
||||
@Column()
|
||||
spaceId!: number
|
||||
|
||||
@Field(() => Space)
|
||||
@ManyToOne(() => Space, space => space.posts, { onDelete: 'CASCADE' })
|
||||
space!: Space
|
||||
|
||||
@OneToMany(() => Comment, comment => comment.post)
|
||||
comments?: Comment[]
|
||||
|
||||
@Field(() => [Tag], { nullable: true })
|
||||
@ManyToMany(() => Tag, { cascade: true })
|
||||
@JoinTable() // Put @JoinTable() on owner side of a MTM relationship
|
||||
tags: Tag[]
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
import { Field, Int, ObjectType } from 'type-graphql'
|
||||
import { BaseEntity, Column, Entity, ManyToOne, PrimaryGeneratedColumn } from 'typeorm'
|
||||
import { User } from './User'
|
||||
|
||||
@ObjectType()
|
||||
@Entity()
|
||||
export class Qualification extends BaseEntity {
|
||||
@Field(() => Int)
|
||||
@PrimaryGeneratedColumn()
|
||||
id!: number
|
||||
|
||||
@Field()
|
||||
@Column()
|
||||
name!: string
|
||||
|
||||
@Field()
|
||||
@Column()
|
||||
issuingOrganisation!: string
|
||||
|
||||
@Field(() => Date, { nullable: true })
|
||||
@Column({ nullable: true, type: 'timestamptz' })
|
||||
issuanceDate?: Date
|
||||
|
||||
@Field()
|
||||
@Column()
|
||||
expire!: boolean
|
||||
|
||||
@Field(() => Date, { nullable: true })
|
||||
@Column({ nullable: true, type: 'timestamptz' })
|
||||
expirationDate?: Date
|
||||
|
||||
@Field({ nullable: true })
|
||||
@Column({ nullable: true })
|
||||
credentialID?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
@Column({ nullable: true })
|
||||
credentialURL?: string
|
||||
|
||||
@Field(() => Int, { nullable: true })
|
||||
@Column({ nullable: true })
|
||||
userId?: number
|
||||
|
||||
@Field(() => User, { nullable: true })
|
||||
@ManyToOne(() => User, user => user.qualifications, { onDelete: 'CASCADE' })
|
||||
user?: User
|
||||
|
||||
@Field({ nullable: true })
|
||||
@Column({ nullable: true })
|
||||
photo?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
photoUrl?: string
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
import { Field, Int, ObjectType } from 'type-graphql'
|
||||
import { BaseEntity, Column, CreateDateColumn, Entity, JoinTable, ManyToMany, OneToMany, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm'
|
||||
import { Post, SpaceSubscription, User } from '@entities'
|
||||
|
||||
@ObjectType()
|
||||
@Entity()
|
||||
export class Space extends BaseEntity {
|
||||
@Field(() => Int)
|
||||
@PrimaryGeneratedColumn()
|
||||
id!: number
|
||||
|
||||
@Field(() => String)
|
||||
@CreateDateColumn()
|
||||
createdAt?: Date
|
||||
|
||||
@Field(() => String)
|
||||
@UpdateDateColumn()
|
||||
updatedAt?: Date
|
||||
|
||||
@Field()
|
||||
@Column({ unique: true })
|
||||
spaceName!: string
|
||||
|
||||
@OneToMany(() => Post, post => post.space)
|
||||
posts?: Post[]
|
||||
|
||||
@OneToMany(() => SpaceSubscription, spaceSubscription => spaceSubscription.space)
|
||||
spaceSubscriptions?: SpaceSubscription[]
|
||||
|
||||
@Field(() => Boolean, { nullable: true })
|
||||
subscriptionStatus?: boolean
|
||||
|
||||
@Field(() => Int)
|
||||
subscriberNumber?: number
|
||||
|
||||
@Field(() => Boolean)
|
||||
modStatus?: boolean
|
||||
|
||||
@Field(() => [User], { nullable: true })
|
||||
@ManyToMany(() => User, { cascade: true })
|
||||
@JoinTable()
|
||||
mods?: User[]
|
||||
|
||||
@Field({ nullable: true })
|
||||
@Column({ nullable: true })
|
||||
avatar?: string // S3 Key (Location) to image
|
||||
|
||||
@Field({ nullable: true })
|
||||
avatarUrl?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
@Column({ nullable: true })
|
||||
coverPhoto?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
coverPhotoUrl?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
@Column({ nullable: true })
|
||||
fullSpaceName?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
@Column({ nullable: true })
|
||||
rules?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
@Column({ nullable: true })
|
||||
headline?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
@Column({ nullable: true })
|
||||
about?: string
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import { Field, Int, ObjectType } from 'type-graphql'
|
||||
import { BaseEntity, Entity, ManyToOne, PrimaryColumn } from 'typeorm'
|
||||
import { Space, User } from '@entities'
|
||||
|
||||
@ObjectType()
|
||||
@Entity()
|
||||
export class SpaceSubscription extends BaseEntity {
|
||||
@Field(() => Int)
|
||||
@PrimaryColumn()
|
||||
userId!: number
|
||||
|
||||
@Field(() => User)
|
||||
@ManyToOne(() => User, user => user.spaceSubscriptions, { onDelete: 'CASCADE' })
|
||||
user?: User
|
||||
|
||||
@Field(() => Int)
|
||||
@PrimaryColumn()
|
||||
spaceId!: number
|
||||
|
||||
@Field(() => Space)
|
||||
@ManyToOne(() => Space, space => space.spaceSubscriptions, { onDelete: 'CASCADE' })
|
||||
space?: Space
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { Field, Int, ObjectType } from 'type-graphql'
|
||||
import { BaseEntity, Column, Entity, PrimaryGeneratedColumn } from 'typeorm'
|
||||
|
||||
@ObjectType()
|
||||
@Entity()
|
||||
export class Tag extends BaseEntity {
|
||||
@Field(() => Int)
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number
|
||||
|
||||
@Field()
|
||||
@Column()
|
||||
name: string
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
import { Comment, CommentVote, CV, EducationItem, Experience, Offer, OfferApplication, PageFollow, Post, Qualification, SpaceSubscription, UserFollow, Vote } from '@entities'
|
||||
import { Field, Float, Int, ObjectType } from 'type-graphql'
|
||||
import { BaseEntity, Column, CreateDateColumn, Entity, OneToMany, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm'
|
||||
|
||||
@ObjectType()
|
||||
@Entity()
|
||||
export class User extends BaseEntity {
|
||||
@Field(() => Int)
|
||||
@PrimaryGeneratedColumn()
|
||||
id!: number
|
||||
|
||||
@Field(() => String, { nullable: true })
|
||||
@CreateDateColumn()
|
||||
createdAt?: Date
|
||||
|
||||
@Field(() => String, { nullable: true })
|
||||
@UpdateDateColumn()
|
||||
updatedAt?: Date
|
||||
|
||||
@Field()
|
||||
@Column({ unique: true, nullable: false })
|
||||
username?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
@Column({ unique: true, nullable: false })
|
||||
email?: string
|
||||
|
||||
@Column({ nullable: false })
|
||||
password?: string
|
||||
|
||||
@OneToMany(() => Post, post => post.creator)
|
||||
posts?: Post[]
|
||||
|
||||
@OneToMany(() => Offer, offer => offer.creator)
|
||||
offers?: Offer[]
|
||||
|
||||
@OneToMany(() => EducationItem, educationItem => educationItem.user, { cascade: true })
|
||||
educationItems?: EducationItem[]
|
||||
|
||||
@OneToMany(() => Experience, experience => experience.user, { cascade: true })
|
||||
experiences?: Experience[]
|
||||
|
||||
@OneToMany(() => Qualification, qualification => qualification.user, { cascade: true })
|
||||
qualifications?: Qualification[]
|
||||
|
||||
@Field(() => [String], { nullable: true })
|
||||
@Column(`simple-array`, { nullable: true })
|
||||
skills?: string[]
|
||||
|
||||
@OneToMany(() => CV, cv => cv.user)
|
||||
cvs?: CV[]
|
||||
|
||||
@OneToMany(() => Vote, vote => vote.user)
|
||||
votes?: Vote[]
|
||||
|
||||
@OneToMany(() => SpaceSubscription, spaceSubscription => spaceSubscription.user)
|
||||
spaceSubscriptions?: SpaceSubscription[]
|
||||
|
||||
@OneToMany(() => PageFollow, pageFollow => pageFollow.user)
|
||||
pageFollows?: PageFollow[]
|
||||
|
||||
// One user can follow many
|
||||
@OneToMany(() => UserFollow, userFollow => userFollow.followingUser)
|
||||
userFollowings?: UserFollow[]
|
||||
|
||||
// One user can be followed by many
|
||||
@OneToMany(() => UserFollow, userFollow => userFollow.followedUser)
|
||||
userFolloweds?: PageFollow[]
|
||||
|
||||
@Field(() => [Comment], { nullable: true })
|
||||
@OneToMany(() => Comment, comment => comment.creator)
|
||||
comments?: Comment[]
|
||||
|
||||
@OneToMany(() => CommentVote, commentVote => commentVote.user)
|
||||
commentVotes?: CommentVote[]
|
||||
|
||||
@Field(() => [OfferApplication], { nullable: true })
|
||||
@OneToMany(() => OfferApplication, offerApplication => offerApplication.user)
|
||||
applications?: OfferApplication[]
|
||||
|
||||
@Field({ nullable: true })
|
||||
@Column({ nullable: true })
|
||||
avatar?: string // S3 Key (Location) to image
|
||||
|
||||
@Field({ nullable: true })
|
||||
avatarUrl?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
@Column({ nullable: true })
|
||||
coverPhoto?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
coverPhotoUrl?: string
|
||||
|
||||
@Field(() => Int)
|
||||
followerNumber?: number
|
||||
|
||||
@Field(() => Int)
|
||||
followingNumber?: number
|
||||
|
||||
@Field({ nullable: true })
|
||||
@Column({ nullable: true })
|
||||
fullName?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
@Column({ nullable: true })
|
||||
headline?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
@Column({ nullable: true })
|
||||
address?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
@Column({ nullable: true })
|
||||
about?: string
|
||||
|
||||
@Field(() => Float, { nullable: true })
|
||||
@Column({ type: 'float', nullable: true })
|
||||
mostRecentLatitude?: number
|
||||
|
||||
@Field(() => Float, { nullable: true })
|
||||
@Column({ type:'float', nullable: true })
|
||||
mostRecentLongitude?: number
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import { Field, Int, ObjectType } from 'type-graphql'
|
||||
import { BaseEntity, Entity, ManyToOne, PrimaryColumn } from 'typeorm'
|
||||
import { User } from './User'
|
||||
|
||||
@ObjectType()
|
||||
@Entity()
|
||||
export class UserFollow extends BaseEntity {
|
||||
@Field(() => Int)
|
||||
@PrimaryColumn()
|
||||
followingUserId!: number
|
||||
|
||||
@Field(() => User)
|
||||
@ManyToOne(() => User, user => user.userFollowings, { onDelete: 'CASCADE' })
|
||||
followingUser?: User
|
||||
|
||||
@Field(() => Int)
|
||||
@PrimaryColumn()
|
||||
followedUserId!: number
|
||||
|
||||
@Field(() => User)
|
||||
@ManyToOne(() => User, user => user.userFolloweds, { onDelete: 'CASCADE' })
|
||||
followedUser?: User
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
import { Post, User } from '@entities'
|
||||
import { Field, Int, ObjectType } from 'type-graphql'
|
||||
import { BaseEntity, Column, Entity, ManyToOne, PrimaryColumn } from 'typeorm'
|
||||
|
||||
@ObjectType()
|
||||
@Entity()
|
||||
export class Vote extends BaseEntity {
|
||||
@Field(() => Int)
|
||||
@Column({ type: 'int' })
|
||||
value!: number
|
||||
|
||||
@Field(() => Int)
|
||||
@PrimaryColumn()
|
||||
userId!: number
|
||||
|
||||
@Field(() => User)
|
||||
@ManyToOne(() => User, user => user.votes, { onDelete: 'CASCADE' })
|
||||
user?: User
|
||||
|
||||
@Field(() => Int)
|
||||
@PrimaryColumn()
|
||||
postId!: number
|
||||
|
||||
@Field(() => Post)
|
||||
@ManyToOne(() => Post, post => post.votes, { onDelete: 'CASCADE' })
|
||||
post?: Post
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
export * from './User'
|
||||
export * from './Post'
|
||||
export * from './Vote'
|
||||
export * from './Space'
|
||||
export * from './SpaceSubscription'
|
||||
export * from './Comment'
|
||||
export * from './CommentVote'
|
||||
export * from './OfferApplication'
|
||||
export * from './Offer'
|
||||
export * from './Tag'
|
||||
export * from './Conversation'
|
||||
export * from './Page'
|
||||
export * from './PageFollow'
|
||||
export * from './UserFollow'
|
||||
export * from './EducationItem'
|
||||
export * from './Experience'
|
||||
export * from './Qualification'
|
||||
export * from './CV'
|
||||
@@ -0,0 +1,12 @@
|
||||
import { ConversationInFirestore } from '@collections'
|
||||
import { Field, ObjectType } from 'type-graphql'
|
||||
import { FieldError } from './FieldError'
|
||||
|
||||
@ObjectType()
|
||||
export class CreateConversationResponse {
|
||||
@Field(() => [FieldError], { nullable: true })
|
||||
errors?: FieldError[]
|
||||
|
||||
@Field(() => ConversationInFirestore, { nullable: true })
|
||||
conversation?: ConversationInFirestore
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import { FileUpload, GraphQLUpload } from 'graphql-upload'
|
||||
import { Field, InputType } from 'type-graphql'
|
||||
|
||||
@InputType()
|
||||
export class EducationItemInput {
|
||||
@Field({ nullable: true })
|
||||
school?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
status?: string
|
||||
|
||||
@Field(() => Date, { nullable: true })
|
||||
startDate?: Date
|
||||
|
||||
@Field(() => Date, { nullable: true })
|
||||
endDate?: Date
|
||||
|
||||
@Field(() => GraphQLUpload, { nullable: true })
|
||||
photo?: Promise<FileUpload>
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { EducationItem } from '@entities'
|
||||
import { Field, ObjectType } from 'type-graphql'
|
||||
import { FieldError } from './FieldError'
|
||||
|
||||
@ObjectType()
|
||||
export class EducationItemResponse {
|
||||
@Field(() => [FieldError], { nullable: true })
|
||||
errors?: FieldError[]
|
||||
|
||||
@Field(() => EducationItem, { nullable: true })
|
||||
educationItem?: EducationItem
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import { FileUpload, GraphQLUpload } from 'graphql-upload'
|
||||
import { Field, InputType } from 'type-graphql'
|
||||
|
||||
@InputType()
|
||||
export class ExperienceInput {
|
||||
@Field({ nullable: true })
|
||||
title?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
workplace?: string
|
||||
|
||||
@Field(() => Date, { nullable: true })
|
||||
startDate?: Date
|
||||
|
||||
@Field(() => Date, { nullable: true })
|
||||
endDate?: Date
|
||||
|
||||
@Field(() => GraphQLUpload, { nullable: true })
|
||||
photo?: Promise<FileUpload>
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { Experience } from '@entities'
|
||||
import { Field, ObjectType } from 'type-graphql'
|
||||
import { FieldError } from './FieldError'
|
||||
|
||||
@ObjectType()
|
||||
export class ExperienceResponse {
|
||||
@Field(() => [FieldError], { nullable: true })
|
||||
errors?: FieldError[]
|
||||
|
||||
@Field(() => Experience, { nullable: true })
|
||||
experience?: Experience
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import { ObjectType, Field } from 'type-graphql'
|
||||
|
||||
@ObjectType()
|
||||
export class FieldError {
|
||||
@Field()
|
||||
field: string
|
||||
|
||||
@Field()
|
||||
message: string
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import { ObjectType, Field } from 'type-graphql'
|
||||
import { FieldError } from './FieldError'
|
||||
|
||||
@ObjectType()
|
||||
export class ForgotPasswordResponse {
|
||||
@Field(() => [FieldError], { nullable: true })
|
||||
errors?: FieldError[]
|
||||
|
||||
@Field(() => Boolean)
|
||||
success: boolean
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import { User } from '@entities'
|
||||
import { Field, ObjectType } from 'type-graphql'
|
||||
|
||||
@ObjectType()
|
||||
export class InboxResponse {
|
||||
@Field(() => String)
|
||||
firestoreCollectionId: string
|
||||
|
||||
@Field(() => User)
|
||||
partner: User
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import { Field, Float, InputType } from 'type-graphql'
|
||||
|
||||
@InputType()
|
||||
export class Location {
|
||||
@Field(() => Float, { nullable: true })
|
||||
latitude?: number
|
||||
|
||||
@Field(() => Float, { nullable: true })
|
||||
longitude?: number
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { FileUpload, GraphQLUpload } from 'graphql-upload'
|
||||
import { Field, InputType } from 'type-graphql'
|
||||
|
||||
@InputType()
|
||||
export class MessageInput {
|
||||
@Field(() => String)
|
||||
type!: 'text' | 'image' | 'video' | 'audio' | 'file'
|
||||
|
||||
@Field(() => GraphQLUpload, { nullable: true })
|
||||
upload?: Promise<FileUpload>
|
||||
|
||||
@Field(() => String, { nullable: true })
|
||||
text?: string
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
import { FileUpload, GraphQLUpload } from 'graphql-upload'
|
||||
import { Field, InputType, Int } from 'type-graphql'
|
||||
|
||||
@InputType()
|
||||
export class OfferInputCreate {
|
||||
@Field(() => Int, { nullable: true })
|
||||
pageId?: number
|
||||
|
||||
@Field({ nullable: true })
|
||||
spaceName?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
title?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
workplace?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
address?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
recruiting?: boolean
|
||||
|
||||
@Field({ nullable: true })
|
||||
employmentType?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
salaryRange?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
department?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
requirements?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
benefits?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
description?: string
|
||||
|
||||
@Field(() => GraphQLUpload, { nullable: true })
|
||||
photo?: Promise<FileUpload>
|
||||
}
|
||||
|
||||
@InputType()
|
||||
export class OfferInputUpdate {
|
||||
@Field({ nullable: true })
|
||||
title?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
workplace?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
address?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
recruiting?: boolean
|
||||
|
||||
@Field({ nullable: true })
|
||||
employmentType?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
salaryRange?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
department?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
requirements?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
benefits?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
description?: string
|
||||
|
||||
@Field(() => GraphQLUpload, { nullable: true })
|
||||
photo?: Promise<FileUpload>
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { Offer } from '@entities'
|
||||
import { Field, ObjectType } from 'type-graphql'
|
||||
import { FieldError } from './FieldError'
|
||||
|
||||
@ObjectType()
|
||||
export class OfferResponse {
|
||||
@Field(() => [FieldError], { nullable: true })
|
||||
errors?: FieldError[]
|
||||
|
||||
@Field(() => Offer, { nullable: true })
|
||||
offer?: Offer
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import { Field, InputType } from 'type-graphql'
|
||||
|
||||
@InputType()
|
||||
export class PageInfo {
|
||||
@Field({ nullable: true })
|
||||
fullPageName?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
headline?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
address?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
about?: string
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { Page } from '@entities'
|
||||
import { Field, ObjectType } from 'type-graphql'
|
||||
import { FieldError } from './FieldError'
|
||||
|
||||
@ObjectType()
|
||||
export class PageResponse {
|
||||
@Field(() => [FieldError], { nullable: true })
|
||||
errors?: FieldError[]
|
||||
|
||||
@Field(() => Page, { nullable: true })
|
||||
page?: Page
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import { Comment } from '@entities'
|
||||
import { Field, ObjectType } from 'type-graphql'
|
||||
|
||||
@ObjectType()
|
||||
export class PaginatedComments {
|
||||
@Field(() => [Comment])
|
||||
comments: Comment[]
|
||||
|
||||
@Field(() => Boolean)
|
||||
hasMore: boolean
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import { Offer } from '@entities'
|
||||
import { Field, ObjectType } from 'type-graphql'
|
||||
|
||||
@ObjectType()
|
||||
export class PaginatedOffers {
|
||||
@Field(() => [Offer])
|
||||
offers: Offer[]
|
||||
|
||||
@Field(() => Boolean)
|
||||
hasMore: boolean
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import { Post } from '@entities'
|
||||
import { Field, ObjectType } from 'type-graphql'
|
||||
|
||||
@ObjectType()
|
||||
export class PaginatedPosts {
|
||||
@Field(() => [Post])
|
||||
posts: Post[]
|
||||
|
||||
@Field(() => Boolean)
|
||||
hasMore: boolean
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import { ObjectType, Field } from 'type-graphql'
|
||||
|
||||
@ObjectType()
|
||||
export class PhotoResponse {
|
||||
@Field(() => String, { nullable: true })
|
||||
key?: string
|
||||
|
||||
@Field(() => String, { nullable: true })
|
||||
url?: string
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
import { Field, InputType, Int } from 'type-graphql'
|
||||
|
||||
@InputType()
|
||||
export class PostInputCreate {
|
||||
@Field(() => Int, { nullable: true })
|
||||
pageId?: number
|
||||
|
||||
@Field({ nullable: true })
|
||||
spaceName?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
title?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
text?: string
|
||||
|
||||
@Field(() => [Int], { nullable: true })
|
||||
tags?: number[]
|
||||
}
|
||||
|
||||
@InputType()
|
||||
export class PostInputUpdate {
|
||||
@Field({ nullable: true })
|
||||
title?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
text?: string
|
||||
|
||||
@Field(() => [Int], { nullable: true })
|
||||
tags?: number[]
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { Post } from '@entities'
|
||||
import { Field, ObjectType } from 'type-graphql'
|
||||
import { FieldError } from './FieldError'
|
||||
|
||||
@ObjectType()
|
||||
export class PostResponse {
|
||||
@Field(() => [FieldError], { nullable: true })
|
||||
errors?: FieldError[]
|
||||
|
||||
@Field(() => Post, { nullable: true })
|
||||
post?: Post
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import { FileUpload, GraphQLUpload } from 'graphql-upload'
|
||||
import { Field, InputType } from 'type-graphql'
|
||||
|
||||
@InputType()
|
||||
export class QualificationInput {
|
||||
@Field()
|
||||
name!: string
|
||||
|
||||
@Field()
|
||||
issuingOrganisation!: string
|
||||
|
||||
@Field(() => Date, { nullable: true })
|
||||
issuanceDate?: Date
|
||||
|
||||
@Field()
|
||||
expire: boolean
|
||||
|
||||
@Field(() => Date, { nullable: true })
|
||||
expirationDate?: Date
|
||||
|
||||
@Field({ nullable: true })
|
||||
credentialID?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
credentialURL?: string
|
||||
|
||||
@Field(() => GraphQLUpload, { nullable: true })
|
||||
photo?: Promise<FileUpload>
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { Qualification } from '@entities'
|
||||
import { Field, ObjectType } from 'type-graphql'
|
||||
import { FieldError } from './FieldError'
|
||||
|
||||
@ObjectType()
|
||||
export class QualificationResponse {
|
||||
@Field(() => [FieldError], { nullable: true })
|
||||
errors?: FieldError[]
|
||||
|
||||
@Field(() => Qualification, { nullable: true })
|
||||
qualification?: Qualification
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import { Field, InputType } from 'type-graphql'
|
||||
|
||||
@InputType()
|
||||
export class SpaceInfo {
|
||||
@Field({ nullable: true })
|
||||
fullSpaceName?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
headline?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
rules?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
about?: string
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { Space } from '@entities'
|
||||
import { Field, ObjectType } from 'type-graphql'
|
||||
import { FieldError } from './FieldError'
|
||||
|
||||
@ObjectType()
|
||||
export class SpaceResponse {
|
||||
@Field(() => [FieldError], { nullable: true })
|
||||
errors?: FieldError[]
|
||||
|
||||
@Field(() => Space, { nullable: true })
|
||||
space?: Space
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import { Field, ObjectType } from 'type-graphql'
|
||||
|
||||
@ObjectType()
|
||||
export class UploadedFileResponse {
|
||||
@Field()
|
||||
filename!: String
|
||||
|
||||
@Field()
|
||||
mimetype!: String
|
||||
|
||||
@Field()
|
||||
encoding!: String
|
||||
|
||||
@Field()
|
||||
url!: String
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import { Field, InputType } from 'type-graphql'
|
||||
|
||||
@InputType()
|
||||
export class UserInfo {
|
||||
@Field({ nullable: true })
|
||||
fullName?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
headline?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
address?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
about?: string
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { User } from '../entities'
|
||||
import { ObjectType, Field } from 'type-graphql'
|
||||
import { FieldError } from './FieldError'
|
||||
|
||||
@ObjectType() // ObjectType is for return values
|
||||
export class UserResponse {
|
||||
@Field(() => [FieldError], { nullable: true })
|
||||
errors?: FieldError[]
|
||||
|
||||
@Field(() => User, { nullable: true })
|
||||
user?: User
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
export * from './FieldError'
|
||||
export * from './UserResponse'
|
||||
export * from './ForgotPasswordResponse'
|
||||
export * from './PaginatedPosts'
|
||||
export * from './PostInput'
|
||||
export * from './PostResponse'
|
||||
export * from './PaginatedComments'
|
||||
export * from './OfferResponse'
|
||||
export * from './OfferInput'
|
||||
export * from './PaginatedOffers'
|
||||
export * from './UploadedFileResponse'
|
||||
export * from './MessageInput'
|
||||
export * from './PhotoResponse'
|
||||
export * from './PageResponse'
|
||||
export * from './SpaceResponse'
|
||||
export * from './UserInfo'
|
||||
export * from './EducationItemResponse'
|
||||
export * from './EducationItemInput'
|
||||
export * from './ExperienceInput'
|
||||
export * from './ExperienceResponse'
|
||||
export * from './QualificationInput'
|
||||
export * from './QualificationResponse'
|
||||
export * from './PageInfo'
|
||||
export * from './SpaceInfo'
|
||||
export * from './InboxResponse'
|
||||
export * from './CreateConversationReponse'
|
||||
export * from './Location'
|
||||
+140
@@ -0,0 +1,140 @@
|
||||
import { __prod__, COOKIE_NAME } from '@constants'
|
||||
import { createApplicantsNoLoader, createApplicationLoader, createApplicationStatusLoader, createCommentVoteLoader, createFollowerNumberLoader, createFollowLoader, createModStatusLoader, createOwnerStatusLoader, createPageLoader, createSpaceLoader, createSubscriberNumberLoader, createSubscriptionLoader, createTagLoader, createUserFollowerNumberLoader, createUserFollowingNumberLoader, createUserFollowLoader, createUserLoader, createVoteLoader } from '@loaders'
|
||||
import { CommentResolver, ConversationResolver, CVResolver, EducationItemResolver, ExperienceResolver, OfferResolver, PageResolver, PostResolver, QualificationResolver, QuicksightResolver, S3Resolver, SpaceResolver, TagResolver, UserResolver } from '@resolvers'
|
||||
import typeORMSource from '@src/type-orm.source'
|
||||
import { Context } from '@types'
|
||||
import { ApolloServer } from 'apollo-server-express'
|
||||
import connectRedis from 'connect-redis'
|
||||
import cors from 'cors'
|
||||
import express from 'express'
|
||||
import session from 'express-session'
|
||||
import { graphqlUploadExpress } from 'graphql-upload'
|
||||
import Redis from 'ioredis'
|
||||
import { buildSchema } from 'type-graphql'
|
||||
|
||||
const main = async () => {
|
||||
const orm = await typeORMSource.initialize()
|
||||
// await orm.dropDatabase()
|
||||
await orm.runMigrations()
|
||||
|
||||
const app = express()
|
||||
app.options('*', cors({
|
||||
credentials: true,
|
||||
origin: process.env.FRONTEND_ORIGIN,
|
||||
methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
|
||||
allowedHeaders: ['Content-Type', 'Authorization']
|
||||
}))
|
||||
app.use(cors({
|
||||
credentials: true,
|
||||
origin: process.env.FRONTEND_ORIGIN,
|
||||
methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
|
||||
allowedHeaders: ['Content-Type', 'Authorization']
|
||||
}))
|
||||
app.use(express.json({
|
||||
limit: '1gb',
|
||||
verify: (_, __, buf) => {
|
||||
if (buf.byteLength / (1024 * 1024) > 1024) {
|
||||
throw new Error(`${process.env.NON_API_ERROR_PREFIX}Request too large. It must be less than 1GB.${process.env.NON_API_ERROR_SUFFIX}`)
|
||||
}
|
||||
}
|
||||
}))
|
||||
|
||||
const RedisStore = connectRedis(session)
|
||||
const redis = new Redis(process.env.REDIS_URL)
|
||||
// await redis.flushall()
|
||||
|
||||
app.set('trust proxy', true)
|
||||
|
||||
app.use(
|
||||
session({
|
||||
name: COOKIE_NAME,
|
||||
store: new RedisStore({
|
||||
client: redis,
|
||||
disableTTL: true,
|
||||
disableTouch: true
|
||||
}),
|
||||
cookie: { // lax + secure false -> chrome dev; none + secure true -> apollo studio, prod: lax + secure
|
||||
maxAge: 1000 * 60 * 60 * 24 * 365 * 10,
|
||||
httpOnly: false,
|
||||
sameSite: 'lax',
|
||||
// sameSite: 'none',
|
||||
secure: true,
|
||||
// secure: false,
|
||||
// domain: __prod__ ? process.env.DOMAIN_SUFFIX : undefined
|
||||
domain: process.env.DOMAIN_SUFFIX
|
||||
},
|
||||
secret: process.env.REDIS_SECRET,
|
||||
saveUninitialized: false,
|
||||
resave: false
|
||||
})
|
||||
)
|
||||
|
||||
app.listen(parseInt(process.env.API_PORT), () => {
|
||||
if (!__prod__) {
|
||||
console.log(`Server started on localhost:${process.env.API_PORT}.`)
|
||||
}
|
||||
else {
|
||||
console.log(`Server started at ${process.env.BACKEND_ORIGIN}.`)
|
||||
}
|
||||
})
|
||||
app.get('/', (_, res) => {
|
||||
res.send('Start querying at /graphql.')
|
||||
})
|
||||
|
||||
const apolloServer = new ApolloServer({
|
||||
introspection: true,
|
||||
schema: await buildSchema({
|
||||
resolvers: [
|
||||
UserResolver,
|
||||
PostResolver,
|
||||
SpaceResolver,
|
||||
CommentResolver,
|
||||
OfferResolver,
|
||||
TagResolver,
|
||||
S3Resolver,
|
||||
ConversationResolver,
|
||||
PageResolver,
|
||||
EducationItemResolver,
|
||||
ExperienceResolver,
|
||||
QualificationResolver,
|
||||
CVResolver,
|
||||
QuicksightResolver
|
||||
],
|
||||
validate: false
|
||||
}),
|
||||
|
||||
context: ({ req, res }): Context => ({
|
||||
orm,
|
||||
req,
|
||||
res,
|
||||
redis,
|
||||
userLoader: createUserLoader(),
|
||||
voteLoader: createVoteLoader(),
|
||||
spaceLoader: createSpaceLoader(),
|
||||
commentVoteLoader: createCommentVoteLoader(),
|
||||
tagLoader: createTagLoader(),
|
||||
subscriptionLoader: createSubscriptionLoader(),
|
||||
modStatusLoader: createModStatusLoader(),
|
||||
pageLoader: createPageLoader(),
|
||||
followLoader: createFollowLoader(),
|
||||
ownerStatusLoader: createOwnerStatusLoader(),
|
||||
userFollowLoader: createUserFollowLoader(),
|
||||
applicationStatusLoader: createApplicationStatusLoader(),
|
||||
applicationLoader: createApplicationLoader(),
|
||||
applicantsNoLoader: createApplicantsNoLoader(),
|
||||
followerNumberLoader: createFollowerNumberLoader(),
|
||||
subscriberNumberLoader: createSubscriberNumberLoader(),
|
||||
userFollowerNumberLoader: createUserFollowerNumberLoader(),
|
||||
userFollowingNumberLoader: createUserFollowingNumberLoader()
|
||||
})
|
||||
})
|
||||
|
||||
await apolloServer.start()
|
||||
apolloServer.applyMiddleware({
|
||||
app,
|
||||
cors: false
|
||||
})
|
||||
app.use(graphqlUploadExpress())
|
||||
}
|
||||
|
||||
main().catch(console.error)
|
||||
@@ -0,0 +1,20 @@
|
||||
import { OfferApplication } from '@entities'
|
||||
import orm from '@src/type-orm.source'
|
||||
import DataLoader from 'dataloader'
|
||||
|
||||
export const createApplicantsNoLoader = () =>
|
||||
new DataLoader<number, number>(async (offerIds) => {
|
||||
const result: { count: string, offerId: number }[] = await orm.createQueryBuilder()
|
||||
.select('COUNT(*), "offerId"')
|
||||
.from(OfferApplication, 'oa')
|
||||
.orWhere(offerIds.map(id => ({ offerId: id })))
|
||||
.groupBy('"offerId"')
|
||||
.execute()
|
||||
return offerIds.map(id => {
|
||||
const count = result.find(r => r.offerId == id)?.count
|
||||
if (count) {
|
||||
return parseInt(count)
|
||||
}
|
||||
return 0
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,11 @@
|
||||
import { OfferApplication } from '@entities'
|
||||
import DataLoader from 'dataloader'
|
||||
import { In } from 'typeorm'
|
||||
|
||||
export const createApplicationLoader = () =>
|
||||
new DataLoader<number, OfferApplication[]>(async (offerIds) => {
|
||||
const applications = await OfferApplication.find({ where: { offerId: In(offerIds as number[]) }, relations: { user: true } })
|
||||
return offerIds.map(offerId => {
|
||||
return applications.filter(application => application.offerId === offerId)
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,15 @@
|
||||
import orm from '@src/type-orm.source'
|
||||
import DataLoader from 'dataloader'
|
||||
|
||||
export const createApplicationStatusLoader = () =>
|
||||
new DataLoader<{ offerId: number, userId: number }, String | null>(async (keys) => {
|
||||
const applications: { id: number, offerId: number, userId: number, status: string }[] = await orm.createQueryBuilder()
|
||||
.select('*')
|
||||
.from('offer_application', 'oa')
|
||||
.orWhere(keys)
|
||||
.execute()
|
||||
return keys.map(key => {
|
||||
const application = applications.find(a => a.offerId == key.offerId && a.userId == key.userId)
|
||||
return application ? application.status : null
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,18 @@
|
||||
import { CommentVote } from '@entities'
|
||||
import orm from '@src/type-orm.source'
|
||||
import DataLoader from 'dataloader'
|
||||
|
||||
export const createCommentVoteLoader = () =>
|
||||
|
||||
new DataLoader<{ commentId: number, userId: number }, CommentVote | null>(async (keys) => {
|
||||
const commentVotes: CommentVote[] = await orm.createQueryBuilder()
|
||||
.select('*')
|
||||
.from(CommentVote, 'cv')
|
||||
.orWhereInIds(keys)
|
||||
.execute()
|
||||
const map: Record<string, CommentVote> = {}
|
||||
commentVotes.forEach(cv => {
|
||||
map[`${cv.userId}-${cv.commentId}`] = cv
|
||||
})
|
||||
return keys.map(key => map[`${key.userId}-${key.commentId}`])
|
||||
})
|
||||
@@ -0,0 +1,16 @@
|
||||
import { PageFollow } from '@entities'
|
||||
import orm from '@src/type-orm.source'
|
||||
import DataLoader from 'dataloader'
|
||||
|
||||
export const createFollowLoader = () =>
|
||||
new DataLoader<{ pageId: number, userId: number }, boolean>(async (keys) => {
|
||||
const follows: PageFollow[] = await orm.createQueryBuilder()
|
||||
.select('*')
|
||||
.from(PageFollow, 'pf')
|
||||
.orWhereInIds(keys)
|
||||
.execute()
|
||||
return keys.map(key => {
|
||||
const follow = follows.find(fol => fol.pageId == key.pageId && fol.userId == key.userId)
|
||||
return follow ? true : false
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,20 @@
|
||||
import { PageFollow } from '@entities'
|
||||
import orm from '@src/type-orm.source'
|
||||
import DataLoader from 'dataloader'
|
||||
|
||||
export const createFollowerNumberLoader = () =>
|
||||
new DataLoader<number, number>(async (pageIds) => {
|
||||
const result: { count: string, pageId: number }[] = await orm.createQueryBuilder()
|
||||
.select('COUNT(*), "pageId"')
|
||||
.from(PageFollow, 'pf')
|
||||
.orWhere(pageIds.map(id => ({ pageId: id })))
|
||||
.groupBy('"pageId"')
|
||||
.execute()
|
||||
return pageIds.map(id => {
|
||||
const count = result.find(r => r.pageId == id)?.count
|
||||
if (count) {
|
||||
return parseInt(count)
|
||||
}
|
||||
return 0
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,16 @@
|
||||
import orm from '@src/type-orm.source'
|
||||
import DataLoader from 'dataloader'
|
||||
|
||||
export const createModStatusLoader = () =>
|
||||
new DataLoader<{ spaceId: number, userId: number }, boolean>(async (keys) => {
|
||||
const modProofs: { spaceId: number, userId: number }[] = await orm.createQueryBuilder()
|
||||
.select('*')
|
||||
.from('space_mods_user', 'smu')
|
||||
.orWhereInIds(keys)
|
||||
.execute()
|
||||
|
||||
return keys.map(key => {
|
||||
const proof = modProofs.find(mp => mp.spaceId == key.spaceId && mp.userId == key.userId)
|
||||
return proof ? true : false
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,15 @@
|
||||
import orm from '@src/type-orm.source'
|
||||
import DataLoader from 'dataloader'
|
||||
|
||||
export const createOwnerStatusLoader = () =>
|
||||
new DataLoader<{ pageId: number, userId: number }, boolean>(async (keys) => {
|
||||
const ownerProofs: { pageId: number, userId: number }[] = await orm.createQueryBuilder()
|
||||
.select('*')
|
||||
.from('page_owners_user', 'pou')
|
||||
.orWhereInIds(keys)
|
||||
.execute()
|
||||
return keys.map(key => {
|
||||
const ownerProof = ownerProofs.find(o => o.pageId == key.pageId && o.userId == key.userId)
|
||||
return ownerProof ? true : false
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,15 @@
|
||||
import DataLoader from 'dataloader'
|
||||
import { In } from 'typeorm'
|
||||
import { Page, User } from '@entities'
|
||||
|
||||
export const createPageLoader = () =>
|
||||
|
||||
new DataLoader<number, User>(async (pageIds) => {
|
||||
const pages = await Page.findBy({ id: In(pageIds as number[]) })
|
||||
|
||||
const map: Record<number, User> = {}
|
||||
pages.forEach(p => {
|
||||
map[p.id] = p
|
||||
})
|
||||
return pageIds.map(id => map[id])
|
||||
})
|
||||
@@ -0,0 +1,15 @@
|
||||
import DataLoader from 'dataloader'
|
||||
import { In } from 'typeorm'
|
||||
import { Space } from '@entities'
|
||||
|
||||
export const createSpaceLoader = () =>
|
||||
|
||||
new DataLoader<number, Space>(async (spaceIds) => {
|
||||
const spaces = await Space.findBy({ id: In(spaceIds as number[]) })
|
||||
|
||||
const map: Record<number, Space> = {}
|
||||
spaces.forEach(s => {
|
||||
map[s.id] = s
|
||||
})
|
||||
return spaceIds.map(id => map[id])
|
||||
})
|
||||
@@ -0,0 +1,20 @@
|
||||
import { SpaceSubscription } from '@entities'
|
||||
import orm from '@src/type-orm.source'
|
||||
import DataLoader from 'dataloader'
|
||||
|
||||
export const createSubscriberNumberLoader = () =>
|
||||
new DataLoader<number, number>(async (spaceIds) => {
|
||||
const result: { count: string, spaceId: number }[] = await orm.createQueryBuilder()
|
||||
.select('COUNT(*), "spaceId"')
|
||||
.from(SpaceSubscription, 'ss')
|
||||
.orWhere(spaceIds.map(id => ({ spaceId: id })))
|
||||
.groupBy('"spaceId"')
|
||||
.execute()
|
||||
return spaceIds.map(id => {
|
||||
const count = result.find(r => r.spaceId == id)?.count
|
||||
if (count) {
|
||||
return parseInt(count)
|
||||
}
|
||||
return 0
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,16 @@
|
||||
import { SpaceSubscription } from '@entities'
|
||||
import orm from '@src/type-orm.source'
|
||||
import DataLoader from 'dataloader'
|
||||
|
||||
export const createSubscriptionLoader = () =>
|
||||
new DataLoader<{ spaceId: number, userId: number }, boolean>(async (keys) => {
|
||||
const subscriptions: SpaceSubscription[] = await orm.createQueryBuilder()
|
||||
.select('*')
|
||||
.from(SpaceSubscription, 'ss')
|
||||
.orWhereInIds(keys)
|
||||
.execute()
|
||||
return keys.map(key => {
|
||||
const subscription = subscriptions.find(sub => sub.spaceId == key.spaceId && sub.userId == key.userId)
|
||||
return subscription ? true : false
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,27 @@
|
||||
import { Tag } from '@entities'
|
||||
import orm from '@src/type-orm.source'
|
||||
import DataLoader from 'dataloader'
|
||||
|
||||
export const createTagLoader = () =>
|
||||
|
||||
new DataLoader<number, Tag[]>(async (postIds) => {
|
||||
const tagItems: { postId: number, tagId: number }[] = await orm.query(`
|
||||
SELECT * FROM post_tags_tag WHERE "postId" IN (${postIds.join(', ')});
|
||||
`)
|
||||
const tagIds = tagItems.map(ti => ti.tagId)
|
||||
if (tagIds.length > 0) {
|
||||
const tags: Tag[] = await orm.query(`
|
||||
SELECT * FROM tag WHERE id IN (${tagIds.join(', ')});
|
||||
`)
|
||||
|
||||
return postIds.map(id => {
|
||||
const postTagItems = tagItems.filter(ti => ti.postId == id)
|
||||
const postTagIds = postTagItems.map(pti => pti.tagId)
|
||||
return tags.filter(t => postTagIds.includes(t.id))
|
||||
})
|
||||
}
|
||||
else {
|
||||
const newArr = postIds.map(id => [])
|
||||
return newArr
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,16 @@
|
||||
import { UserFollow } from '@entities'
|
||||
import orm from '@src/type-orm.source'
|
||||
import DataLoader from 'dataloader'
|
||||
|
||||
export const createUserFollowLoader = () =>
|
||||
new DataLoader<{ followedUserId: number, followingUserId: number }, boolean>(async (keys) => {
|
||||
const follows: UserFollow[] = await orm.createQueryBuilder()
|
||||
.select('*')
|
||||
.from(UserFollow, 'uf')
|
||||
.orWhereInIds(keys)
|
||||
.execute()
|
||||
return keys.map(key => {
|
||||
const follow = follows.find(fol => fol.followedUserId == key.followedUserId && fol.followingUserId == key.followingUserId)
|
||||
return follow ? true : false
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,20 @@
|
||||
import { UserFollow } from '@entities'
|
||||
import orm from '@src/type-orm.source'
|
||||
import DataLoader from 'dataloader'
|
||||
|
||||
export const createUserFollowerNumberLoader = () =>
|
||||
new DataLoader<number, number>(async (userIds) => {
|
||||
const result: { count: string, followedUserId: number }[] = await orm.createQueryBuilder()
|
||||
.select('COUNT(*), "followedUserId"')
|
||||
.from(UserFollow, 'uf')
|
||||
.orWhere(userIds.map(id => ({ followedUserId: id })))
|
||||
.groupBy('"followedUserId"')
|
||||
.execute()
|
||||
return userIds.map(id => {
|
||||
const count = result.find(r => r.followedUserId == id)?.count
|
||||
if (count) {
|
||||
return parseInt(count)
|
||||
}
|
||||
return 0
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,20 @@
|
||||
import { UserFollow } from '@entities'
|
||||
import orm from '@src/type-orm.source'
|
||||
import DataLoader from 'dataloader'
|
||||
|
||||
export const createUserFollowingNumberLoader = () =>
|
||||
new DataLoader<number, number>(async (userIds) => {
|
||||
const result: { count: string, followingUserId: number }[] = await orm.createQueryBuilder()
|
||||
.select('COUNT(*), "followingUserId"')
|
||||
.from(UserFollow, 'uf')
|
||||
.orWhere(userIds.map(id => ({ followingUserId: id })))
|
||||
.groupBy('"followingUserId"')
|
||||
.execute()
|
||||
return userIds.map(id => {
|
||||
const count = result.find(r => r.followingUserId == id)?.count
|
||||
if (count) {
|
||||
return parseInt(count)
|
||||
}
|
||||
return 0
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,15 @@
|
||||
import DataLoader from 'dataloader'
|
||||
import { In } from 'typeorm'
|
||||
import { User } from '@entities'
|
||||
|
||||
export const createUserLoader = () =>
|
||||
|
||||
new DataLoader<number, User>(async (userIds) => {
|
||||
const users = await User.findBy({ id: In(userIds as number[]) })
|
||||
|
||||
const map: Record<number, User> = {}
|
||||
users.forEach(u => {
|
||||
map[u.id] = u
|
||||
})
|
||||
return userIds.map(id => map[id])
|
||||
})
|
||||
@@ -0,0 +1,18 @@
|
||||
import DataLoader from 'dataloader'
|
||||
import { Vote } from '@entities'
|
||||
import orm from '@src/type-orm.source'
|
||||
|
||||
export const createVoteLoader = () =>
|
||||
|
||||
new DataLoader<{ postId: number, userId: number }, Vote | null>(async (keys) => {
|
||||
const votes: Vote[] = await orm.createQueryBuilder()
|
||||
.select('*')
|
||||
.from(Vote, 'v')
|
||||
.orWhereInIds(keys)
|
||||
.execute()
|
||||
const map: Record<string, Vote> = {}
|
||||
votes.forEach(v => {
|
||||
map[`${v.userId}-${v.postId}`] = v
|
||||
})
|
||||
return keys.map(key => map[`${key.userId}-${key.postId}`])
|
||||
})
|
||||
@@ -0,0 +1,18 @@
|
||||
export * from './createUserLoader'
|
||||
export * from './createVoteLoader'
|
||||
export * from './createSpaceLoader'
|
||||
export * from './createCommentVoteLoader'
|
||||
export * from './createTagLoader'
|
||||
export * from './createSubscriptionLoader'
|
||||
export * from './createModStatusLoader'
|
||||
export * from './createPageLoader'
|
||||
export * from './createFollowLoader'
|
||||
export * from './createOwnerStatusLoader'
|
||||
export * from './createUserFollowLoader'
|
||||
export * from './createApplicationStatusLoader'
|
||||
export * from './createApplicationLoader'
|
||||
export * from './createApplicantsNoLoader'
|
||||
export * from './createFollowerNumberLoader'
|
||||
export * from './createSubscriberNumberLoader'
|
||||
export * from './createUserFollowerNumberLoader'
|
||||
export * from './createUserFollowingNumberLoader'
|
||||
@@ -0,0 +1 @@
|
||||
export * from './isAuth'
|
||||
@@ -0,0 +1,12 @@
|
||||
import { Context } from '@types'
|
||||
import { MiddlewareFn } from 'type-graphql'
|
||||
import { User } from '@entities'
|
||||
|
||||
export const isAuth: MiddlewareFn<Context> = async ({ context }, next) => {
|
||||
if (!context.req.session.userId ||
|
||||
!(await User.findOne({ where: { id: context.req.session.userId } }))
|
||||
) {
|
||||
throw new Error('Not authenticated.')
|
||||
}
|
||||
await next()
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||
|
||||
export class Initial1660494342130 implements MigrationInterface {
|
||||
name = 'Initial1660494342130'
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`CREATE TABLE "user" ("id" SERIAL NOT NULL, "createdAt" TIMESTAMP NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP NOT NULL DEFAULT now(), "username" character varying NOT NULL, "email" character varying NOT NULL, "password" character varying NOT NULL, "skills" text, "avatar" character varying, "coverPhoto" character varying, "fullName" character varying, "headline" character varying, "address" character varying, "about" character varying, "mostRecentLatitude" double precision, "mostRecentLongitude" double precision, CONSTRAINT "UQ_78a916df40e02a9deb1c4b75edb" UNIQUE ("username"), CONSTRAINT "UQ_e12875dfb3b1d92d7d7c5377e22" UNIQUE ("email"), CONSTRAINT "PK_cace4a159ff9f2512dd42373760" PRIMARY KEY ("id"))`);
|
||||
await queryRunner.query(`CREATE TABLE "post" ("id" SERIAL NOT NULL, "createdAt" TIMESTAMP NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP NOT NULL DEFAULT now(), "title" character varying NOT NULL, "text" character varying NOT NULL, "creatorType" character varying NOT NULL DEFAULT 'user', "creatorId" integer, "pageCreatorId" integer, "points" integer NOT NULL DEFAULT '0', "spaceId" integer NOT NULL, CONSTRAINT "PK_be5fda3aac270b134ff9c21cdee" PRIMARY KEY ("id"))`);
|
||||
await queryRunner.query(`CREATE TABLE "vote" ("value" integer NOT NULL, "userId" integer NOT NULL, "postId" integer NOT NULL, CONSTRAINT "PK_16e301aa5efdd994626b2635186" PRIMARY KEY ("userId", "postId"))`);
|
||||
await queryRunner.query(`CREATE TABLE "space" ("id" SERIAL NOT NULL, "createdAt" TIMESTAMP NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP NOT NULL DEFAULT now(), "spaceName" character varying NOT NULL, "avatar" character varying, "coverPhoto" character varying, "fullSpaceName" character varying, "rules" character varying, "headline" character varying, "about" character varying, CONSTRAINT "UQ_d3a1749188980a055b0bcd4321d" UNIQUE ("spaceName"), CONSTRAINT "PK_094f5ec727fe052956a11623640" PRIMARY KEY ("id"))`);
|
||||
await queryRunner.query(`CREATE TABLE "space_subscription" ("userId" integer NOT NULL, "spaceId" integer NOT NULL, CONSTRAINT "PK_d628d32fd2777438e93174bc72a" PRIMARY KEY ("userId", "spaceId"))`);
|
||||
await queryRunner.query(`CREATE TABLE "comment" ("id" SERIAL NOT NULL, "createdAt" TIMESTAMP NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP NOT NULL DEFAULT now(), "text" character varying NOT NULL, "creatorType" character varying NOT NULL DEFAULT 'user', "creatorId" integer, "pageCreatorId" integer, "postId" integer NOT NULL, "points" integer NOT NULL DEFAULT '0', CONSTRAINT "PK_0b0e4bbc8415ec426f87f3a88e2" PRIMARY KEY ("id"))`);
|
||||
await queryRunner.query(`CREATE TABLE "comment_vote" ("value" integer NOT NULL, "userId" integer NOT NULL, "commentId" integer NOT NULL, CONSTRAINT "PK_9194f426d41fb9a8abc3aae5114" PRIMARY KEY ("userId", "commentId"))`);
|
||||
await queryRunner.query(`CREATE TABLE "offer_application" ("id" SERIAL NOT NULL, "userId" integer NOT NULL, "offerId" integer NOT NULL, "status" character varying NOT NULL DEFAULT 'applied', CONSTRAINT "PK_d8989a17a7c87cfa5ff63ea84c1" PRIMARY KEY ("id"))`);
|
||||
await queryRunner.query(`CREATE TABLE "offer" ("id" SERIAL NOT NULL, "createdAt" TIMESTAMP NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP NOT NULL DEFAULT now(), "creatorType" character varying NOT NULL DEFAULT 'user', "creatorId" integer, "pageCreatorId" integer, "spaceId" integer NOT NULL, "title" character varying NOT NULL, "workplace" character varying, "address" character varying, "recruiting" boolean NOT NULL DEFAULT false, "employmentType" character varying, "salaryRange" character varying, "department" character varying, "requirements" character varying, "benefits" character varying, "description" character varying, "photo" character varying, CONSTRAINT "PK_57c6ae1abe49201919ef68de900" PRIMARY KEY ("id"))`);
|
||||
await queryRunner.query(`CREATE TABLE "tag" ("id" SERIAL NOT NULL, "name" character varying NOT NULL, CONSTRAINT "PK_8e4052373c579afc1471f526760" PRIMARY KEY ("id"))`);
|
||||
await queryRunner.query(`CREATE TABLE "conversation" ("id" SERIAL NOT NULL, "participants" integer array NOT NULL, "firestoreCollectionId" character varying NOT NULL, CONSTRAINT "PK_864528ec4274360a40f66c29845" PRIMARY KEY ("id"))`);
|
||||
await queryRunner.query(`CREATE TABLE "page" ("id" SERIAL NOT NULL, "createdAt" TIMESTAMP NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP NOT NULL DEFAULT now(), "pageName" character varying NOT NULL, "email" character varying, "avatar" character varying, "coverPhoto" character varying, "fullPageName" character varying, "headline" character varying, "address" character varying, "about" character varying, CONSTRAINT "UQ_37f114be85015bdfea6ecfefe6d" UNIQUE ("pageName"), CONSTRAINT "UQ_add9b61d89ec1480843a61c924d" UNIQUE ("email"), CONSTRAINT "PK_742f4117e065c5b6ad21b37ba1f" PRIMARY KEY ("id"))`);
|
||||
await queryRunner.query(`CREATE TABLE "page_follow" ("userId" integer NOT NULL, "pageId" integer NOT NULL, CONSTRAINT "PK_ac8f7df2a892662f4edf458ca33" PRIMARY KEY ("userId", "pageId"))`);
|
||||
await queryRunner.query(`CREATE TABLE "user_follow" ("followingUserId" integer NOT NULL, "followedUserId" integer NOT NULL, CONSTRAINT "PK_bdb4b69fec91b1b2deb7df00b5e" PRIMARY KEY ("followingUserId", "followedUserId"))`);
|
||||
await queryRunner.query(`CREATE TABLE "education_item" ("id" SERIAL NOT NULL, "school" character varying NOT NULL, "status" character varying, "startDate" TIMESTAMP WITH TIME ZONE, "endDate" TIMESTAMP WITH TIME ZONE, "userId" integer, "photo" character varying, CONSTRAINT "PK_115272e55085398f5a282496bb8" PRIMARY KEY ("id"))`);
|
||||
await queryRunner.query(`CREATE TABLE "experience" ("id" SERIAL NOT NULL, "title" character varying NOT NULL, "workplace" character varying, "startDate" TIMESTAMP WITH TIME ZONE, "endDate" TIMESTAMP WITH TIME ZONE, "userId" integer, "photo" character varying, CONSTRAINT "PK_5e8d5a534100e1b17ee2efa429a" PRIMARY KEY ("id"))`);
|
||||
await queryRunner.query(`CREATE TABLE "qualification" ("id" SERIAL NOT NULL, "name" character varying NOT NULL, "issuingOrganisation" character varying NOT NULL, "issuanceDate" TIMESTAMP WITH TIME ZONE, "expire" boolean NOT NULL, "expirationDate" TIMESTAMP WITH TIME ZONE, "credentialID" character varying, "credentialURL" character varying, "userId" integer, "photo" character varying, CONSTRAINT "PK_c8244868552c4364a5264440a66" PRIMARY KEY ("id"))`);
|
||||
await queryRunner.query(`CREATE TABLE "cv" ("id" SERIAL NOT NULL, "filename" character varying NOT NULL, "key" character varying NOT NULL, "userId" integer, CONSTRAINT "PK_4ddf7891daf83c3506efa503bb8" PRIMARY KEY ("id"))`);
|
||||
await queryRunner.query(`CREATE TABLE "post_tags_tag" ("postId" integer NOT NULL, "tagId" integer NOT NULL, CONSTRAINT "PK_e9b7b8e6a07bdccb6a954171676" PRIMARY KEY ("postId", "tagId"))`);
|
||||
await queryRunner.query(`CREATE INDEX "IDX_b651178cc41334544a7a9601c4" ON "post_tags_tag" ("postId") `);
|
||||
await queryRunner.query(`CREATE INDEX "IDX_41e7626b9cc03c5c65812ae55e" ON "post_tags_tag" ("tagId") `);
|
||||
await queryRunner.query(`CREATE TABLE "space_mods_user" ("spaceId" integer NOT NULL, "userId" integer NOT NULL, CONSTRAINT "PK_4768be7da937c7ee02c260fb761" PRIMARY KEY ("spaceId", "userId"))`);
|
||||
await queryRunner.query(`CREATE INDEX "IDX_6fac656f12453c24f08855fbef" ON "space_mods_user" ("spaceId") `);
|
||||
await queryRunner.query(`CREATE INDEX "IDX_2172d469a5e9c5e4397bcb94ff" ON "space_mods_user" ("userId") `);
|
||||
await queryRunner.query(`CREATE TABLE "page_owners_user" ("pageId" integer NOT NULL, "userId" integer NOT NULL, CONSTRAINT "PK_2b7f0419bfbb8f0550592d2cf37" PRIMARY KEY ("pageId", "userId"))`);
|
||||
await queryRunner.query(`CREATE INDEX "IDX_1c5a8df532d6c129c4f1642b2f" ON "page_owners_user" ("pageId") `);
|
||||
await queryRunner.query(`CREATE INDEX "IDX_5bd7deaf0c8e15ea861d15efc3" ON "page_owners_user" ("userId") `);
|
||||
await queryRunner.query(`ALTER TABLE "post" ADD CONSTRAINT "FK_9e91e6a24261b66f53971d3f96b" FOREIGN KEY ("creatorId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
|
||||
await queryRunner.query(`ALTER TABLE "post" ADD CONSTRAINT "FK_605fe7290cfa226a4d444c05ca4" FOREIGN KEY ("pageCreatorId") REFERENCES "page"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
|
||||
await queryRunner.query(`ALTER TABLE "post" ADD CONSTRAINT "FK_899a1931431768b2800f695ac60" FOREIGN KEY ("spaceId") REFERENCES "space"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
|
||||
await queryRunner.query(`ALTER TABLE "vote" ADD CONSTRAINT "FK_f5de237a438d298031d11a57c3b" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
|
||||
await queryRunner.query(`ALTER TABLE "vote" ADD CONSTRAINT "FK_43cc1af57676ac1b7ec774bd10f" FOREIGN KEY ("postId") REFERENCES "post"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
|
||||
await queryRunner.query(`ALTER TABLE "space_subscription" ADD CONSTRAINT "FK_9f89ed79bb85a199306ce7e3ae1" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
|
||||
await queryRunner.query(`ALTER TABLE "space_subscription" ADD CONSTRAINT "FK_4c2cf829c698bede8b9c8608f10" FOREIGN KEY ("spaceId") REFERENCES "space"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
|
||||
await queryRunner.query(`ALTER TABLE "comment" ADD CONSTRAINT "FK_b6bf60ecb9f6c398e349adff52f" FOREIGN KEY ("creatorId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
|
||||
await queryRunner.query(`ALTER TABLE "comment" ADD CONSTRAINT "FK_37de0ca7e7c8dd9f6a3e1f2b6d3" FOREIGN KEY ("pageCreatorId") REFERENCES "page"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
|
||||
await queryRunner.query(`ALTER TABLE "comment" ADD CONSTRAINT "FK_94a85bb16d24033a2afdd5df060" FOREIGN KEY ("postId") REFERENCES "post"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
|
||||
await queryRunner.query(`ALTER TABLE "comment_vote" ADD CONSTRAINT "FK_ade7498b89296b9fb63bcd8dbdd" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
|
||||
await queryRunner.query(`ALTER TABLE "comment_vote" ADD CONSTRAINT "FK_5d77d92a6925ae3fc8da14e1257" FOREIGN KEY ("commentId") REFERENCES "comment"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
|
||||
await queryRunner.query(`ALTER TABLE "offer_application" ADD CONSTRAINT "FK_dcfd5b26f80494128baf7bb7578" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
|
||||
await queryRunner.query(`ALTER TABLE "offer_application" ADD CONSTRAINT "FK_6cb6ed00606a2fb71c05fb3c871" FOREIGN KEY ("offerId") REFERENCES "offer"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
|
||||
await queryRunner.query(`ALTER TABLE "offer" ADD CONSTRAINT "FK_cd84aed04fbd70e9ad48139c727" FOREIGN KEY ("creatorId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
|
||||
await queryRunner.query(`ALTER TABLE "offer" ADD CONSTRAINT "FK_f4621bc66549eda711a0b7c6558" FOREIGN KEY ("pageCreatorId") REFERENCES "page"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
|
||||
await queryRunner.query(`ALTER TABLE "offer" ADD CONSTRAINT "FK_69bbcc303da6f7da97744be788a" FOREIGN KEY ("spaceId") REFERENCES "space"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
|
||||
await queryRunner.query(`ALTER TABLE "page_follow" ADD CONSTRAINT "FK_732300fd551f8b08e267018ed99" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
|
||||
await queryRunner.query(`ALTER TABLE "page_follow" ADD CONSTRAINT "FK_b0cd715ee8609422e661e0c43fc" FOREIGN KEY ("pageId") REFERENCES "page"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
|
||||
await queryRunner.query(`ALTER TABLE "user_follow" ADD CONSTRAINT "FK_90ab1c414dac6701f4c126fb736" FOREIGN KEY ("followingUserId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
|
||||
await queryRunner.query(`ALTER TABLE "user_follow" ADD CONSTRAINT "FK_4e493e20c9c272183e73da57ddf" FOREIGN KEY ("followedUserId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
|
||||
await queryRunner.query(`ALTER TABLE "education_item" ADD CONSTRAINT "FK_1dd0c4d5f3e2500b08c3d137b29" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
|
||||
await queryRunner.query(`ALTER TABLE "experience" ADD CONSTRAINT "FK_cbfb1d1219454c9b45f1b3c4274" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
|
||||
await queryRunner.query(`ALTER TABLE "qualification" ADD CONSTRAINT "FK_6550f632c00a2739a1dad0381c1" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
|
||||
await queryRunner.query(`ALTER TABLE "cv" ADD CONSTRAINT "FK_e4b7330e64fd0ecce86720e62f9" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
|
||||
await queryRunner.query(`ALTER TABLE "post_tags_tag" ADD CONSTRAINT "FK_b651178cc41334544a7a9601c45" FOREIGN KEY ("postId") REFERENCES "post"("id") ON DELETE CASCADE ON UPDATE CASCADE`);
|
||||
await queryRunner.query(`ALTER TABLE "post_tags_tag" ADD CONSTRAINT "FK_41e7626b9cc03c5c65812ae55e8" FOREIGN KEY ("tagId") REFERENCES "tag"("id") ON DELETE CASCADE ON UPDATE CASCADE`);
|
||||
await queryRunner.query(`ALTER TABLE "space_mods_user" ADD CONSTRAINT "FK_6fac656f12453c24f08855fbefc" FOREIGN KEY ("spaceId") REFERENCES "space"("id") ON DELETE CASCADE ON UPDATE CASCADE`);
|
||||
await queryRunner.query(`ALTER TABLE "space_mods_user" ADD CONSTRAINT "FK_2172d469a5e9c5e4397bcb94ff2" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE CASCADE`);
|
||||
await queryRunner.query(`ALTER TABLE "page_owners_user" ADD CONSTRAINT "FK_1c5a8df532d6c129c4f1642b2ff" FOREIGN KEY ("pageId") REFERENCES "page"("id") ON DELETE CASCADE ON UPDATE CASCADE`);
|
||||
await queryRunner.query(`ALTER TABLE "page_owners_user" ADD CONSTRAINT "FK_5bd7deaf0c8e15ea861d15efc36" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE CASCADE`);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`ALTER TABLE "page_owners_user" DROP CONSTRAINT "FK_5bd7deaf0c8e15ea861d15efc36"`);
|
||||
await queryRunner.query(`ALTER TABLE "page_owners_user" DROP CONSTRAINT "FK_1c5a8df532d6c129c4f1642b2ff"`);
|
||||
await queryRunner.query(`ALTER TABLE "space_mods_user" DROP CONSTRAINT "FK_2172d469a5e9c5e4397bcb94ff2"`);
|
||||
await queryRunner.query(`ALTER TABLE "space_mods_user" DROP CONSTRAINT "FK_6fac656f12453c24f08855fbefc"`);
|
||||
await queryRunner.query(`ALTER TABLE "post_tags_tag" DROP CONSTRAINT "FK_41e7626b9cc03c5c65812ae55e8"`);
|
||||
await queryRunner.query(`ALTER TABLE "post_tags_tag" DROP CONSTRAINT "FK_b651178cc41334544a7a9601c45"`);
|
||||
await queryRunner.query(`ALTER TABLE "cv" DROP CONSTRAINT "FK_e4b7330e64fd0ecce86720e62f9"`);
|
||||
await queryRunner.query(`ALTER TABLE "qualification" DROP CONSTRAINT "FK_6550f632c00a2739a1dad0381c1"`);
|
||||
await queryRunner.query(`ALTER TABLE "experience" DROP CONSTRAINT "FK_cbfb1d1219454c9b45f1b3c4274"`);
|
||||
await queryRunner.query(`ALTER TABLE "education_item" DROP CONSTRAINT "FK_1dd0c4d5f3e2500b08c3d137b29"`);
|
||||
await queryRunner.query(`ALTER TABLE "user_follow" DROP CONSTRAINT "FK_4e493e20c9c272183e73da57ddf"`);
|
||||
await queryRunner.query(`ALTER TABLE "user_follow" DROP CONSTRAINT "FK_90ab1c414dac6701f4c126fb736"`);
|
||||
await queryRunner.query(`ALTER TABLE "page_follow" DROP CONSTRAINT "FK_b0cd715ee8609422e661e0c43fc"`);
|
||||
await queryRunner.query(`ALTER TABLE "page_follow" DROP CONSTRAINT "FK_732300fd551f8b08e267018ed99"`);
|
||||
await queryRunner.query(`ALTER TABLE "offer" DROP CONSTRAINT "FK_69bbcc303da6f7da97744be788a"`);
|
||||
await queryRunner.query(`ALTER TABLE "offer" DROP CONSTRAINT "FK_f4621bc66549eda711a0b7c6558"`);
|
||||
await queryRunner.query(`ALTER TABLE "offer" DROP CONSTRAINT "FK_cd84aed04fbd70e9ad48139c727"`);
|
||||
await queryRunner.query(`ALTER TABLE "offer_application" DROP CONSTRAINT "FK_6cb6ed00606a2fb71c05fb3c871"`);
|
||||
await queryRunner.query(`ALTER TABLE "offer_application" DROP CONSTRAINT "FK_dcfd5b26f80494128baf7bb7578"`);
|
||||
await queryRunner.query(`ALTER TABLE "comment_vote" DROP CONSTRAINT "FK_5d77d92a6925ae3fc8da14e1257"`);
|
||||
await queryRunner.query(`ALTER TABLE "comment_vote" DROP CONSTRAINT "FK_ade7498b89296b9fb63bcd8dbdd"`);
|
||||
await queryRunner.query(`ALTER TABLE "comment" DROP CONSTRAINT "FK_94a85bb16d24033a2afdd5df060"`);
|
||||
await queryRunner.query(`ALTER TABLE "comment" DROP CONSTRAINT "FK_37de0ca7e7c8dd9f6a3e1f2b6d3"`);
|
||||
await queryRunner.query(`ALTER TABLE "comment" DROP CONSTRAINT "FK_b6bf60ecb9f6c398e349adff52f"`);
|
||||
await queryRunner.query(`ALTER TABLE "space_subscription" DROP CONSTRAINT "FK_4c2cf829c698bede8b9c8608f10"`);
|
||||
await queryRunner.query(`ALTER TABLE "space_subscription" DROP CONSTRAINT "FK_9f89ed79bb85a199306ce7e3ae1"`);
|
||||
await queryRunner.query(`ALTER TABLE "vote" DROP CONSTRAINT "FK_43cc1af57676ac1b7ec774bd10f"`);
|
||||
await queryRunner.query(`ALTER TABLE "vote" DROP CONSTRAINT "FK_f5de237a438d298031d11a57c3b"`);
|
||||
await queryRunner.query(`ALTER TABLE "post" DROP CONSTRAINT "FK_899a1931431768b2800f695ac60"`);
|
||||
await queryRunner.query(`ALTER TABLE "post" DROP CONSTRAINT "FK_605fe7290cfa226a4d444c05ca4"`);
|
||||
await queryRunner.query(`ALTER TABLE "post" DROP CONSTRAINT "FK_9e91e6a24261b66f53971d3f96b"`);
|
||||
await queryRunner.query(`DROP INDEX "public"."IDX_5bd7deaf0c8e15ea861d15efc3"`);
|
||||
await queryRunner.query(`DROP INDEX "public"."IDX_1c5a8df532d6c129c4f1642b2f"`);
|
||||
await queryRunner.query(`DROP TABLE "page_owners_user"`);
|
||||
await queryRunner.query(`DROP INDEX "public"."IDX_2172d469a5e9c5e4397bcb94ff"`);
|
||||
await queryRunner.query(`DROP INDEX "public"."IDX_6fac656f12453c24f08855fbef"`);
|
||||
await queryRunner.query(`DROP TABLE "space_mods_user"`);
|
||||
await queryRunner.query(`DROP INDEX "public"."IDX_41e7626b9cc03c5c65812ae55e"`);
|
||||
await queryRunner.query(`DROP INDEX "public"."IDX_b651178cc41334544a7a9601c4"`);
|
||||
await queryRunner.query(`DROP TABLE "post_tags_tag"`);
|
||||
await queryRunner.query(`DROP TABLE "cv"`);
|
||||
await queryRunner.query(`DROP TABLE "qualification"`);
|
||||
await queryRunner.query(`DROP TABLE "experience"`);
|
||||
await queryRunner.query(`DROP TABLE "education_item"`);
|
||||
await queryRunner.query(`DROP TABLE "user_follow"`);
|
||||
await queryRunner.query(`DROP TABLE "page_follow"`);
|
||||
await queryRunner.query(`DROP TABLE "page"`);
|
||||
await queryRunner.query(`DROP TABLE "conversation"`);
|
||||
await queryRunner.query(`DROP TABLE "tag"`);
|
||||
await queryRunner.query(`DROP TABLE "offer"`);
|
||||
await queryRunner.query(`DROP TABLE "offer_application"`);
|
||||
await queryRunner.query(`DROP TABLE "comment_vote"`);
|
||||
await queryRunner.query(`DROP TABLE "comment"`);
|
||||
await queryRunner.query(`DROP TABLE "space_subscription"`);
|
||||
await queryRunner.query(`DROP TABLE "space"`);
|
||||
await queryRunner.query(`DROP TABLE "vote"`);
|
||||
await queryRunner.query(`DROP TABLE "post"`);
|
||||
await queryRunner.query(`DROP TABLE "user"`);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
import { __prod__ } from '@constants'
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm'
|
||||
|
||||
export class AddSpaces1660494342131 implements MigrationInterface {
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
if (!__prod__) {
|
||||
await queryRunner.query(`--sql
|
||||
BEGIN;
|
||||
INSERT INTO space ("spaceName") VALUES ('CS');
|
||||
INSERT INTO space ("spaceName") VALUES ('economics');
|
||||
INSERT INTO space ("spaceName") VALUES ('politics');
|
||||
INSERT INTO space ("spaceName") VALUES ('arts');
|
||||
INSERT INTO space ("spaceName") VALUES ('law');
|
||||
INSERT INTO space ("spaceName") VALUES ('agriculture');
|
||||
INSERT INTO space ("spaceName") VALUES ('tourism');
|
||||
INSERT INTO space ("spaceName") VALUES ('engineering');
|
||||
INSERT INTO space ("spaceName") VALUES ('science');
|
||||
INSERT INTO space ("spaceName") VALUES ('history');
|
||||
INSERT INTO space ("spaceName") VALUES ('philosophy');
|
||||
INSERT INTO space ("spaceName") VALUES ('maths');
|
||||
INSERT INTO space ("spaceName") VALUES ('physics');
|
||||
INSERT INTO space ("spaceName") VALUES ('chemistry');
|
||||
INSERT INTO space ("spaceName") VALUES ('biology');
|
||||
INSERT INTO space ("spaceName") VALUES ('sports');
|
||||
COMMIT;
|
||||
`)
|
||||
}
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
if (!__prod__) {
|
||||
await queryRunner.query(`--sql
|
||||
DELETE FROM space WHERE true;
|
||||
`)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
import { __prod__ } from '@constants'
|
||||
import { faker } from '@faker-js/faker'
|
||||
import _ from 'lodash'
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm'
|
||||
|
||||
export class AddUsers1660494342132 implements MigrationInterface {
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
if (!__prod__) {
|
||||
await queryRunner.query(`
|
||||
INSERT INTO "user" ("username", "email", "password") VALUES ('admin', 'quyanh.nguyen@helsinki.fi', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('nullett0', 'drubbert0@oracle.com', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2013-02-21 05:19:19', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('evigers1', 'eolyet1@a8.net', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2016-08-06 04:15:03', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('tpaoloni2', 'fgaenor2@unesco.org', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2019-02-23 16:59:03', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('cmacconneely3', 'gglanfield3@google.pl', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2017-09-30 18:06:03', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('bcraghead4', 'sickovitz4@sakura.ne.jp', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2015-08-25 23:12:55', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('ieat5', 'hkopf5@yellowbook.com', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2018-06-14 10:33:57', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('harling6', 'hlortz6@wsj.com', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2021-02-18 15:17:28', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('lbrandel7', 'kbuyers7@slate.com', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2015-02-21 06:04:22', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('lkatte8', 'clanston8@i2i.jp', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2016-09-18 20:16:31', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('baronowitz9', 'spossek9@upenn.edu', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2020-09-03 06:56:17', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('mkalinovicha', 'mmcenerya@unicef.org', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2018-11-15 03:21:09', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('dburkettb', 'cscuphamb@un.org', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2018-10-09 05:42:19', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('bmitchelhillc', 'ccoathc@unc.edu', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2021-12-22 04:00:30', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('eadamczewskid', 'crozenzweigd@amazonaws.com', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2012-08-16 17:24:33', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('fbeszante', 'mfloate@arstechnica.com', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2010-04-18 11:23:07', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('prozsaf', 'eturonef@live.com', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2013-09-12 22:12:07', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('mvittelg', 'nreadittg@icq.com', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2013-02-24 00:11:29', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('fcasoh', 'fhaversh@independent.co.uk', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2014-02-20 03:35:50', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('wmugfordi', 'jcuestai@cmu.edu', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2011-11-17 03:05:33', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('mbruckenthalj', 'skhrishtafovichj@mashable.com', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2018-05-19 17:03:47', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('gmacgormank', 'khurrellk@tiny.cc', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2019-07-11 06:32:04', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('plesliel', 'nmclesel@oaic.gov.au', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2021-06-08 08:03:24', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('rlangmeadm', 'hlamymanm@foxnews.com', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2018-08-19 21:44:19', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('gchapelhown', 'wcoupmann@posterous.com', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2021-06-04 17:34:58', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('nbarwacko', 'mtethcoteo@deviantart.com', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2018-05-25 20:09:36', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('lcardenasp', 'jbridep@wiley.com', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2021-03-16 03:10:29', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('fwhatsizeq', 'wadiscotq@berkeley.edu', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2018-02-27 05:13:13', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('lbeardowr', 'kdashkovichr@youtube.com', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2019-05-01 03:39:50', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('sdellos', 'wdartnells@smugmug.com', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2011-11-01 13:16:25', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('clindwassert', 'afustt@yahoo.com', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2018-05-26 16:18:36', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('sgoffu', 'krochesteru@narod.ru', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2014-01-28 03:50:40', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('cimlackev', 'bnorthamv@storify.com', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2010-09-17 13:07:23', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('hnaerupw', 'ccunniffw@liveinternet.ru', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2010-07-24 15:57:24', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('brylandsx', 'sgutsellx@vkontakte.ru', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2015-07-13 16:24:12', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('mbottomleyy', 'glamberthy@paginegialle.it', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2012-01-10 09:11:07', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('gmacgaughiez', 'bbarrittz@youtube.com', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2010-09-03 12:45:37', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('mdochon10', 'jpostians10@hao123.com', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2016-01-24 15:08:32', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('ksommerville11', 'lslader11@histats.com', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2012-03-23 01:38:11', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('sclemitt12', 'wbickerdike12@gnu.org', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2017-03-09 07:20:39', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('rmertin13', 'mphilott13@netscape.com', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2018-07-17 11:42:00', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('jcreane14', 'borrill14@simplemachines.org', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2017-07-15 16:42:57', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('hbrood15', 'mgudgin15@go.com', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2014-09-14 00:34:51', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('shofler16', 'dchappel16@economist.com', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2021-12-03 17:18:12', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('ndavydychev17', 'eeggleton17@goodreads.com', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2016-07-01 12:55:01', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('bcroutear18', 'droe18@samsung.com', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2015-09-01 23:30:53', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('dsalvidge19', 'wmollitt19@chicagotribune.com', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2010-04-04 18:28:56', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('rthundercliffe1a', 'baveling1a@yale.edu', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2017-06-23 11:25:30', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('chealeas1b', 'jbuckley1b@theatlantic.com', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2011-04-13 01:16:19', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('dmayers1c', 'aphetteplace1c@a8.net', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2012-03-08 09:43:10', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('trope1d', 'brosone1d@free.fr', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2015-03-12 04:33:36', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('pizzard1e', 'dmahoney1e@slate.com', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2011-08-29 22:48:53', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('hmcilwrick1f', 'fbullock1f@dedecms.com', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2020-04-13 12:16:56', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('mkilfoyle1g', 'mduffell1g@drupal.org', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2011-04-06 00:06:11', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('aoutright1h', 'lshouler1h@tinyurl.com', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2015-03-10 01:46:56', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('vphethean1i', 'egrabban1i@cdbaby.com', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2015-08-03 22:31:30', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('thammand1j', 'memms1j@myspace.com', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2019-03-17 20:05:07', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('scabotto1k', 'lmorey1k@washington.edu', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2019-08-02 14:07:16', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('ahardwin1l', 'avaller1l@fema.gov', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2017-08-02 04:00:56', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('hbatha1m', 'omonini1m@sbwire.com', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2020-12-10 00:48:51', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('gfrigot1n', 'fjoderli1n@linkedin.com', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2021-11-05 10:10:38', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('gcorn1o', 'cpainten1o@usgs.gov', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2016-11-25 18:56:43', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('mbecken1p', 'bflippen1p@addtoany.com', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2014-03-25 20:36:23', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('nvangeffen1q', 'wverbrugge1q@amazon.co.jp', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2014-08-05 04:05:19', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('shelversen1r', 'idemanche1r@chron.com', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2019-09-11 21:39:30', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('vepperson1s', 'pwalburn1s@example.com', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2012-03-14 03:48:40', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('cluckin1t', 'nmehaffey1t@webmd.com', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2021-07-24 13:26:57', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('edecort1u', 'jcanto1u@artisteer.com', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2011-08-09 17:01:53', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('jell1v', 'dhissett1v@angelfire.com', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2012-11-14 15:37:08', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('kseamarke1w', 'fdeniskevich1w@pcworld.com', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2020-02-23 14:51:15', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('jteal1x', 'rmustard1x@clickbank.net', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2013-08-11 03:57:23', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('colenane1y', 'jisakov1y@intel.com', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2015-08-21 15:36:04', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('junwins1z', 'acuredell1z@hexun.com', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2014-06-26 13:46:42', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('jpetyt20', 'ahuff20@examiner.com', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2014-01-29 17:28:07', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('mgarrelts21', 'rcopeman21@vistaprint.com', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2013-09-16 22:44:37', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('aplacidi22', 'mfeldharker22@usda.gov', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2017-07-20 20:47:24', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('tloft23', 'mdur23@mlb.com', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2021-05-02 09:20:22', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('nbladon24', 'mplose24@gizmodo.com', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2014-07-21 04:32:58', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('gmccaughan25', 'glindl25@yandex.ru', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2011-12-20 15:15:27', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('ocasini26', 'chasloch26@360.cn', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2016-07-06 09:25:32', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('hwoolmore27', 'ltriggel27@taobao.com', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2010-04-10 10:13:08', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('mfaccini28', 'klasselle28@epa.gov', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2017-11-12 04:27:10', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('nnoddings29', 'nsiddons29@studiopress.com', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2012-04-26 00:16:37', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('dscarlin2a', 'jkarys2a@marriott.com', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2020-01-24 08:07:07', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('jfields2b', 'lrooze2b@wordpress.org', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2015-02-07 03:05:29', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('fedgington2c', 'gsurmeir2c@tmall.com', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2011-01-27 07:05:49', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('kmeekings2d', 'ayeabsley2d@surveymonkey.com', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2013-01-11 22:02:29', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('tkirkebye2e', 'mgipps2e@state.tx.us', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2018-02-06 16:28:54', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('tosmar2f', 'kguntrip2f@shinystat.com', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2010-06-02 01:18:00', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('mdubber2g', 'cheadey2g@usgs.gov', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2014-07-03 06:12:22', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('hfeldklein2h', 'peronie2h@cyberchimps.com', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2017-10-21 13:13:28', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('ccaneo2i', 'iadaway2i@aboutads.info', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2014-07-14 16:22:46', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('lyansons2j', 'tauckland2j@home.pl', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2018-04-02 17:08:09', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('savann2k', 'hsnelman2k@aboutads.info', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2015-10-09 15:14:30', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('palyokhin2l', 'piacovolo2l@t.co', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2010-01-03 09:12:00', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('dmacallen2m', 'kgorgler2m@instagram.com', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2018-01-03 11:50:11', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('rpollendine2n', 'emaccahey2n@usda.gov', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2021-12-06 15:51:04', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('ndurie2o', 'wgrigolashvill2o@ask.com', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2021-11-05 17:40:10', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('mohdirscoll2p', 'gbrombell2p@illinois.edu', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2021-05-28 17:29:47', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('abetke2q', 'lcurrie2q@paginegialle.it', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2014-06-29 00:06:53', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
INSERT INTO "user" ("username", "email", "password", "createdAt", "mostRecentLatitude", "mostRecentLongitude") VALUES ('pberrow2r', 'echettoe2r@techcrunch.com', '$argon2id$v=19$m=4096,t=3,p=1$8AOn1wH68/N07ssOrcsA2Q$ckLNkSP5nTGVoNmi5/w2O5VUVvvVCvHHNIaBPmcqK5k', '2013-09-05 01:58:34', '${faker.address.latitude()}', '${faker.address.longitude()}');
|
||||
`)
|
||||
|
||||
for (let i = 1; i <= 101; i++) { // for each user to be followed
|
||||
let queryString = ''
|
||||
const numberOfFollowers = i == 1 ? 100 : _.random(1, 100)
|
||||
const arr = _.sampleSize(_.range(2, 102), numberOfFollowers).filter(n => n != i)
|
||||
for (let y = 0; y < arr.length; y++) {
|
||||
queryString += `\nINSERT INTO user_follow ("followedUserId", "followingUserId") VALUES (${i}, ${arr[y]});`
|
||||
}
|
||||
await queryRunner.query(queryString)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
if (!__prod__) {
|
||||
await queryRunner.query(`--sql
|
||||
DELETE FROM "user" WHERE true;
|
||||
DELETE FROM "user_follow" WHERE true;
|
||||
`)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
import { __prod__ } from '@constants'
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm'
|
||||
|
||||
export class AddAdminAsModToSpaces1660494342133 implements MigrationInterface {
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
if (!__prod__) {
|
||||
await queryRunner.query(`--sql
|
||||
CREATE OR REPLACE PROCEDURE main()
|
||||
AS $$
|
||||
DECLARE
|
||||
s integer;
|
||||
BEGIN
|
||||
FOR s IN
|
||||
SELECT id FROM space
|
||||
LOOP
|
||||
INSERT INTO space_mods_user ("spaceId", "userId") VALUES (s, (SELECT id FROM "user" WHERE username = 'admin'));
|
||||
END LOOP;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
CALL main();
|
||||
`)
|
||||
}
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
if (!__prod__) {
|
||||
await queryRunner.query(`--sql
|
||||
DELETE FROM space_mods_user WHERE "userId" = (SELECT id FROM "user" WHERE username = 'admin');
|
||||
`)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,337 @@
|
||||
import { __prod__ } from '@constants'
|
||||
import _ from 'lodash'
|
||||
import { MigrationInterface, QueryRunner } from "typeorm"
|
||||
|
||||
export class AddPosts1660494342134 implements MigrationInterface {
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
if (!__prod__) {
|
||||
await queryRunner.query(`--sql
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('osiggin0', 'Turcotte-Cronin');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('tbasley1', 'Wolf-Price');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('mbarthel2', 'Hagenes, Russel and Block');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('kduckinfield3', 'Koelpin, Rowe and O''Kon');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('mmougeot4', 'Stroman-Lind');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('medden5', 'Wintheiser LLC');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('astoney6', 'McGlynn, Hoppe and Little');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('cventam7', 'Corwin-Gerhold');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('cpragnall8', 'Fahey, Hayes and Predovic');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('gkissick9', 'Abbott Group');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('dkedwella', 'Bode LLC');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('osprostonb', 'Hartmann, Dibbert and Lang');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('snorkettc', 'Reinger LLC');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('tjurczikd', 'Hauck-Jones');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('fhoofee', 'Kiehn-Spinka');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('hgasperif', 'Reilly and Sons');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('lbennitg', 'Ziemann LLC');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('tclaireh', 'Hegmann-Wiza');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('vbutteli', 'Stracke LLC');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('kmarchantj', 'Hermann and Sons');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('cdonoghuek', 'Runolfsdottir, Ziemann and Grady');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('ojelksl', 'Schroeder, Smith and Wunsch');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('jmallenderm', 'Macejkovic, Labadie and O''Kon');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('tsiemonsn', 'Goldner LLC');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('amethingamo', 'Champlin, Ruecker and Collier');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('dleevesp', 'Feil LLC');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('jdoumerq', 'Larkin and Sons');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('mkestenr', 'Donnelly and Sons');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('lpostins', 'Wisoky Group');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('avolkt', 'Thiel, Jacobson and Hermiston');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('tbabinskiu', 'Johnston and Sons');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('csavilev', 'Rosenbaum LLC');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('vmayesw', 'Jenkins Group');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('ywillcockx', 'Satterfield and Sons');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('dbulfieldy', 'Steuber-Kreiger');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('tcottrillz', 'Fahey, Rowe and Champlin');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('mlangthorne10', 'Rogahn and Sons');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('zparratt11', 'Schaden and Sons');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('edoucette12', 'Gulgowski, Paucek and Herman');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('gwillavize13', 'Crona, Effertz and King');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('rziemke14', 'Larkin-Walter');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('tpickover15', 'Roob and Sons');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('awaghorn16', 'Cormier, Graham and Metz');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('lspruce17', 'Ebert-Bosco');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('sarmistead18', 'Cremin Group');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('odanick19', 'Harber Group');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('dflipsen1a', 'Kirlin and Sons');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('pbygrave1b', 'Kessler, Kutch and Streich');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('dbattabee1c', 'O''Conner, Stehr and Becker');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('abalfre1d', 'Beatty Group');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('elewer1e', 'Bogan, O''Connell and Klocko');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('hmclaine1f', 'Zemlak-Stiedemann');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('mbevan1g', 'Borer, McKenzie and Mueller');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('leldon1h', 'Heller, Johnson and Kuvalis');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('gthunnercliff1i', 'Adams Inc');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('scrowhurst1j', 'Boyle, Gaylord and Flatley');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('mgilloran1k', 'Mosciski and Sons');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('cbertholin1l', 'Hodkiewicz-Wolf');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('ecastiglione1m', 'Kshlerin, Hills and Jacobs');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('sgearty1n', 'Mertz Group');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('bpatesel1o', 'Yundt and Sons');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('vhoudmont1p', 'Stanton-Jacobs');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('cpikhno1q', 'Shanahan, Lueilwitz and Wolf');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('lpaute1r', 'Kiehn, Emard and Lemke');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('rabramchik1s', 'Smith LLC');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('csommerville1t', 'Crooks-Monahan');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('jjaume1u', 'Leuschke LLC');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('alethbury1v', 'Howe, Hand and Jerde');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('gdoogood1w', 'Howe-Streich');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('ldrabble1x', 'Balistreri-Greenfelder');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('pudie1y', 'Wisozk Inc');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('econiam1z', 'Legros, Weimann and Stiedemann');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('pkipping20', 'Braun, Hessel and Blick');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('mcaccavella21', 'Skiles-Douglas');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('jbelhomme22', 'Schoen, Rice and Cassin');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('dsikora23', 'Swift, Glover and Jerde');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('gnorewood24', 'O''Kon and Sons');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('jscowcraft25', 'Cronin, Leffler and Spencer');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('wjeffreys26', 'Ritchie Group');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('amaccoughen27', 'Hickle, Price and Bergstrom');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('oseywood28', 'Bailey Group');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('kdennison29', 'Hettinger LLC');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('etzuker2a', 'McKenzie Inc');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('mguidoni2b', 'Bailey-Hartmann');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('etaaffe2c', 'Halvorson, Pagac and Jones');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('bglynne2d', 'Kessler Inc');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('jmatejovsky2e', 'Blick, Greenholt and Nader');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('ftilio2f', 'Nitzsche, Auer and Kemmer');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('skhadir2g', 'Beier-Osinski');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('blanktree2h', 'Luettgen LLC');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('htofts2i', 'Pagac, Kuhlman and Ernser');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('ccrisford2j', 'Pollich LLC');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('vwinterflood2k', 'Reichel LLC');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('mdominey2l', 'Hahn-Green');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('ngrave2m', 'Farrell LLC');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('ttoomey2n', 'Yost-Reichel');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('tdog2o', 'Johnston LLC');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('aseabon2p', 'Goyette and Sons');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('tlutsch2q', 'Cassin-Gottlieb');
|
||||
INSERT INTO page ("pageName", "fullPageName") VALUES ('lwickardt2r', 'Marvin, Hand and McCullough');
|
||||
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (1, 61);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (2, 84);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (3, 56);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (4, 73);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (5, 17);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (6, 43);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (7, 56);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (8, 81);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (9, 23);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (10, 96);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (11, 71);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (12, 16);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (13, 86);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (14, 74);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (15, 44);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (16, 56);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (17, 49);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (18, 71);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (19, 29);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (20, 48);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (21, 53);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (22, 11);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (23, 60);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (24, 22);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (25, 80);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (26, 54);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (27, 95);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (28, 41);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (29, 19);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (30, 31);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (31, 39);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (32, 14);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (33, 40);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (34, 8);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (35, 36);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (36, 21);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (37, 46);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (38, 29);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (39, 79);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (40, 91);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (41, 41);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (42, 86);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (43, 46);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (44, 94);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (45, 5);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (46, 51);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (47, 63);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (48, 26);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (49, 24);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (50, 6);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (51, 27);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (52, 32);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (53, 94);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (54, 4);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (55, 3);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (56, 77);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (57, 62);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (58, 95);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (59, 49);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (60, 65);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (61, 14);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (62, 70);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (63, 73);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (64, 23);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (65, 26);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (66, 8);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (67, 35);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (68, 30);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (69, 41);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (70, 20);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (71, 44);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (72, 76);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (73, 43);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (74, 90);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (75, 35);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (76, 77);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (77, 52);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (78, 84);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (79, 7);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (80, 28);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (81, 22);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (82, 90);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (83, 92);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (84, 58);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (85, 18);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (86, 6);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (87, 36);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (88, 19);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (89, 62);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (90, 3);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (91, 19);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (92, 16);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (93, 95);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (94, 73);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (95, 34);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (96, 39);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (97, 27);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (98, 93);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (99, 49);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (100, 88);
|
||||
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (1, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (2, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (3, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (4, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (5, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (6, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (7, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (8, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (9, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (10, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (11, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (12, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (13, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (14, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (15, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (16, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (17, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (18, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (19, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (20, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (21, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (22, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (23, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (24, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (25, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (26, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (27, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (28, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (29, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (30, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (31, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (32, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (33, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (34, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (35, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (36, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (37, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (38, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (39, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (40, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (41, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (42, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (43, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (44, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (45, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (46, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (47, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (48, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (49, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (50, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (51, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (52, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (53, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (54, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (55, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (56, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (57, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (58, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (59, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (60, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (61, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (62, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (63, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (64, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (65, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (66, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (67, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (68, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (69, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (70, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (71, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (72, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (73, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (74, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (75, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (76, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (77, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (78, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (79, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (80, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (81, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (82, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (83, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (84, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (85, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (86, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (87, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (88, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (89, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (90, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (91, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (92, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (93, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (94, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (95, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (96, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (97, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (98, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (99, 1);
|
||||
INSERT INTO page_owners_user ("pageId", "userId") VALUES (100, 1);
|
||||
`)
|
||||
|
||||
for (let i = 1; i <= 100; i++) { // for each page
|
||||
let queryString = ''
|
||||
const numberOfFollowers = _.random(1, 100)
|
||||
// Generate an array of unique random integers (min 2, max 101) with length equal to numberOfFollowers
|
||||
const arr = _.sampleSize(_.range(2, 102), numberOfFollowers)
|
||||
for (let y = 0; y < arr.length; y++) { // a page can have a maximum of 100 followers
|
||||
queryString += `\nINSERT INTO page_follow ("pageId", "userId") VALUES (${i}, ${arr[y]});`
|
||||
}
|
||||
await queryRunner.query(queryString)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
if (!__prod__) {
|
||||
await queryRunner.query(`--sql
|
||||
DELETE FROM page WHERE true;
|
||||
DELETE FROM page_owners_user WHERE true;
|
||||
DELETE FROM page_follow WHERE true;
|
||||
`)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import { __prod__ } from '@constants'
|
||||
import _ from 'lodash'
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm'
|
||||
|
||||
export class AddSpaceSubscribers1660494342135 implements MigrationInterface {
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
if (!__prod__) {
|
||||
for (let i = 1; i <= 16; i++) { // for each space
|
||||
let queryString = ''
|
||||
const numberOfSubscribers = _.random(1, 100)
|
||||
const arr = _.sampleSize(_.range(2, 102), numberOfSubscribers)
|
||||
for (let y = 0; y < arr.length; y++) {
|
||||
queryString += `\nINSERT INTO space_subscription ("spaceId", "userId") VALUES (${i}, ${arr[y]});`
|
||||
}
|
||||
await queryRunner.query(queryString)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
if (!__prod__) {
|
||||
await queryRunner.query(`--sql
|
||||
DELETE FROM space_subscription WHERE true;
|
||||
`)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
import { __prod__ } from '@constants'
|
||||
import { MigrationInterface, QueryRunner } from "typeorm"
|
||||
|
||||
export class AddTags1660494342136 implements MigrationInterface {
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`--sql
|
||||
BEGIN;
|
||||
INSERT INTO tag (name) VALUES ('Question');
|
||||
INSERT INTO tag (name) VALUES ('Help');
|
||||
INSERT INTO tag (name) VALUES ('Fundraising');
|
||||
INSERT INTO tag (name) VALUES ('Introduction');
|
||||
INSERT INTO tag (name) VALUES ('Self');
|
||||
INSERT INTO tag (name) VALUES ('AMA');
|
||||
INSERT INTO tag (name) VALUES ('Resources');
|
||||
INSERT INTO tag (name) VALUES ('Educational');
|
||||
INSERT INTO tag (name) VALUES ('Poll');
|
||||
INSERT INTO tag (name) VALUES ('Recruitment');
|
||||
INSERT INTO tag (name) VALUES ('Contract');
|
||||
INSERT INTO tag (name) VALUES ('Networking');
|
||||
INSERT INTO tag (name) VALUES ('Opinion');
|
||||
INSERT INTO tag (name) VALUES ('Other');
|
||||
COMMIT;
|
||||
`)
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`--sql
|
||||
DELETE FROM tag WHERE true;
|
||||
`)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
import { __prod__ } from '@constants'
|
||||
import { faker } from '@faker-js/faker'
|
||||
import _ from 'lodash'
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm'
|
||||
|
||||
export class AddPosts1660494342137 implements MigrationInterface {
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
if (!__prod__) {
|
||||
let queryString = ''
|
||||
for (let i = 0; i < 1000; i++) {
|
||||
const title = faker.company.catchPhrase()
|
||||
const text = faker.lorem.paragraph()
|
||||
const spaceId = _.random(1, 16)
|
||||
const creatorId = faker.datatype.boolean() ? _.random(2, 101) : null
|
||||
const pageCreatorId = creatorId ? null : _.random(1, 100)
|
||||
const creatorType = creatorId ? 'user' : 'page'
|
||||
const createdAt = faker.date.between('2020-01-01T00:00:00.000Z', '2021-01-01T00:00:00.000Z').toISOString()
|
||||
queryString += `\nINSERT INTO post ("title", "text", "spaceId", "creatorId", "pageCreatorId", "createdAt", "creatorType") VALUES ('${title}', '${text}', ${spaceId}, ${creatorId}, ${pageCreatorId}, '${createdAt}', '${creatorType}');`
|
||||
}
|
||||
await queryRunner.query(queryString)
|
||||
queryString = ''
|
||||
for (let i = 1; i < 1001; i++) {
|
||||
const numberOfTags = _.random(1, 4)
|
||||
const arr = _.sampleSize(_.range(1, 15), numberOfTags)
|
||||
for (let y = 0; y < numberOfTags; y++) {
|
||||
queryString += `\nINSERT INTO post_tags_tag ("postId", "tagId") VALUES (${i}, ${arr[y]});`
|
||||
}
|
||||
}
|
||||
await queryRunner.query(queryString)
|
||||
}
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
if (!__prod__) {
|
||||
await queryRunner.query(`--sql
|
||||
DELETE FROM post WHERE true;
|
||||
DELETE FROM post_tags_tag WHERE true;
|
||||
`)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
import { __prod__ } from '@constants'
|
||||
import { faker } from '@faker-js/faker'
|
||||
import _ from 'lodash'
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm'
|
||||
|
||||
export class AddOffers1660494342138 implements MigrationInterface {
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
if (!__prod__) {
|
||||
let queryString = ''
|
||||
for (let i = 0; i < 1000; i++) {
|
||||
const title = faker.name.jobTitle().replaceAll('\'', '')
|
||||
const workplace = faker.company.name().replaceAll('\'', '')
|
||||
const address = faker.address.streetAddress(true).replaceAll('\'', '')
|
||||
const recruiting = faker.datatype.boolean()
|
||||
const employmentType = _.sample([
|
||||
'Full-time',
|
||||
'Part-time',
|
||||
'Freelance',
|
||||
'Online',
|
||||
'Internship',
|
||||
'Temporary',
|
||||
'Contract',
|
||||
'Volunteer',
|
||||
'Other'
|
||||
])
|
||||
const currency = faker.finance.currencySymbol()
|
||||
const salaryRange = `${currency}${_.random(0, 10000)} - ${currency}${_.random(10000, 999999)}`
|
||||
const department = faker.name.jobArea()
|
||||
const requirements = `Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.`
|
||||
const benefits = `Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?`
|
||||
const description = `At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat.`
|
||||
const spaceId = _.random(1, 16)
|
||||
const creatorId = faker.datatype.boolean() ? _.random(2, 101) : null
|
||||
const pageCreatorId = creatorId ? null : _.random(1, 100)
|
||||
const creatorType = creatorId ? 'user' : 'page'
|
||||
const createdAt = faker.date.between('2020-01-01T00:00:00.000Z', '2021-01-01T00:00:00.000Z').toISOString()
|
||||
queryString +=
|
||||
`\nINSERT INTO offer ("title", "workplace", "address", "recruiting", "employmentType", "salaryRange", "department", "requirements", "benefits", "description", "spaceId", "creatorId", "pageCreatorId", "creatorType", "createdAt") VALUES ('${title}', '${workplace}', '${address}', ${recruiting}, '${employmentType}', '${salaryRange}', '${department}', '${requirements}', '${benefits}', '${description}', ${spaceId}, ${creatorId}, ${pageCreatorId}, '${creatorType}', '${createdAt}') ;`
|
||||
}
|
||||
await queryRunner.query(queryString)
|
||||
|
||||
queryString = ''
|
||||
for (let i = 1; i < 1001; i++) {
|
||||
const offerId = i
|
||||
const numberOfApplications = _.random(0, 3)
|
||||
const arr = _.sampleSize(_.range(2, 102), numberOfApplications)
|
||||
for (let y = 0; y < numberOfApplications; y++) {
|
||||
const status = _.sample(['applied', 'accepted', 'rejected'])
|
||||
queryString +=
|
||||
`\nINSERT INTO offer_application ("offerId", "userId", "status") VALUES (${offerId}, ${arr[y]}, '${status}') ;`
|
||||
}
|
||||
}
|
||||
await queryRunner.query(queryString)
|
||||
}
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
if (!__prod__) {
|
||||
await queryRunner.query(`--sql
|
||||
DELETE FROM offer WHERE true;
|
||||
DELETE FROM offer_application WHERE true;
|
||||
`)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,202 @@
|
||||
import { Comment, CommentVote, Page, Post, User } from '@entities'
|
||||
import { PaginatedComments } from '@graphql-types'
|
||||
import { isAuth } from '@middlewares'
|
||||
import { Context } from '@types'
|
||||
import { toPostgresTime } from '@utils'
|
||||
import { Arg, Ctx, FieldResolver, Int, Mutation, Query, Resolver, Root, UseMiddleware } from 'type-graphql'
|
||||
|
||||
@Resolver(Comment)
|
||||
export class CommentResolver {
|
||||
|
||||
@FieldResolver(() => User)
|
||||
creator(
|
||||
@Root() root: Comment,
|
||||
@Ctx() { userLoader }: Context
|
||||
) {
|
||||
return root.creatorId ? userLoader.load(root.creatorId) : null
|
||||
}
|
||||
|
||||
@FieldResolver(() => Page)
|
||||
pageCreator(
|
||||
@Root() root: Comment,
|
||||
@Ctx() { pageLoader }: Context
|
||||
) {
|
||||
return root.pageCreatorId ? pageLoader.load(root.pageCreatorId) : null
|
||||
}
|
||||
|
||||
@Query(() => PaginatedComments)
|
||||
async comments(
|
||||
@Ctx() { req, orm }: Context,
|
||||
@Arg('postId', () => Int) postId: number,
|
||||
@Arg('limit', () => Int) limit: number,
|
||||
@Arg('cursor', () => String, { nullable: true }) cursor: string | null,
|
||||
): Promise<PaginatedComments | null> {
|
||||
const { userId } = req.session
|
||||
|
||||
const realLimit = Math.min(limit, 5)
|
||||
const realLimitPlusOne = realLimit + 1
|
||||
|
||||
const comments = await orm.query(`
|
||||
SELECT *
|
||||
FROM comment c
|
||||
WHERE c."postId" = ${postId}
|
||||
${cursor ? `AND c."createdAt" < '${toPostgresTime(cursor)}'` : ''}
|
||||
ORDER BY
|
||||
${userId ? `c."creatorId" = ${userId} DESC,` : ''}
|
||||
c.points DESC,
|
||||
c."createdAt" DESC
|
||||
LIMIT ${realLimitPlusOne}
|
||||
`)
|
||||
|
||||
return {
|
||||
comments: comments.slice(0, realLimit),
|
||||
hasMore: comments.length - 1 == realLimit
|
||||
}
|
||||
}
|
||||
|
||||
@FieldResolver(() => Int, { nullable: true })
|
||||
async voteStatus(
|
||||
@Root() root: Comment,
|
||||
@Ctx() { req, commentVoteLoader }: Context
|
||||
) {
|
||||
return req.session?.userId ?
|
||||
(await commentVoteLoader.load({ commentId: root.id, userId: req.session.userId }))?.value
|
||||
:
|
||||
null
|
||||
}
|
||||
|
||||
@UseMiddleware(isAuth)
|
||||
@Mutation(() => Comment)
|
||||
async createComment(
|
||||
@Arg('postId', () => Int) postId: number,
|
||||
@Arg('text', () => String) text: string,
|
||||
@Arg('pageId', () => Int, { nullable: true }) pageId: number,
|
||||
@Ctx() { req, orm }: Context
|
||||
): Promise<Comment | null> {
|
||||
const { userId } = req.session
|
||||
const post = await Post.findOneBy({ id: postId })
|
||||
if (!post) {
|
||||
return null
|
||||
}
|
||||
if (pageId) {
|
||||
const page = await Page.findOne({ where: { id: pageId } })
|
||||
if (!page) {
|
||||
throw new Error('Page does not exist!')
|
||||
}
|
||||
const ownerProof: { userId: number, pageId: number }[] = await orm.query(`
|
||||
SELECT * FROM page_owners_user WHERE "userId" = ${userId} AND "pageId" = ${pageId};
|
||||
`)
|
||||
if (ownerProof.length == 0) {
|
||||
throw new Error('You are not an owner of this page.')
|
||||
}
|
||||
}
|
||||
return await Comment.create({
|
||||
text,
|
||||
postId,
|
||||
creatorType: pageId ? 'page' : 'user',
|
||||
creatorId: pageId ? undefined : userId,
|
||||
pageCreatorId: pageId,
|
||||
}).save()
|
||||
}
|
||||
|
||||
@Mutation(() => Comment, { nullable: true })
|
||||
@UseMiddleware(isAuth)
|
||||
async updateComment(
|
||||
@Arg('id', () => Int) id: number,
|
||||
@Arg('text', () => String) text: string,
|
||||
@Ctx() { orm, req }: Context
|
||||
): Promise<Comment | null> {
|
||||
const comment = await Comment.findOne({ where: { id } })
|
||||
if (comment) {
|
||||
if (comment.creatorType == 'user') {
|
||||
if (comment.creatorId != req.session.userId) {
|
||||
throw new Error('Not authorised!')
|
||||
}
|
||||
}
|
||||
else {
|
||||
const ownerProof: { userId: number, pageId: number }[] = await orm.query(`
|
||||
SELECT * FROM page_owners_user WHERE "userId" = ${req.session.userId} AND "pageId" = ${comment.pageCreatorId};
|
||||
`)
|
||||
if (ownerProof.length == 0) {
|
||||
throw new Error('Not authorised!')
|
||||
}
|
||||
}
|
||||
comment.text = text
|
||||
return comment.save()
|
||||
}
|
||||
else {
|
||||
throw new Error('Post not found.')
|
||||
}
|
||||
}
|
||||
|
||||
@UseMiddleware(isAuth)
|
||||
@Mutation(() => Boolean)
|
||||
async deleteComment(
|
||||
@Arg('id', () => Int) id: number,
|
||||
@Ctx() { orm, req }: Context
|
||||
): Promise<boolean> {
|
||||
const comment = await Comment.findOneBy({ id })
|
||||
if (!comment) {
|
||||
throw new Error('Comment not found!')
|
||||
}
|
||||
if (comment.creatorType == 'user') {
|
||||
if (comment.creatorId != req.session.userId) {
|
||||
throw new Error('Not authorised!')
|
||||
}
|
||||
}
|
||||
else {
|
||||
const ownerProof: { userId: number, pageId: number }[] = await orm.query(`
|
||||
SELECT * FROM page_owners_user WHERE "userId" = ${req.session.userId} AND "pageId" = ${comment.pageCreatorId};
|
||||
`)
|
||||
if (ownerProof.length == 0) {
|
||||
throw new Error('Not authorised!')
|
||||
}
|
||||
}
|
||||
await comment.remove()
|
||||
return true
|
||||
}
|
||||
|
||||
@UseMiddleware(isAuth)
|
||||
@Mutation(() => Boolean)
|
||||
async voteComment(
|
||||
@Arg('commentId', () => Int) commentId: number,
|
||||
@Arg('value', () => Int) value: number,
|
||||
@Ctx() { req, orm }: Context
|
||||
) {
|
||||
const { userId } = req.session
|
||||
if (value == 0) return false
|
||||
const realValue = value > 0 ? 1 : value < 0 ? -1 : 0
|
||||
|
||||
const commentVote = await CommentVote.findOne({ where: { commentId, userId } })
|
||||
|
||||
if (commentVote) {
|
||||
if (commentVote.value == realValue) {
|
||||
await commentVote.remove()
|
||||
const comment = await Comment.findOne({ where: { id: commentId } })
|
||||
if (comment) {
|
||||
comment.points = comment.points + (realValue == 1 ? -1 : 1)
|
||||
await comment.save()
|
||||
}
|
||||
}
|
||||
else {
|
||||
await orm.transaction(async transactionalEntityManager => {
|
||||
commentVote.value = realValue
|
||||
await transactionalEntityManager.save(commentVote)
|
||||
await transactionalEntityManager.increment(Comment, { id: commentId }, 'points', realValue == -1 ? -2 : 2)
|
||||
})
|
||||
}
|
||||
}
|
||||
else {
|
||||
await orm.transaction(async transactionalEntityManager => {
|
||||
const newCommentVote = new CommentVote()
|
||||
newCommentVote.userId = userId!
|
||||
newCommentVote.commentId = commentId
|
||||
newCommentVote.value = realValue
|
||||
await transactionalEntityManager.save(newCommentVote)
|
||||
await transactionalEntityManager.increment(Comment, { id: commentId }, 'points', realValue)
|
||||
})
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,215 @@
|
||||
import { ConversationCol, ConversationInFirestore, Inbox, InboxCol, Message } from '@collections'
|
||||
import { s3 } from '@configs'
|
||||
import { Conversation as ConversationEnt, User } from '@entities'
|
||||
import { CreateConversationResponse, InboxResponse, MessageInput } from '@graphql-types'
|
||||
import { isAuth } from '@middlewares'
|
||||
import { Context } from '@types'
|
||||
import { getExtensionFromFilename } from '@utils'
|
||||
import { FileUpload } from 'graphql-upload'
|
||||
import { Arg, Ctx, Int, Mutation, Query, Resolver, UseMiddleware } from 'type-graphql'
|
||||
import { ArrayContains, In } from 'typeorm'
|
||||
import { v4 } from 'uuid'
|
||||
|
||||
@Resolver(ConversationInFirestore)
|
||||
export class ConversationResolver {
|
||||
|
||||
@UseMiddleware(isAuth)
|
||||
@Query(() => [ConversationEnt])
|
||||
async conversations(
|
||||
@Ctx() { req }: Context
|
||||
): Promise<ConversationEnt[]> {
|
||||
const { userId } = req.session
|
||||
return await ConversationEnt.find({
|
||||
where: {
|
||||
participants: ArrayContains([userId])
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@UseMiddleware(isAuth)
|
||||
@Query(() => [User])
|
||||
async participants(
|
||||
@Arg('firestoreCollectionId', () => String) firestoreCollectionId: string,
|
||||
@Ctx() { req }: Context
|
||||
): Promise<User[]> {
|
||||
const { userId } = req.session
|
||||
const convo = await ConversationEnt.findOneBy({ firestoreCollectionId })
|
||||
if (!convo) {
|
||||
return []
|
||||
}
|
||||
if (!convo.participants.includes(userId!)) {
|
||||
throw new Error('Not authorised!')
|
||||
}
|
||||
return User.findBy({ id: In(convo.participants) })
|
||||
}
|
||||
|
||||
@UseMiddleware(isAuth)
|
||||
@Query(() => [InboxResponse])
|
||||
async inboxes(
|
||||
@Arg('firestoreCollectionIds', () => [String]) firestoreCollectionIds: string[],
|
||||
@Ctx() { req }: Context
|
||||
): Promise<InboxResponse[]> {
|
||||
const { userId } = req.session
|
||||
const convos = await ConversationEnt.findBy({ firestoreCollectionId: In(firestoreCollectionIds) })
|
||||
return Promise.all(firestoreCollectionIds.map(async fci => {
|
||||
const convo = convos.find(c => c.firestoreCollectionId == fci)!
|
||||
const partnerId = convo.participants.find(id => id != userId)
|
||||
const partner = (await User.findOne({ where: { id: partnerId } }))!
|
||||
return {
|
||||
partner,
|
||||
firestoreCollectionId: fci
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
|
||||
@UseMiddleware(isAuth)
|
||||
@Mutation(() => CreateConversationResponse)
|
||||
async createConversation(
|
||||
@Arg('partnerUsername', () => String) partnerUsername: string,
|
||||
@Ctx() { req }: Context
|
||||
): Promise<CreateConversationResponse> {
|
||||
const { userId } = req.session
|
||||
const partner = await User.findOne({ where: { username: partnerUsername } })
|
||||
if (!partner) {
|
||||
return {
|
||||
errors: [{
|
||||
field: 'partnerUsername',
|
||||
message: 'Invalid username.'
|
||||
}]
|
||||
}
|
||||
}
|
||||
const partnerId = partner.id
|
||||
const existingConvo = await ConversationEnt.findOne({
|
||||
where: {
|
||||
participants: ArrayContains([userId, partnerId])
|
||||
}
|
||||
})
|
||||
if (existingConvo) {
|
||||
return {
|
||||
errors: [{
|
||||
field: 'partnerUsername',
|
||||
message: 'Conversation already exists.'
|
||||
}]
|
||||
}
|
||||
}
|
||||
const convo = new ConversationInFirestore()
|
||||
const convoItem = await ConversationCol.create(convo)
|
||||
let inbox = await InboxCol.whereEqualTo('userId', userId!).findOne()
|
||||
let partnerInbox = await InboxCol.whereEqualTo('userId', partnerId!).findOne()
|
||||
if (!inbox) {
|
||||
inbox = new Inbox()
|
||||
inbox.userId = userId!
|
||||
inbox.conversationIds = []
|
||||
await InboxCol.create(inbox)
|
||||
}
|
||||
if (!partnerInbox) {
|
||||
partnerInbox = new Inbox()
|
||||
partnerInbox.userId = partnerId!
|
||||
partnerInbox.conversationIds = []
|
||||
await InboxCol.create(partnerInbox)
|
||||
}
|
||||
inbox.conversationIds.push(convoItem.id)
|
||||
partnerInbox.conversationIds.push(convoItem.id)
|
||||
await InboxCol.update(inbox)
|
||||
await InboxCol.update(partnerInbox)
|
||||
const convoEnt = new ConversationEnt()
|
||||
convoEnt.participants = [userId!, partnerId]
|
||||
convoEnt.firestoreCollectionId = convoItem.id
|
||||
await convoEnt.save()
|
||||
return { conversation: convoItem }
|
||||
}
|
||||
|
||||
@UseMiddleware(isAuth)
|
||||
@Mutation(() => Boolean)
|
||||
async deleteConversation(
|
||||
@Arg('firestoreCollectionId', () => String) firestoreCollectionId: string,
|
||||
@Ctx() { req }: Context
|
||||
): Promise<boolean> {
|
||||
const { userId } = req.session
|
||||
const convo = await ConversationEnt.findOneBy({ firestoreCollectionId })
|
||||
if (!convo) {
|
||||
throw new Error('Conversation not found.')
|
||||
}
|
||||
if (!convo.participants.includes(userId!)) {
|
||||
throw new Error('Not authorised!')
|
||||
}
|
||||
const partnerId = convo.participants.find(id => id != userId)
|
||||
const inbox = await InboxCol.whereEqualTo('userId', userId!).findOne()
|
||||
const partnerInbox = await InboxCol.whereEqualTo('userId', partnerId!).findOne()
|
||||
const firestoreConvo = await ConversationCol.findById(firestoreCollectionId)
|
||||
await ConversationCol.delete(firestoreConvo.id)
|
||||
inbox!.conversationIds = inbox!.conversationIds.filter(id => id != firestoreConvo.id)
|
||||
partnerInbox!.conversationIds = partnerInbox!.conversationIds.filter(id => id != firestoreConvo.id)
|
||||
await InboxCol.update(inbox!)
|
||||
await InboxCol.update(partnerInbox!)
|
||||
await convo.remove()
|
||||
return true
|
||||
}
|
||||
|
||||
@UseMiddleware(isAuth)
|
||||
@Mutation(() => Message)
|
||||
async createMessage(
|
||||
@Arg('firestoreCollectionId', () => String) firestoreCollectionId: string,
|
||||
@Arg('input', () => MessageInput) input: MessageInput,
|
||||
@Ctx() { req }: Context
|
||||
): Promise<Message> {
|
||||
const { userId } = req.session
|
||||
const { type, upload, text } = input
|
||||
|
||||
const convoEnt = await ConversationEnt.findOne({
|
||||
where: {
|
||||
firestoreCollectionId,
|
||||
participants: ArrayContains([userId])
|
||||
}
|
||||
})
|
||||
if (!convoEnt) {
|
||||
throw new Error('Not authorised!')
|
||||
}
|
||||
const message = new Message()
|
||||
message.senderId = userId!
|
||||
message.type = type
|
||||
|
||||
if (type == 'text') {
|
||||
message.content = text!
|
||||
}
|
||||
else {
|
||||
const { createReadStream, filename } = await upload as FileUpload
|
||||
const stream = createReadStream()
|
||||
const ext = getExtensionFromFilename(filename)
|
||||
const uploaded = await s3.upload({
|
||||
Bucket: process.env.S3_BUCKET,
|
||||
Body: stream,
|
||||
Key: `conversations/${convoEnt.id}/media/${type}s/${v4()}.${ext}`,
|
||||
}).promise()
|
||||
message.content = uploaded.Key
|
||||
}
|
||||
const convo = await ConversationCol.findById(firestoreCollectionId)
|
||||
message.createdAt = new Date()
|
||||
message.updatedAt = new Date()
|
||||
return convo.messages.create(message)
|
||||
}
|
||||
|
||||
@UseMiddleware(isAuth)
|
||||
@Mutation(() => Boolean)
|
||||
async deleteMessage(
|
||||
@Arg('firestoreCollectionId', () => String) firestoreCollectionId: string,
|
||||
@Arg('messageDocumentId', () => String) messageDocumentId: string,
|
||||
@Ctx() { req }: Context
|
||||
): Promise<boolean> {
|
||||
const { userId } = req.session
|
||||
const convo = await ConversationCol.findById(firestoreCollectionId)
|
||||
if (!convo) {
|
||||
throw new Error('Conversation not found.')
|
||||
}
|
||||
const message = await convo.messages.findById(messageDocumentId)
|
||||
if (!message) {
|
||||
throw new Error('Message not found.')
|
||||
}
|
||||
if (message.senderId != userId) {
|
||||
throw new Error('Not authorised!')
|
||||
}
|
||||
await convo.messages.delete(messageDocumentId)
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
import { Arg, Ctx, FieldResolver, Int, Mutation, Query, Resolver, Root, UseMiddleware } from 'type-graphql'
|
||||
import { CV } from '@entities'
|
||||
import { UploadedFileResponse } from '@graphql-types'
|
||||
import { isAuth } from '@middlewares'
|
||||
import { getExtensionFromFilename } from '@utils'
|
||||
import { GraphQLUpload, FileUpload } from 'graphql-upload'
|
||||
import { v4 } from 'uuid'
|
||||
import { Context } from '@types'
|
||||
import { s3 } from '@configs'
|
||||
|
||||
@Resolver(CV)
|
||||
export class CVResolver {
|
||||
|
||||
@FieldResolver()
|
||||
async url(
|
||||
@Root() cv: CV,
|
||||
@Ctx() { req }: Context
|
||||
): Promise<string> {
|
||||
return cv.key ? s3.getSignedUrlPromise('getObject', { Bucket: process.env.S3_BUCKET, Key: cv.key }) : ''
|
||||
}
|
||||
|
||||
@Mutation(() => UploadedFileResponse, { nullable: true })
|
||||
@UseMiddleware(isAuth)
|
||||
async uploadCV(
|
||||
@Arg('upload', () => GraphQLUpload) upload: FileUpload,
|
||||
@Ctx() { req }: Context
|
||||
): Promise<UploadedFileResponse> {
|
||||
const { userId } = req.session
|
||||
const { createReadStream, filename, mimetype, encoding } = upload as FileUpload
|
||||
const stream = createReadStream()
|
||||
const uploaded = await s3.upload({
|
||||
Bucket: process.env.S3_BUCKET,
|
||||
Body: stream,
|
||||
Key: `users/${userId}/cvs/${filename}`,
|
||||
}).promise()
|
||||
await CV.create({ filename, key: uploaded.Key, userId }).save()
|
||||
return {
|
||||
filename,
|
||||
mimetype,
|
||||
encoding,
|
||||
url: await s3.getSignedUrlPromise('getObject', { Bucket: process.env.S3_BUCKET, Key: uploaded.Key })
|
||||
}
|
||||
}
|
||||
|
||||
@Query(() => [CV], { nullable: true })
|
||||
async cvs(
|
||||
@Arg('userId', () => Int) userId: number,
|
||||
): Promise<CV[] | null> {
|
||||
return CV.findBy({ userId })
|
||||
}
|
||||
|
||||
@UseMiddleware(isAuth)
|
||||
@Mutation(() => Boolean)
|
||||
async deleteCV(
|
||||
@Arg('id', () => Int) id: number,
|
||||
@Ctx() { req }: Context
|
||||
): Promise<boolean> {
|
||||
const { userId } = req.session
|
||||
const cv = await CV.findOneBy({ id, userId })
|
||||
if (!cv) {
|
||||
throw new Error('Not authorised!')
|
||||
}
|
||||
await s3.deleteObject({ Bucket: process.env.S3_BUCKET, Key: cv.key! }).promise()
|
||||
await cv.remove()
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
import { s3 } from '@configs'
|
||||
import { EducationItem } from '@entities'
|
||||
import { EducationItemInput, EducationItemResponse } from '@graphql-types'
|
||||
import { isAuth } from '@middlewares'
|
||||
import { Context } from '@types'
|
||||
import { getExtensionFromFilename, saveAttributes } from '@utils'
|
||||
import { Arg, Ctx, FieldResolver, Int, Mutation, Query, Resolver, Root, UseMiddleware } from 'type-graphql'
|
||||
import { v4 } from 'uuid'
|
||||
|
||||
@Resolver(EducationItem)
|
||||
export class EducationItemResolver {
|
||||
@FieldResolver(() => String)
|
||||
async photoUrl(
|
||||
@Root() item: EducationItem
|
||||
): Promise<string | null> {
|
||||
return item.photo ? s3.getSignedUrlPromise('getObject', { Bucket: process.env.S3_BUCKET, Key: item.photo }) : null
|
||||
}
|
||||
|
||||
@Query(() => [EducationItem])
|
||||
async educationItems(
|
||||
@Arg('userId', () => Int) userId: number
|
||||
): Promise<EducationItem[]> {
|
||||
return (await EducationItem.find({ where: { userId } }))
|
||||
}
|
||||
|
||||
@UseMiddleware(isAuth)
|
||||
@Mutation(() => EducationItemResponse)
|
||||
async createEducationItem(
|
||||
@Arg('input', () => EducationItemInput) input: EducationItemInput,
|
||||
@Ctx() { req }: Context
|
||||
): Promise<EducationItemResponse> {
|
||||
const { userId } = req.session
|
||||
const { school, status, startDate, endDate, photo } = input
|
||||
if (!school) {
|
||||
return {
|
||||
errors: [{
|
||||
field: 'school',
|
||||
message: 'School cannot be empty!'
|
||||
}]
|
||||
}
|
||||
}
|
||||
let key
|
||||
if (photo) {
|
||||
const { createReadStream, filename } = await photo
|
||||
const stream = createReadStream()
|
||||
const ext = getExtensionFromFilename(filename)
|
||||
const uploaded = await s3.upload({
|
||||
Bucket: process.env.S3_BUCKET,
|
||||
Body: stream,
|
||||
Key: `users/${userId}/photos/educationItems/${v4()}.${ext}`
|
||||
}).promise()
|
||||
key = uploaded.Key
|
||||
}
|
||||
return {
|
||||
educationItem: await EducationItem.create({
|
||||
school,
|
||||
status,
|
||||
startDate,
|
||||
endDate,
|
||||
photo: key,
|
||||
userId
|
||||
}).save()
|
||||
}
|
||||
}
|
||||
|
||||
@UseMiddleware(isAuth)
|
||||
@Mutation(() => EducationItemResponse)
|
||||
async updateEducationItem(
|
||||
@Arg('id', () => Int) id: number,
|
||||
@Arg('input', () => EducationItemInput) input: EducationItemInput,
|
||||
@Ctx() { req }: Context
|
||||
): Promise<EducationItemResponse> {
|
||||
const { userId } = req.session
|
||||
const { school, photo } = input
|
||||
if (school != undefined && school == '') {
|
||||
return {
|
||||
errors: [{
|
||||
field: 'school',
|
||||
message: 'School cannot be empty!'
|
||||
}]
|
||||
}
|
||||
}
|
||||
const educationItem = await EducationItem.findOne({ where: { id, userId } })
|
||||
if (!educationItem) {
|
||||
throw new Error('Not authorised!')
|
||||
}
|
||||
saveAttributes<EducationItem, EducationItemInput>(educationItem, input)
|
||||
if (photo) {
|
||||
const { createReadStream, filename, } = await photo
|
||||
const ext = getExtensionFromFilename(filename)
|
||||
const stream = createReadStream()
|
||||
const uploaded = await s3.upload({
|
||||
Bucket: process.env.S3_BUCKET,
|
||||
Body: stream,
|
||||
Key: `users/${userId}/photos/educationItems/${v4()}.${ext}`,
|
||||
}).promise()
|
||||
educationItem.photo = uploaded.Key
|
||||
}
|
||||
return {
|
||||
educationItem: await educationItem.save()
|
||||
}
|
||||
}
|
||||
|
||||
@UseMiddleware(isAuth)
|
||||
@Mutation(() => Boolean)
|
||||
async deleteEducationItem(
|
||||
@Arg('id', () => Int) id: number,
|
||||
@Ctx() { req }: Context
|
||||
): Promise<boolean> {
|
||||
const { userId } = req.session
|
||||
const educationItem = await EducationItem.findOne({ where: { id, userId } })
|
||||
if (!educationItem) {
|
||||
throw new Error('Not authorised!')
|
||||
}
|
||||
await educationItem.remove()
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
import { s3 } from '@configs'
|
||||
import { Experience } from '@entities'
|
||||
import { ExperienceInput, ExperienceResponse } from '@graphql-types'
|
||||
import { isAuth } from '@middlewares'
|
||||
import { Context } from '@types'
|
||||
import { getExtensionFromFilename, saveAttributes } from '@utils'
|
||||
import { Arg, Ctx, FieldResolver, Int, Mutation, Query, Resolver, Root, UseMiddleware } from 'type-graphql'
|
||||
import { v4 } from 'uuid'
|
||||
|
||||
@Resolver(Experience)
|
||||
export class ExperienceResolver {
|
||||
@FieldResolver(() => String)
|
||||
async photoUrl(
|
||||
@Root() item: Experience
|
||||
): Promise<string | null> {
|
||||
return item.photo ? s3.getSignedUrlPromise('getObject', { Bucket: process.env.S3_BUCKET, Key: item.photo }) : null
|
||||
}
|
||||
|
||||
@Query(() => [Experience])
|
||||
async experiences(
|
||||
@Arg('userId', () => Int) userId: number
|
||||
): Promise<Experience[]> {
|
||||
return (await Experience.find({ where: { userId } }))
|
||||
}
|
||||
|
||||
@UseMiddleware(isAuth)
|
||||
@Mutation(() => ExperienceResponse)
|
||||
async createExperience(
|
||||
@Arg('input', () => ExperienceInput) input: ExperienceInput,
|
||||
@Ctx() { req }: Context
|
||||
): Promise<ExperienceResponse> {
|
||||
const { userId } = req.session
|
||||
const { title, workplace, startDate, endDate, photo } = input
|
||||
if (!title) {
|
||||
return {
|
||||
errors: [{
|
||||
field: 'title',
|
||||
message: 'Title cannot be empty!'
|
||||
}]
|
||||
}
|
||||
}
|
||||
let key
|
||||
if (photo) {
|
||||
const { createReadStream, filename } = await photo
|
||||
const stream = createReadStream()
|
||||
const ext = getExtensionFromFilename(filename)
|
||||
const uploaded = await s3.upload({
|
||||
Bucket: process.env.S3_BUCKET,
|
||||
Body: stream,
|
||||
Key: `users/${userId}/photos/experiences/${v4()}.${ext}`,
|
||||
}).promise()
|
||||
key = uploaded.Key
|
||||
}
|
||||
return {
|
||||
experience: await Experience.create({
|
||||
title,
|
||||
workplace,
|
||||
startDate,
|
||||
endDate,
|
||||
photo: key,
|
||||
userId
|
||||
}).save()
|
||||
}
|
||||
}
|
||||
|
||||
@UseMiddleware(isAuth)
|
||||
@Mutation(() => ExperienceResponse)
|
||||
async updateExperience(
|
||||
@Arg('id', () => Int) id: number,
|
||||
@Arg('input', () => ExperienceInput) input: ExperienceInput,
|
||||
@Ctx() { req }: Context
|
||||
): Promise<ExperienceResponse> {
|
||||
const { userId } = req.session
|
||||
const { title, photo } = input
|
||||
if (title != undefined && title == '') {
|
||||
return {
|
||||
errors: [{
|
||||
field: 'title',
|
||||
message: 'Title cannot be empty!'
|
||||
}]
|
||||
}
|
||||
}
|
||||
const experience = await Experience.findOne({ where: { id, userId } })
|
||||
if (!experience) {
|
||||
throw new Error('Not authorised!')
|
||||
}
|
||||
saveAttributes<Experience, ExperienceInput>(experience, input)
|
||||
if (photo) {
|
||||
const { createReadStream, filename, } = await photo
|
||||
const ext = getExtensionFromFilename(filename)
|
||||
const stream = createReadStream()
|
||||
const uploaded = await s3.upload({
|
||||
Bucket: process.env.S3_BUCKET,
|
||||
Body: stream,
|
||||
Key: `users/${userId}/photos/experiences/${v4()}.${ext}`,
|
||||
}).promise()
|
||||
experience.photo = uploaded.Key
|
||||
}
|
||||
return {
|
||||
experience: await experience.save()
|
||||
}
|
||||
}
|
||||
|
||||
@UseMiddleware(isAuth)
|
||||
@Mutation(() => Boolean)
|
||||
async deleteExperience(
|
||||
@Arg('id', () => Int) id: number,
|
||||
@Ctx() { req }: Context
|
||||
): Promise<boolean> {
|
||||
const { userId } = req.session
|
||||
const experience = await Experience.findOne({ where: { id, userId } })
|
||||
if (!experience) {
|
||||
throw new Error('Not authorised!')
|
||||
}
|
||||
await experience.remove()
|
||||
return true
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user