Skip to content

Commit

Permalink
Merge branch 'quest-challenge-rework' of github.com:ducompsoc/durhack…
Browse files Browse the repository at this point in the history
…-megateams into quest-challenge-rework
  • Loading branch information
JacobWrenn committed Oct 18, 2024
2 parents 97c4dd7 + fb095a2 commit 986aadd
Show file tree
Hide file tree
Showing 11 changed files with 66 additions and 38 deletions.
2 changes: 1 addition & 1 deletion client/src/config/site.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ export const siteConfig = {

if (PHASE_DEVELOPMENT_SERVER) {
Object.assign(siteConfig, {
url: "http://megateams.durhack.com",
url: "http://megateams.durhack-dev.com",
})
}
5 changes: 3 additions & 2 deletions server/src/auth/keycloak-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,14 @@ function adaptClientConfig(clientConfig: typeof keycloakConfig): ClientMetadata
} satisfies ClientMetadata
}

export const keycloakIssuer = await Issuer.discover(keycloakConfig.url)
const keycloakIssuerUrl = new URL(`/realms/${keycloakConfig.realm}`, keycloakConfig.baseUrl)
export const keycloakIssuer = await Issuer.discover(keycloakIssuerUrl.toString())

const keycloakClientConfig = adaptClientConfig(keycloakConfig)
export const keycloakClient = new keycloakIssuer.Client(keycloakClientConfig)
const keycloakAdminClient = new KeycloakAdminClient({
baseUrl: keycloakConfig.adminBaseUrl,
realmName: "durhack",
realmName: keycloakConfig.realm,
})

async function fetchKeycloakClientCredentials() {
Expand Down
22 changes: 13 additions & 9 deletions server/src/config/default.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,18 @@ import type { ConfigIn } from "./schema"

export default {
listen: {
host: "127.0.0.1",
port: 3101,
host: "localhost",
port: 3101, // Megateams project has ports 3100-3199
},
hostname: "http://localhost:3101",
origin: "http://megateams.durhack-dev.com",
flags: {},
csrf: {
enabled: true,
secret: "csrfisoverrated",
options: {
cookieOptions: {
name: "durhack-megateams.x-csrf-token",
domain: "megateams.durhack-dev.com",
sameSite: "strict",
path: "/",
secure: false,
Expand All @@ -26,18 +27,20 @@ export default {
session: {
cookie: {
name: "durhack-megateams-session",
domain: "megateams.durhack-dev.com",
sameSite: "lax",
path: "/",
secure: false,
},
},
megateams: {
maxTeamMembers: 4,
QRCodeRedemptionURL: "https://megateams.durhack.com/hacker/redeem",
},
discord: {
apiEndpoint: "https://discord.com/api/v10",
clientId: "yourDiscordAppClientIdHere",
clientSecret: "yourDiscordAppClientSecretHere",
redirectUri: "https://megateams.durhack.com/api/discord/redirect",
redirectUri: "http://megateams.durhack-dev.com/api/discord/redirect",
botToken: "yourDiscordBotTokenHere",
guildID: "yourDiscordGuildIDHere",
inviteLink: "https://discord.gg/xyz",
Expand All @@ -46,8 +49,8 @@ export default {
jsonwebtoken: {
accessTokenLifetime: 1800,
refreshTokenLifetime: 1209600,
issuer: "https://megateams.durhack.com",
audience: "https://megateams.durhack.com",
issuer: "http://megateams.durhack-dev.com",
audience: "http://megateams.durhack-dev.com",
authorities: [
{
for: TokenType.accessToken,
Expand All @@ -67,11 +70,12 @@ export default {
],
},
keycloak: {
url: "https://auth.durhack.com/realms/durhack",
realm: "durhack-dev",
baseUrl: "https://auth.durhack.com",
adminBaseUrl: "https://admin.auth.durhack.com",
clientId: "not-a-real-client-id",
clientSecret: "not-a-real-client-secret",
responseTypes: ["code"],
redirectUris: ["https://megateams.durhack.com/api/auth/keycloak/callback"],
redirectUris: ["http://megateams.durhack-dev.com/api/auth/keycloak/callback"],
},
} satisfies ConfigIn
11 changes: 0 additions & 11 deletions server/src/config/development.ts

This file was deleted.

2 changes: 1 addition & 1 deletion server/src/config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export const {
session: sessionConfig,
discord: discordConfig,
keycloak: keycloakConfig,
hostname,
origin,
megateams: megateamsConfig,
} = config

Expand Down
23 changes: 22 additions & 1 deletion server/src/config/production.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,36 @@ import type { DeepPartial } from "@server/types/deep-partial"
import type { ConfigIn } from "./schema"

export default {
origin: "https://megateams.durhack.com",
csrf: {
options: {
cookieOptions: {
name: "__Host-durhack-megateams.x-csrf-token",
domain: undefined,
path: "/",
secure: true,
sameSite: "strict",
},
},
},
session: {
cookie: { secure: true },
cookie: {
name: "__Host-durhack-megateams-session",
domain: undefined,
path: "/",
secure: true,
sameSite: "lax",
},
},
discord: {
redirectUri: "https://megateams.durhack.com/api/discord/redirect",
},
jsonwebtoken: {
issuer: "https://megateams.durhack.com",
audience: "https://megateams.durhack.com",
},
keycloak: {
realm: "durhack",
redirectUris: ["https://megateams.durhack.com/api/auth/keycloak/redirect"],
}
} satisfies DeepPartial<ConfigIn>
7 changes: 4 additions & 3 deletions server/src/config/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export const cookie_options_schema = z.object({
sameSite: z.union([z.literal("none"), z.literal("lax"), z.literal("strict")]).optional(),
path: z.string().optional(),
secure: z.boolean(),
domain: z.string().optional(),
})

export const doubleCsrfOptionsSchema = z.object({
Expand All @@ -29,7 +30,8 @@ export const sessionOptionsSchema = z.object({
})

export const keycloakOptionsSchema = z.object({
url: z.string().url(),
realm: z.string(),
baseUrl: z.string().url(),
adminBaseUrl: z.string().url(),
clientId: z.string(),
clientSecret: z.string(),
Expand All @@ -50,7 +52,7 @@ export const discordOptionsSchema = z.object({

export const configSchema = z.object({
listen: listenOptionsSchema,
hostname: z.string().url(),
origin: z.string().url(),
flags: z.object({}),
csrf: z.object({
enabled: z.boolean(),
Expand All @@ -62,7 +64,6 @@ export const configSchema = z.object({
session: sessionOptionsSchema,
megateams: z.object({
maxTeamMembers: z.number().positive(),
QRCodeRedemptionURL: z.string().url(),
}),
discord: discordOptionsSchema,
keycloak: keycloakOptionsSchema,
Expand Down
6 changes: 3 additions & 3 deletions server/src/database/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { ClientError } from "@otterhttp/errors"
import { type Prisma, PrismaClient } from "@prisma/client"
import { getChallengePointsByUser } from "@prisma/client/sql"
import assert from "node:assert/strict"

import { decodeTeamJoinCode } from "@server/common/decode-team-join-code"
import { megateamsConfig } from "@server/config"
import { getChallengePointsByUser } from "@prisma/client/sql"
import { megateamsConfig, origin } from "@server/config"

export type Area = Prisma.AreaGetPayload<{ select: undefined }>
export type Megateam = Prisma.MegateamGetPayload<{ select: undefined }>
Expand Down Expand Up @@ -123,7 +123,7 @@ export const prisma = basePrisma.$extends({
needs: { payload: true },
compute(qrCode) {
const redemptionUrlSearchParams = new URLSearchParams({ qr_id: qrCode.payload })
return `${megateamsConfig.QRCodeRedemptionURL}?${redemptionUrlSearchParams.toString()}`
return `${origin}/hacker/redeem?${redemptionUrlSearchParams.toString()}`
},
},
},
Expand Down
4 changes: 2 additions & 2 deletions server/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { App } from "@otterhttp/app"
import { Server as SocketIO } from "socket.io"

import { matchSignedCookie, signCookie, unsignCookieOrThrow } from "@server/auth/cookies"
import { listenConfig } from "@server/config"
import { origin, listenConfig } from "@server/config"
import { apiErrorHandler } from "@server/routes/error-handling"

import { Request } from "./request"
Expand Down Expand Up @@ -54,7 +54,7 @@ async function main() {

server.listen(listenConfig.port, listenConfig.host, () => {
console.log(
`> Server listening on http://${listenConfig.host}:${listenConfig.port} as ${dev ? "development" : environment}`,
`> Server listening on http://${listenConfig.host}:${listenConfig.port} as ${dev ? "development" : environment}, access via ${origin}`,
)
})
}
Expand Down
4 changes: 2 additions & 2 deletions server/src/routes/auth/keycloak/keycloak-handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { type Client, generators } from "openid-client"
import { adaptTokenSetToDatabase } from "@server/auth/adapt-token-set"
import { keycloakClient } from "@server/auth/keycloak-client"
import { getSession } from "@server/auth/session"
import { hostname } from "@server/config"
import { origin } from "@server/config"
import { type User, prisma } from "@server/database"
import type { Middleware } from "@server/types"

Expand Down Expand Up @@ -41,7 +41,7 @@ export class KeycloakHandlers {
}
}

static redirectUri = new URL("/api/auth/keycloak/callback", hostname).toString()
static redirectUri = new URL("/api/auth/keycloak/callback", origin).toString()

oauth2FlowCallback(): Middleware {
return async (request: Request & { user?: User }, response: Response, next: NextFunction) => {
Expand Down
18 changes: 15 additions & 3 deletions server/src/routes/points/points-handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,24 @@ class PointHandlers {
})
}

const new_instance = await prisma.point.create({
data: parsedPayload,
const adminClient = await getKeycloakAdminClient()
const userProfile = await adminClient.users.findOne({ id: parsedPayload.redeemerUserId })

if (userProfile == null) {
throw new ClientError(`User ID ${parsedPayload.redeemerUserId} does not correspond to a keycloak user.`, {
statusCode: HttpStatus.UnprocessableEntity,
expected: true,
})
}

await prisma.user.upsert({
where: { keycloakUserId: parsedPayload.redeemerUserId },
create: { keycloakUserId: parsedPayload.redeemerUserId, points: { create: parsedPayload } },
update: { points: { create: parsedPayload } },
})

response.status(200)
response.json({ status: response.statusCode, message: "OK", data: new_instance })
response.json({ status: response.statusCode, message: "OK" })
}
}

Expand Down

0 comments on commit 986aadd

Please sign in to comment.