Compare commits

...

No commits in common. "dd1aab37d0e85790b7f64d4dfcf704081519b062" and "f3f36938df4095c4885fbddac51c632f23b2e181" have entirely different histories.

33 changed files with 332 additions and 2200 deletions

6
.dockerignore Normal file
View File

@ -0,0 +1,6 @@
.git
.editorconfig
docker-minecraft.png
LICENSE
Makefile
README.md

16
.editorconfig Normal file
View File

@ -0,0 +1,16 @@
root = true
[*]
charset = utf-8
end_of_line = lf
indent_size = 4
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
[*.{yaml,yml}]
indent_size = 2
[Makefile]
indent_size = 4
indent_style = tab

View File

@ -1,25 +0,0 @@
module.exports = {
env: {
es2021: true,
node: true
},
extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended'],
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaVersion: 'latest',
sourceType: 'module'
},
plugins: ['@typescript-eslint', 'prettier'],
rules: {
yoda: 'error',
eqeqeq: 'error',
complexity: 'error',
'prefer-const': 'error',
'prefer-template': 'error',
'object-shorthand': 'warn',
'prettier/prettier': 'warn',
'prefer-destructuring': 'warn',
'prefer-arrow-callback': 'error',
'@typescript-eslint/no-namespace': 'off'
}
};

3
.github/FUNDING.yml vendored Normal file
View File

@ -0,0 +1,3 @@
github: PHLAK
patreon: PHLAK
custom: https://paypal.me/ChrisKankiewicz

8
.github/dependabot.yml vendored Normal file
View File

@ -0,0 +1,8 @@
version: 2
updates:
- package-ecosystem: docker
directory: "/"
schedule:
interval: monthly
timezone: US/Arizona
open-pull-requests-limit: 10

40
.github/workflows/publish-image.yaml vendored Normal file
View File

@ -0,0 +1,40 @@
name: Publish Image
on:
push:
branches: ['master']
tags: ['*']
env:
DOCKER_HUB_USER: phlak
jobs:
build-and-push:
name: Build & Push
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v2
- name: Log in to Docker Hub
uses: docker/login-action@v1
with:
username: ${{ env.DOCKER_HUB_USER }}
password: ${{ secrets.DOCKER_HUB_TOKEN }}
- name: Extract Metadata
id: extract-metadata
uses: docker/metadata-action@v3
with:
images: ${{ env.DOCKER_HUB_USER }}/minecraft
tags: |
type=raw,value=latest
type=ref,event=tag
- name: Build & Push Image
uses: docker/build-push-action@v2
with:
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.extract-metadata.outputs.tags }}
labels: ${{ steps.extract-metadata.outputs.labels }}

15
.github/workflows/tests.yaml vendored Normal file
View File

@ -0,0 +1,15 @@
name: Tests
on: [pull_request_target]
jobs:
build-image:
name: Build Image
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v2
- name: Build Image
run: make build

7
.gitignore vendored
View File

@ -1,4 +1,3 @@
node_modules/
dist/
.env
README.md
data/
db/
files/server.jar

View File

@ -1,12 +0,0 @@
{
"tabWidth": 2,
"useTabs": false,
"singleQuote": true,
"arrowParens": "avoid",
"bracketSpacing": true,
"semi": true,
"printWidth": 100,
"trailingComma": "none",
"endOfLine": "lf"
}

View File

@ -1,23 +1,49 @@
FROM node:18-alpine
FROM alpine:3.16.0
LABEL maintainer='Andriy Cherniy <qugalet@m0e.space>'
WORKDIR /app
# Minecraft version
ARG MC_VERSION=bta
ARG MC_JAR_SHA1=8399e1211e95faa421c1507b322dbeae86d604df
COPY ./package.json ./
# Set default JVM options
ENV _JAVA_OPTIONS '-Xms256M -Xmx4G'
ARG JAVA_VERSION=19
RUN npm i
# Create Minecraft directories
RUN mkdir -pv /opt/minecraft /etc/minecraft
COPY ./.env ./
# Create non-root user
RUN adduser -DHs /sbin/nologin minecraft
COPY ./prisma/schema.prisma ./
# Add the EULA file
COPY files/eula.txt /etc/minecraft/eula.txt
RUN npm run migrate
# Add the ops script
COPY files/ops /usr/local/bin/ops
RUN chmod +x /usr/local/bin/ops
RUN npm run generate
# Install dependencies, fetch Minecraft server jar file and chown files
#ARG JAR_URL=https://launcher.mojang.com/v1/objects/${MC_JAR_SHA1}/server.jar
RUN apk add --update ca-certificates nss tzdata wget \
&& apk add openjdk19-jre \
#&& wget -O /opt/minecraft/minecraft_server.jar ${JAR_URL} \
#&& apk del --purge wget && rm -rf /var/cache/apk/* \
&& rm -rf /var/cache/apk/* \
&& chown -R minecraft:minecraft /etc/minecraft /opt/minecraft
COPY . .
COPY files/server.jar /opt/minecraft/minecraft_server.jar
RUN npm run build
# Define volumes
VOLUME /etc/minecraft
EXPOSE 8080
# Expose port
EXPOSE 25565
CMD ["node", "dist"]
# Set running user
USER minecraft
# Set the working dir
WORKDIR /etc/minecraft
# Default run command
CMD ["java", "-jar", "/opt/minecraft/minecraft_server.jar", "nogui"]

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2021 Chris Kankiewicz <Chris@ChrisKankiewicz.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

8
Makefile Normal file
View File

@ -0,0 +1,8 @@
IMAGE_NAME="phlak/minecraft"
IMAGE_TAG="$$(grep 'ARG MC_VERSION' Dockerfile | awk -F = '{print $$2}')"
build:
@docker build --force-rm --pull --tag $(IMAGE_NAME):$(IMAGE_TAG) .
purge:
@docker image rm --force $(IMAGE_NAME):$(IMAGE_TAG)

123
README.md.old Normal file
View File

@ -0,0 +1,123 @@
docker-minecraft
================
<p align="center">
<img src="docker-minecraft.png" alt="Docker Minecraft" width="500">
</p>
<p align="center">
<a href="https://github.com/PHLAK/docker-minecraft/discussions"><img src="https://img.shields.io/badge/Join_the-Community-7b16ff.svg?style=for-the-badge" alt="Join the Community"></a>
<a href="https://github.com/users/PHLAK/sponsorship"><img src="https://img.shields.io/badge/Become_a-Sponsor-cc4195.svg?style=for-the-badge" alt="Become a Sponsor"></a>
<a href="https://paypal.me/ChrisKankiewicz"><img src="https://img.shields.io/badge/Make_a-Donation-006bb6.svg?style=for-the-badge" alt="One-time Donation"></a>
<br>
<a href="https://hub.docker.com/repository/docker/phlak/minecraft/tags"><img alt="Docker Image Version" src="https://img.shields.io/docker/v/phlak/minecraft?style=flat-square&sort=semver"></a>
<a href="https://hub.docker.com/repository/docker/phlak/minecraft"><img alt="Docker Pulls" src="https://img.shields.io/docker/pulls/phlak/minecraft?style=flat-square"></a>
<a href="https://github.com/PHLAK/docker-minecraft/blob/master/LICENSE"><img src="https://img.shields.io/github/license/PHLAK/docker-minecraft?style=flat-square" alt="License"></a>
<a href="https://hub.docker.com/r/phlak/minecraft/builds"><img alt="Docker Cloud Build Status" src="https://img.shields.io/docker/cloud/build/phlak/minecraft"></a>
</p>
<p align="center">
Docker image for <a href="https://minecraft.net/">Minecraft</a> server.
</p>
---
Running the Container
---------------------
First create a named data volume to hold the persistent world and config data:
docker volume create --name minecraft-data
Then run the Minecraft server:
docker run -it -d -p 25565:25565 -v minecraft-data:/etc/minecraft --name minecraft-server phlak/minecraft
#### Optional 'docker run' Arguments
<dl>
<dt><code>-e _JAVA_OPTIONS='-Xms256M -Xmx2048M'</code></dt>
<dd>Set JVM arguments for minimum/maximum memory consumption (default: '-Xms256M -Xmx2048M')</dd>
</dl>
<dl>
<dt><code>-e TZ=America/Phoenix</code></dt>
<dd>Set the timezone for your server. You can find your timezone in this <a href="https://goo.gl/uy1J6q">list of timezones</a>. Use the (case sensitive) value from the <code>TZ</code> column. If left unset, timezone will be UTC.</dd>
</dl>
<dl>
<dt><code>--restart unless-stopped</code></dt>
<dd>Always restart the container regardless of the exit status, but do not start it on daemon startup if the container has been put to a stopped state before. See the Docker <a href="https://goo.gl/Y0dlDH">restart policies</a> for additional details.</dd>
</dl>
**NOTE:** See the [Minecraft Wiki](http://minecraft.gamepedia.com/Server/Requirements) for more info
on memory requirements.
Editing the Server Config
-------------------------
Once you have a running container, you can edit the Minecraft [server config](https://minecraft.gamepedia.com/Server.properties) with:
docker exec -it minecraft-server vi /etc/minecraft/server.properties
After saving changes, restart your container with `docker restart minecraft-server`
Adding OPs
----------
Once you have a running server container you can add OPs by running:
docker exec minecraft-server ops [PLAYER_NAMES]
**NOTE:** Replace `[PLAYER_NAMES]` with the name of one or more players you wish to give OP
privileges separated by a space. If a players name contains spaces wrap it in quotation marks.
Here's an example granting OP to three players with name's `Marty`, `Jennifer` and `Doc Brown`:
docker exec minecraft-server ops Marty Jennifer "Doc Brown"
Running Server Commands
-----------------------
You can run [commands](https://minecraft.gamepedia.com/Commands) on the server
(e.g. `kick`, `ban`, `say`, etc.) by attaching to the running container and
running the commands. Attach to the server by running:
docker attach minecraft-server
Once attached you can run your commands like normal.
say Hello world!
[10:11:56] [Server thread/INFO]: [Server] Hello world!
list
[10:12:08] [Server thread/INFO]: There are 3 of a max 10 players online: Marty, Jennifer, Doc Brown
seed
[10:12:19] [Server thread/INFO]: Seed: [-5234790158571010769]
**NOTE:** In order to detach from the container and leave it running use the
`Ctrl + P` then `Ctrl + Q` key sequence.
Upgrading the Server
--------------------
First pull down the latest image:
docker pull phlak/minecraft
Remove your running server container:
docker rm -f minecraft-server
And run a new one with the same command/arguments as before.
Troubleshooting
---------------
For general help and support join our [GitHub Discussions](https://github.com/PHLAK/docker-minecraft/discussions) or reach out on [Twitter](https://twitter.com/PHLAK).
Please report bugs to the [GitHub Issue Tracker](https://github.com/PHLAK/docker-minecraft/issues).
Copyright
---------
This project is licensed under the [MIT License](https://github.com/PHLAK/docker-minecraft/blob/master/LICENSE).

12
README.org Normal file
View File

@ -0,0 +1,12 @@
* Minecraft Docker
Dockerfile and docker-compose for your own server jar
** Usage
Change your JAVA_VERSION in [[./Dockerfile][Dockerfile]] and build:
#+BEGIN_SRC shell
docker compose build
#+END_SRC
Place server.jar to ~files/~ folder, change your [[./docker-compose.yml][Docker Compose]] file and run:
#+BEGIN_SRC shell
docker compose up -d
#+END_SRC

View File

@ -1,9 +1,28 @@
version: '2'
services:
backend:
build: .
db:
image: postgres
volumes:
- ./db:/var/lib/postgresql/data
environment:
- POSTGRES_DB=rpz_auth
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
auth:
build: ./auth
depends_on:
- db
restart: unless-stopped
minecraft:
build: .
stdin_open: true # docker run -i
tty: true # docker run -t
restart: unless-stopped
volumes:
- ./data:/etc/minecraft
ports:
- '9030:8080'
env_file:
- ./.env
- 25565:25565
depends_on:
- db
- auth

BIN
docker-minecraft.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

1
files/eula.txt Normal file
View File

@ -0,0 +1 @@
eula=true

13
files/ops Normal file
View File

@ -0,0 +1,13 @@
#!/usr/bin/env sh
set -o errexit
OPS_FILE="/etc/minecraft/ops.txt"
[ ! -e "${OPS_FILE}" ] && touch ${OPS_FILE}
for OP in "$@"; do
if grep -qx "${OP}" ${OPS_FILE}; then
echo "NOTICE: '${OP}' already present in OPs file"; continue
fi
echo "${OP}" >> ${OPS_FILE} && echo "SUCCESS: '${OP}' added to OPs file"
done

View File

@ -1,40 +0,0 @@
{
"name": "rpz_auth",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"generate": "prisma generate",
"migrate": "prisma migrate deploy",
"build": "rm -rf dist/** && tsc",
"dev": "tsc -w",
"start": "node ./dist"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@tsconfig/node18": "^1.0.1",
"@types/jsonwebtoken": "^8.5.9",
"@types/node": "^18.7.13",
"@typescript-eslint/eslint-plugin": "^5.36.0",
"@typescript-eslint/parser": "^5.35.1",
"eslint": "^8.23.0",
"eslint-plugin-prettier": "^4.2.1",
"prettier": "^2.7.1",
"typescript": "^4.8.2"
},
"dependencies": {
"@fastify/autoload": "^5.2.0",
"@fastify/cookie": "^8.1.0",
"@prisma/client": "^4.2.1",
"axios": "^0.27.2",
"fastify": "^4.5.3",
"json-schema-to-ts": "^2.5.5",
"jsonwebtoken": "^8.5.1",
"nanoid": "3",
"prisma": "^4.3.0",
"redis": "^4.3.0",
"simple-oauth2": "^4.3.0"
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,23 +0,0 @@
-- CreateTable
CREATE TABLE "User" (
"id" TEXT NOT NULL,
"nickname" TEXT NOT NULL,
CONSTRAINT "User_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "Session" (
"id" TEXT NOT NULL,
"userNickname" TEXT NOT NULL,
"ip" TEXT NOT NULL,
"expiredAfter" TIMESTAMP(3) NOT NULL,
CONSTRAINT "Session_pkey" PRIMARY KEY ("id")
);
-- CreateIndex
CREATE UNIQUE INDEX "User_nickname_key" ON "User"("nickname");
-- AddForeignKey
ALTER TABLE "Session" ADD CONSTRAINT "Session_userNickname_fkey" FOREIGN KEY ("userNickname") REFERENCES "User"("nickname") ON DELETE RESTRICT ON UPDATE CASCADE;

View File

@ -1,5 +0,0 @@
-- AlterTable
ALTER TABLE "Session" ADD COLUMN "verified" BOOLEAN NOT NULL DEFAULT false;
-- AlterTable
ALTER TABLE "User" ALTER COLUMN "nickname" DROP NOT NULL;

View File

@ -1,13 +0,0 @@
/*
Warnings:
- You are about to drop the column `userNickname` on the `Session` table. All the data in the column will be lost.
- Added the required column `nickname` to the `Session` table without a default value. This is not possible if the table is not empty.
*/
-- DropForeignKey
ALTER TABLE "Session" DROP CONSTRAINT "Session_userNickname_fkey";
-- AlterTable
ALTER TABLE "Session" DROP COLUMN "userNickname",
ADD COLUMN "nickname" TEXT NOT NULL;

View File

@ -1,14 +0,0 @@
-- CreateTable
CREATE TABLE "Link" (
"id" TEXT NOT NULL,
"sessionId" TEXT NOT NULL,
"link" TEXT NOT NULL,
CONSTRAINT "Link_pkey" PRIMARY KEY ("id")
);
-- CreateIndex
CREATE UNIQUE INDEX "Link_sessionId_key" ON "Link"("sessionId");
-- AddForeignKey
ALTER TABLE "Link" ADD CONSTRAINT "Link_sessionId_fkey" FOREIGN KEY ("sessionId") REFERENCES "Session"("id") ON DELETE RESTRICT ON UPDATE CASCADE;

View File

@ -1,3 +0,0 @@
# Please do not edit this file manually
# It should be added in your version-control system (i.e. Git)
provider = "postgresql"

View File

@ -1,29 +0,0 @@
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model User {
id String @id
nickname String? @unique
}
model Session {
id String @id @default(uuid())
nickname String
ip String
verified Boolean @default(false)
expiredAfter DateTime
link Link?
}
model Link {
id String @id
session Session @relation(fields: [sessionId], references: [id])
sessionId String @unique
link String
}

View File

@ -1,21 +0,0 @@
import { PrismaClient } from '@prisma/client';
import('nanoid').then(nanoid => {
const db = new PrismaClient();
db.session
.create({
data: {
id: nanoid.nanoid(10),
ip: '127.0.0.1',
nickname: 'Qugalet',
expiredAfter: new Date(Date.now() + 604800)
}
})
.then(session =>
console.log(
encodeURI(
`https://auth.m0e.space/application/o/authorize/?client_id=7f24f967b2faf3d8c1c53771661abff8e07060c0&response_type=code&redirect_uri=http://localhost:8080/api/auth/verify?session=${session.id}&scope=profile openid`
)
)
);
});

View File

@ -1,68 +0,0 @@
import fastify from 'fastify';
import fastifyAutoload from '@fastify/autoload';
import { PrismaClient } from '@prisma/client';
// import { createClient, RedisClientType } from 'redis';
// import fastifySchedule from '@fastify/schedule';
// import fastifyCors from '@fastify/cors';
import path from 'path';
declare module 'fastify' {
interface FastifyInstance {
db: PrismaClient;
// redis: RedisClientType;
}
}
declare global {
namespace NodeJS {
interface ProcessEnv {
NODE_ENV: 'development' | 'production';
PORT: number;
JWT_REFRESH_SECRET: string;
JWT_ACCESS_SECRET: string;
AUTH_CLIENT_ID: string;
AUTH_CLIENT_SECRET: string;
REDIS_URL: string;
URL_TOKEN: string;
}
}
}
fastify({
logger: true,
ajv: { customOptions: { allErrors: true } }
})
.decorate('db', new PrismaClient())
// .decorate('redis', async () => {
// const client = createClient({
// url: process.env.REDIS_URL
// });
// client.on('error', err => console.log('Redis Client Error', err));
// await client.connect();
// return client;
// })
.addHook('onRoute', route => console.log(route.url))
// .register(fastifyCors, {
// origin: ['http://127.0.0.1:3000'],
// credentials: true
// })
.register(fastifyAutoload, {
dir: path.join(__dirname, 'routes'),
routeParams: true,
autoHooks: true,
options: { prefix: '/api' }
})
.register(fastifyAutoload, {
dir: path.join(__dirname, 'link'),
routeParams: true,
autoHooks: true,
options: { prefix: '/a' }
})
.listen({ port: process.env.PORT || 8080, host: '0.0.0.0' })
// eslint-disable-next-line no-console
.then(() => console.log('Server Started'))
// eslint-disable-next-line no-console
.catch(console.error);

View File

@ -1,76 +0,0 @@
import { FastifyInstance } from 'fastify';
import { FromSchema } from 'json-schema-to-ts';
import { nanoid } from 'nanoid/async';
const schema = {
querystring: {
type: 'object',
required: ['session', 'key'],
properties: {
session: { type: 'string' },
key: { type: 'string' }
}
}
} as const;
export default async (server: FastifyInstance) =>
server.get<{ Querystring: FromSchema<typeof schema.querystring> }>(
'/create',
async (req, reply) => {
if (req.query.key !== process.env.URL_TOKEN) return reply.code(403).send('Forbidden');
const session = await server.db.session.findFirst({
where: {
id: req.query.session
}
});
if (!session) return reply.code(404).send('Session is not found');
const linkedSession = await server.db.link.findFirst({
where: { session: { id: req.query.session } },
select: {
id: true
}
});
if (linkedSession)
reply.send(
`${
process.env.NODE_ENV === 'production'
? 'https://mc.m0e.space/a'
: 'http://localhost:8080/a'
}/${linkedSession.id}`
);
let linkId = await nanoid(5);
// eslint-disable-next-line no-constant-condition
while (true) {
const link = await server.db.link.findFirst({
where: { id: linkId },
select: { id: true }
});
if (!link) break;
linkId = await nanoid(5);
}
await server.db.link.create({
data: {
id: linkId,
link: encodeURI(
`https://auth.m0e.space/application/o/authorize/?client_id=7f24f967b2faf3d8c1c53771661abff8e07060c0&response_type=code&redirect_uri=${
process.env.NODE_ENV === 'production'
? 'https://mc.m0e.space'
: 'http://localhost:8080'
}/api/auth/verify?session=${req.query.session}&scope=profile openid`
),
session: {
connect: {
id: req.query.session
}
}
}
});
reply.send(
`${
process.env.NODE_ENV === 'production'
? 'https://mc.m0e.space/a'
: 'http://localhost:8080/a'
}/${linkId}`
);
}
);

View File

@ -1,9 +0,0 @@
import { FastifyInstance } from 'fastify';
export default async (server: FastifyInstance) =>
server.get<{ Params: { id: string } }>('/:id', (req, reply) =>
server.db.link
.findFirstOrThrow({ where: { id: req.params.id } })
.then(link => reply.redirect(link.link))
.catch(() => reply.code(404).send('URL not found'))
);

View File

@ -1,49 +0,0 @@
import { FastifyInstance, FastifyReply } from 'fastify';
import { CookieSerializeOptions } from '@fastify/cookie';
import { User } from '@prisma/client';
import jwt from 'jsonwebtoken';
const cookieSettings: CookieSerializeOptions = {
httpOnly: true,
path: '/api/auth/refresh_token',
sameSite: 'strict',
maxAge: 2629800, //1 month
secure: process.env.NODE_ENV === 'production'
};
declare module 'fastify' {
interface FastifyReply {
sendTokens: (user: User) => FastifyReply;
clearTokens: () => FastifyReply;
}
}
export default async (server: FastifyInstance) =>
server
.decorateReply('sendTokens', function (this: FastifyReply, { id, nickname }: User) {
return this.setCookie(
'owo',
jwt.sign({ tokenVersion: 0, id }, process.env.JWT_REFRESH_SECRET, {
expiresIn: '30d'
}),
cookieSettings
).send({
user: {
id,
nickname
},
token: jwt.sign(
{
id,
nickname
},
process.env.JWT_ACCESS_SECRET,
{
expiresIn: '15m'
}
)
});
})
.decorateReply('clearTokens', function (this: FastifyReply) {
return this.clearCookie('owo', cookieSettings);
});

View File

@ -1,88 +0,0 @@
import { FastifyInstance } from 'fastify';
import { FromSchema } from 'json-schema-to-ts';
import { stringify } from 'querystring';
import axios from 'axios';
const schema = {
querystring: {
type: 'object',
required: ['code', 'session'],
properties: {
code: { type: 'string' },
session: { type: 'string' }
}
}
} as const;
export default async (server: FastifyInstance) =>
server.get<{ Querystring: FromSchema<typeof schema.querystring> }>(
'/verify',
{ schema },
(req, reply) => {
axios
.post(
'https://auth.m0e.space/application/o/token/',
stringify({
client_id: process.env.AUTH_CLIENT_ID,
client_secret: process.env.AUTH_CLIENT_SECRET,
grant_type: 'authorization_code',
redirect_uri:
process.env.NODE_ENV === 'production'
? 'https://mc.m0e.space/api/auth/verify'
: 'http://localhost:8080/api/auth/verify',
code: req.query.code
})
)
.then(res =>
axios
.get('https://auth.m0e.space/application/o/userinfo/', {
headers: { Authorization: `Bearer ${res.data.access_token}` }
})
.then(async res => {
const user =
(await server.db.user.findFirst({ where: { id: res.data.sub } })) ||
(await server.db.user.create({ data: { id: res.data.sub } }));
const session = await server.db.session.findFirst({
where: { id: req.query.session }
});
if (!session) return reply.code(400).send('Invalid session');
const userByNickname = await server.db.user.findFirst({
where: { nickname: session.nickname }
});
if (!userByNickname) {
await Promise.all([
server.db.user.update({
where: { id: user.id },
data: { nickname: session.nickname }
}),
server.db.session.update({
where: { id: req.query.session },
data: {
verified: true
}
})
]).then(() => reply.redirect('https://mc.m0e.space/message/success'));
// await server.redis.publish('rpz_auth', req.query.session);
} else if (userByNickname.id !== user.id) reply.send(403).send('Forbidden');
else
await server.db.session
.update({
where: { id: req.query.session },
data: {
verified: true
}
})
.then(() => reply.redirect('https://mc.m0e.space/message/success'));
})
.catch(err => {
console.log(err);
reply.code(500).send(err);
})
)
.catch(err => {
console.log(err);
reply.code(500).send(err);
});
}
);

View File

@ -1,9 +0,0 @@
{
"extends": "@tsconfig/node18/tsconfig.json",
"compilerOptions": {
"outDir": "dist"
// "module": "esnext"
},
"esModuleInterop": true,
"resolveJsonModule": true
}