Skip to content

Commit 6f526ed

Browse files
authored
Merge pull request #34 from authorizerdev/chore-v3
implement v2 apis of authorizer
2 parents 3e34c13 + f998d45 commit 6f526ed

8 files changed

Lines changed: 470 additions & 1320 deletions

File tree

.github/workflows/main.yml

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ on: [push, pull_request]
55
jobs:
66
test:
77
runs-on: ubuntu-latest
8+
timeout-minutes: 60
89

910
services:
1011
docker:
@@ -22,8 +23,13 @@ jobs:
2223
- name: Set up Node.js
2324
uses: actions/setup-node@v3
2425
with:
25-
node-version: '16' # Specify your Node.js version here
26+
node-version: "18" # Specify your Node.js version here
27+
28+
- name: Set up pnpm
29+
run: |
30+
corepack enable
31+
corepack prepare pnpm --activate
2632
- name: Install dependencies
27-
run: npm install
33+
run: pnpm install
2834
- name: Run integration tests
29-
run: npm test # Make sure this command runs your integration tests
35+
run: pnpm test # Make sure this command runs your integration tests

.npmrc

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +0,0 @@
1-
ignore-workspace-root-check=true

__test__/index.test.ts

Lines changed: 101 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,17 @@
1+
import { randomUUID } from 'node:crypto';
12
import { GenericContainer, StartedTestContainer, Wait } from 'testcontainers';
23
import { ApiResponse, AuthToken, Authorizer } from '../lib';
34

4-
const authorizerConfig = {
5+
jest.setTimeout(1200000); // Integration tests can be slow on CI (20 minutes)
6+
7+
const authorizerConfig: {
8+
authorizerURL: string;
9+
redirectURL: string;
10+
adminSecret: string;
11+
clientID?: string;
12+
} = {
513
authorizerURL: 'http://localhost:8080',
614
redirectURL: 'http://localhost:8080/app',
7-
// clientID: '3fab5e58-5693-46f2-8123-83db8133cd22',
815
adminSecret: 'secret',
916
};
1017

@@ -18,38 +25,71 @@ const testConfig = {
1825
maginLinkLoginEmail: 'test_magic_link@test.com',
1926
};
2027

21-
// Using etheral.email for email sink: https://ethereal.email/create
22-
const authorizerENV = {
23-
ENV: 'production',
24-
DATABASE_URL: 'data.db',
25-
DATABASE_TYPE: 'sqlite',
26-
CUSTOM_ACCESS_TOKEN_SCRIPT:
27-
'function(user,tokenPayload){var data = tokenPayload;data.extra = {\'x-extra-id\': user.id};return data;}',
28-
DISABLE_PLAYGROUND: 'true',
29-
SMTP_HOST: 'smtp.ethereal.email',
30-
SMTP_PASSWORD: 'WncNxwVFqb6nBjKDQJ',
31-
SMTP_USERNAME: 'sydnee.lesch77@ethereal.email',
32-
LOG_LELVEL: 'debug',
33-
SMTP_PORT: '587',
34-
SENDER_EMAIL: 'test@authorizer.dev',
35-
ADMIN_SECRET: 'secret',
36-
};
28+
// Build v2 CLI args for authorizer (see authorizer/cmd/root.go). Using etheral.email for email sink.
29+
function buildAuthorizerCliArgs(): { args: string[]; clientId: string } {
30+
const clientId = randomUUID();
31+
const clientSecret = randomUUID();
32+
const jwtSecret = randomUUID();
33+
34+
const args = [
35+
'--client-id',
36+
clientId,
37+
'--client-secret',
38+
clientSecret,
39+
'--jwt-type',
40+
'HS256',
41+
'--jwt-secret',
42+
jwtSecret,
43+
'--admin-secret',
44+
authorizerConfig.adminSecret,
45+
'--env',
46+
'production',
47+
'--database-type',
48+
'sqlite',
49+
'--database-url',
50+
'/tmp/authorizer.db',
51+
'--enable-playground=false',
52+
'--log-level',
53+
'debug',
54+
'--smtp-host',
55+
'smtp.ethereal.email',
56+
'--smtp-port',
57+
'587',
58+
'--smtp-username',
59+
'sydnee.lesch77@ethereal.email',
60+
'--smtp-password',
61+
'WncNxwVFqb6nBjKDQJ',
62+
'--smtp-sender-email',
63+
'test@authorizer.dev',
64+
'--enable-email-verification=true',
65+
'--enable-magic-link-login=true',
66+
];
67+
return { args, clientId };
68+
}
3769

3870
// const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
3971

4072
const verificationRequests =
4173
'query {_verification_requests { verification_requests { id token email expires identifier } } }';
4274

4375
describe('Integration Tests - authorizer-js', () => {
44-
let container: StartedTestContainer;
76+
let container: StartedTestContainer | undefined;
4577

4678
let authorizer: Authorizer;
4779

4880
beforeAll(async () => {
49-
container = await new GenericContainer('lakhansamani/authorizer:latest')
50-
.withEnvironment(authorizerENV)
81+
const { args, clientId } = buildAuthorizerCliArgs();
82+
83+
container = await new GenericContainer('lakhansamani/authorizer:2.0.0-rc.6')
84+
.withCommand(args)
5185
.withExposedPorts(8080)
5286
.withWaitStrategy(Wait.forHttp('/health', 8080).forStatusCode(200))
87+
.withStartupTimeout(900000) // 15 minutes (CI can be slow)
88+
// Surface container stdout/stderr to help diagnose CI startup failures.
89+
.withLogConsumer((chunk) => {
90+
// Avoid changing log format; just mirror what container prints.
91+
process.stdout.write(chunk.toString());
92+
})
5393
.start();
5494

5595
authorizerConfig.authorizerURL = `http://${container.getHost()}:${container.getMappedPort(
@@ -58,19 +98,13 @@ describe('Integration Tests - authorizer-js', () => {
5898
authorizerConfig.redirectURL = `http://${container.getHost()}:${container.getMappedPort(
5999
8080,
60100
)}/app`;
101+
authorizerConfig.clientID = clientId;
61102
console.log('Authorizer URL:', authorizerConfig.authorizerURL);
62103
authorizer = new Authorizer(authorizerConfig);
63-
// get metadata
64-
const metadataRes = await authorizer.getMetaData();
65-
// await sleep(50000);
66-
expect(metadataRes?.data).toBeDefined();
67-
if (metadataRes?.data?.client_id) {
68-
authorizer.config.clientID = metadataRes?.data?.client_id;
69-
}
70104
});
71105

72106
afterAll(async () => {
73-
await container.stop();
107+
if (container) await container.stop();
74108
});
75109

76110
it('should signup with email verification enabled', async () => {
@@ -101,10 +135,13 @@ describe('Integration Tests - authorizer-js', () => {
101135
(i: { email: string }) => i.email === testConfig.email,
102136
);
103137
expect(item).not.toBeNull();
138+
expect(item?.token).toBeDefined();
104139

105140
const verifyEmailRes = await authorizer.verifyEmail({ token: item.token });
106141
expect(verifyEmailRes?.data).toBeDefined();
107142
expect(verifyEmailRes?.errors).toHaveLength(0);
143+
expect(verifyEmailRes?.data?.access_token).toBeDefined();
144+
expect(verifyEmailRes?.data?.access_token).not.toBeNull();
108145
expect(verifyEmailRes?.data?.access_token?.length).toBeGreaterThan(0);
109146
});
110147

@@ -117,13 +154,23 @@ describe('Integration Tests - authorizer-js', () => {
117154
});
118155
expect(loginRes?.data).toBeDefined();
119156
expect(loginRes?.errors).toHaveLength(0);
120-
expect(loginRes?.data?.access_token.length).not.toEqual(0);
121-
expect(loginRes?.data?.refresh_token?.length).not.toEqual(0);
122-
expect(loginRes?.data?.expires_in).not.toEqual(0);
123-
expect(loginRes?.data?.id_token.length).not.toEqual(0);
157+
expect(loginRes?.data?.access_token).toBeDefined();
158+
expect(loginRes?.data?.access_token).not.toBeNull();
159+
expect(loginRes?.data?.access_token?.length).toBeGreaterThan(0);
160+
expect(loginRes?.data?.refresh_token).toBeDefined();
161+
expect(loginRes?.data?.refresh_token).not.toBeNull();
162+
expect(loginRes?.data?.refresh_token?.length).toBeGreaterThan(0);
163+
expect(loginRes?.data?.expires_in).toBeDefined();
164+
expect(loginRes?.data?.expires_in).not.toBeNull();
165+
expect(loginRes?.data?.expires_in).toBeGreaterThan(0);
166+
expect(loginRes?.data?.id_token).toBeDefined();
167+
expect(loginRes?.data?.id_token).not.toBeNull();
168+
expect(loginRes?.data?.id_token?.length).toBeGreaterThan(0);
124169
});
125170

126171
it('should validate jwt token', async () => {
172+
expect(loginRes?.data?.access_token).toBeDefined();
173+
expect(loginRes?.data?.access_token).not.toBeNull();
127174
const validateRes = await authorizer.validateJWTToken({
128175
token_type: 'access_token',
129176
token: loginRes?.data?.access_token || '',
@@ -134,6 +181,8 @@ describe('Integration Tests - authorizer-js', () => {
134181
});
135182

136183
it('should update profile successfully', async () => {
184+
expect(loginRes?.data?.access_token).toBeDefined();
185+
expect(loginRes?.data?.access_token).not.toBeNull();
137186
const updateProfileRes = await authorizer.updateProfile(
138187
{
139188
given_name: 'bob',
@@ -147,28 +196,36 @@ describe('Integration Tests - authorizer-js', () => {
147196
});
148197

149198
it('should fetch profile successfully', async () => {
199+
expect(loginRes?.data?.access_token).toBeDefined();
200+
expect(loginRes?.data?.access_token).not.toBeNull();
150201
const profileRes = await authorizer.getProfile({
151202
Authorization: `Bearer ${loginRes?.data?.access_token}`,
152203
});
153204
expect(profileRes?.data).toBeDefined();
154205
expect(profileRes?.errors).toHaveLength(0);
206+
expect(profileRes?.data?.given_name).toBeDefined();
155207
expect(profileRes?.data?.given_name).toMatch('bob');
156208
});
157209

158210
it('should get access_token using refresh_token', async () => {
211+
expect(loginRes?.data?.refresh_token).toBeDefined();
212+
expect(loginRes?.data?.refresh_token).not.toBeNull();
159213
const tokenRes = await authorizer.getToken({
160214
grant_type: 'refresh_token',
161-
refresh_token: loginRes?.data?.refresh_token,
215+
refresh_token: loginRes?.data?.refresh_token || '',
162216
});
163217
expect(tokenRes?.data).toBeDefined();
164218
expect(tokenRes?.errors).toHaveLength(0);
165-
expect(tokenRes?.data?.access_token.length).not.toEqual(0);
219+
expect(tokenRes?.data?.access_token).toBeDefined();
220+
expect(tokenRes?.data?.access_token?.length).toBeGreaterThan(0);
166221
if (loginRes && loginRes.data) {
167222
loginRes.data.access_token = tokenRes?.data?.access_token || '';
168223
}
169224
});
170225

171226
it('should deactivate account', async () => {
227+
expect(loginRes?.data?.access_token).toBeDefined();
228+
expect(loginRes?.data?.access_token).not.toBeNull();
172229
const deactivateRes = await authorizer.deactivateAccount({
173230
Authorization: `Bearer ${loginRes?.data?.access_token}`,
174231
});
@@ -177,11 +234,13 @@ describe('Integration Tests - authorizer-js', () => {
177234
});
178235

179236
it('should throw error while accessing profile after deactivation', async () => {
237+
expect(loginRes?.data?.access_token).toBeDefined();
180238
const resp = await authorizer.getProfile({
181239
Authorization: `Bearer ${loginRes?.data?.access_token}`,
182240
});
183241
expect(resp?.data).toBeUndefined();
184-
expect(resp?.errors).toHaveLength(1);
242+
expect(resp?.errors).toBeDefined();
243+
expect(resp?.errors.length).toBeGreaterThan(0);
185244
});
186245

187246
describe('magic link login', () => {
@@ -195,22 +254,28 @@ describe('Integration Tests - authorizer-js', () => {
195254
it('should verify email', async () => {
196255
const verificationRequestsRes = await authorizer.graphqlQuery({
197256
query: verificationRequests,
257+
variables: {},
198258
headers: {
199259
'x-authorizer-admin-secret': authorizerConfig.adminSecret,
200260
},
201261
});
202262
const requests =
203263
verificationRequestsRes?.data?._verification_requests
204264
.verification_requests;
265+
expect(verificationRequestsRes?.data).toBeDefined();
266+
expect(verificationRequestsRes?.errors).toHaveLength(0);
205267
const item = requests.find(
206268
(i: { email: string }) => i.email === testConfig.maginLinkLoginEmail,
207269
);
208270
expect(item).not.toBeNull();
271+
expect(item?.token).toBeDefined();
209272
const verifyEmailRes = await authorizer.verifyEmail({
210273
token: item.token,
211274
});
212275
expect(verifyEmailRes?.data).toBeDefined();
213276
expect(verifyEmailRes?.errors).toHaveLength(0);
277+
expect(verifyEmailRes?.data?.user).toBeDefined();
278+
expect(verifyEmailRes?.data?.user?.signup_methods).toBeDefined();
214279
expect(verifyEmailRes?.data?.user?.signup_methods).toContain(
215280
'magic_link_login',
216281
);

package.json

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@authorizerdev/authorizer-js",
3-
"version": "2.0.3",
3+
"version": "3.0.0-rc.1",
44
"packageManager": "pnpm@7.28.0",
55
"author": "Lakhan Samani",
66
"license": "MIT",
@@ -30,14 +30,14 @@
3030
"node": ">=16"
3131
},
3232
"scripts": {
33-
"start": "rollup -w --config rollup.test.config.js",
34-
"ts-types": "tsc --emitDeclarationOnly --outDir lib",
33+
"start": "tsup --watch",
3534
"build": "tsup",
3635
"test": "npm run build && jest --testTimeout=500000 --runInBand",
3736
"prepare": "husky install",
3837
"prepublishOnly": "npm run build",
3938
"release": "pnpm build && bumpp --commit --push --tag && pnpm publish",
4039
"release-beta": "pnpm build && bumpp --commit --push --tag && pnpm publish --tag beta",
40+
"release-rc": "pnpm build && pnpm publish --tag rc",
4141
"lint": "eslint --ignore-pattern 'tsup.config.ts' --ext .ts,.tsx,.js,.jsx,.json .",
4242
"lint:fix": "eslint --ignore-pattern 'tsup.config.ts' --ext .ts,.tsx,.js,.jsx,.json . --fix"
4343
},
@@ -54,9 +54,6 @@
5454
},
5555
"devDependencies": {
5656
"@antfu/eslint-config": "^2.1.0",
57-
"@rollup/plugin-node-resolve": "^15.2.3",
58-
"@rollup/plugin-terser": "^0.4.4",
59-
"@rollup/plugin-typescript": "^11.1.5",
6057
"@swc/core": "^1.3.99",
6158
"@types/jest": "^29.5.12",
6259
"@types/node": "^20.9.4",
@@ -67,9 +64,6 @@
6764
"husky": "^8.0.0",
6865
"jest": "^29.7.0",
6966
"lint-staged": "^15.2.0",
70-
"rollup": "^2.79.1",
71-
"rollup-plugin-filesize": "^10.0.0",
72-
"rollup-plugin-serve": "^2.0.2",
7367
"testcontainers": "^10.3.2",
7468
"ts-jest": "^29.1.1",
7569
"tslib": "^2.6.2",

0 commit comments

Comments
 (0)