mirror of
https://github.com/ragestudio/comty.git
synced 2025-07-08 08:44:15 +00:00
Refactor users service routes and add websocket support
- Standardize middleware naming to useMiddlewares - Add websocket support and handleWsUpgrade to users service - Update getFollowers to support pagination and return metadata - Emit user update events via websockets - Add linebridge^1.0.0 dependency - Minor code style and consistency improvements across routes
This commit is contained in:
parent
35df3a421f
commit
33fe2044c4
@ -1,35 +1,44 @@
|
||||
import { User, UserFollow } from "@db_models"
|
||||
|
||||
export default async (payload = {}) => {
|
||||
const { user_id, data = false, limit = 50, offset = 0 } = payload
|
||||
const { user_id, data = false, limit = 50, page = 0 } = payload
|
||||
|
||||
if (!user_id) {
|
||||
throw new OperationError(400, "Missing user_id")
|
||||
}
|
||||
|
||||
if (data) {
|
||||
const total_followers = await UserFollow.countDocuments({
|
||||
to: user_id,
|
||||
})
|
||||
|
||||
if (data === true) {
|
||||
let followers = await UserFollow.find({
|
||||
to: user_id,
|
||||
})
|
||||
.limit(limit)
|
||||
.skip(offset)
|
||||
.skip(limit * page)
|
||||
.lean()
|
||||
|
||||
followers = followers.map((follow) => {
|
||||
return follow.user_id
|
||||
})
|
||||
|
||||
const followersData = await User.find({
|
||||
_id: {
|
||||
$in: followers.map((follow) => {
|
||||
return follow.user_id
|
||||
}),
|
||||
$in: followers,
|
||||
},
|
||||
})
|
||||
|
||||
return followersData
|
||||
} else {
|
||||
const count = await UserFollow.countDocuments({
|
||||
to: user_id,
|
||||
})
|
||||
const nextPage = page + 1
|
||||
|
||||
return {
|
||||
count,
|
||||
items: followersData,
|
||||
total_items: total_followers,
|
||||
has_more: total_followers > limit * nextPage,
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
count: total_followers,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,5 +25,13 @@ export default async (user_id, update) => {
|
||||
|
||||
user = user.toObject()
|
||||
|
||||
const userSockets = await global.websockets.find.clientsByUserId(
|
||||
user._id.toString(),
|
||||
)
|
||||
|
||||
for (const userSocket of userSockets) {
|
||||
userSocket.emit(`self:user:update`, user)
|
||||
}
|
||||
|
||||
return user
|
||||
}
|
||||
|
@ -1,3 +1,6 @@
|
||||
{
|
||||
"name": "users"
|
||||
"name": "users",
|
||||
"dependencies": {
|
||||
"linebridge": "^1.0.0-alpha.4"
|
||||
}
|
||||
}
|
||||
|
@ -5,17 +5,17 @@ export default {
|
||||
const { user_id } = req.params
|
||||
|
||||
const user = await User.findOne({
|
||||
_id: user_id
|
||||
_id: user_id,
|
||||
}).catch((err) => {
|
||||
return false
|
||||
})
|
||||
|
||||
const badges = await Badge.find({
|
||||
name: {
|
||||
$in: user.badges
|
||||
}
|
||||
$in: user.badges,
|
||||
},
|
||||
})
|
||||
|
||||
return badges
|
||||
}
|
||||
},
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
import Users from "@classes/users"
|
||||
|
||||
export default {
|
||||
middlewares: ["withOptionalAuthentication"],
|
||||
useMiddlewares: ["withOptionalAuthentication"],
|
||||
fn: async (req) => {
|
||||
const { user_id } = req.params
|
||||
|
||||
@ -10,7 +10,7 @@ export default {
|
||||
return await Users.data({
|
||||
user_id: ids.length > 1 ? ids : user_id,
|
||||
from_user_id: req.auth?.session.user_id,
|
||||
basic: req.query?.basic,
|
||||
basic: ToBoolean(req.query?.basic),
|
||||
})
|
||||
},
|
||||
}
|
||||
|
@ -1,12 +1,12 @@
|
||||
import User from "@classes/users"
|
||||
|
||||
export default {
|
||||
middlewares: ["withAuthentication"],
|
||||
useMiddlewares: ["withAuthentication"],
|
||||
fn: async (req) => {
|
||||
return await User.toggleFollow({
|
||||
user_id: req.params.user_id,
|
||||
from_user_id: req.auth.session.user_id,
|
||||
to: req.body?.to,
|
||||
})
|
||||
}
|
||||
},
|
||||
}
|
@ -5,8 +5,8 @@ export default {
|
||||
return await User.getFollowers({
|
||||
user_id: req.params.user_id,
|
||||
data: ToBoolean(req.query.fetchData),
|
||||
limit: req.query.limit,
|
||||
offset: req.query.offset,
|
||||
limit: parseInt(req.query.limit),
|
||||
page: parseInt(req.query.page),
|
||||
})
|
||||
}
|
||||
},
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
import { UserPublicKey } from "@db_models"
|
||||
|
||||
export default {
|
||||
middlewares: ["withAuthentication"],
|
||||
useMiddlewares: ["withAuthentication"],
|
||||
fn: async (req) => {
|
||||
const targetUserId = req.params.user_id
|
||||
|
||||
|
@ -1,12 +1,12 @@
|
||||
import Users from "@classes/users"
|
||||
|
||||
export default {
|
||||
middlewares: ["withOptionalAuthentication"],
|
||||
useMiddlewares: ["withOptionalAuthentication"],
|
||||
fn: async (req) => {
|
||||
const data = await Users.data({
|
||||
user_id: req.auth.session.user_id,
|
||||
})
|
||||
|
||||
return data.roles
|
||||
}
|
||||
},
|
||||
}
|
@ -1,18 +1,18 @@
|
||||
import { UserConfig } from "@db_models"
|
||||
|
||||
export default {
|
||||
middlewares: ["withAuthentication"],
|
||||
useMiddlewares: ["withAuthentication"],
|
||||
fn: async (req) => {
|
||||
const key = req.query.key
|
||||
|
||||
let config = await UserConfig.findOne({
|
||||
user_id: req.auth.session.user_id
|
||||
user_id: req.auth.session.user_id,
|
||||
})
|
||||
|
||||
if (!config) {
|
||||
config = await UserConfig.create({
|
||||
user_id: req.auth.session.user_id,
|
||||
values: {}
|
||||
values: {},
|
||||
})
|
||||
}
|
||||
|
||||
@ -21,5 +21,5 @@ export default {
|
||||
}
|
||||
|
||||
return config.values
|
||||
}
|
||||
},
|
||||
}
|
@ -5,20 +5,20 @@ const baseConfig = [
|
||||
{
|
||||
key: "app:language",
|
||||
type: "string",
|
||||
value: "en-us"
|
||||
value: "en-us",
|
||||
},
|
||||
{
|
||||
key: "auth:mfa",
|
||||
type: "boolean",
|
||||
value: false
|
||||
value: false,
|
||||
},
|
||||
]
|
||||
|
||||
export default {
|
||||
middlewares: ["withAuthentication"],
|
||||
useMiddlewares: ["withAuthentication"],
|
||||
fn: async (req) => {
|
||||
let config = await UserConfig.findOne({
|
||||
user_id: req.auth.session.user_id
|
||||
user_id: req.auth.session.user_id,
|
||||
})
|
||||
|
||||
const values = {}
|
||||
@ -29,33 +29,38 @@ export default {
|
||||
if (typeof fromBody === config.type) {
|
||||
values[config.key] = req.body[config.key]
|
||||
} else {
|
||||
throw new OperationError(400, `Invalid type for ${config.key}`)
|
||||
throw new OperationError(
|
||||
400,
|
||||
`Invalid type for ${config.key}`,
|
||||
)
|
||||
}
|
||||
} else {
|
||||
values[config.key] = config.value
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
if (!config) {
|
||||
config = await UserConfig.create({
|
||||
user_id: req.auth.session.user_id,
|
||||
values
|
||||
values,
|
||||
})
|
||||
} else {
|
||||
const newValues = lodash.merge(config.values, values)
|
||||
|
||||
config = await UserConfig.updateOne({
|
||||
user_id: req.auth.session.user_id
|
||||
}, {
|
||||
values: newValues
|
||||
})
|
||||
config = await UserConfig.updateOne(
|
||||
{
|
||||
user_id: req.auth.session.user_id,
|
||||
},
|
||||
{
|
||||
values: newValues,
|
||||
},
|
||||
)
|
||||
|
||||
config = await UserConfig.findOne({
|
||||
user_id: req.auth.session.user_id
|
||||
user_id: req.auth.session.user_id,
|
||||
})
|
||||
}
|
||||
|
||||
return config.values
|
||||
}
|
||||
},
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
import Users from "@classes/users"
|
||||
|
||||
export default {
|
||||
middlewares: ["withAuthentication"],
|
||||
useMiddlewares: ["withAuthentication"],
|
||||
fn: async (req) => {
|
||||
return await Users.data({
|
||||
user_id: req.auth.session.user_id,
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { UserDHKeyPair } from "@db_models"
|
||||
|
||||
export default {
|
||||
middlewares: ["withAuthentication"],
|
||||
useMiddlewares: ["withAuthentication"],
|
||||
fn: async (req) => {
|
||||
const userId = req.auth.session.user_id
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { UserDHKeyPair } from "@db_models"
|
||||
|
||||
export default {
|
||||
middlewares: ["withAuthentication"],
|
||||
useMiddlewares: ["withAuthentication"],
|
||||
fn: async (req) => {
|
||||
const userId = req.auth.session.user_id
|
||||
const { str } = req.body
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { UserPublicKey } from "@db_models"
|
||||
|
||||
export default {
|
||||
middlewares: ["withAuthentication"],
|
||||
useMiddlewares: ["withAuthentication"],
|
||||
fn: async (req) => {
|
||||
const userId = req.auth.session.user_id
|
||||
const { public_key } = req.body
|
||||
|
@ -1,7 +1,7 @@
|
||||
import Users from "@classes/users"
|
||||
|
||||
export default {
|
||||
middlewares: ["withAuthentication"],
|
||||
useMiddlewares: ["withAuthentication"],
|
||||
fn: async (req) => {
|
||||
const data = await Users.data({
|
||||
user_id: user_id,
|
||||
@ -12,5 +12,5 @@ export default {
|
||||
}
|
||||
|
||||
return data.roles
|
||||
}
|
||||
},
|
||||
}
|
@ -19,7 +19,7 @@ const MaxStringsLengths = {
|
||||
}
|
||||
|
||||
export default {
|
||||
middlewares: ["withAuthentication"],
|
||||
useMiddlewares: ["withAuthentication"],
|
||||
fn: async (req) => {
|
||||
const update = {}
|
||||
|
||||
@ -27,10 +27,16 @@ export default {
|
||||
AllowedPublicUpdateFields.forEach((key) => {
|
||||
if (typeof req.body[key] !== "undefined") {
|
||||
// check maximung strings length
|
||||
if (typeof req.body[key] === "string" && MaxStringsLengths[key]) {
|
||||
if (
|
||||
typeof req.body[key] === "string" &&
|
||||
MaxStringsLengths[key]
|
||||
) {
|
||||
if (req.body[key].length > MaxStringsLengths[key]) {
|
||||
// create a substring
|
||||
update[key] = req.body[key].substring(0, MaxStringsLengths[key])
|
||||
update[key] = req.body[key].substring(
|
||||
0,
|
||||
MaxStringsLengths[key],
|
||||
)
|
||||
} else {
|
||||
update[key] = req.body[key]
|
||||
}
|
||||
@ -53,5 +59,5 @@ export default {
|
||||
}
|
||||
|
||||
return await UserClass.update(req.auth.session.user_id, update)
|
||||
}
|
||||
},
|
||||
}
|
@ -4,12 +4,19 @@ import DbManager from "@shared-classes/DbManager"
|
||||
import RedisClient from "@shared-classes/RedisClient"
|
||||
|
||||
import SharedMiddlewares from "@shared-middlewares"
|
||||
import InjectedAuth from "@shared-lib/injectedAuth"
|
||||
|
||||
export default class API extends Server {
|
||||
static refName = "users"
|
||||
static useEngine = "hyper-express"
|
||||
static routesPath = `${__dirname}/routes`
|
||||
static listen_port = process.env.HTTP_LISTEN_PORT ?? 3008
|
||||
static listenPort = process.env.HTTP_LISTEN_PORT ?? 3008
|
||||
|
||||
static useMiddlewares = ["logs"]
|
||||
|
||||
static websockets = {
|
||||
enabled: true,
|
||||
path: "/users",
|
||||
}
|
||||
|
||||
middlewares = {
|
||||
...SharedMiddlewares,
|
||||
@ -20,6 +27,24 @@ export default class API extends Server {
|
||||
redis: RedisClient(),
|
||||
}
|
||||
|
||||
handleWsUpgrade = async (context, token, res) => {
|
||||
if (!token) {
|
||||
return res.upgrade(context)
|
||||
}
|
||||
|
||||
context = await InjectedAuth(context, token, res).catch(() => {
|
||||
res.close(401, "Failed to verify auth token")
|
||||
return false
|
||||
})
|
||||
|
||||
if (!context || !context.user) {
|
||||
res.close(401, "Unauthorized or missing auth token")
|
||||
return false
|
||||
}
|
||||
|
||||
return res.upgrade(context)
|
||||
}
|
||||
|
||||
async onInitialize() {
|
||||
await this.contexts.db.initialize()
|
||||
await this.contexts.redis.initialize()
|
||||
|
Loading…
x
Reference in New Issue
Block a user