Compare commits

..

No commits in common. "a0ea5ec191a9eb12d44f64c0b5aaded9411db60e" and "795c22145315848e6f496e1c90b1455387c562a3" have entirely different histories.

18 changed files with 169 additions and 5129 deletions

View File

@ -1,18 +1,5 @@
{
"root": true,
"extends": ["eslint:recommended", "@nuxtjs/eslint-config-typescript", "plugin:tailwindcss/recommended"],
"rules": {
"vue/max-attributes-per-line": ["error", {
"singleline": {
"max": 4
},
"multiline": {
"max": 2
}
}],
"vue/multi-word-component-names": "off",
"vue/singleline-html-element-content-newline": "off",
"no-undef": "off",
"no-console": "off"
}
"extends": [
"@nuxt/eslint-config"
]
}

View File

@ -1,6 +0,0 @@
export default defineAppConfig({
ui: {
primary: 'cyan',
gray: 'cool'
}
})

View File

@ -1,5 +1,5 @@
<template>
<div class="min-h-screen w-full overflow-y-auto bg-gray-100 dark:bg-gray-900">
<NuxtLayout />
<div>
<NuxtWelcome />
</div>
</template>

View File

@ -1,3 +0,0 @@
<template>
<NuxtPage />
</template>

View File

@ -1,5 +0,0 @@
<template>
<div>
<NuxtPage />
</div>
</template>

View File

@ -1,25 +0,0 @@
export default defineNuxtRouteMiddleware(async (to) => {
if (process.server) {
return
}
try {
const user = await $fetch('/api/auth/user')
if (!user.id) {
throw createError({ statusCode: 500, statusMessage: 'No user was found' })
}
useState('user', () => user)
if (to.meta.moderator && !user.role.moderator) {
return navigateTo('/')
}
} catch (e) {
console.error('Failed to get user', e)
useState('user', () => null)
return navigateTo('/login')
}
})

View File

@ -1,25 +1,6 @@
// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
ssr: false,
typescript: {
typeCheck: true
},
nitro: {
plugins: ['~/server/index.ts']
},
modules: [
'@nuxthq/ui'
],
runtimeConfig: {
discordClientId: '',
discordClientSecret: '',
oauthRedirectUri: 'http://localhost:3000/api/auth',
jwtSecret: '',
mongoUrl: '',
mongoUser: '',
mongoPass: '',
public: {
oauthUrl: 'https://discord.com/api/oauth2/authorize?client_id=1052974736432443432&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fapi%2Fauth&response_type=code&scope=identify'
}
typeCheck: true,
}
})

5011
webv2/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -6,22 +6,16 @@
"dev": "nuxt dev",
"generate": "nuxt generate",
"preview": "nuxt preview",
"postinstall": "nuxt prepare",
"lint": "eslint .",
"lint-fix": "eslint . --fix"
"postinstall": "nuxt prepare"
},
"devDependencies": {
"@nuxthq/ui": "^2.2.1",
"@nuxtjs/eslint-config-typescript": "^12.0.0",
"@types/node": "^18",
"eslint": "^8.41.0",
"eslint-plugin-tailwindcss": "^3.12.1",
"nuxt": "^3.5.2"
},
"dependencies": {
"@types/jsonwebtoken": "^9.0.2",
"jsonwebtoken": "^9.0.0",
"mongoose": "^7.2.2",
"@nuxt/eslint-config": "^0.1.1",
"typescript": "^5.0.4",
"vue-tsc": "^1.6.5"
}

View File

@ -1,13 +0,0 @@
<template>
<div>
Index
</div>
</template>
<script lang="ts" setup>
definePageMeta({
middleware: ['auth']
})
const user = useState('user')
</script>

View File

@ -1,17 +0,0 @@
<template>
<div class="flex h-screen flex-col items-center justify-center">
<h1 class="text-primary-500 mb-5 text-center text-3xl font-bold">Polarcraft S5</h1>
<p class="mx-3 mb-5 max-w-2xl">
<b>Welkom bij Polarcraft seizoen 5!</b> Start door in te loggen met Discord en vervolgens je account te koppelen met Minecraft. Als je problemen hebt maak dan in Discord een post aan in het <b>#help</b> channel.
</p>
<UButton @click="navigateTo(config.public.oauthUrl, { external: true })">Log in with Discord</UButton>
</div>
</template>
<script lang="ts" setup>
definePageMeta({
layout: 'blank'
})
const config = useRuntimeConfig()
</script>

View File

@ -1,93 +1,5 @@
import jwt from 'jsonwebtoken'
type AccessTokenResponse = {
access_token: string,
token_type: string,
expires_in: number,
refresh_token: string,
scope: string
}
type DiscordUser = {
id: string,
username: string,
discriminator: string,
avatar: string,
bot?: boolean,
system?: boolean,
mfa_enabled?: boolean,
banner?: string,
accent_color?: number,
locale?: string,
verified?: boolean,
email?: string,
flags?: number,
premium_type?: number,
public_flags?: number
}
export default defineEventHandler(async (event) => {
const { code }: { code?: string } = getQuery(event)
if (!code) {
return sendRedirect(event, '/', 302)
return {
hello: 'world'
}
let tokenResponse: AccessTokenResponse
let authorizationResponse: DiscordUser
try {
tokenResponse = await $fetch('https://discord.com/api/oauth2/token', {
method: 'POST',
body: new URLSearchParams({
client_id: config.discordClientId,
client_secret: config.discordClientSecret,
code,
grant_type: 'authorization_code',
redirect_uri: config.oauthRedirectUri,
scope: 'identify'
}),
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
})
authorizationResponse = await $fetch('https://discord.com/api/users/@me', {
headers: {
authorization: `Bearer ${tokenResponse.access_token}`
}
})
} catch (e) {
console.error('Discord authentication failed', e)
throw createError({ statusCode: 500, statusMessage: 'Discord authentication failed' })
}
try {
await UserModel.updateOne({ 'discord.id': authorizationResponse.id }, {
$set: {
discord: {
id: authorizationResponse.id,
username: authorizationResponse.username,
avatarHash: authorizationResponse.avatar
}
},
$setOnInsert: {
username: authorizationResponse.username
}
}, { upsert: true })
const token = jwt.sign({
accessToken: tokenResponse.access_token,
refreshToken: tokenResponse.refresh_token,
discordId: authorizationResponse.id
}, config.jwtSecret, { expiresIn: tokenResponse.expires_in })
setCookie(event, 'jwt', token, { httpOnly: true, maxAge: tokenResponse.expires_in * 1000 })
} catch (e) {
console.error('Updating user information failed', e)
throw createError({ statusCode: 500, statusMessage: 'Updating user information failed' })
}
return sendRedirect(event, '/', 302)
})

View File

@ -0,0 +1,5 @@
export default defineEventHandler((event) => {
return {
hello: 'world'
}
})

View File

@ -1,14 +0,0 @@
import mongoose from 'mongoose'
export default async () => {
try {
await mongoose.connect(config.mongoUrl, {
authSource: 'admin',
user: config.mongoUser,
pass: config.mongoPass
})
console.log('DB connection established')
} catch (e) {
console.error('DB connection failed', e)
}
}

View File

@ -1 +0,0 @@
export const config = useRuntimeConfig()

View File

@ -1,24 +0,0 @@
import { Schema, Types, model } from 'mongoose'
const userSchema = new Schema({
username: { type: String, required: true },
usernameType: { type: String, required: true, default: 'discord' },
discord: {
id: { type: String, required: true, unique: true },
username: { type: String, required: true }
},
minecraft: {
uuid: { type: String, required: false, unique: true },
username: { type: String, required: false }
},
role: {
admin: Boolean,
moderator: Boolean,
teamAdmin: Boolean
},
teamInvites: [
Types.ObjectId
]
})
export const UserModel = model<IUser>('User', userSchema)

View File

@ -1,7 +1,4 @@
{
// https://nuxt.com/docs/guide/concepts/typescript
"extends": "./.nuxt/tsconfig.json",
"compilerOptions": {
"typeRoots": ["./types"]
}
"extends": "./.nuxt/tsconfig.json"
}

View File

@ -1,23 +0,0 @@
export {}
declare global {
interface IUser {
_id: string,
username: string,
discord: {
id: string,
username: string,
avatarHash: string
},
minecraft?: {
uuid: string,
username: string
},
teamInvites: string[],
role: {
admin: boolean,
moderator: boolean,
},
teamId: string,
}
}