Skip to content

Commit 1ba33c6

Browse files
authored
Merge pull request #126 from ThisIsMissEm/refactor/oauth-logic
2 parents 18fa897 + 6f81fcc commit 1ba33c6

30 files changed

Lines changed: 697 additions & 187 deletions

.env.test

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/hollo_test
22
SECRET_KEY="test_determinist_key_DO_NOT_USE_IN_PRODUCTION"
33

4-
LOG_LEVEL=debug
5-
LOG_QUERY=true
4+
# LOG_LEVEL=debug
5+
# LOG_QUERY=true
66

77
# Setting ALLOW_PRIVATE_ADDRESS to true disables SSRF (Server-Side Request Forgery) protection
88
# Set to true to test in local network

bin/routes.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { showRoutes } from "hono/dev";
2+
import app from "../src/index";
3+
4+
showRoutes(app, {
5+
colorize: true,
6+
});

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
"scripts": {
88
"prod": "pnpm run migrate && tsx --env-file-if-exists=.env --dns-result-order=ipv6first bin/server.ts",
99
"dev": "pnpm run migrate && tsx watch --env-file-if-exists=.env --dns-result-order=ipv6first bin/server.ts",
10+
"list:routes": "tsx --env-file-if-exists=.env bin/routes.ts",
1011
"test": "pnpm run migrate:test && tsx --env-file-if-exists=.env.test --test",
1112
"test:ci": "tsx --test --test-reporter=@reporters/github --test-reporter-destination=stdout --test-reporter=spec --test-reporter-destination=stdout",
1213
"check": "tsc && biome check .",

src/api/v1/accounts.test.ts

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
import { afterEach, beforeEach, describe, it } from "node:test";
2+
import type { TestContext } from "node:test";
3+
4+
import { cleanDatabase } from "../../../tests/helpers";
5+
import {
6+
createAccount,
7+
createOAuthApplication,
8+
getAccessToken,
9+
} from "../../../tests/helpers/oauth";
10+
11+
import app from "../../index";
12+
13+
describe("/api/v1/accounts/", () => {
14+
let client: Awaited<ReturnType<typeof createOAuthApplication>>;
15+
let account: Awaited<ReturnType<typeof createAccount>>;
16+
17+
beforeEach(async () => {
18+
account = await createAccount();
19+
client = await createOAuthApplication({
20+
scopes: ["read:accounts", "write"],
21+
});
22+
});
23+
24+
afterEach(async () => {
25+
await cleanDatabase();
26+
});
27+
28+
describe("verify_credentials", () => {
29+
it("Successfully returns the current accounts profile with a valid access token", async (t: TestContext) => {
30+
t.plan(7);
31+
32+
const accessToken = await getAccessToken(client, account, [
33+
"read:accounts",
34+
]);
35+
36+
const response = await app.request(
37+
"/api/v1/accounts/verify_credentials",
38+
{
39+
method: "GET",
40+
headers: {
41+
Authorization: accessToken.authorizationHeader,
42+
},
43+
},
44+
);
45+
46+
t.assert.equal(response.status, 200);
47+
t.assert.equal(response.headers.get("content-type"), "application/json");
48+
t.assert.equal(response.headers.get("access-control-allow-origin"), "*");
49+
50+
const credentialAccount = await response.json();
51+
52+
t.assert.equal(typeof credentialAccount, "object");
53+
t.assert.equal(credentialAccount.id, account.id);
54+
t.assert.equal(credentialAccount.username, "hollo");
55+
t.assert.equal(credentialAccount.acct, "hollo@hollo.test");
56+
});
57+
58+
it("does not return the account when an invalid scope is used", async (t: TestContext) => {
59+
t.plan(4);
60+
61+
const accessToken = await getAccessToken(client, account, ["write"]);
62+
63+
const response = await app.request(
64+
"/api/v1/accounts/verify_credentials",
65+
{
66+
method: "GET",
67+
headers: {
68+
Authorization: accessToken.authorizationHeader,
69+
},
70+
},
71+
);
72+
73+
t.assert.equal(response.status, 403);
74+
t.assert.equal(response.headers.get("content-type"), "application/json");
75+
t.assert.equal(response.headers.get("access-control-allow-origin"), "*");
76+
77+
const error = await response.json();
78+
79+
t.assert.deepStrictEqual(error, {
80+
error: "insufficient_scope",
81+
});
82+
});
83+
84+
it("does not return the account when no access token is used", async (t: TestContext) => {
85+
t.plan(4);
86+
87+
const response = await app.request(
88+
"/api/v1/accounts/verify_credentials",
89+
{
90+
method: "GET",
91+
},
92+
);
93+
94+
t.assert.equal(response.status, 401);
95+
t.assert.equal(response.headers.get("content-type"), "application/json");
96+
t.assert.equal(response.headers.get("access-control-allow-origin"), "*");
97+
98+
const error = await response.json();
99+
100+
t.assert.deepStrictEqual(error, {
101+
error: "unauthorized",
102+
});
103+
});
104+
});
105+
});

src/api/v1/accounts.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,11 @@ import {
3636
persistAccountPosts,
3737
unfollowAccount,
3838
} from "../../federation/account";
39-
import { type Variables, scopeRequired, tokenRequired } from "../../oauth";
39+
import {
40+
type Variables,
41+
scopeRequired,
42+
tokenRequired,
43+
} from "../../oauth/middleware";
4044
import {
4145
type Account,
4246
type AccountOwner,

src/api/v1/apps.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { getLogger } from "@logtape/logtape";
33
import { Hono } from "hono";
44
import { z } from "zod";
55
import { db } from "../../db";
6-
import { type Variables, tokenRequired } from "../../oauth";
6+
import { type Variables, tokenRequired } from "../../oauth/middleware";
77
import {
88
type NewApplication,
99
type Scope,

src/api/v1/featured_tags.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,11 @@ import { Hono } from "hono";
1313
import { z } from "zod";
1414
import db from "../../db";
1515
import { serializeFeaturedTag } from "../../entities/tag";
16-
import { type Variables, scopeRequired, tokenRequired } from "../../oauth";
16+
import {
17+
type Variables,
18+
scopeRequired,
19+
tokenRequired,
20+
} from "../../oauth/middleware";
1721
import type * as schema from "../../schema";
1822
import { featuredTags, posts } from "../../schema";
1923
import { type Uuid, isUuid, uuidv7 } from "../../uuid";

src/api/v1/follow_requests.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,11 @@ import {
99
} from "../../entities/account";
1010
import { federation } from "../../federation";
1111
import { updateAccountStats } from "../../federation/account";
12-
import { type Variables, scopeRequired, tokenRequired } from "../../oauth";
12+
import {
13+
type Variables,
14+
scopeRequired,
15+
tokenRequired,
16+
} from "../../oauth/middleware";
1317
import { accounts, blocks, follows, mutes } from "../../schema";
1418
import { isUuid } from "../../uuid";
1519

src/api/v1/index.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@ import { db } from "../../db";
77
import { serializeAccount } from "../../entities/account";
88
import { getPostRelations, serializePost } from "../../entities/status";
99
import { serializeTag } from "../../entities/tag";
10-
import { type Variables, scopeRequired, tokenRequired } from "../../oauth";
10+
import {
11+
type Variables,
12+
scopeRequired,
13+
tokenRequired,
14+
} from "../../oauth/middleware";
1115
import {
1216
accounts as accountsTable,
1317
blocks,

src/api/v1/lists.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,11 @@ import { z } from "zod";
55
import { db } from "../../db";
66
import { serializeAccount } from "../../entities/account";
77
import { serializeList } from "../../entities/list";
8-
import { type Variables, scopeRequired, tokenRequired } from "../../oauth";
8+
import {
9+
type Variables,
10+
scopeRequired,
11+
tokenRequired,
12+
} from "../../oauth/middleware";
913
import { listMembers, lists } from "../../schema";
1014
import { isUuid, uuid, uuidv7 } from "../../uuid";
1115

0 commit comments

Comments
 (0)