Add website api graphql endpoint
This commit is contained in:
parent
2e4357f7f8
commit
3e1f7e01f0
13 changed files with 918 additions and 33 deletions
8
.idea/modules.xml
Normal file
8
.idea/modules.xml
Normal file
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/backend/backend.iml" filepath="$PROJECT_DIR$/backend/backend.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
9
backend/backend.iml
Normal file
9
backend/backend.iml
Normal file
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="WEB_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$" />
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
811
backend/package-lock.json
generated
811
backend/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -17,6 +17,7 @@
|
|||
"@types/express": "^4.17.10",
|
||||
"@types/lodash": "^4.14.167",
|
||||
"@types/node": "^14.14.21",
|
||||
"apollo-server-fastify": "^2.19.2",
|
||||
"dotenv": "^8.2.0",
|
||||
"fastify": "^3.10.1",
|
||||
"fastify-cookie": "^5.1.0",
|
||||
|
@ -28,6 +29,7 @@
|
|||
"pino-pretty": "^4.3.0",
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"ts-node": "^9.1.1",
|
||||
"type-graphql": "^1.1.1",
|
||||
"typeorm": "^0.2.30",
|
||||
"typescript": "^4.1.3"
|
||||
},
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
import { nanoid } from 'nanoid';
|
||||
import {
|
||||
BaseEntity,
|
||||
Column, Entity, ObjectID, ObjectIdColumn,
|
||||
} from 'typeorm';
|
||||
|
||||
@Entity()
|
||||
export default class Application {
|
||||
export default class Application extends BaseEntity {
|
||||
@ObjectIdColumn()
|
||||
public _id!: ObjectID;
|
||||
|
||||
|
@ -23,9 +24,6 @@ export default class Application {
|
|||
@Column()
|
||||
public redirectUris!: string[];
|
||||
|
||||
@Column()
|
||||
public public!: string[];
|
||||
|
||||
public static generateClientId(): string {
|
||||
return nanoid(12);
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import FastifySensible from 'fastify-sensible';
|
|||
import FastifySession from 'fastify-session';
|
||||
import database from './database/database';
|
||||
import registerOAuth from './routes/oauth2';
|
||||
import registerWebsiteApi from './routes/website-api';
|
||||
import { parseIntStrict, requireEnv } from './utils';
|
||||
|
||||
const server = Fastify({
|
||||
|
@ -28,6 +29,7 @@ async function start() {
|
|||
},
|
||||
});
|
||||
await server.register(registerOAuth, { prefix: '/api/oauth', logLevel: 'info' });
|
||||
await server.register(registerWebsiteApi, { prefix: '/api/website', logLevel: 'info' });
|
||||
|
||||
await database.connect();
|
||||
server.log.info('Connected to database');
|
||||
|
|
|
@ -13,12 +13,10 @@ export default function registerAuthorize(server: MyFastifyInstance): void {
|
|||
request,
|
||||
reply,
|
||||
) => {
|
||||
console.log(request.query);
|
||||
if (!isObject(request.query)) {
|
||||
server.log.warn('Request query is not an object');
|
||||
throw server.httpErrors.badRequest();
|
||||
}
|
||||
server.log.info(JSON.stringify(request.body));
|
||||
try {
|
||||
validateParam('client_id', request.query.client_id);
|
||||
validateParam('redirect_uri', request.query.redirect_uri);
|
||||
|
@ -63,7 +61,7 @@ export default function registerAuthorize(server: MyFastifyInstance): void {
|
|||
sessionData.prompts.set(promptId, {
|
||||
clientId: request.query.client_id,
|
||||
redirectUri: request.query.redirect_uri,
|
||||
scopes,
|
||||
scopes: requestedScopes,
|
||||
state: request.query.state,
|
||||
codeChallenge: request.query.code_challenge === undefined ? undefined : {
|
||||
method: codeChallengeMethod,
|
||||
|
|
26
backend/src/routes/website-api/index.ts
Normal file
26
backend/src/routes/website-api/index.ts
Normal file
|
@ -0,0 +1,26 @@
|
|||
import { ApolloServer } from 'apollo-server-fastify';
|
||||
import { buildSchema } from 'type-graphql';
|
||||
import { ApolloContext, MyFastifyInstance } from '../../types';
|
||||
import { getSessionData } from '../../utils';
|
||||
import PromptInfoResolver from './resolvers/prompt-info-resolver';
|
||||
import { WebsiteAPIContext } from './types';
|
||||
|
||||
export default async function registerWebsiteApi(server: MyFastifyInstance): Promise<void> {
|
||||
const schema = await buildSchema({
|
||||
authMode: 'error',
|
||||
resolvers: [PromptInfoResolver],
|
||||
});
|
||||
const apolloServer = new ApolloServer({
|
||||
schema,
|
||||
context: ((context: ApolloContext): WebsiteAPIContext => ({
|
||||
...context,
|
||||
sessionData: getSessionData(context.request.session),
|
||||
})),
|
||||
});
|
||||
await server.register(apolloServer.createHandler({
|
||||
cors: {
|
||||
origin: 'https://google.com',
|
||||
},
|
||||
}));
|
||||
console.log(apolloServer.graphqlPath);
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
import { Field, ObjectType } from 'type-graphql';
|
||||
|
||||
@ObjectType()
|
||||
export default class PromptInfoApplication {
|
||||
@Field(() => String)
|
||||
public name!: string;
|
||||
|
||||
@Field(() => String, {
|
||||
nullable: true,
|
||||
})
|
||||
public iconUrl!: string | null;
|
||||
|
||||
@Field(() => Boolean)
|
||||
public verified!: boolean;
|
||||
}
|
17
backend/src/routes/website-api/models/prompt-info.ts
Normal file
17
backend/src/routes/website-api/models/prompt-info.ts
Normal file
|
@ -0,0 +1,17 @@
|
|||
import { Field, ObjectType } from 'type-graphql';
|
||||
import PromptInfoApplication from './prompt-info-application';
|
||||
|
||||
@ObjectType()
|
||||
export default class PromptInfo {
|
||||
@Field(() => String)
|
||||
public id!: string;
|
||||
|
||||
@Field(() => [String])
|
||||
public scopes!: string[];
|
||||
|
||||
@Field(() => String)
|
||||
public clientId!: string;
|
||||
|
||||
@Field(() => PromptInfoApplication)
|
||||
public application!: PromptInfoApplication;
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/* eslint-disable class-methods-use-this */
|
||||
import {
|
||||
Arg, Ctx, FieldResolver, Query, Resolver, ResolverInterface, Root,
|
||||
} from 'type-graphql';
|
||||
import database from '../../../database/database';
|
||||
import PromptInfo from '../models/prompt-info';
|
||||
import PromptInfoApplication from '../models/prompt-info-application';
|
||||
import { WebsiteAPIContext } from '../types';
|
||||
|
||||
@Resolver(PromptInfo)
|
||||
export default class PromptInfoResolver implements ResolverInterface<PromptInfo> {
|
||||
@Query(() => PromptInfo)
|
||||
public promptInfo(
|
||||
@Arg('id') id: string,
|
||||
@Ctx() { sessionData }: WebsiteAPIContext,
|
||||
): Partial<PromptInfo> {
|
||||
const prompt = sessionData.prompts.get(id);
|
||||
if (!prompt) throw new Error('Prompt data not found');
|
||||
return {
|
||||
id,
|
||||
clientId: prompt.clientId,
|
||||
scopes: prompt.scopes,
|
||||
};
|
||||
}
|
||||
|
||||
@FieldResolver()
|
||||
public async application(@Root() prompt: PromptInfo): Promise<PromptInfoApplication> {
|
||||
const application = await database.applicationRepo.findOne({
|
||||
where: {
|
||||
clientId: prompt.clientId,
|
||||
},
|
||||
});
|
||||
if (!application) throw new Error('Prompt data not found');
|
||||
return {
|
||||
name: application.name,
|
||||
iconUrl: application.iconUrl,
|
||||
verified: application.verified,
|
||||
};
|
||||
}
|
||||
}
|
5
backend/src/routes/website-api/types.ts
Normal file
5
backend/src/routes/website-api/types.ts
Normal file
|
@ -0,0 +1,5 @@
|
|||
import { ApolloContext, SessionData } from '../../types';
|
||||
|
||||
export interface WebsiteAPIContext extends ApolloContext {
|
||||
sessionData: SessionData;
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
import {
|
||||
FastifyInstance, RawReplyDefaultExpression, RawRequestDefaultExpression, RawServerDefault,
|
||||
FastifyInstance, FastifyRequest, RawReplyDefaultExpression, RawRequestDefaultExpression, RawServerDefault,
|
||||
} from 'fastify';
|
||||
|
||||
export interface Prompt {
|
||||
|
@ -26,3 +26,7 @@ export interface Session {
|
|||
}
|
||||
|
||||
export type MyFastifyInstance = FastifyInstance<RawServerDefault, RawRequestDefaultExpression<RawServerDefault>, RawReplyDefaultExpression<RawServerDefault>>;
|
||||
|
||||
export interface ApolloContext {
|
||||
request: FastifyRequest;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue