Skip to content

Commit 8c2d4be

Browse files
committed
feat: port oauth to the new architecture
1 parent 7bd7db0 commit 8c2d4be

File tree

9 files changed

+348
-288
lines changed

9 files changed

+348
-288
lines changed

packages/oauth/package.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,13 @@
2929
"@accounts/server": "^0.33.1",
3030
"@types/jest": "27.5.2",
3131
"@types/node": "20.2.3",
32+
"graphql-modules": "2.1.2",
3233
"jest": "27.3.1",
3334
"rimraf": "5.0.1",
3435
"ts-jest": "27.1.5"
36+
},
37+
"peerDependencies": {
38+
"@accounts/server": "^0.32.0 || ^0.33.0",
39+
"graphql-modules": "^2.0.0"
3540
}
3641
}

packages/oauth/src/accounts-oauth.ts

Lines changed: 71 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,87 @@
1-
import { User, DatabaseInterface, AuthenticationService } from '@accounts/types';
2-
import { AccountsServer, ServerHooks } from '@accounts/server';
3-
import { OAuthOptions } from './types/oauth-options';
1+
import {
2+
User,
3+
DatabaseInterface,
4+
AuthenticationService,
5+
DatabaseInterfaceSessions,
6+
DatabaseInterfaceUser,
7+
} from '@accounts/types';
8+
import {
9+
AccountsServer,
10+
/*DatabaseInterfaceSessionsToken,*/ DatabaseInterfaceUserToken,
11+
ServerHooks,
12+
} from '@accounts/server';
13+
import { OAuthProviders } from './types/oauth-providers';
414
import { OAuthUser } from './types/oauth-user';
15+
import { ExecutionContext, Inject, Injectable } from 'graphql-modules';
16+
import { OAuthProvidersToken } from './types/OAuthProviders.symbol';
517

618
const getRegistrationPayloadDefault = async (oauthUser: OAuthUser) => {
719
return {
820
email: oauthUser.email,
921
};
1022
};
1123

12-
export class AccountsOauth implements AuthenticationService {
24+
@Injectable({
25+
global: true,
26+
})
27+
export class AccountsOauth<CustomUser extends User = User>
28+
implements AuthenticationService<CustomUser>
29+
{
30+
@ExecutionContext() public context!: ExecutionContext;
1331
public server!: AccountsServer;
1432
public serviceName = 'oauth';
15-
private db!: DatabaseInterface;
16-
private options: OAuthOptions;
33+
private db!: DatabaseInterfaceUser<CustomUser>;
34+
// private dbSessions!: DatabaseInterfaceSessions;
35+
36+
constructor(
37+
@Inject(OAuthProvidersToken) public oauthProviders: OAuthProviders,
38+
@Inject(DatabaseInterfaceUserToken)
39+
db?: DatabaseInterface<CustomUser> | DatabaseInterfaceUser<CustomUser>,
40+
// @Inject(DatabaseInterfaceSessionsToken) dbSessions?: DatabaseInterfaceSessions,
41+
server?: AccountsServer
42+
) {
43+
if (db) {
44+
this.db = db;
45+
// this.dbSessions = dbSessions ?? (db as DatabaseInterfaceSessions);
46+
}
47+
48+
if (server) {
49+
this.server = server;
50+
}
51+
}
1752

18-
constructor(options: OAuthOptions) {
19-
this.options = options;
53+
private getOAuthProvider(providerName: string) {
54+
const instanceOrCtor = this.oauthProviders[providerName];
55+
// If it's a constructor we use dependency injection (GraphQL), otherwise we already have an instance (REST)
56+
const provider =
57+
typeof instanceOrCtor === 'function'
58+
? this.context.injector.get(instanceOrCtor)
59+
: instanceOrCtor;
60+
if (!provider) {
61+
throw new Error(`No OAuth provider with the name ${providerName} was registered.`);
62+
}
63+
return provider;
2064
}
2165

22-
public setStore(store: DatabaseInterface) {
66+
public getOAuthProviders(): OAuthProviders {
67+
return this.oauthProviders;
68+
}
69+
70+
public setUserStore(store: DatabaseInterfaceUser<CustomUser>) {
2371
this.db = store;
2472
}
2573

26-
public async authenticate(params: any): Promise<User | null> {
27-
if (!params.provider || !this.options[params.provider]) {
74+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
75+
public setSessionsStore(store: DatabaseInterfaceSessions) {
76+
//this.dbSessions = store;
77+
}
78+
79+
public async authenticate(params: any): Promise<CustomUser | null> {
80+
if (!params.provider || !this.getOAuthProvider(params.provider)) {
2881
throw new Error('Invalid provider');
2982
}
3083

31-
const userProvider = this.options[params.provider];
84+
const userProvider = this.getOAuthProvider(params.provider);
3285

3386
if (typeof userProvider.authenticate !== 'function') {
3487
throw new Error('Invalid provider');
@@ -49,7 +102,11 @@ export class AccountsOauth implements AuthenticationService {
49102

50103
const userId = await this.db.createUser(userData);
51104

52-
user = (await this.db.findUserById(userId)) as User;
105+
user = await this.db.findUserById(userId);
106+
107+
if (user == null) {
108+
throw new Error(`Cannot find user ${userId}`);
109+
}
53110

54111
if (this.server) {
55112
await this.server.getHooks().emit(ServerHooks.CreateUserSuccess, user);
@@ -69,7 +126,7 @@ export class AccountsOauth implements AuthenticationService {
69126
}
70127

71128
public async unlink(userId: string, provider: string) {
72-
if (!provider || !this.options[provider]) {
129+
if (!provider || !this.getOAuthProvider(provider)) {
73130
throw new Error('Invalid provider');
74131
}
75132

packages/oauth/src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@ export default AccountsOauth;
33

44
export { AccountsOauth } from './accounts-oauth';
55
export { OAuthProvider } from './types/oauth-provider';
6-
export { OAuthOptions } from './types/oauth-options';
6+
export { OAuthProviders } from './types/oauth-providers';
77
export { OAuthUser } from './types/oauth-user';
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import { InjectionToken } from 'graphql-modules';
2+
import { OAuthProviders } from './oauth-providers';
3+
4+
export const OAuthProvidersToken = new InjectionToken<OAuthProviders>('OauthProviders');

packages/oauth/src/types/oauth-options.ts

Lines changed: 0 additions & 5 deletions
This file was deleted.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { OAuthProvider } from './oauth-provider';
2+
3+
export interface OAuthProviders {
4+
[key: string]: (new (args: any) => OAuthProvider) | OAuthProvider | undefined;
5+
}

packages/oauth/tsconfig.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
{
22
"extends": "../../tsconfig.json",
33
"compilerOptions": {
4+
"experimentalDecorators": true,
5+
"emitDecoratorMetadata": true,
46
"outDir": "./lib",
57
"importHelpers": true
68
},

packages/password/src/accounts-password.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ const defaultOptions = {
180180
global: true,
181181
})
182182
export default class AccountsPassword<CustomUser extends User = User>
183-
implements AuthenticationService
183+
implements AuthenticationService<CustomUser>
184184
{
185185
public serviceName = 'password';
186186
public server!: AccountsServer;

0 commit comments

Comments
 (0)