mirror of
https://github.com/linux-odyssey/linux-odyssey.git
synced 2026-11-08 11:30:12 +08:00
refactor utils
This commit is contained in:
1 parent
9509bbc355
commit
d6c95cea4a
13 files changed
+126
-31
No files matched your search
@@ -60,6 +60,11 @@ module.exports = {
|
|||||||
tsx: 'never',
|
tsx: 'never',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
'lines-between-class-members': [
|
||||||
|
'error',
|
||||||
|
'always',
|
||||||
|
{ exceptAfterSingleLine: true },
|
||||||
|
],
|
||||||
},
|
},
|
||||||
overrides: [
|
overrides: [
|
||||||
{
|
{
|
||||||
|
|||||||
+1
-1
@@ -15,7 +15,7 @@
|
|||||||
"app": "yarn workspace app dev",
|
"app": "yarn workspace app dev",
|
||||||
"app:local": "yarn workspace app dev:local",
|
"app:local": "yarn workspace app dev:local",
|
||||||
"build": "yarn workspaces foreach -Apt run build",
|
"build": "yarn workspaces foreach -Apt run build",
|
||||||
"dev": "yarn workspaces foreach -Rpi --from '{server,app}' run watch",
|
"dev": "yarn workspaces foreach -Api --include '{server,app}' run watch",
|
||||||
"server": "yarn workspace server dev",
|
"server": "yarn workspace server dev",
|
||||||
"cli": "yarn workspace client start",
|
"cli": "yarn workspace client start",
|
||||||
"lint": "eslint .",
|
"lint": "eslint .",
|
||||||
|
|||||||
@@ -45,8 +45,13 @@
|
|||||||
"yaml": "^2.3.1"
|
"yaml": "^2.3.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@types/bcrypt": "^5.0.2",
|
||||||
"@types/express": "^4.17.21",
|
"@types/express": "^4.17.21",
|
||||||
"@types/express-session": "^1.17.10",
|
"@types/express-session": "^1.17.10",
|
||||||
|
"@types/jsonwebtoken": "^9.0.5",
|
||||||
|
"@types/passport": "^1.0.16",
|
||||||
|
"@types/passport-oauth2": "^1.4.15",
|
||||||
|
"@types/validator": "^13.11.9",
|
||||||
"concurrently": "^8.2.2",
|
"concurrently": "^8.2.2",
|
||||||
"jest": "^29.6.1",
|
"jest": "^29.6.1",
|
||||||
"nodemon": "^3.0.1",
|
"nodemon": "^3.0.1",
|
||||||
|
|||||||
@@ -1,9 +1,22 @@
|
|||||||
import { User } from '@linux-odyssey/models'
|
import { User } from '@linux-odyssey/models'
|
||||||
|
import type { Profile } from 'passport'
|
||||||
|
import type { VerifyCallback } from 'passport-oauth2'
|
||||||
|
|
||||||
export default async function oauthVerify(provider, profile, query, cb) {
|
export type SocialLogin = {
|
||||||
|
provider: string
|
||||||
|
id: string
|
||||||
|
displayName: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export default async function oauthVerify(
|
||||||
|
provider: string,
|
||||||
|
profile: Profile,
|
||||||
|
query: Record<string, any>,
|
||||||
|
cb: VerifyCallback
|
||||||
|
) {
|
||||||
process.nextTick(async () => {
|
process.nextTick(async () => {
|
||||||
try {
|
try {
|
||||||
const email = profile.emails[0]?.value
|
const email = profile.emails ? profile.emails[0]?.value : undefined
|
||||||
if (!email) {
|
if (!email) {
|
||||||
return cb(new Error('No email found'))
|
return cb(new Error('No email found'))
|
||||||
}
|
}
|
||||||
@@ -26,7 +39,9 @@ export default async function oauthVerify(provider, profile, query, cb) {
|
|||||||
|
|
||||||
return cb(null, user)
|
return cb(null, user)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return cb(err)
|
return cb(
|
||||||
|
err instanceof Error ? err : new Error('An unknown error occurred')
|
||||||
|
)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -5,17 +5,18 @@ import { get } from './utils/env.js'
|
|||||||
// Import dotenv and load ../.env
|
// Import dotenv and load ../.env
|
||||||
dotenv.config({ path: '../.env' })
|
dotenv.config({ path: '../.env' })
|
||||||
|
|
||||||
function getTrustProxies(key) {
|
function getTrustProxies(key: string): string[] {
|
||||||
if (!process.env[key]) {
|
const value = process.env[key]
|
||||||
|
if (!value) {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
return process.env[key]
|
return value
|
||||||
.split(',')
|
.split(',')
|
||||||
.map((p) => validator.trim(p))
|
.map((p) => validator.trim(p))
|
||||||
.filter((p) => validator.isIPRange(p) || validator.isIP(p))
|
.filter((p) => validator.isIPRange(p) || validator.isIP(p))
|
||||||
}
|
}
|
||||||
|
|
||||||
function getUrl(key) {
|
function getUrl(key: string): string {
|
||||||
const url = get(key, '')
|
const url = get(key, '')
|
||||||
if (validator.isURL(url)) {
|
if (validator.isURL(url)) {
|
||||||
return validator.trim(url)
|
return validator.trim(url)
|
||||||
@@ -50,8 +51,8 @@ function createConfig() {
|
|||||||
clientSecret: get('GITHUB_CLIENT_SECRET', ''),
|
clientSecret: get('GITHUB_CLIENT_SECRET', ''),
|
||||||
},
|
},
|
||||||
trustedProxies: getTrustProxies('TRUSTED_PROXIES'),
|
trustedProxies: getTrustProxies('TRUSTED_PROXIES'),
|
||||||
surveyUrl: getUrl('SURVEY_URL', ''),
|
surveyUrl: getUrl('SURVEY_URL'),
|
||||||
bugReportUrl: getUrl('BUG_REPORT_URL', ''),
|
bugReportUrl: getUrl('BUG_REPORT_URL'),
|
||||||
|
|
||||||
docker: {
|
docker: {
|
||||||
network: get('DOCKER_NETWORK', 'host'),
|
network: get('DOCKER_NETWORK', 'host'),
|
||||||
@@ -74,7 +75,7 @@ function createConfig() {
|
|||||||
|
|
||||||
const config = createConfig()
|
const config = createConfig()
|
||||||
|
|
||||||
export function getQuestImage(id) {
|
export function getQuestImage(id: string): string {
|
||||||
return `${config.docker.imagePrefix}${id}`
|
return `${config.docker.imagePrefix}${id}`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,7 +1,12 @@
|
|||||||
import { User, UserProfile } from '@linux-odyssey/models'
|
import { User, UserProfile } from '@linux-odyssey/models'
|
||||||
|
import { SocialLogin } from '../auth/oauthVerify.js'
|
||||||
import { hashPassword } from '../utils/auth.js'
|
import { hashPassword } from '../utils/auth.js'
|
||||||
|
|
||||||
export async function createUser(username, email, { password, socialLogin }) {
|
export async function createUser(
|
||||||
|
username: string,
|
||||||
|
email: string,
|
||||||
|
{ password, socialLogin }: { password?: string; socialLogin?: SocialLogin }
|
||||||
|
) {
|
||||||
const user = new User({
|
const user = new User({
|
||||||
username,
|
username,
|
||||||
email,
|
email,
|
||||||
@@ -2,11 +2,11 @@ import jwt from 'jsonwebtoken'
|
|||||||
import bcrypt from 'bcrypt'
|
import bcrypt from 'bcrypt'
|
||||||
import config from '../config.js'
|
import config from '../config.js'
|
||||||
|
|
||||||
export function hashPassword(password) {
|
export function hashPassword(password: string): Promise<string> {
|
||||||
return bcrypt.hash(password, 10)
|
return bcrypt.hash(password, 10)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function genJWT(payload) {
|
export function genJWT(payload: any): Promise<string> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
jwt.sign(
|
jwt.sign(
|
||||||
payload,
|
payload,
|
||||||
@@ -15,6 +15,8 @@ export function genJWT(payload) {
|
|||||||
(err, token) => {
|
(err, token) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
reject(err)
|
reject(err)
|
||||||
|
} else if (token === undefined) {
|
||||||
|
reject(new Error('Token is undefined'))
|
||||||
} else {
|
} else {
|
||||||
resolve(token)
|
resolve(token)
|
||||||
}
|
}
|
||||||
@@ -23,7 +25,7 @@ export function genJWT(payload) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function verifyJWT(token) {
|
export function verifyJWT(token: string): Promise<any> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
jwt.verify(token, config.secret, (err, decoded) => {
|
jwt.verify(token, config.secret, (err, decoded) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
import crypto from 'crypto'
|
|
||||||
|
|
||||||
export function get(key, defaultValue) {
|
|
||||||
const value = process.env[key]
|
|
||||||
if (value != null) {
|
|
||||||
return value
|
|
||||||
}
|
|
||||||
return defaultValue
|
|
||||||
}
|
|
||||||
|
|
||||||
export function genSecret() {
|
|
||||||
return crypto.randomUUID()
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
import crypto from 'crypto'
|
||||||
|
|
||||||
|
export function get<T>(key: string, defaultValue: T): T {
|
||||||
|
const value = process.env[key]
|
||||||
|
return value !== undefined ? (value as unknown as T) : defaultValue
|
||||||
|
}
|
||||||
|
|
||||||
|
export function genSecret() {
|
||||||
|
return crypto.randomUUID()
|
||||||
|
}
|
||||||
File renamed without changes.
@@ -8,7 +8,10 @@ import logger from './logger.js'
|
|||||||
const questDirectory = path.join(process.cwd(), '..', 'quests')
|
const questDirectory = path.join(process.cwd(), '..', 'quests')
|
||||||
|
|
||||||
class QuestValidationError extends Error {
|
class QuestValidationError extends Error {
|
||||||
constructor(message, questId, error) {
|
questId: string
|
||||||
|
error: any
|
||||||
|
|
||||||
|
constructor(message: string, questId: string, error: any) {
|
||||||
super(message)
|
super(message)
|
||||||
this.name = 'QuestValidationError'
|
this.name = 'QuestValidationError'
|
||||||
this.questId = questId
|
this.questId = questId
|
||||||
@@ -16,7 +19,10 @@ class QuestValidationError extends Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function mapQuests(callback) {
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
type QuestCallback = (id: string, questPath: string) => Promise<any>
|
||||||
|
|
||||||
|
async function mapQuests(callback: QuestCallback) {
|
||||||
const questNames = await fs.readdir(questDirectory, {
|
const questNames = await fs.readdir(questDirectory, {
|
||||||
withFileTypes: true,
|
withFileTypes: true,
|
||||||
})
|
})
|
||||||
@@ -44,7 +50,7 @@ export async function loadAndUpdateQuests() {
|
|||||||
return mapQuests(async (id, questPath) => {
|
return mapQuests(async (id, questPath) => {
|
||||||
const files = await fs.readdir(questPath)
|
const files = await fs.readdir(questPath)
|
||||||
if (!files.includes('game.yml')) {
|
if (!files.includes('game.yml')) {
|
||||||
throw new QuestValidationError(`Missing game.yml`, id)
|
throw new QuestValidationError(`Missing game.yml`, id, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
File renamed without changes.
@@ -1351,6 +1351,15 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"@types/bcrypt@npm:^5.0.2":
|
||||||
|
version: 5.0.2
|
||||||
|
resolution: "@types/bcrypt@npm:5.0.2"
|
||||||
|
dependencies:
|
||||||
|
"@types/node": "npm:*"
|
||||||
|
checksum: 10c0/dd7f05e183b9b1fc08ec499069febf197ab8e9c720766b5bbb5628395082e248f9a444c60882fe7788361fcadc302e21e055ab9c26a300f100e08791c353e6aa
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"@types/body-parser@npm:*":
|
"@types/body-parser@npm:*":
|
||||||
version: 1.19.5
|
version: 1.19.5
|
||||||
resolution: "@types/body-parser@npm:1.19.5"
|
resolution: "@types/body-parser@npm:1.19.5"
|
||||||
@@ -1484,6 +1493,15 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"@types/jsonwebtoken@npm:^9.0.5":
|
||||||
|
version: 9.0.5
|
||||||
|
resolution: "@types/jsonwebtoken@npm:9.0.5"
|
||||||
|
dependencies:
|
||||||
|
"@types/node": "npm:*"
|
||||||
|
checksum: 10c0/c582b8420586f3b9550f7e34992cb32be300bc953636f3b087ed9c180ce7ea5c2e4b35090be2d57f0d3168cc3ca1074932907caa2afe09f4e9c84cf5c0daefa8
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"@types/mime@npm:*":
|
"@types/mime@npm:*":
|
||||||
version: 3.0.4
|
version: 3.0.4
|
||||||
resolution: "@types/mime@npm:3.0.4"
|
resolution: "@types/mime@npm:3.0.4"
|
||||||
@@ -1507,6 +1525,35 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"@types/oauth@npm:*":
|
||||||
|
version: 0.9.4
|
||||||
|
resolution: "@types/oauth@npm:0.9.4"
|
||||||
|
dependencies:
|
||||||
|
"@types/node": "npm:*"
|
||||||
|
checksum: 10c0/fcf8f5db7756a3e4d406ce3520abf78fecaf5e14963ad75fe0057425bb8b754e98d09dcb2b73a70e8fbe1e345b7d972d8090cf8cf08247e80d6eaac3acbe3fc7
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"@types/passport-oauth2@npm:^1.4.15":
|
||||||
|
version: 1.4.15
|
||||||
|
resolution: "@types/passport-oauth2@npm:1.4.15"
|
||||||
|
dependencies:
|
||||||
|
"@types/express": "npm:*"
|
||||||
|
"@types/oauth": "npm:*"
|
||||||
|
"@types/passport": "npm:*"
|
||||||
|
checksum: 10c0/3f2b1c5c96ce0a1af9d55c07b18d68e443adccd9c5d429c0b08c6e35f0ca259bf77c29cecf2b94c1a035ce7c1c84087a2528e5ecc5ecfa0fba543e158bab7427
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"@types/passport@npm:*, @types/passport@npm:^1.0.16":
|
||||||
|
version: 1.0.16
|
||||||
|
resolution: "@types/passport@npm:1.0.16"
|
||||||
|
dependencies:
|
||||||
|
"@types/express": "npm:*"
|
||||||
|
checksum: 10c0/7120c1186c8c67e3818683b5b6a4439d102f67da93cc1c7d8f32484f7bf10e8438dd5de0bf571910b23d06caa43dd1ad501933b48618bfaf54e63219500993fe
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"@types/qs@npm:*":
|
"@types/qs@npm:*":
|
||||||
version: 6.9.11
|
version: 6.9.11
|
||||||
resolution: "@types/qs@npm:6.9.11"
|
resolution: "@types/qs@npm:6.9.11"
|
||||||
@@ -1577,6 +1624,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"@types/validator@npm:^13.11.9":
|
||||||
|
version: 13.11.9
|
||||||
|
resolution: "@types/validator@npm:13.11.9"
|
||||||
|
checksum: 10c0/856ebfcfe25d6c91a90235e0eb27302a737832530898195bbfb265da52ae7fe6d68f684942574f8818d3c262cae7a1de99f145dac73fc57217933af1bfc199cb
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"@types/webidl-conversions@npm:*":
|
"@types/webidl-conversions@npm:*":
|
||||||
version: 7.0.3
|
version: 7.0.3
|
||||||
resolution: "@types/webidl-conversions@npm:7.0.3"
|
resolution: "@types/webidl-conversions@npm:7.0.3"
|
||||||
@@ -8433,8 +8487,13 @@ __metadata:
|
|||||||
"@linux-odyssey/file-graph": "npm:*"
|
"@linux-odyssey/file-graph": "npm:*"
|
||||||
"@linux-odyssey/models": "npm:*"
|
"@linux-odyssey/models": "npm:*"
|
||||||
"@linux-odyssey/utils": "npm:*"
|
"@linux-odyssey/utils": "npm:*"
|
||||||
|
"@types/bcrypt": "npm:^5.0.2"
|
||||||
"@types/express": "npm:^4.17.21"
|
"@types/express": "npm:^4.17.21"
|
||||||
"@types/express-session": "npm:^1.17.10"
|
"@types/express-session": "npm:^1.17.10"
|
||||||
|
"@types/jsonwebtoken": "npm:^9.0.5"
|
||||||
|
"@types/passport": "npm:^1.0.16"
|
||||||
|
"@types/passport-oauth2": "npm:^1.4.15"
|
||||||
|
"@types/validator": "npm:^13.11.9"
|
||||||
bcrypt: "npm:^5.1.1"
|
bcrypt: "npm:^5.1.1"
|
||||||
commander: "npm:^11.0.0"
|
commander: "npm:^11.0.0"
|
||||||
concurrently: "npm:^8.2.2"
|
concurrently: "npm:^8.2.2"
|
||||||
|
|||||||
Reference in new issue
Block a user