mirror of
https://git.suyu.dev/suyu/website.git
synced 2025-12-26 09:14:40 +01:00
Merge branch 'dev' into dev
This commit is contained in:
commit
067c0609d3
11 changed files with 774 additions and 68 deletions
|
|
@ -1,6 +1,6 @@
|
|||
import type { IJwtData } from "$types/auth";
|
||||
import type { Role } from "$types/db";
|
||||
import { PUBLIC_KEY } from "../secrets/secrets.json";
|
||||
import { PUB_KEY } from "$env/static/private";
|
||||
import jwt from "jsonwebtoken";
|
||||
|
||||
export function json<T>(body: T, status?: number): Response {
|
||||
|
|
@ -14,7 +14,7 @@ export function json<T>(body: T, status?: number): Response {
|
|||
|
||||
export async function getJwtData(token: string): Promise<IJwtData> {
|
||||
return new Promise((resolve, reject) => {
|
||||
jwt.verify(token, PUBLIC_KEY, { algorithms: ["RS256"] }, (err, data) => {
|
||||
jwt.verify(token, PUB_KEY, { algorithms: ["RS256"] }, (err, data) => {
|
||||
if (err) reject(err);
|
||||
else resolve(data as IJwtData);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { userRepo } from "$lib/server/repo";
|
||||
import type { SuyuUser } from "$lib/server/schema";
|
||||
import { PUBLIC_KEY } from "$lib/server/secrets/secrets.json";
|
||||
import { PUB_KEY } from "$env/static/private";
|
||||
import type { IJwtData } from "$types/auth";
|
||||
import cookie from "cookie";
|
||||
import jwt from "jsonwebtoken";
|
||||
|
|
@ -18,7 +18,7 @@ export async function useAuth(
|
|||
}
|
||||
if (apiKey.startsWith("Bearer ")) {
|
||||
const token = apiKey.replace("Bearer ", "");
|
||||
const decoded: IJwtData = jwt.verify(token, Buffer.from(PUBLIC_KEY), {
|
||||
const decoded: IJwtData = jwt.verify(token, Buffer.from(PUB_KEY), {
|
||||
algorithms: ["RS256"],
|
||||
}) as IJwtData;
|
||||
let user = await userRepo.findOne({
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ let starCount = 0;
|
|||
let roleMembers = {
|
||||
"1214817156420862012": 50,
|
||||
};
|
||||
let gitCommits = 0;
|
||||
|
||||
async function fetchServerSideData() {
|
||||
console.log("Fetching member count");
|
||||
|
|
@ -22,16 +23,17 @@ async function fetchServerSideData() {
|
|||
fetch("https://git.suyu.dev/api/v1/repos/suyu/suyu"),
|
||||
];
|
||||
|
||||
const [res, roles, gitlabRes] = await Promise.all(promises);
|
||||
const [res, roles, gitlabRes, suyuGitRes] = await Promise.all(promises);
|
||||
const jsonPromises = [res.json(), roles.json(), gitlabRes.json()];
|
||||
const [resJson, rolesJson, gitResJson] = await Promise.all(jsonPromises);
|
||||
|
||||
|
||||
memberCount = resJson.approximate_member_count;
|
||||
starCount = gitResJson.stars_count;
|
||||
gitCommits = parseInt(suyuGitRes?.headers?.get('x-total'), 10) || 0;
|
||||
if (DISCORD_USER_TOKEN) roleMembers = rolesJson;
|
||||
|
||||
console.log("Member count:", memberCount);
|
||||
console.log("Stars count:", starCount);
|
||||
console.log('Git commit count', gitCommits);
|
||||
}
|
||||
|
||||
if (!building) {
|
||||
|
|
@ -46,5 +48,6 @@ export async function load({ cookies }) {
|
|||
memberCount,
|
||||
starCount,
|
||||
roleMembers,
|
||||
gitCommits
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,8 +8,9 @@
|
|||
|
||||
export let data: PageData;
|
||||
$: memberCount = parseFloat(data.memberCount?.toPrecision(2));
|
||||
$: contributors = parseFloat(data.roleMembers["1214817156420862012"]?.toPrecision(2));
|
||||
$: contributors = parseFloat(data.roleMembers?.["1214817156420862012"]?.toPrecision(2));
|
||||
$: starCount = parseFloat(data.starCount?.toPrecision(2));
|
||||
$: gitCommits = parseFloat(data.gitCommits?.toPrecision(2));
|
||||
let metadata = {
|
||||
url: "https://suyu.dev",
|
||||
title: "suyu - Open-source, non-profit Switch emulator",
|
||||
|
|
@ -70,12 +71,8 @@
|
|||
and open-source, forever.
|
||||
</p>
|
||||
<div class="flex flex-col gap-4 md:flex-row">
|
||||
<a
|
||||
href="/download"
|
||||
rel="noreferrer noopener"
|
||||
class="cta-button"
|
||||
>
|
||||
Download <svg
|
||||
<a href="/download" rel="noreferrer noopener" class="cta-button">
|
||||
Download <svg
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
|
|
@ -116,8 +113,7 @@
|
|||
>
|
||||
<h1 class="text-[48px] leading-[0.9]">By the numbers</h1>
|
||||
<HomepageCounter count={contributors} subText="dedicated contributors" />
|
||||
<!-- The wording "Repository stars" was voted on by the community -->
|
||||
<HomepageCounter count={starCount} subText="Repository stars" />
|
||||
<HomepageCounter count={gitCommits} subText="Git commits" />
|
||||
<HomepageCounter count={4000} subText="supported games" />
|
||||
<HomepageCounter count={memberCount} subText="members on Discord" />
|
||||
</div>
|
||||
|
|
@ -187,8 +183,8 @@
|
|||
>
|
||||
<h2 class="text-[24px] leading-[1.41] md:text-[60px] md:leading-[1.1]">Git</h2>
|
||||
<p class="mt-2 text-lg leading-relaxed">
|
||||
Our Git instance is where all the magic of suyu happens. We're always looking for new contributors
|
||||
to help us out, so feel free to check out our code.
|
||||
Our Git instance is where all the magic of suyu happens. We're always looking for new
|
||||
contributors to help us out, so feel free to check out our code.
|
||||
</p>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@
|
|||
// },
|
||||
];
|
||||
|
||||
function navClick(e: MouseEvent | HTMLAnchorElement) {
|
||||
function navClick(e: MouseEvent | HTMLAnchorElement, ignoreAnimation = false) {
|
||||
const navBars = document.querySelectorAll<HTMLDivElement>(".navbar");
|
||||
if (navBars.length !== 1)
|
||||
navBars.forEach((bar) => {
|
||||
|
|
@ -52,6 +52,7 @@
|
|||
const bounds = target.getBoundingClientRect();
|
||||
const navBounds = navBar.getBoundingClientRect();
|
||||
const pillBounds = indicator.getBoundingClientRect();
|
||||
if (ignoreAnimation) return;
|
||||
indicator.style.transform = `translateX(${bounds.left - navBounds.left}px)`;
|
||||
indicator.style.width = `${bounds.width}px`;
|
||||
if (
|
||||
|
|
@ -190,7 +191,7 @@
|
|||
<a
|
||||
href={item.href}
|
||||
data-index={i}
|
||||
on:click={navClick}
|
||||
on:click={(e) => navClick(e, true)}
|
||||
class={`navitem flex flex-grow basis-[0] items-center justify-center whitespace-nowrap rounded-full px-4 py-2 text-sm font-bold ${
|
||||
selected === i ? " text-[#a9a9a9] opacity-100" : "opacity-50"
|
||||
}`}
|
||||
|
|
|
|||
24
src/routes/jwt/external/[audience]/+server.ts
vendored
Normal file
24
src/routes/jwt/external/[audience]/+server.ts
vendored
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
import { PRIVATE_KEY } from "$env/static/private";
|
||||
import { userRepo } from "$lib/server/repo/index.js";
|
||||
import { getJwtData } from "$lib/server/util/index.js";
|
||||
import { useAuth } from "$lib/util/api/index.js";
|
||||
import type { IJwtData } from "$types/auth.js";
|
||||
import jwt from "jsonwebtoken";
|
||||
|
||||
export async function POST({ request }) {
|
||||
const jwtData = await getJwtData(request.headers.get("authorization")?.split(" ")[1] || "");
|
||||
const user = await userRepo.findOne({
|
||||
where: {
|
||||
apiKey: jwtData.apiKey,
|
||||
},
|
||||
});
|
||||
const token = jwt.sign({ ...user }, Buffer.from(PRIVATE_KEY), {
|
||||
algorithm: "RS256",
|
||||
});
|
||||
return new Response(token, {
|
||||
status: 200,
|
||||
headers: {
|
||||
"content-type": "text/html",
|
||||
},
|
||||
});
|
||||
}
|
||||
44
src/routes/jwt/external/key.pem/+server.ts
vendored
44
src/routes/jwt/external/key.pem/+server.ts
vendored
|
|
@ -1,45 +1,11 @@
|
|||
import { json } from "$lib/server/util/index.js";
|
||||
import { PUB_KEY } from "$env/static/private";
|
||||
|
||||
export function GET({ request }) {
|
||||
return new Response(
|
||||
`-----BEGIN CERTIFICATE-----
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
|
||||
-----END CERTIFICATE-----`,
|
||||
{
|
||||
headers: {
|
||||
"content-type": "text/plain",
|
||||
},
|
||||
return new Response(PUB_KEY, {
|
||||
headers: {
|
||||
"content-type": "text/plain",
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
export function POST({ request }) {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { PRIVATE_KEY } from "$lib/server/secrets/secrets.json";
|
||||
import { PRIVATE_KEY } from "$env/static/private";
|
||||
import { useAuth } from "$lib/util/api/index.js";
|
||||
import jwt from "jsonwebtoken";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import { Room, RoomManager } from "$lib/server/class/Room";
|
||||
import { userRepo } from "$lib/server/repo/index.js";
|
||||
import { SuyuUser } from "$lib/server/schema";
|
||||
import { PUBLIC_KEY } from "$lib/server/secrets/secrets.json";
|
||||
import { json } from "$lib/server/util";
|
||||
import { useAuth } from "$lib/util/api/index.js";
|
||||
import type { IJwtData } from "$types/auth.js";
|
||||
|
|
@ -65,12 +64,5 @@ export async function POST({ request, getClientAddress }) {
|
|||
host: user,
|
||||
hasPassword: body.hasPassword || false,
|
||||
});
|
||||
console.log("Room added:", JSON.stringify(room, null, 2));
|
||||
// push every room to the top which starts with `[SUYU OFFICIAL]` and was created with username "suyu"
|
||||
const suyuRoom = RoomManager.rooms.find((r) => r.roomInfo.name.startsWith("[SUYU OFFICIAL]"));
|
||||
if (suyuRoom && suyuRoom.host.username === "suyu") {
|
||||
RoomManager.rooms.splice(RoomManager.rooms.indexOf(suyuRoom), 1);
|
||||
RoomManager.rooms.unshift(suyuRoom);
|
||||
}
|
||||
return json(room.toJSON());
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue