Introduces legacy endpoints for login, joinserver, and checkserver, along with their input validation schemas. Updates sessionsService with joinLegacyServer to support legacy session handling. This enables compatibility with legacy clients requiring these authentication flows.
178 lines
5.4 KiB
JavaScript
178 lines
5.4 KiB
JavaScript
const utils = require("../modules/utils")
|
|
const authRepository = require("../repositories/authRepository")
|
|
const sessionRepository = require("../repositories/sessionsRepository")
|
|
const { DefaultError } = require("../errors/errors")
|
|
|
|
async function registerLegacySession({ uuid, sessionId }) {
|
|
try {
|
|
await sessionRepository.insertLegacyClientSessions(sessionId, uuid)
|
|
return { code: 200 }
|
|
} catch (error) {
|
|
if (error instanceof DefaultError) throw error
|
|
throw new DefaultError(500, "Internal Server Error", error.toString())
|
|
}
|
|
}
|
|
|
|
async function validateLegacySession({ name, sessionId }) {
|
|
let userResult
|
|
try {
|
|
userResult = await authRepository.getUser(name)
|
|
} catch (error) {
|
|
if (error.code === 404) {
|
|
throw error
|
|
}
|
|
throw error
|
|
}
|
|
|
|
try {
|
|
await sessionRepository.validateLegacyClientSession(sessionId, userResult.user.uuid)
|
|
return { code: 200 }
|
|
} catch (error) {
|
|
if (error.code === 404) {
|
|
throw new DefaultError(403, "Invalid session.", "ForbiddenOperationException")
|
|
}
|
|
throw error
|
|
}
|
|
}
|
|
|
|
async function getBlockedServers() {
|
|
try {
|
|
return await sessionRepository.getBlockedServers()
|
|
} catch (error) {
|
|
throw new DefaultError(500, "Unable to fetch blocked servers.", error.toString())
|
|
}
|
|
}
|
|
|
|
async function getProfile({ uuid, unsigned = false }) {
|
|
let userResult
|
|
try {
|
|
userResult = await authRepository.getUser(uuid, false)
|
|
} catch (error) {
|
|
if (error.code === 404) {
|
|
return { code: 204, message: "User not found" }
|
|
}
|
|
throw error
|
|
}
|
|
|
|
const dbUser = userResult.user
|
|
const username = dbUser.username
|
|
const cleanUuid = dbUser.uuid.replace(/-/g, "")
|
|
|
|
const [skinResult, capeResult, actionsResult] = await Promise.all([
|
|
sessionRepository.getActiveSkin(dbUser.uuid).catch(() => ({ data: null })),
|
|
sessionRepository.getActiveCape(dbUser.uuid).catch(() => ({ data: null })),
|
|
sessionRepository.getProfileActionsList(dbUser.uuid).catch(() => ({ data: [] }))
|
|
])
|
|
|
|
const activeSkin = skinResult.data
|
|
const activeCape = capeResult.data
|
|
const profileActions = actionsResult.data || []
|
|
|
|
const isSkinBanned = profileActions.includes("USING_BANNED_SKIN")
|
|
const hasValidSkin = activeSkin && !isSkinBanned
|
|
const hasValidCape = !!activeCape
|
|
|
|
const skinNode = hasValidSkin ? {
|
|
url: (process.env.TEXTURES_ENDPOINTS || `http://localhost:${process.env.WEB_PORT}/textures`) + activeSkin.url,
|
|
metadata: activeSkin.variant === "SLIM" ? { model: "slim" } : undefined
|
|
} : undefined
|
|
|
|
const capeNode = hasValidCape ? {
|
|
url: (process.env.TEXTURES_ENDPOINTS || `http://localhost:${process.env.WEB_PORT}/textures`) + activeCape.url
|
|
} : undefined
|
|
|
|
const texturesObject = {
|
|
...(skinNode && { SKIN: skinNode }),
|
|
...(capeNode && { CAPE: capeNode })
|
|
}
|
|
|
|
const texturePayload = {
|
|
timestamp: Date.now(),
|
|
profileId: cleanUuid,
|
|
profileName: username,
|
|
signatureRequired: !unsigned,
|
|
textures: texturesObject
|
|
}
|
|
|
|
const payloadJson = JSON.stringify(texturePayload)
|
|
const base64Value = Buffer.from(payloadJson).toString("base64")
|
|
|
|
const signature = unsigned ? null : utils.signProfileData(base64Value)
|
|
|
|
const propertyNode = {
|
|
name: "textures",
|
|
value: base64Value,
|
|
...(signature && { signature: signature })
|
|
}
|
|
|
|
return {
|
|
code: 200,
|
|
data: {
|
|
id: cleanUuid,
|
|
name: username,
|
|
properties: [propertyNode],
|
|
profileActions: profileActions
|
|
}
|
|
}
|
|
}
|
|
|
|
async function joinServer({ accessToken, selectedProfile, clientToken, serverId, ip }) {
|
|
try {
|
|
await authRepository.validateClientSession(accessToken, clientToken)
|
|
} catch (error) {
|
|
throw new DefaultError(403, "Invalid access token", "ForbiddenOperationException")
|
|
}
|
|
await sessionRepository.saveServerSession(selectedProfile, accessToken, serverId, ip)
|
|
return { code: 204 }
|
|
}
|
|
|
|
async function hasJoinedServer({ username, serverId, ip }) {
|
|
let userResult
|
|
try {
|
|
userResult = await authRepository.getUser(username, false)
|
|
} catch (error) {
|
|
if (error.code === 404) return { code: 204, message: "User not found" }
|
|
throw error
|
|
}
|
|
|
|
const { uuid } = userResult.user
|
|
const joinCheck = await sessionRepository.getServerSession(uuid, serverId)
|
|
|
|
if (joinCheck.code !== 200 || !joinCheck.valid) {
|
|
return { code: 204, message: "Join verification failed" }
|
|
}
|
|
|
|
if (ip && ip.trim() !== "" && joinCheck.ip !== ip) {
|
|
return { code: 204, message: "Invalid IP address" }
|
|
}
|
|
|
|
return await getProfile({
|
|
uuid: uuid,
|
|
unsigned: false
|
|
})
|
|
}
|
|
|
|
async function joinLegacyServer({ name, sessionId, serverId }) {
|
|
try {
|
|
await validateLegacySession({ name, sessionId })
|
|
} catch (error) {
|
|
throw new DefaultError(403, "Bad login", "ForbiddenOperationException")
|
|
}
|
|
|
|
const userResult = await authRepository.getUser(name)
|
|
const uuid = userResult.user.uuid
|
|
|
|
await sessionRepository.saveServerSession(uuid, sessionId, serverId, "0.0.0.0")
|
|
|
|
return { code: 200, message: "OK" }
|
|
}
|
|
|
|
module.exports = {
|
|
getProfile,
|
|
joinServer,
|
|
hasJoinedServer,
|
|
joinLegacyServer,
|
|
getBlockedServers,
|
|
registerLegacySession,
|
|
validateLegacySession,
|
|
} |