Skip to content

Commit

Permalink
Merge pull request #7 from crybapp/master
Browse files Browse the repository at this point in the history
Catchup
  • Loading branch information
Soliel authored Dec 7, 2019
2 parents 01bf237 + beffb19 commit 4d93312
Show file tree
Hide file tree
Showing 18 changed files with 147 additions and 52 deletions.
17 changes: 17 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# editorconfig.org

root = true

[*]
charset = utf-8
end_of_line = lf
indent_size = 4
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true

[*.md]
trim_trailing_whitespace = false

[*.json]
indent_size = 2
10 changes: 8 additions & 2 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ PORTALS_API_KEY=api-portals-key

# The base WS endpoint that is used to talk to @cryb/aperture which is sent to the client via WS once the stream is ready
APERTURE_WS_URL=ws://localhost:9001
# This should the same secure key in @cryb/aperture/.env under 'APERTURE_WS_KEY'
# This should be the same secure key in @cryb/aperture/.env under 'APERTURE_KEY'
APERTURE_WS_KEY=api-aperture-key

# The URI used for connecting to the MongoDB database
Expand All @@ -30,7 +30,7 @@ DISCORD_CLIENT_ID=
DISCORD_CLIENT_SECRET=
DISCORD_CALLBACK_URL=http://localhost:3000/auth/discord

# This should be a list of comma-separated (not space) Oauth2 Redirect URLs
# This should be a list of comma (,) separated (not space) Discord OAuth2 Redirect URLs
DISCORD_OAUTH_ORIGINS=http://localhost:3000

# Optional: User Configurable
Expand All @@ -40,3 +40,9 @@ DISCORD_OAUTH_ORIGINS=http://localhost:3000

# The amount of members a room needs to hit for a Portal (VM) to be created / queued (default 2)
# MIN_MEMBER_PORTAL_CREATION_COUNT=2

# Whenever destroy portals when room gets empty
# DESTROY_PORTAL_WHEN_EMPTY=true

# The timeout before an empty room gets their portal destroyed in seconds (default 5)
# EMPTY_ROOM_PORTAL_DESTROY=5
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

_**API** - Core services_

[![GitHub contributors](https://img.shields.io/github/contributors/crybapp/api)](https://github.com/crybapp/api/graphs/contributors) [![License](https://img.shields.io/github/license/crybapp/api)](https://github.com/crybapp/api/blob/master/LICENSE) [![PayPal Donate](https://img.shields.io/badge/donate-PayPal-blue.svg)](https://paypal.me/williamsthing)
[![GitHub contributors](https://img.shields.io/github/contributors/crybapp/api)](https://github.com/crybapp/api/graphs/contributors) [![License](https://img.shields.io/github/license/crybapp/api)](https://github.com/crybapp/api/blob/master/LICENSE) [![Patreon Donate](https://img.shields.io/badge/donate-Patreon-red.svg)](https://patreon.com/cryb)

## Docs
* [Info](#info)
Expand Down Expand Up @@ -83,4 +83,4 @@ It is recommended that in production you run `yarn build`, then `yarn start`.

## Questions / Issues

If you have an issues with `@cryb/api`, please either open a GitHub issue, contact a maintainer or join the [Cryb Discord Server](https://discord.gg/ShTATH4) and ask in #tech-support.
If you have an issues with `@cryb/api`, please either open a GitHub issue, contact a maintainer or join the [Cryb Discord Server](https://discord.gg/ShTATH4) and ask in #tech-support.
13 changes: 12 additions & 1 deletion src/config/defaults.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,16 @@ export default {
/**
* The maximum amount of members a room can have (default 10)
*/
max_room_member_count: parseInt(process.env.MAX_ROOM_MEMBER_COUNT || '10')
max_room_member_count: parseInt(process.env.MAX_ROOM_MEMBER_COUNT || '10'),

/**
* Whenever destroy portals when room gets empty
*/
destroy_portal_when_empty: typeof process.env.DESTROY_PORTAL_WHEN_EMPTY !== 'undefined' ?
(process.env.DESTROY_PORTAL_WHEN_EMPTY === 'true') : true,

/**
* The timeout before an empty room gets their portal destroyed in seconds (default 5)
*/
empty_room_portal_destroy: parseInt(process.env.EMPTY_ROOM_PORTAL_DESTROY || '5')
}
8 changes: 4 additions & 4 deletions src/controllers/internal.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@ app.put('/portal', authenticate, async (req, res) => {

try {
const doc = await StoredRoom.findOne({ 'info.portal.id': id })
if(!doc) throw RoomNotFound
if(!doc) return RoomNotFound

console.log('room found, updating status...')

const room = new Room(doc)
const { portal: allocation } = await room.updatePortalAllocation({ status }),
{ online } = await room.fetchOnlineMemberIds()
Expand All @@ -57,7 +57,7 @@ app.put('/portal', authenticate, async (req, res) => {
if(status === 'open') {
const token = signApertureToken(id), apertureMessage = new WSMessage(0, { ws: process.env.APERTURE_WS_URL, t: token }, 'APERTURE_CONFIG')
apertureMessage.broadcast(online)
}
}
}

res.sendStatus(200)
Expand All @@ -73,7 +73,7 @@ app.post('/queue', authenticate, (req, res) => {
try {
const op = 0, d = { pos: i, len: queue.length }, t = 'PORTAL_QUEUE_UPDATE',
message = new WSMessage(op, d, t)

message.broadcastRoom(id)
} catch(error) {
console.error(error)
Expand Down
27 changes: 26 additions & 1 deletion src/controllers/room.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@ import express from 'express'
import User from '../models/user'
import Room from '../models/room'

import { RoomType } from '../models/room/defs'

import { extractUserId } from '../utils/helpers.utils'
import { authenticate } from '../config/passport.config'
import { handleError, UserNotInRoom, UserAlreadyInRoom } from '../utils/errors.utils'

const app = express()
const app = express(),
AVAILABLE_TYPES: RoomType[] = ['vm']

app.get('/', authenticate, async (req, res) => {
const { user } = req as { user: User }
Expand Down Expand Up @@ -132,6 +135,28 @@ app.post('/leave', authenticate, async (req, res) => {
}
})

app.patch('/type', authenticate, async (req, res) => {
const { user } = req as { user: User }, { type } = req.body as { type: RoomType }
if(!user.room) return handleError(UserNotInRoom, res)

if(typeof user.room === 'string')
return res.status(500)

if(extractUserId(user.room.owner) !== user.id)
return res.status(401)

if(AVAILABLE_TYPES.indexOf(type) === -1)
return res.status(406)

try {
await user.room.updateType(type)

res.sendStatus(200)
} catch(error) {
handleError(error, res)
}
})

app.use('/member', require('./member.controller').default)
app.use('/message', require('./message.controller').default)
app.use('/controller', require('./controller.controller').default)
Expand Down
8 changes: 4 additions & 4 deletions src/drivers/portals.driver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export const createPortal = (room: Room) => new Promise(async (resolve, reject)
try {
const headers = await generateHeaders(room)
log(`Sending request to ${url}create with room id: ${room.id}`, [ { content: 'portals', color: 'MAGENTA' }])

await axios.post(`${url}create`, { roomId: room.id }, { headers })

resolve()
Expand All @@ -30,10 +30,10 @@ export const createPortal = (room: Room) => new Promise(async (resolve, reject)
export const destroyPortal = (room: Room) => new Promise(async (resolve, reject) => {
try {
const headers = await generateHeaders(room), { portal } = room
if(!portal.id) throw NoPortalFound
if(!portal.id) return

await axios.delete(`${url}${portal.id}`, { headers })

resolve()
} catch(error) {
reject(error)
Expand Down
9 changes: 6 additions & 3 deletions src/models/room/defs.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import { Document } from 'mongoose'

export type RoomType = 'vm'

/**
* open - The portal is open
* starting - The portal has been created and is now starting
* creating - The portal is currently being created by the microservice
* in-queue - The portal is in a queue to be created by the microservice
* requested - A portal has been requested and is being allocated by the microservice
* waiting - The room is waiting until the right conditions are met for the microservice to be contacted
*
*
* error - An error occured
* closed - The portal was closed for one reason or another
*/
Expand All @@ -27,8 +29,9 @@ export default interface IRoom {
createdAt: number
endedAt?: number

portal: PortalAllocation

type: RoomType
portal?: PortalAllocation

owner: string
controller: string
}
Expand Down
30 changes: 26 additions & 4 deletions src/models/room/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import StoredUser from '../../schemas/user.schema'
import StoredInvite from '../../schemas/invite.schema'
import StoredMessage from '../../schemas/message.schema'

import IRoom, { PortalAllocation } from './defs'
import StoredRoom from '../../schemas/room.schema'
import IRoom, { PortalAllocation, RoomType } from './defs'
import { destroyPortal, createPortal } from '../../drivers/portals.driver'

import client from '../../config/redis.config'
Expand All @@ -22,12 +22,13 @@ export default class Room {
id: string
createdAt: number
endedAt?: number


type: RoomType
active: boolean
invites: Invite[]
owner: UserResolvable

portal: PortalAllocation
portal?: PortalAllocation
controller: UserResolvable

name: string
Expand All @@ -46,7 +47,7 @@ export default class Room {
load = (id: string) => new Promise<Room>(async (resolve, reject) => {
try {
const doc = await StoredRoom.findOne({ 'info.id': id })
if(!doc) throw RoomNotFound
if(!doc) return reject(RoomNotFound)

this.setup(doc)

Expand All @@ -66,6 +67,8 @@ export default class Room {
info: {
id: generateFlake(),
createdAt: Date.now(),

type: 'vm',
portal: {
status: 'waiting',
lastUpdatedAt: Date.now()
Expand Down Expand Up @@ -407,6 +410,24 @@ export default class Room {
delete this.portal
}

updateType = (type: RoomType) => new Promise<Room>(async (resolve, reject) => {
try {
await StoredRoom.updateOne({
'info.id': this.id
}, {
$set: {
'info.type': type
}
})

this.type = type

resolve(this)
} catch(error) {
reject(error)
}
})

destroy = () => new Promise(async (resolve, reject) => {
try {
const message = new WSMessage(0, {}, 'ROOM_DESTROY')
Expand Down Expand Up @@ -438,6 +459,7 @@ export default class Room {
this.createdAt = json.info.createdAt
this.endedAt = json.info.endedAt

this.type = json.info.type
this.portal = json.info.portal

this.owner = json.info.owner
Expand Down
6 changes: 3 additions & 3 deletions src/models/user/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export default class User {
username: string

roles: Role[]

name: string
icon: string

Expand All @@ -47,7 +47,7 @@ export default class User {

if(this.room)
await this.fetchRoom()

resolve(this)
} catch(error) {
reject(error)
Expand Down Expand Up @@ -85,7 +85,7 @@ export default class User {
'security.credentials.refreshToken': refreshToken
}
})

resolve(this)
} else {
const json: IUser = {
Expand Down
7 changes: 4 additions & 3 deletions src/schemas/room.schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,17 @@ const RoomSchema = new Schema({
id: String,
createdAt: Number,
endedAt: Number,

owner: String,
invite: String,

type: String,
portal: {
id: String,

status: String,
lastUpdatedAt: String
},

owner: String,
invite: String,
controller: String
},
profile: {
Expand Down
4 changes: 2 additions & 2 deletions src/server/websocket/handlers/internal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ export interface WSInternalEvent {
}

export default (message: WSEvent, recipients: string[], sync: boolean, wss: Server) => {
if(recipients.length === 0) return
logMessage(message, recipients)
if (recipients.length === 0) return
if (process.env.NODE_ENV !== 'production') logMessage(message, recipients)

let delivered = []

Expand Down
6 changes: 4 additions & 2 deletions src/server/websocket/handlers/message.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import client, { createPubSubClient } from '../../../config/redis.config'
import WSEvent, { WSEventType } from '../models/event'
import WSSocket from '../models/socket'
import WSMessage from '../models/message'
import User from '../../../models/user'

import logMessage from '../log'
import { validateControllerEvent } from '../../../utils/validate.utils'
Expand All @@ -13,18 +14,19 @@ const pub = createPubSubClient(),

export default async (message: WSEvent, socket: WSSocket) => {
const { op, d, t } = message
logMessage(message)
if (process.env.NODE_ENV !== 'production') logMessage(message)

if(op === 0) {
if(t === 'TYPING_UPDATE') {
const message = new WSMessage(0, { u: socket.user.id, typing: !!d.typing }, 'TYPING_UPDATE')
message.broadcastRoom(socket.user.room, [ socket.user.id ])
} else if(CONTROLLER_EVENT_TYPES.indexOf(t) > -1){
if(!validateControllerEvent(d, t)) return

if(!socket.user) return // Check if the socket is actually authenticated
if(!socket.user.room) return // Check if the user is in a room
if(typeof socket.user.room === 'string') return // Check if room is unreadable
if(!socket.user.room.portal.id) socket.set('user', await new User().load(socket.user.id)) // Workaround for controller bug
if(await client.hget('controller', extractRoomId(socket.user.room)) !== extractUserId(socket.user)) return // Check if the user has the controller

pub.publish('portals', JSON.stringify({
Expand Down
Loading

0 comments on commit 4d93312

Please sign in to comment.