kopia lustrzana https://github.com/cloudflare/wildebeest
Merge pull request #11 from cloudflare/be-lint-no-unsafe-returns
enable be no-unsafe-return eslint rule also apply some related refactoring to make the code more DRYpull/14/head
commit
371fa7e02f
|
|
@ -13,6 +13,7 @@ module.exports = {
|
||||||
root: true,
|
root: true,
|
||||||
rules: {
|
rules: {
|
||||||
'no-var': 'error',
|
'no-var': 'error',
|
||||||
|
'@typescript-eslint/no-unsafe-return': 'error',
|
||||||
/*
|
/*
|
||||||
Note: the following rules have been set to off so that linting
|
Note: the following rules have been set to off so that linting
|
||||||
can pass with the current code, but we need to gradually
|
can pass with the current code, but we need to gradually
|
||||||
|
|
@ -29,7 +30,6 @@ module.exports = {
|
||||||
'@typescript-eslint/require-await': 'off',
|
'@typescript-eslint/require-await': 'off',
|
||||||
'@typescript-eslint/restrict-template-expressions': 'off',
|
'@typescript-eslint/restrict-template-expressions': 'off',
|
||||||
'@typescript-eslint/no-misused-promises': 'off',
|
'@typescript-eslint/no-misused-promises': 'off',
|
||||||
'@typescript-eslint/no-unsafe-return': 'off',
|
|
||||||
'@typescript-eslint/no-unnecessary-type-assertion': 'off',
|
'@typescript-eslint/no-unnecessary-type-assertion': 'off',
|
||||||
'no-console': 'off',
|
'no-console': 'off',
|
||||||
'@typescript-eslint/no-explicit-any': 'off',
|
'@typescript-eslint/no-explicit-any': 'off',
|
||||||
|
|
|
||||||
|
|
@ -78,7 +78,7 @@ export function getPayload(jwt: string): JWTPayload {
|
||||||
}
|
}
|
||||||
const [, payload] = parts
|
const [, payload] = parts
|
||||||
|
|
||||||
const payloadObj = JSON.parse(textDecoder.decode(base64URLDecode(payload)))
|
const payloadObj: JWTPayload = JSON.parse(textDecoder.decode(base64URLDecode(payload)))
|
||||||
return payloadObj
|
return payloadObj
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@ export async function handle(
|
||||||
}
|
}
|
||||||
if (activity.object instanceof URL) {
|
if (activity.object instanceof URL) {
|
||||||
// This is used for testing only.
|
// This is used for testing only.
|
||||||
return activity.object
|
return activity.object as URL
|
||||||
}
|
}
|
||||||
if (url === null) {
|
if (url === null) {
|
||||||
throw new Error('unknown value: ' + JSON.stringify(activity.object))
|
throw new Error('unknown value: ' + JSON.stringify(activity.object))
|
||||||
|
|
@ -85,7 +85,7 @@ export async function handle(
|
||||||
}
|
}
|
||||||
if (activity.actor instanceof URL) {
|
if (activity.actor instanceof URL) {
|
||||||
// This is used for testing only.
|
// This is used for testing only.
|
||||||
return activity.actor
|
return activity.actor as URL
|
||||||
}
|
}
|
||||||
if (url === null) {
|
if (url === null) {
|
||||||
throw new Error('unknown value: ' + JSON.stringify(activity.actor))
|
throw new Error('unknown value: ' + JSON.stringify(activity.actor))
|
||||||
|
|
|
||||||
|
|
@ -233,5 +233,5 @@ export function personFromRow(row: any): Person {
|
||||||
// It's very possible that properties override the values set above.
|
// It's very possible that properties override the values set above.
|
||||||
// Almost guaranteed for remote user.
|
// Almost guaranteed for remote user.
|
||||||
...JSON.parse(row.properties),
|
...JSON.parse(row.properties),
|
||||||
}
|
} as Person
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,7 @@ export async function createObject(
|
||||||
mastodonId: row.mastodon_id,
|
mastodonId: row.mastodon_id,
|
||||||
published: new Date(row.cdate).toISOString(),
|
published: new Date(row.cdate).toISOString(),
|
||||||
originalActorId: row.original_actor_id,
|
originalActorId: row.original_actor_id,
|
||||||
}
|
} as Object
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function get<T>(url: URL): Promise<T> {
|
export async function get<T>(url: URL): Promise<T> {
|
||||||
|
|
@ -114,7 +114,7 @@ export async function cacheObject(
|
||||||
mastodonId: row.mastodon_id,
|
mastodonId: row.mastodon_id,
|
||||||
originalActorId: row.original_actor_id,
|
originalActorId: row.original_actor_id,
|
||||||
originalObjectId: row.original_object_id,
|
originalObjectId: row.original_object_id,
|
||||||
}
|
} as Object
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -168,5 +168,5 @@ WHERE objects.${key}=?
|
||||||
mastodonId: result.mastodon_id,
|
mastodonId: result.mastodon_id,
|
||||||
originalActorId: result.original_actor_id,
|
originalActorId: result.original_actor_id,
|
||||||
originalObjectId: result.original_object_id,
|
originalObjectId: result.original_object_id,
|
||||||
}
|
} as Object
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@ export async function generateVAPIDKeys(db: D1Database) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function get(db: D1Database, name: string): Promise<string> {
|
export async function get(db: D1Database, name: string): Promise<string> {
|
||||||
const row: any = await db.prepare('SELECT value FROM instance_config WHERE key = ?').bind(name).first()
|
const row: { value: string } = await db.prepare('SELECT value FROM instance_config WHERE key = ?').bind(name).first()
|
||||||
if (!row) {
|
if (!row) {
|
||||||
throw new Error(`configuration not found: ${name}`)
|
throw new Error(`configuration not found: ${name}`)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import type { Actor } from 'wildebeest/backend/src/activitypub/actors'
|
import type { Actor } from 'wildebeest/backend/src/activitypub/actors'
|
||||||
|
import { getResultsField } from './utils'
|
||||||
|
|
||||||
const STATE_PENDING = 'pending'
|
const STATE_PENDING = 'pending'
|
||||||
const STATE_ACCEPTED = 'accepted'
|
const STATE_ACCEPTED = 'accepted'
|
||||||
|
|
@ -8,9 +9,9 @@ export async function addFollowing(db: D1Database, actor: Actor, target: Actor,
|
||||||
const id = crypto.randomUUID()
|
const id = crypto.randomUUID()
|
||||||
|
|
||||||
const query = `
|
const query = `
|
||||||
INSERT INTO actor_following (id, actor_id, target_actor_id, state, target_actor_acct)
|
INSERT INTO actor_following (id, actor_id, target_actor_id, state, target_actor_acct)
|
||||||
VALUES (?, ?, ?, ?, ?)
|
VALUES (?, ?, ?, ?, ?)
|
||||||
`
|
`
|
||||||
|
|
||||||
const out = await db
|
const out = await db
|
||||||
.prepare(query)
|
.prepare(query)
|
||||||
|
|
@ -27,8 +28,8 @@ export async function acceptFollowing(db: D1Database, actor: Actor, target: Acto
|
||||||
const id = crypto.randomUUID()
|
const id = crypto.randomUUID()
|
||||||
|
|
||||||
const query = `
|
const query = `
|
||||||
UPDATE actor_following SET state=? WHERE actor_id=? AND target_actor_id=? AND state=?
|
UPDATE actor_following SET state=? WHERE actor_id=? AND target_actor_id=? AND state=?
|
||||||
`
|
`
|
||||||
|
|
||||||
const out = await db
|
const out = await db
|
||||||
.prepare(query)
|
.prepare(query)
|
||||||
|
|
@ -41,8 +42,8 @@ export async function acceptFollowing(db: D1Database, actor: Actor, target: Acto
|
||||||
|
|
||||||
export async function removeFollowing(db: D1Database, actor: Actor, target: Actor) {
|
export async function removeFollowing(db: D1Database, actor: Actor, target: Actor) {
|
||||||
const query = `
|
const query = `
|
||||||
DELETE FROM actor_following WHERE actor_id=? AND target_actor_id=?
|
DELETE FROM actor_following WHERE actor_id=? AND target_actor_id=?
|
||||||
`
|
`
|
||||||
|
|
||||||
const out = await db.prepare(query).bind(actor.id.toString(), target.id.toString()).run()
|
const out = await db.prepare(query).bind(actor.id.toString(), target.id.toString()).run()
|
||||||
if (!out.success) {
|
if (!out.success) {
|
||||||
|
|
@ -50,70 +51,41 @@ export async function removeFollowing(db: D1Database, actor: Actor, target: Acto
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getFollowingAcct(db: D1Database, actor: Actor): Promise<Array<string>> {
|
export function getFollowingAcct(db: D1Database, actor: Actor): Promise<Array<string>> {
|
||||||
const query = `
|
const query = `
|
||||||
SELECT target_actor_acct FROM actor_following WHERE actor_id=? AND state=?
|
SELECT target_actor_acct FROM actor_following WHERE actor_id=? AND state=?
|
||||||
`
|
`
|
||||||
|
const statement = db.prepare(query).bind(actor.id.toString(), STATE_ACCEPTED)
|
||||||
|
|
||||||
const out: any = await db.prepare(query).bind(actor.id.toString(), STATE_ACCEPTED).all()
|
return getResultsField(statement, 'target_actor_acct')
|
||||||
if (!out.success) {
|
|
||||||
throw new Error('SQL error: ' + out.error)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (out.results !== null) {
|
|
||||||
return out.results.map((x: any) => x.target_actor_acct)
|
|
||||||
} else {
|
|
||||||
return []
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getFollowingRequestedAcct(db: D1Database, actor: Actor): Promise<Array<string>> {
|
export function getFollowingRequestedAcct(db: D1Database, actor: Actor): Promise<Array<string>> {
|
||||||
const query = `
|
const query = `
|
||||||
SELECT target_actor_acct FROM actor_following WHERE actor_id=? AND state=?
|
SELECT target_actor_acct FROM actor_following WHERE actor_id=? AND state=?
|
||||||
`
|
`
|
||||||
|
|
||||||
const out: any = await db.prepare(query).bind(actor.id.toString(), STATE_PENDING).all()
|
const statement = db.prepare(query).bind(actor.id.toString(), STATE_PENDING)
|
||||||
if (!out.success) {
|
|
||||||
throw new Error('SQL error: ' + out.error)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (out.results !== null) {
|
return getResultsField(statement, 'target_actor_acct')
|
||||||
return out.results.map((x: any) => x.target_actor_acct)
|
|
||||||
} else {
|
|
||||||
return []
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getFollowingId(db: D1Database, actor: Actor): Promise<Array<string>> {
|
export function getFollowingId(db: D1Database, actor: Actor): Promise<Array<string>> {
|
||||||
const query = `
|
const query = `
|
||||||
SELECT target_actor_id FROM actor_following WHERE actor_id=? AND state=?
|
SELECT target_actor_id FROM actor_following WHERE actor_id=? AND state=?
|
||||||
`
|
`
|
||||||
|
|
||||||
const out: any = await db.prepare(query).bind(actor.id.toString(), STATE_ACCEPTED).all()
|
const statement = db.prepare(query).bind(actor.id.toString(), STATE_ACCEPTED)
|
||||||
if (!out.success) {
|
|
||||||
throw new Error('SQL error: ' + out.error)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (out.results !== null) {
|
return getResultsField(statement, 'target_actor_id')
|
||||||
return out.results.map((x: any) => x.target_actor_id)
|
|
||||||
} else {
|
|
||||||
return []
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getFollowers(db: D1Database, actor: Actor): Promise<Array<string>> {
|
export function getFollowers(db: D1Database, actor: Actor): Promise<Array<string>> {
|
||||||
const query = `
|
const query = `
|
||||||
SELECT actor_id FROM actor_following WHERE target_actor_id=? AND state=?
|
SELECT actor_id FROM actor_following WHERE target_actor_id=? AND state=?
|
||||||
`
|
`
|
||||||
|
|
||||||
const out: any = await db.prepare(query).bind(actor.id.toString(), STATE_ACCEPTED).all()
|
const statement = db.prepare(query).bind(actor.id.toString(), STATE_ACCEPTED)
|
||||||
if (!out.success) {
|
|
||||||
throw new Error('SQL error: ' + out.error)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (out.results !== null) {
|
return getResultsField(statement, 'actor_id')
|
||||||
return out.results.map((x: any) => x.actor_id)
|
|
||||||
} else {
|
|
||||||
return []
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,32 +1,27 @@
|
||||||
import type { Object } from 'wildebeest/backend/src/activitypub/objects'
|
import type { Object } from 'wildebeest/backend/src/activitypub/objects'
|
||||||
import type { Actor } from 'wildebeest/backend/src/activitypub/actors'
|
import type { Actor } from 'wildebeest/backend/src/activitypub/actors'
|
||||||
|
import { getResultsField } from './utils'
|
||||||
|
|
||||||
export async function insertLike(db: D1Database, actor: Actor, obj: Object) {
|
export async function insertLike(db: D1Database, actor: Actor, obj: Object) {
|
||||||
const id = crypto.randomUUID()
|
const id = crypto.randomUUID()
|
||||||
|
|
||||||
const query = `
|
const query = `
|
||||||
INSERT INTO actor_favourites (id, actor_id, object_id)
|
INSERT INTO actor_favourites (id, actor_id, object_id)
|
||||||
VALUES (?, ?, ?)
|
VALUES (?, ?, ?)
|
||||||
`
|
`
|
||||||
|
|
||||||
const out = await db.prepare(query).bind(id, actor.id.toString(), obj.id.toString()).run()
|
const out = await db.prepare(query).bind(id, actor.id.toString(), obj.id.toString()).run()
|
||||||
if (!out.success) {
|
if (!out.success) {
|
||||||
throw new Error('SQL error: ' + out.error)
|
throw new Error('SQL error: ' + out.error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getLikes(db: D1Database, obj: Object): Promise<Array<string>> {
|
export function getLikes(db: D1Database, obj: Object): Promise<Array<string>> {
|
||||||
const query = `
|
const query = `
|
||||||
SELECT actor_id FROM actor_favourites WHERE object_id=?
|
SELECT actor_id FROM actor_favourites WHERE object_id=?
|
||||||
`
|
`
|
||||||
|
|
||||||
const out: any = await db.prepare(query).bind(obj.id.toString()).all()
|
const statement = db.prepare(query).bind(obj.id.toString())
|
||||||
if (!out.success) {
|
|
||||||
throw new Error('SQL error: ' + out.error)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (out.results !== null) {
|
return getResultsField(statement, 'actor_id')
|
||||||
return out.results.map((x: any) => x.actor_id)
|
|
||||||
} else {
|
|
||||||
return []
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ export async function createNotification(
|
||||||
VALUES (?, ?, ?, ?)
|
VALUES (?, ?, ?, ?)
|
||||||
RETURNING id
|
RETURNING id
|
||||||
`
|
`
|
||||||
const row: any = await db
|
const row: { id: string } = await db
|
||||||
.prepare(query)
|
.prepare(query)
|
||||||
.bind(type, actor.id.toString(), fromActor.id.toString(), obj.id.toString())
|
.bind(type, actor.id.toString(), fromActor.id.toString(), obj.id.toString())
|
||||||
.first()
|
.first()
|
||||||
|
|
@ -41,7 +41,7 @@ export async function insertFollowNotification(db: D1Database, actor: Actor, fro
|
||||||
VALUES (?, ?, ?)
|
VALUES (?, ?, ?)
|
||||||
RETURNING id
|
RETURNING id
|
||||||
`
|
`
|
||||||
const row: any = await db.prepare(query).bind(type, actor.id.toString(), fromActor.id.toString()).first()
|
const row: { id: string } = await db.prepare(query).bind(type, actor.id.toString(), fromActor.id.toString()).first()
|
||||||
return row.id
|
return row.id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,33 +2,28 @@
|
||||||
|
|
||||||
import type { Object } from 'wildebeest/backend/src/activitypub/objects'
|
import type { Object } from 'wildebeest/backend/src/activitypub/objects'
|
||||||
import type { Actor } from 'wildebeest/backend/src/activitypub/actors'
|
import type { Actor } from 'wildebeest/backend/src/activitypub/actors'
|
||||||
|
import { getResultsField } from './utils'
|
||||||
|
|
||||||
export async function insertReblog(db: D1Database, actor: Actor, obj: Object) {
|
export async function insertReblog(db: D1Database, actor: Actor, obj: Object) {
|
||||||
const id = crypto.randomUUID()
|
const id = crypto.randomUUID()
|
||||||
|
|
||||||
const query = `
|
const query = `
|
||||||
INSERT INTO actor_reblogs (id, actor_id, object_id)
|
INSERT INTO actor_reblogs (id, actor_id, object_id)
|
||||||
VALUES (?, ?, ?)
|
VALUES (?, ?, ?)
|
||||||
`
|
`
|
||||||
|
|
||||||
const out = await db.prepare(query).bind(id, actor.id.toString(), obj.id.toString()).run()
|
const out = await db.prepare(query).bind(id, actor.id.toString(), obj.id.toString()).run()
|
||||||
if (!out.success) {
|
if (!out.success) {
|
||||||
throw new Error('SQL error: ' + out.error)
|
throw new Error('SQL error: ' + out.error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getReblogs(db: D1Database, obj: Object): Promise<Array<string>> {
|
export function getReblogs(db: D1Database, obj: Object): Promise<Array<string>> {
|
||||||
const query = `
|
const query = `
|
||||||
SELECT actor_id FROM actor_reblogs WHERE object_id=?
|
SELECT actor_id FROM actor_reblogs WHERE object_id=?
|
||||||
`
|
`
|
||||||
|
|
||||||
const out: any = await db.prepare(query).bind(obj.id.toString()).all()
|
const statement = db.prepare(query).bind(obj.id.toString())
|
||||||
if (!out.success) {
|
|
||||||
throw new Error('SQL error: ' + out.error)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (out.results !== null) {
|
return getResultsField(statement, 'actor_id')
|
||||||
return out.results.map((x: any) => x.actor_id)
|
|
||||||
} else {
|
|
||||||
return []
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -129,7 +129,7 @@ export async function getVAPIDKeys(db: D1Database): Promise<JWK> {
|
||||||
if (!row) {
|
if (!row) {
|
||||||
throw new Error('missing VAPID keys')
|
throw new Error('missing VAPID keys')
|
||||||
}
|
}
|
||||||
const value = JSON.parse(row.value)
|
const value: JWK = JSON.parse(row.value)
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
export async function getResultsField(statement: D1PreparedStatement, fieldName: string): Promise<Array<string>> {
|
||||||
|
const out: D1Result<Record<string, string>> = await statement.all()
|
||||||
|
|
||||||
|
if (!out.success) {
|
||||||
|
throw new Error('SQL error: ' + out.error)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (out.results ?? []).map((x) => x[fieldName])
|
||||||
|
}
|
||||||
|
|
@ -31,7 +31,7 @@ export class InvalidAlgorithmError extends HttpSignatureError {
|
||||||
* @returns {[string, string]}
|
* @returns {[string, string]}
|
||||||
*/
|
*/
|
||||||
export function validateAlgorithm(algorithm: string, publicKeyType?: string): [string, string] {
|
export function validateAlgorithm(algorithm: string, publicKeyType?: string): [string, string] {
|
||||||
var alg = algorithm.toLowerCase().split('-')
|
const alg = algorithm.toLowerCase().split('-')
|
||||||
|
|
||||||
if (alg[0] === 'hs2019') {
|
if (alg[0] === 'hs2019') {
|
||||||
return publicKeyType !== undefined ? validateAlgorithm(publicKeyType + '-sha256') : ['hs2019', 'sha256']
|
return publicKeyType !== undefined ? validateAlgorithm(publicKeyType + '-sha256') : ['hs2019', 'sha256']
|
||||||
|
|
|
||||||
|
|
@ -157,7 +157,8 @@ const DEC = {
|
||||||
'-': '+',
|
'-': '+',
|
||||||
_: '/',
|
_: '/',
|
||||||
'.': '=',
|
'.': '=',
|
||||||
}
|
} as const
|
||||||
|
type KeyOfDEC = keyof typeof DEC
|
||||||
export function urlsafeBase64Decode(v: string) {
|
export function urlsafeBase64Decode(v: string) {
|
||||||
return atob(v.replace(/[-_.]/g, (m: string) => (DEC as any)[m]))
|
return atob(v.replace(/[-_.]/g, (m: string) => DEC[m as KeyOfDEC]))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ const kv_cache: any = {
|
||||||
async put() {},
|
async put() {},
|
||||||
}
|
}
|
||||||
|
|
||||||
const waitUntil = async (p: Promise<any>) => await p
|
const waitUntil = async (p: Promise<void>) => await p
|
||||||
|
|
||||||
describe('ActivityPub', () => {
|
describe('ActivityPub', () => {
|
||||||
test('send Note to non existant user', async () => {
|
test('send Note to non existant user', async () => {
|
||||||
|
|
|
||||||
Ładowanie…
Reference in New Issue