From 575d247c9028f6aaf95234a030178c38506d0f3a Mon Sep 17 00:00:00 2001 From: Armin Talaie Date: Sat, 9 Mar 2024 11:45:55 -0800 Subject: [PATCH] team post authors --- lib/team.stack.ts | 2 +- package.json | 2 +- .../database/migrations/1708560752515.sql | 13 +++++++--- resources/database/setup.ts | 2 +- scripts/build | 6 +++-- src/posts/createPost.ts | 14 +++++----- src/posts/getPosts.ts | 26 ++++++++++++++++--- src/teams/createTeam.ts | 22 ++++++++++------ src/teams/getTeams.ts | 16 +++++++----- src/util/db.ts | 14 +++++++--- src/util/middleware/authorizer.ts | 23 +++++----------- 11 files changed, 86 insertions(+), 54 deletions(-) diff --git a/lib/team.stack.ts b/lib/team.stack.ts index 2cdae09..7b18534 100644 --- a/lib/team.stack.ts +++ b/lib/team.stack.ts @@ -37,7 +37,7 @@ export class TeamStack extends cdk.Stack { const apiResources: IApiResources = { subresources: { - announcements: { + posts: { endpoints: { GET: { id: 'getPosts', diff --git a/package.json b/package.json index 2adbd15..de68cac 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "test": "jest", "test:watch": "jest --watch", "test:src": "jest --verbose ./src", - "start:local:api": "sam local start-api -t ./cdk.out/$npm_config_stack.template.json --port 8000 --container-host-interface host.docker.internal", + "start:local:api": "sam local start-api -t ./cdk.out/team-stack.template.json --port 3003 ", "invoke:lambda": "sam local invoke -t ./cdk.out/$npm_config_stack.template.json -e $npm_config_event ${npm_config_warm-containers=LAZY}", "start:local:lambdas": "sam local start-lambda -t ./cdk.out/$npm_config_stack.template.json ${npm_config_port:3000} ${npm_config_warm-containers=LAZY}", diff --git a/resources/database/migrations/1708560752515.sql b/resources/database/migrations/1708560752515.sql index 454dd8c..e0c09e7 100644 --- a/resources/database/migrations/1708560752515.sql +++ b/resources/database/migrations/1708560752515.sql @@ -12,6 +12,13 @@ image_link VARCHAR(255), meta_data JSON ); +CREATE TABLE IF NOT EXISTS team_term ( + term_year INT NOT NULL, + teamid INT NOT NULL, + PRIMARY KEY (term_year, teamid) +); + + -- Create post table CREATE TABLE IF NOT EXISTS post ( id INT AUTO_INCREMENT PRIMARY KEY, @@ -19,10 +26,8 @@ teamid INT NOT NULL, userid INT NOT NULL, title VARCHAR(255) NOT NULL, status ENUM('pinned', 'bookmarked', 'archived', 'default') DEFAULT 'default', -type ENUM('post', 'event', 'news', 'update','discussion', 'anouncement') DEFAULT 'announcement', +type ENUM('post', 'event', 'news', 'update','discussion', 'announcement') DEFAULT 'announcement', created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP, -contents JSON, -FOREIGN KEY (`teamid`) REFERENCES `team` (`id`) -FOREIGN KEY (`userid`) REFERENCES `person` (`id`) +contents JSON ); \ No newline at end of file diff --git a/resources/database/setup.ts b/resources/database/setup.ts index f811c6e..35c356b 100644 --- a/resources/database/setup.ts +++ b/resources/database/setup.ts @@ -6,7 +6,7 @@ import mysql, { Connection } from 'mysql2'; console.log('Connected to PlanetScale!') dotenv.config(); -const DATABASE_NAME = 'userbase'; +const DATABASE_NAME = 'cosmic-dev'; const MIGRATION_PATH = './resources/database/migrations'; const setUpDatabase = async ( diff --git a/scripts/build b/scripts/build index b03b999..6856c5f 100644 --- a/scripts/build +++ b/scripts/build @@ -21,5 +21,7 @@ esbuild ./src/**/*.ts \ --entry-names=[dir]/[name]/index \ --bundle \ --platform=node \ - --target=node16.14 \ - --outdir=./dist/ + --target=node18 \ + --outdir=./dist/ \ + --sourcemap=inline \ + diff --git a/src/posts/createPost.ts b/src/posts/createPost.ts index b705f2c..4eced29 100644 --- a/src/posts/createPost.ts +++ b/src/posts/createPost.ts @@ -1,24 +1,24 @@ import { getDatabase, NewPost } from '../util/db'; -import { LambdaBuilder } from '../util/middleware/middleware'; +import { LambdaBuilder, LambdaInput } from '../util/middleware/middleware'; import { APIResponse, SuccessResponse } from '../util/middleware/response'; -import { InputValidator } from '../util/middleware/inputValidator'; -import { APIGatewayProxyEvent } from 'aws-lambda'; import { Authorizer } from '../util/middleware/authorizer'; const db = getDatabase(); export const handler = new LambdaBuilder(router) - .use(new InputValidator()) - .use(new Authorizer({shouldGetUser: true, db: db})) + .use(new Authorizer(db, { shouldGetUser: true })) .build(); export async function router( - event: APIGatewayProxyEvent + event: LambdaInput ): Promise { if (!event.body) throw new Error('No body provided'); const body = JSON.parse(event.body); - const postParams = {body , userid: body.user.id} as unknown as NewPost; + console.log(event.googleAccount.id); + console.log(event.googleAccount.email); + + const postParams = {...body , userid: event.googleAccount.id} as unknown as NewPost; const newPost = await createPost(postParams); return new SuccessResponse({ message: `post with id : ${newPost} created`, diff --git a/src/posts/getPosts.ts b/src/posts/getPosts.ts index a6ed119..ed5d17b 100644 --- a/src/posts/getPosts.ts +++ b/src/posts/getPosts.ts @@ -3,6 +3,8 @@ import { LambdaBuilder } from '../util/middleware/middleware'; import { APIResponse, SuccessResponse } from '../util/middleware/response'; import { InputValidator } from '../util/middleware/inputValidator'; import { APIGatewayEvent } from 'aws-lambda'; +import { S3 } from 'aws-sdk'; + const db = getDatabase(); @@ -16,6 +18,13 @@ export async function router( ): Promise { const q = event.queryStringParameters; + + const s3 = new S3({ + accessKeyId: process.env.ACCESS_KEY, + secretAccessKey: process.env.SECRET_ACCESS_KEY + }); + + console.log(s3) if (q && q.teamid) { const team = await getPosts(Number(q.teamid)); return new SuccessResponse(team); @@ -25,11 +34,20 @@ export async function router( } } export const getPosts = async (teamid?: number) => { - const post = await db + let posts = await db .selectFrom('post') - .selectAll() + .innerJoin('person', 'person.id', 'post.userid') + .select(['person.email', 'person.first_name', 'person.last_name', 'post.contents', + 'post.status', 'post.updated_at', 'post.id', 'post.title', 'post.teamid', 'post.userid', 'post.type', + 'post.created_at' + ]) .$if(teamid !== undefined, (query) => query.where('teamid', '=', teamid as number)) .orderBy('updated_at desc') .execute(); - return post; -}; + + posts = posts.map((post: any) => { + return {...post, author: `${post.first_name} ${post.last_name}`}; + }); + + return posts; +} \ No newline at end of file diff --git a/src/teams/createTeam.ts b/src/teams/createTeam.ts index 9354c91..7761ac9 100644 --- a/src/teams/createTeam.ts +++ b/src/teams/createTeam.ts @@ -3,7 +3,6 @@ import { LambdaBuilder } from '../util/middleware/middleware'; import { APIResponse, SuccessResponse } from '../util/middleware/response'; import { InputValidator } from '../util/middleware/inputValidator'; import { APIGatewayProxyEvent } from 'aws-lambda'; -import { Authorizer } from '../util/middleware/authorizer'; const db = getDatabase(); @@ -17,20 +16,27 @@ export async function router( ): Promise { if (!event.body) throw new Error('No body provided'); - const body = JSON.parse(event.body) as NewTeam; + const body = JSON.parse(event.body) as NewTeam & { term_year: number} const newTeamId = await createTeam(body); return new SuccessResponse({ message: `team with id : ${newTeamId} created`, }); } -export const createTeam = async (newTeam: NewTeam) => { - const param = newTeam; - param.meta_data = JSON.stringify(newTeam.meta_data); - console.log(param.meta_data); - console.log(param); +export const createTeam = async (newTeam: NewTeam & { term_year: number}) => { + const { term_year, ...team } = newTeam; + team.meta_data = JSON.stringify(team.meta_data); + const { insertId } = await db .insertInto('team') - .values(param) + .values(team) .executeTakeFirst(); + + if (!insertId) throw new Error('Failed to create team'); + + await db + .insertInto('team_term') + .values({ teamid: Number(insertId), term_year }) + .executeTakeFirst(); + return insertId; }; diff --git a/src/teams/getTeams.ts b/src/teams/getTeams.ts index e7c61ab..0ed2159 100644 --- a/src/teams/getTeams.ts +++ b/src/teams/getTeams.ts @@ -7,7 +7,6 @@ const db = getDatabase(); export const handler = new LambdaBuilder(router) .use(new InputValidator()) - // .use(new Authorizer()) .build(); export async function router(): Promise { @@ -15,9 +14,14 @@ export async function router(): Promise { return new SuccessResponse(teams); } export const getTeams = async () => { - const teams = await db - .selectFrom('team') - .selectAll() - .execute(); - return teams; + const teams = await db.selectFrom('team').selectAll().execute(); + const teamTerms = await db.selectFrom('team_term').selectAll().execute(); + const teamsWithTerms: any[]= [] + for (const team of teams) { + const t = team as any; + t.team_terms = teamTerms.filter(term => term.teamid === team.id).map(term => term.term_year); + teamsWithTerms.push(t); + } + + return teamsWithTerms; }; diff --git a/src/util/db.ts b/src/util/db.ts index 669eaba..9d5ba30 100644 --- a/src/util/db.ts +++ b/src/util/db.ts @@ -9,7 +9,6 @@ import { } from 'kysely'; import { config } from 'dotenv'; import { PlanetScaleDialect } from 'kysely-planetscale' -import { fetch } from 'undici' import { Link } from './types/general'; config(); @@ -25,15 +24,14 @@ export interface Database { specialization: SpecializationTable; standing: StandingTable; team: TeamTable; + team_term: TeamTermTable; post: PostTable; } export function getDatabase() { - console.log('getDatabase'); console.log(process.env.DATABASE_USERNAME); const db = new Kysely({ dialect: new PlanetScaleDialect({ - fetch, host: process.env.DATABASE_HOST, username: process.env.DATABASE_USERNAME, password: process.env.DATABASE_PASSWORD @@ -117,6 +115,16 @@ export type Team = Selectable; export type NewTeam = Insertable; export type UpdateTeam = Updateable; +export interface TeamTermTable { + teamid: number; + term_year: number; +} + +export type TeamTerm = Selectable; +export type NewTeamTerm = Insertable; +export type UpdateTeamTerm = Updateable; + + export interface PostTable { id: Generated; title: string; diff --git a/src/util/middleware/authorizer.ts b/src/util/middleware/authorizer.ts index 3ef9420..a4ed442 100644 --- a/src/util/middleware/authorizer.ts +++ b/src/util/middleware/authorizer.ts @@ -21,9 +21,8 @@ export class Authorizer implements IMiddleware { } const googleAuth = await this.verifyUserIsLoggedIn(auth); - if (this.params.shouldGetUser) { - return this.getUser(googleAuth, this.connection); - } + console.log(googleAuth); + console.log("gwe"); return { googleAccount: googleAuth}; }; @@ -35,27 +34,17 @@ export class Authorizer implements IMiddleware { throw new NotFoundError('User not found'); } - const user = await this.connection.selectFrom('person').where('email','=', googleAuthUser.email).executeTakeFirst(); + console.log(googleAuthUser.email); + const user = await this.connection.selectFrom('person').where('email','=', googleAuthUser.email).selectAll().executeTakeFirst(); + console.log("user"); if (!user) { throw new NotFoundError('User not found'); } - return googleAuthUser; + return user; }; - getUser = async (googleAuth: GoogleAuthUser, db: Kysely) => { - const user = await db - .selectFrom('person') - .where('email', '=', googleAuth.email) - .selectAll() - .executeTakeFirst(); - - if (!user) { - throw new NotFoundError('User not found'); - } - return { user, googleAccount: googleAuth }; - }; constructor(connection: Kysely, params = { shouldGetUser: false}) { this.params = params;