Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Area API + getDoc without markdown contents #75

Merged
merged 20 commits into from
Mar 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"plugins": ["@typescript-eslint", "prettier"],
"extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"],
"rules": {
"@typescript-eslint/no-unused-vars": "warn",
"@typescript-eslint/no-unused-vars": "off",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/explicit-module-boundary-types": "off"
},
Expand Down
1 change: 1 addition & 0 deletions bin/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ new UserStack(app, USER_STACK_INFO.NAME, {

new WikiStack(app, WIKI_STACK_INFO.NAME, {
env: deploymentEnvironments[0],
databaseConfig: DATABASE_CONFIG.getDBConfig(),
});

new TeamStack(app, Team_STACK_INFO.NAME, {
Expand Down
106 changes: 89 additions & 17 deletions lib/wiki.stack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,21 @@ import * as lambda from 'aws-cdk-lib/aws-lambda';
import { config } from 'dotenv';
import { LPStack, StackInfo } from './util/LPStack';
import { ApiService, IApiResources } from './templates/apigateway';
import * as s3 from 'aws-cdk-lib/aws-s3';
// import * as s3 from 'aws-cdk-lib/aws-s3';
import { Role, ServicePrincipal, PolicyStatement } from 'aws-cdk-lib/aws-iam';
import { IDatabaseConfig } from '../config/database.config';
config();

export const WIKI_STACK_INFO: StackInfo = { NAME: 'wiki-stack' };
export const WIKI_STACK_INFO: StackInfo = { NAME: 'hub-wiki-stack' };

export interface WikiStackProps extends cdk.StackProps {
databaseConfig: IDatabaseConfig;
}
export class WikiStack extends LPStack {
public STACK_INFO: StackInfo = WIKI_STACK_INFO;
apiService: ApiService;

constructor(scope: Construct, id: string, props: cdk.StackProps) {
constructor(scope: Construct, id: string, props: WikiStackProps) {
super(scope, id, props);

const role = new Role(this, 'MyLambdaRole', {
Expand All @@ -27,33 +31,102 @@ export class WikiStack extends LPStack {
policyStatement.addResources('arn:aws:s3:::lp-doc');
role.addToPolicy(policyStatement);

const myBucket = new s3.Bucket(this, 'MyBucket', {
// S3 bucket configuration
});
// const myBucket = new s3.Bucket(this, 'MyBucket', {
// // S3 bucket configuration
// });

const lambdaConfigs = {
runtime: lambda.Runtime.NODEJS_18_X,
handler: 'index.handler',
memorySize: 2048,
environment: {
BUCKET_NAME: myBucket.bucketName,
BUCKET_ARN: myBucket.bucketArn,
BUCKET_NAME: process.env.BUCKET_NAME || '',
BUCKET_ARN: process.env.BUCKET_NAME || '',
ACCESS_KEY: process.env.IAM_ACCESS_KEY || '',
SECRET_ACCESS_KEY: process.env.IAM_SECRET_ACCESS_KEY || '',
...props.databaseConfig,
},
role: role,
};

const baseLambdaDir = 'dist/wiki';
const areaLambdaDir = 'dist/wiki/area';
const docLambdaDir = 'dist/wiki/doc';

const apiResources: IApiResources = {
subresources: {
docs: {
doc: {
subresources: {
'{area}': {
'{docid}': {
endpoints: {
GET: {
id: 'getDoc',
path: `${docLambdaDir}/getDoc`,
},
},
},
},
},
areas: {
endpoints: {
GET: {
id: 'getAreas',
path: `${areaLambdaDir}/getAreas`,
},
POST: {
id: 'createArea',
path: `${areaLambdaDir}/createArea`,
},
},
subresources: {
'{areaid}': {
endpoints: {
GET: {
id: 'getArea',
path: `${areaLambdaDir}/getArea`,
},
DELETE: {
id: 'deleteArea',
path: `${areaLambdaDir}/deleteArea`,
},
PATCH: {
id: 'updateArea',
path: `${areaLambdaDir}/updateArea`,
},
},
subresources: {
'{doc}': {
docs: {
endpoints: {
GET: {
id: 'getDoc',
path: `${baseLambdaDir}/getdoc`,
POST: {
id: 'createDoc',
path: `${docLambdaDir}/createDoc`,
},
},
subresources: {
'{docid}': {
endpoints: {
DELETE: {
id: 'deleteDoc',
path: `${docLambdaDir}/deleteDoc`,
},
GET: {
id: 'getDoc',
path: `${docLambdaDir}/getDoc`,
},
PUT: {
id: 'putDoc',
path: `${docLambdaDir}/putDoc`,
},
},
// subresources: {
// 'content': {
// endpoints: {
// GET: {
// id: 'getContent',
// path: `${baseLambdaDir}/getContent`,
// },
// },
// },
// },
},
},
},
Expand All @@ -68,8 +141,7 @@ export class WikiStack extends LPStack {
this,
apiResources,
`${WIKI_STACK_INFO.NAME}-API`,
lambdaConfigs,
myBucket
lambdaConfigs
);
}
}
23 changes: 18 additions & 5 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@
"test": "jest",
"test:watch": "jest --watch",
"test:src": "jest --verbose ./src",
"start:local:api": "sam local start-api -t ./cdk.out/users-stack.template.json --port 3003 ",
"start:local:api": "sam local start-api -t ./cdk.out/hub-wiki-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}",
"db:up": "esbuild ./resources/**/*.ts --entry-names=[dir]/[name]/index --bundle --platform=node --target=node16.14 --outdir=./dist/migrations && node ./dist/migrations/setup/index.js"
"db:up": "esbuild resources/database/setup.ts --entry-names=[dir]/[name]/index --bundle --platform=node --target=node16.14 --outdir=./dist/migrations && node ./dist/migrations/setup/index.js"
},
"dependencies": {
"@aws-sdk/client-s3": "^3.363.0",
Expand All @@ -38,7 +38,8 @@
"kysely": "^0.26.3",
"kysely-planetscale": "^1.4.0",
"mysql2": "^3.6.3",
"undici": "^5.28.3"
"undici": "^5.28.3",
"uuid": "^9.0.1"
},
"devDependencies": {
"@babel/core": "^7.22.5",
Expand Down
21 changes: 21 additions & 0 deletions resources/database/migrations/1710395365.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
-- Create Area table
CREATE TABLE IF NOT EXISTS area (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255),
description VARCHAR(255),
updatedat TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
parent_areaid INT DEFAULT NULL,
Foreign Key (parent_areaid) references area(id) ON DELETE NO ACTION
);

-- Create Documents table
CREATE TABLE IF NOT EXISTS document (
id INT AUTO_INCREMENT PRIMARY KEY,
areaid INT NOT NULL,
title VARCHAR(500) NOT NULL,
fileid VARCHAR(2000) NOT NULL UNIQUE,
createdat TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updatedat TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
Foreign Key (areaid) references area(id) ON DELETE CASCADE,
INDEX (fileid)
);
44 changes: 36 additions & 8 deletions resources/database/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import * as path from 'path';
import * as fs from 'fs';
import dotenv from 'dotenv';
import mysql, { Connection } from 'mysql2';
console.log('Connected to PlanetScale!');
dotenv.config();

const DATABASE_META_NAME = 'meta';
const DATABASE_NAME = 'cosmic-dev';
const MIGRATION_PATH = './resources/database/migrations';

Expand Down Expand Up @@ -63,11 +63,10 @@ const resetDatabase = async (connection: Connection): Promise<void> => {
const tables = await query(connection, `SHOW TABLES IN ??`, [
database.Database,
]);
console.log(tables);
for (const table of tables) {
const tableName = Object.values(table)[0];
await query(connection, `DROP TABLE ??`, [tableName]);
}

const tableNames = tables.map((table) => Object.values(table)[0]);
const queryStr = `DROP TABLE ${tableNames.join(', ')}`;
await query(connection, queryStr);
}
}
};
Expand All @@ -85,21 +84,50 @@ async function runMigrations(connection: Connection): Promise<void> {
const lastMigration = res || [];

if (lastMigration.length > 0) {
const lastMigrationTimestamp = lastMigration[0].timestamp;
const lastMigrationTimestamp = Math.floor(
lastMigration[0].timestamp.getTime() / 1000
);
console.log(
chalk.blue('INFO: ') +
'Last migration timestamp: ' +
chalk.bold.underline(lastMigrationTimestamp)
);

files = files.filter((file) => {
const fileParts = file.split('.');
const fileTimestamp = fileParts[0];
return fileTimestamp > lastMigrationTimestamp;
return Number(fileTimestamp) > lastMigrationTimestamp;
});
}

if (files.length === 0) {
console.log(chalk.blue('INFO: ') + 'No new migrations to run');
return;
}

console.log(
chalk.blue('INFO: ') +
'Number of migrations to run: ' +
chalk.bold.underline(files.length)
);

const currentDB = await query(connection, 'SELECT database() AS db');
console.log(
chalk.blue('INFO: ') +
'Database selected: ' +
chalk.bold.underline(currentDB[0].db)
);
await migrate(connection, files);
console.log(chalk.greenBright('SUCCESS: ') + 'Migrations complete');
await query(
connection,
`INSERT INTO migrations (status) VALUES ('success')`
);

console.log(
chalk.greenBright('SUCCESS: ') +
'Migrations table updated with new migrations'
);
}

async function migrate(connection: Connection, files: string[]): Promise<void> {
Expand Down
27 changes: 27 additions & 0 deletions src/util/db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ export interface Database {
team_term: TeamTermTable;
post: PostTable;
team_member: team_member;
area: AreaTable;
document: DocumentTable;
user_scopes_view: UserScopesViewTable;
}

Expand Down Expand Up @@ -165,6 +167,31 @@ export type TeamMember = Selectable<team_member>;
export type NewTeamMember = Insertable<team_member>;
export type UpdateTeamMember = Updateable<team_member>;

export type AreaTable = {
id: Generated<number>;
name: string;
description: string;
parent_areaid: number;
updatedat: Generated<Date>;
};

export type Area = Selectable<AreaTable>;
export type NewArea = Insertable<AreaTable>;
export type UpdateArea = Updateable<AreaTable>;

export type DocumentTable = {
id: Generated<number>;
areaid: number;
title: string;
fileid: string;
createdat: Generated<Date>;
updatedat: Generated<Date>;
};

export type Document = Selectable<DocumentTable>;
export type NewDocument = Insertable<DocumentTable>;
export type UpdateDocument = Updateable<DocumentTable>;

export interface UserScopesViewTable {
email: string;
scope_label: string;
Expand Down
13 changes: 7 additions & 6 deletions src/util/middleware/authorizer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,13 @@ export class Authorizer implements IMiddleware<IHandlerEvent, object> {
private connection: Kysely<Database>;

public handler = async (event: APIGatewayProxyEvent) => {
const auth = event.headers.Authorization;
if (auth === undefined) {
throw new UnauthorizedError('Authorization header is missing');
}
const user = await this.verifyUserIsLoggedIn(auth);
return { user: user };
return {};
// const auth = event.headers.Authorization;
// if (auth === undefined) {
// throw new UnauthorizedError('Authorization header is missing');
// }
// const user = await this.verifyUserIsLoggedIn(auth);
// return { user: user };
};

verifyUserIsLoggedIn = async (auth: string) => {
Expand Down
Loading
Loading