Skip to content
This repository has been archived by the owner on Aug 11, 2024. It is now read-only.

Commit

Permalink
First pass at generating API docs
Browse files Browse the repository at this point in the history
  • Loading branch information
wpf500 committed Jan 12, 2024
1 parent 48cecc2 commit c315dd7
Show file tree
Hide file tree
Showing 30 changed files with 375 additions and 116 deletions.
69 changes: 68 additions & 1 deletion package-lock.json

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

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
"chance": "^1.1.11",
"class-transformer": "^0.5.1",
"class-validator": "^0.14.0",
"class-validator-jsonschema": "^4.0.0",
"clean-deep": "^3.4.0",
"connect-busboy": "^1.0.0",
"connect-pg-simple": "^9.0.1",
Expand Down Expand Up @@ -81,6 +82,7 @@
"query-string": "^7.1.3",
"reflect-metadata": "^0.1.13",
"routing-controllers": "^0.10.4",
"routing-controllers-openapi": "^4.0.0",
"slugify": "^1.6.6",
"stripe": "^9.16.0",
"tar-stream": "^3.1.6",
Expand Down
36 changes: 2 additions & 34 deletions src/api/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,7 @@ import {
useExpressServer
} from "routing-controllers";

import { ApiKeyController } from "./controllers/ApiKeyController";
import { AuthController } from "./controllers/AuthController";
import { CalloutController } from "./controllers/CalloutController";
import { CalloutResponseController } from "./controllers/CalloutResponseController";
import { CalloutResponseCommentController } from "./controllers/CalloutResponseCommentController";
import { ContentController } from "./controllers/ContentController";
import { EmailController } from "./controllers/EmailController";
import { ContactController } from "./controllers/ContactController";
import { NoticeController } from "./controllers/NoticeController";
import { PaymentController } from "./controllers/PaymentController";
import { SegmentController } from "./controllers/SegmentController";
import { SignupController } from "./controllers/SignupController";
import { StatsController } from "./controllers/StatsController";
import { ResetPasswordController } from "./controllers/ResetPasswordController";
import { ResetDeviceController } from "./controllers/ResetDeviceController";
import { UploadController } from "./controllers/UploadController";
import controllers from "@api/controllers";

import { ValidateResponseInterceptor } from "./interceptors/ValidateResponseInterceptor";

Expand Down Expand Up @@ -72,24 +57,7 @@ initApp()

useExpressServer(app, {
routePrefix: "/1.0",
controllers: [
ApiKeyController,
AuthController,
CalloutController,
CalloutResponseController,
CalloutResponseCommentController,
ContentController,
EmailController,
ContactController,
NoticeController,
PaymentController,
SegmentController,
SignupController,
StatsController,
ResetPasswordController,
ResetDeviceController,
UploadController
],
controllers,
interceptors: [ValidateResponseInterceptor],
currentUserChecker,
authorizationChecker,
Expand Down
17 changes: 12 additions & 5 deletions src/api/controllers/ApiKeyController.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { plainToInstance } from "class-transformer";
import {
JsonController,
Authorized,
Expand All @@ -11,6 +12,7 @@ import {
Delete,
Param
} from "routing-controllers";
import { OpenAPI, ResponseSchema } from "routing-controllers-openapi";

import { getRepository } from "@core/database";
import { generateApiKey } from "@core/utils/auth";
Expand All @@ -21,23 +23,27 @@ import Contact from "@models/Contact";
import {
CreateApiKeyDto,
GetApiKeyDto,
ListApiKeysDto
GetApiKeysListDto,
ListApiKeysDto,
NewApiKeyDto
} from "@api/dto/ApiKeyDto";
import { PaginatedDto } from "@api/dto/PaginatedDto";
import ApiKeyTransformer from "@api/transformers/ApiKeyTransformer";

@OpenAPI({ tags: ["API Keys"] })
@JsonController("/api-key")
@Authorized("admin")
export class ApiKeyController {
@Get("/")
@ResponseSchema(GetApiKeysListDto)
async getApiKeys(
@CurrentUser({ required: true }) caller: Contact,
@QueryParams() query: ListApiKeysDto
): Promise<PaginatedDto<GetApiKeyDto>> {
): Promise<GetApiKeysListDto> {
return await ApiKeyTransformer.fetch(caller, query);
}

@Get("/:id")
@ResponseSchema(GetApiKeyDto, { statusCode: 200 })
async getApiKey(
@CurrentUser({ required: true }) caller: Contact,
@Param("id") id: string
Expand All @@ -46,10 +52,11 @@ export class ApiKeyController {
}

@Post("/")
@ResponseSchema(NewApiKeyDto)
async createApiKey(
@Body() data: CreateApiKeyDto,
@CurrentUser({ required: true }) creator: Contact
): Promise<{ token: string }> {
): Promise<NewApiKeyDto> {
const { id, secretHash, token } = generateApiKey();

await getRepository(ApiKey).save({
Expand All @@ -60,7 +67,7 @@ export class ApiKeyController {
expires: data.expires
});

return { token };
return plainToInstance(NewApiKeyDto, { token });
}

@OnUndefined(204)
Expand Down
26 changes: 6 additions & 20 deletions src/api/controllers/AuthController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,32 +21,18 @@ import passport from "@core/lib/passport";

import ContactsService from "@core/services/ContactsService";

import { LoginDto } from "@api/dto/LoginDto";
import { login } from "@api/utils";

import Contact from "@models/Contact";
import ContactRole from "@models/ContactRole";

import { login } from "@api/utils";
import { LOGIN_CODES } from "@enums/login-codes";

import { PassportLoginInfo } from "@type/passport-login-info";

import { LOGIN_CODES } from "@enums/login-codes";

import config from "@config";

export class LoginData {
@IsEmail()
email!: string;

// We deliberately don't validate with IsPassword here so
// invalid passwords return a 401
@IsString()
password!: string;

/** Optional multi factor authentication token */
@IsString()
@IsOptional()
token?: string;
}

@JsonController("/auth")
export class AuthController {
@OnUndefined(204)
Expand All @@ -55,7 +41,7 @@ export class AuthController {
@Req() req: Request,
@Res() res: Response,
/** Just used for validation (`email`, `password` and `req.data.token` are in passport strategy) */
@Body() _: LoginData
@Body() _: LoginDto
): Promise<void> {
const user = await new Promise<Contact>((resolve, reject) => {
passport.authenticate(
Expand Down Expand Up @@ -99,7 +85,7 @@ export class AuthController {

@OnUndefined(204)
@Get("/login/as/:id")
async loginAs(@Req() req: Request, @Param("id") id: string) {
async loginAs(@Req() req: Request, @Param("id") id: string): Promise<void> {
if (!config.dev) {
throw new NotFoundError();
}
Expand Down
Loading

0 comments on commit c315dd7

Please sign in to comment.