Merge pull request #374 from cloudflare/fix-aliases-auth-routing

improve/fix frontend authenticated vs admin settings
pull/370/head
Dario Piotrowicz 2023-03-06 19:45:09 +00:00 zatwierdzone przez GitHub
commit 7e1592203b
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
25 zmienionych plików z 95 dodań i 72 usunięć

Wyświetl plik

@ -0,0 +1,15 @@
import { type Database } from 'wildebeest/backend/src/database'
import { Person, personFromRow } from 'wildebeest/backend/src/activitypub/actors'
export async function getAdmins(db: Database): Promise<Person[]> {
let rows: unknown[] = []
try {
const stmt = db.prepare('SELECT * FROM actors WHERE is_admin=1')
const result = await stmt.all<unknown>()
rows = result.success ? (result.results as unknown[]) : []
} catch {
/* empty */
}
return rows.map(personFromRow)
}

Wyświetl plik

@ -1,8 +1,8 @@
import { emailSymbol } from 'wildebeest/backend/src/activitypub/actors'
import { Database } from 'wildebeest/backend/src/database'
import { getAdmins } from 'wildebeest/functions/api/wb/settings/server/admins'
import { checkAuth } from './checkAuth'
import { getJwtEmail } from './getJwtEmail'
import { getJwtEmail } from 'wildebeest/backend/src/utils/auth/getJwtEmail'
import { getAdmins } from './getAdmins'
import { isUserAuthenticated } from './isUserAuthenticated'
export async function isUserAdmin(
request: Request,
@ -14,7 +14,7 @@ export async function isUserAdmin(
let email: string
try {
const authenticated = await checkAuth(request, jwt, accessAuthDomain, accessAud)
const authenticated = await isUserAuthenticated(request, jwt, accessAuthDomain, accessAud)
if (!authenticated) {
return false
}

Wyświetl plik

@ -1,6 +1,6 @@
import * as access from 'wildebeest/backend/src/access'
export const checkAuth = async (request: Request, jwt: string, accessAuthDomain: string, accessAud: string) => {
export async function isUserAuthenticated(request: Request, jwt: string, accessAuthDomain: string, accessAud: string) {
if (!jwt) return false
try {

Wyświetl plik

@ -8,7 +8,7 @@ import { getPersonByEmail } from 'wildebeest/backend/src/activitypub/actors'
import { getErrorHtml } from '~/utils/getErrorHtml/getErrorHtml'
import { buildRedirect } from 'wildebeest/functions/oauth/authorize'
import { getDatabase } from 'wildebeest/backend/src/database'
import { getJwtEmail } from '~/utils/getJwtEmail'
import { getJwtEmail } from 'wildebeest/backend/src/utils/auth/getJwtEmail'
export const clientLoader = loader$<Promise<Client>>(async ({ platform, query, html }) => {
const client_id = query.get('client_id') || ''

Wyświetl plik

@ -0,0 +1,11 @@
import { component$, Slot } from '@builder.io/qwik'
export { adminLoader } from '~/utils/adminLoader'
export default component$(() => {
return (
<>
<Slot />
</>
)
})

Wyświetl plik

@ -17,7 +17,9 @@ export const action = action$(async (data, { request, platform }) => {
try {
const response = await handleRequestPost(
await getDatabase(platform),
new Request(request, { body: JSON.stringify(data) })
new Request(request, { body: JSON.stringify(data) }),
platform.ACCESS_AUTH_DOMAIN,
platform.ACCESS_AUD
)
success = response.ok
} catch (e: unknown) {

Wyświetl plik

@ -18,7 +18,9 @@ export const action = action$(async (data, { request, platform }) => {
try {
const response = await handleRequestPost(
await getDatabase(platform),
new Request(request, { body: JSON.stringify(data) })
new Request(request, { body: JSON.stringify(data) }),
platform.ACCESS_AUTH_DOMAIN,
platform.ACCESS_AUD
)
success = response.ok
} catch (e: unknown) {

Wyświetl plik

@ -1,15 +1,4 @@
import { component$, useStore, useSignal, $ } from '@builder.io/qwik'
import { loader$ } from '@builder.io/qwik-city'
import { checkAuth } from '~/utils/checkAuth'
export const loader = loader$(async ({ cookie, request, platform, redirect }) => {
const jwt = cookie.get('CF_Authorization')?.value ?? ''
const isAuthorized = await checkAuth(request, jwt, platform.ACCESS_AUTH_DOMAIN, platform.ACCESS_AUD)
if (!isAuthorized) {
redirect(303, '/explore')
}
})
export default component$(() => {
const ref = useSignal<Element>()

Wyświetl plik

@ -0,0 +1,11 @@
import { component$, Slot } from '@builder.io/qwik'
export { authLoader } from '~/utils/authLoader'
export default component$(() => {
return (
<>
<Slot />
</>
)
})

Wyświetl plik

@ -1,21 +1,5 @@
import { component$, Slot } from '@builder.io/qwik'
import { loader$ } from '@builder.io/qwik-city'
import { parse } from 'cookie'
import { getDatabase } from 'wildebeest/backend/src/database'
import { WildebeestLogo } from '~/components/MastodonLogo'
import { getErrorHtml } from '~/utils/getErrorHtml/getErrorHtml'
import { isUserAdmin } from '~/utils/isUserAdmin'
export const authLoader = loader$(async ({ request, platform, html }) => {
const database = await getDatabase(platform)
const cookie = parse(request.headers.get('Cookie') || '')
const jwtCookie = cookie.CF_Authorization ?? ''
const isAdmin = await isUserAdmin(request, jwtCookie, platform.ACCESS_AUTH_DOMAIN, platform.ACCESS_AUD, database)
if (!isAdmin) {
return html(401, getErrorHtml("You're unauthorized to view this page"))
}
})
export default component$(() => {
return (

Wyświetl plik

@ -6,14 +6,14 @@ import { handleRequestGet as settingsHandleRequestGet } from 'wildebeest/functio
import { handleRequestGet as rulesHandleRequestGet } from 'wildebeest/functions/api/v1/instance/rules'
import { Accordion } from '~/components/Accordion/Accordion'
import { HtmlContent } from '~/components/HtmlContent/HtmlContent'
import { ServerSettingsData } from '~/routes/(admin)/settings/server-settings/layout'
import { ServerSettingsData } from '~/routes/(admin)/settings/(admin)/server-settings/layout'
import { Account } from '~/types'
import { getDocumentHead } from '~/utils/getDocumentHead'
import { instanceLoader } from '../layout'
import { getAdmins } from 'wildebeest/functions/api/wb/settings/server/admins'
import { emailSymbol } from 'wildebeest/backend/src/activitypub/actors'
import { loadLocalMastodonAccount } from 'wildebeest/backend/src/mastodon/account'
import { AccountCard } from '~/components/AccountCard/AccountCard'
import { getAdmins } from 'wildebeest/backend/src/utils/auth/getAdmins'
type AboutInfo = {
image: string

Wyświetl plik

@ -1,15 +1,15 @@
import { component$, Slot } from '@builder.io/qwik'
import { loader$ } from '@builder.io/qwik-city'
import { checkAuth } from '~/utils/checkAuth'
import { isUserAuthenticated } from 'wildebeest/backend/src/utils/auth/isUserAuthenticated'
type AuthLoaderData = {
loginUrl: string
loginUrl: URL
isAuthorized: boolean
}
export const authLoader = loader$<Promise<AuthLoaderData>>(async ({ platform, request, cookie }) => {
const jwt = cookie.get('CF_Authorization')?.value ?? ''
const isAuthorized = await checkAuth(request, jwt, platform.ACCESS_AUTH_DOMAIN, platform.ACCESS_AUD)
const isAuthorized = await isUserAuthenticated(request, jwt, platform.ACCESS_AUTH_DOMAIN, platform.ACCESS_AUD)
// FIXME(sven): remove hardcoded value
const UI_CLIENT_ID = '924801be-d211-495d-8cac-e73503413af8'
const params = new URLSearchParams({

Wyświetl plik

@ -0,0 +1,16 @@
import { loader$ } from '@builder.io/qwik-city'
import { parse } from 'cookie'
import { getDatabase } from 'wildebeest/backend/src/database'
import { isUserAdmin } from 'wildebeest/backend/src/utils/auth/isUserAdmin'
import { getErrorHtml } from './getErrorHtml/getErrorHtml'
export const adminLoader = loader$(async ({ request, platform, html }) => {
const database = await getDatabase(platform)
const cookie = parse(request.headers.get('Cookie') || '')
const jwtCookie = cookie.CF_Authorization ?? ''
const isAdmin = await isUserAdmin(request, jwtCookie, platform.ACCESS_AUTH_DOMAIN, platform.ACCESS_AUD, database)
if (!isAdmin) {
return html(401, getErrorHtml('You need to be an admin to view this page'))
}
})

Wyświetl plik

@ -0,0 +1,19 @@
import { loader$ } from '@builder.io/qwik-city'
import { parse } from 'cookie'
import { isUserAuthenticated } from 'wildebeest/backend/src/utils/auth/isUserAuthenticated'
import { getErrorHtml } from './getErrorHtml/getErrorHtml'
export const authLoader = loader$(async ({ request, platform, html }) => {
const cookie = parse(request.headers.get('Cookie') || '')
const jwtCookie = cookie.CF_Authorization ?? ''
const isAuthenticated = await isUserAuthenticated(
request,
jwtCookie,
platform.ACCESS_AUTH_DOMAIN,
platform.ACCESS_AUD
)
if (!isAuthenticated) {
return html(401, getErrorHtml("You're not authorized to view this page"))
}
})

Wyświetl plik

@ -1,26 +0,0 @@
import type { Env } from 'wildebeest/backend/src/types/env'
import type { ContextData } from 'wildebeest/backend/src/types/context'
import { type Database, getDatabase } from 'wildebeest/backend/src/database'
import { Person, personFromRow } from 'wildebeest/backend/src/activitypub/actors'
export const onRequestGet: PagesFunction<Env, any, ContextData> = async ({ env }) => {
return handleRequestGet(await getDatabase(env))
}
export async function handleRequestGet(db: Database) {
const admins = await getAdmins(db)
return new Response(JSON.stringify(admins), { status: 200 })
}
export async function getAdmins(db: Database): Promise<Person[]> {
let rows: unknown[] = []
try {
const stmt = db.prepare('SELECT * FROM actors WHERE is_admin=1')
const result = await stmt.all<unknown>()
rows = result.success ? (result.results as unknown[]) : []
} catch {
/* empty */
}
return rows.map(personFromRow)
}

Wyświetl plik

@ -2,8 +2,8 @@ import type { Env } from 'wildebeest/backend/src/types/env'
import type { ContextData } from 'wildebeest/backend/src/types/context'
import * as errors from 'wildebeest/backend/src/errors'
import { type Database, getDatabase } from 'wildebeest/backend/src/database'
import { isUserAdmin } from 'wildebeest/frontend/src/utils/isUserAdmin'
import { parse } from 'cookie'
import { isUserAdmin } from 'wildebeest/backend/src/utils/auth/isUserAdmin'
export const onRequestGet: PagesFunction<Env, any, ContextData> = async ({ env, request }) => {
return handleRequestPost(await getDatabase(env), request, env.ACCESS_AUTH_DOMAIN, env.ACCESS_AUD)

Wyświetl plik

@ -3,8 +3,8 @@ import type { ContextData } from 'wildebeest/backend/src/types/context'
import * as errors from 'wildebeest/backend/src/errors'
import { type Database, getDatabase } from 'wildebeest/backend/src/database'
import { parse } from 'cookie'
import { isUserAdmin } from 'wildebeest/frontend/src/utils/isUserAdmin'
import { ServerSettingsData } from 'wildebeest/frontend/src/routes/(admin)/settings/server-settings/layout'
import { ServerSettingsData } from 'wildebeest/frontend/src/routes/(admin)/settings/(admin)/server-settings/layout'
import { isUserAdmin } from 'wildebeest/backend/src/utils/auth/isUserAdmin'
export const onRequestGet: PagesFunction<Env, any, ContextData> = async ({ env, request }) => {
return handleRequestPost(await getDatabase(env), request, env.ACCESS_AUTH_DOMAIN, env.ACCESS_AUD)

Wyświetl plik

@ -7,7 +7,7 @@ import { parse } from 'cookie'
import * as errors from 'wildebeest/backend/src/errors'
import * as access from 'wildebeest/backend/src/access'
import { type Database, getDatabase } from 'wildebeest/backend/src/database'
import { getJwtEmail } from 'wildebeest/frontend/src/utils/getJwtEmail'
import { getJwtEmail } from 'wildebeest/backend/src/utils/auth/getJwtEmail'
export const onRequestPost: PagesFunction<Env, any, ContextData> = async ({ request, env }) => {
return handlePostRequest(request, await getDatabase(env), env.userKEK, env.ACCESS_AUTH_DOMAIN, env.ACCESS_AUD)

Wyświetl plik

@ -8,7 +8,7 @@ import { getClientById } from 'wildebeest/backend/src/mastodon/client'
import * as access from 'wildebeest/backend/src/access'
import { getPersonByEmail } from 'wildebeest/backend/src/activitypub/actors'
import { type Database, getDatabase } from 'wildebeest/backend/src/database'
import { checkAuth } from 'wildebeest/frontend/src/utils/checkAuth'
import { isUserAuthenticated } from 'wildebeest/backend/src/utils/auth/isUserAuthenticated'
// Extract the JWT token sent by Access (running before us).
const extractJWTFromRequest = (request: Request) => request.headers.get('Cf-Access-Jwt-Assertion') || ''
@ -80,7 +80,7 @@ export async function handleRequestPost(
}
const jwt = extractJWTFromRequest(request)
const isAuthenticated = await checkAuth(request, jwt, accessDomain, accessAud)
const isAuthenticated = await isUserAuthenticated(request, jwt, accessDomain, accessAud)
if (!isAuthenticated) {
return new Response('', { status: 401 })