Dwayne Harris 5 years ago
parent
commit
3f91c1366a
  1. 3
      src/constants.ts
  2. 31
      src/lib/collections.ts
  3. 17
      src/lib/database.ts
  4. 17
      src/plugins/api/authentication.ts
  5. 14
      src/plugins/api/groups.ts
  6. 4
      src/plugins/api/index.ts
  7. 36
      src/plugins/api/posts.ts
  8. 61
      src/plugins/api/users.ts
  9. 3
      src/types/collections.ts

3
src/constants.ts

@ -0,0 +1,3 @@
export const MAX_ID_LENGTH = 40
export const MAX_NAME_LENGTH = 80
export const SUBSCRIBER_BATCH_SIZE = 100

31
src/lib/collections.ts

@ -1,45 +1,36 @@
import { CosmosClient } from '@azure/cosmos'
import { Logger } from 'fastify'
import uniq from 'lodash/uniq'
import { containerFor, createQuerySpec, IDatabaseItem } from './database'
import { containerFor, createQuerySpec, queryItems, IDatabaseItem } from './database'
import { IUser, IUserSubscription, IUserBlock } from '../types/collections'
export async function getUsers(client: CosmosClient, ids: string[]): Promise<IUser[]> {
const container = await containerFor(client, 'Users')
const { resources: users } = await container.items.query<IUser>(createQuerySpec(
export async function getUsers(client: CosmosClient, ids: string[], logger?: Logger): Promise<IUser[]> {
return await queryItems<IUser>(containerFor(client, 'Users'), createQuerySpec(
'SELECT u.id, u.name, u.imageUrl, u.coverImageUrl, u.group, u.created FROM Users u WHERE ARRAY_CONTAINS(@ids, u.id)', {
ids: uniq(ids),
}), {}).fetchAll()
return users
}), logger)
}
export async function getUsersFromItems<T extends IDatabaseItem>(client: CosmosClient, items: T[]): Promise<IUser[]> {
return await getUsers(client, items.map(i => i.id))
}
export async function getSubscriptions(client: CosmosClient, from: string, to: string): Promise<IUserSubscription[]> {
const query = createQuerySpec(`
export async function getApprovedSubscriptions(client: CosmosClient, from: string, to: string, logger?: Logger): Promise<IUserSubscription[]> {
return await queryItems<IUserSubscription>(containerFor(client, 'Users'), createQuerySpec(`
SELECT u.id FROM Users u WHERE
u.subscriberId = @to
u.partitionKey = @from AND
u.type = 'subscription' AND
u.pending = false
`, { from, to })
const { resources: subscriptions } = await containerFor(client, 'Users').items.query<IUserSubscription>(query, {}).fetchAll()
return subscriptions
`, { from, to }), logger)
}
export async function getUserBlocks(client: CosmosClient, from: string, to: string[]): Promise<IUserBlock[]> {
const query = createQuerySpec(`
export async function getUserBlocks(client: CosmosClient, from: string, to: string[], logger?: Logger): Promise<IUserBlock[]> {
return await queryItems<IUserBlock>(containerFor(client, 'Users'), createQuerySpec(`
SELECT u.id FROM Users u WHERE
u.partitionKey = @from
AND u.type = 'block'
AND ARRAY_CONTAINS(@to, u.blockedId)
`, { from, to })
const { resources: blocks } = await containerFor(client, 'Users').items.query<IUserBlock>(query, {}).fetchAll()
return blocks
`, { from, to }), logger)
}

17
src/lib/database.ts

@ -1,4 +1,5 @@
import { CosmosClient, Container, SqlQuerySpec } from '@azure/cosmos'
import { Logger } from 'fastify'
interface IQueryParams {
[key: string]: string | string[] | number | boolean
@ -24,13 +25,21 @@ export function createQuerySpec(query: string, params: IQueryParams = {}): SqlQu
}
}
export async function queryItems<T>(container: Container, querySpec: SqlQuerySpec): Promise<T[]> {
const { resources } = await container.items.query<T>(querySpec, {}).fetchAll()
export async function queryItems<T>(container: Container, querySpec: SqlQuerySpec, logger?: Logger): Promise<T[]> {
const { resources, requestCharge } = await container.items.query<T>(querySpec, {}).fetchAll()
if (logger) logger.trace('Query: %d', requestCharge)
return resources
}
export async function getItem<T>(container: Container, id: string, partitionKey?: string): Promise<T | undefined> {
const { resource } = await container.item(id, partitionKey || id).read<T>()
export async function getItem<T>(container: Container, id: string, logger?: Logger): Promise<T | undefined>
export async function getItem<T>(container: Container, id: string, partitionKey: string, logger?: Logger): Promise<T | undefined>
export async function getItem<T>(container: Container, id: string, partitionKeyOrLogger?: string | Logger, logger?: Logger): Promise<T | undefined> {
const partitionKey = (typeof partitionKeyOrLogger === 'string') ? partitionKeyOrLogger : id
const { resource, requestCharge } = await container.item(id, partitionKey).read<T>()
if (logger) logger.trace('Get: %d', requestCharge)
return resource
}

17
src/plugins/api/authentication.ts

@ -65,14 +65,14 @@ function registerRoute(server: FastifyInstance<Server, IncomingMessage, ServerRe
if (password.length < 5) return badRequestError(reply, 'password must be at least 5 characters', 'password')
const userContainer = containerFor(server.database.client, 'Users')
const existingUser = await getItem<IUser>(userContainer, id)
const existingUser = await getItem<IUser>(userContainer, id, request.log)
if (existingUser) return badRequestError(reply, 'User id already taken', 'id')
let userPending = false
let groupPartial: IGroupPartial | undefined
if (groupId) {
const group = await getItem<IGroup>(containerFor(server.database.client, 'Groups'), groupId)
const group = await getItem<IGroup>(containerFor(server.database.client, 'Groups'), groupId, request.log)
if (!group) return badRequestError(reply, 'Group not found', 'groupId')
if (!group.open) return badRequestError(reply, 'Group registration closed', 'groupId')
@ -147,12 +147,11 @@ function authenticateRoute(server: FastifyInstance<Server, IncomingMessage, Serv
const container = containerFor(server.database.client, 'Users')
const id = normalize(request.body.id)
const { password } = request.body
const user = await getItem<IUser>(container, id)
const user = await getItem<IUser>(container, id, request.log)
if (!user) return badRequestError(reply, 'User not found')
const result = await verifyPassword(user.passwordHash, password)
const result = await verifyPassword(user.passwordHash, request.body.password)
if (!result) return badRequestError(reply, 'Incorrect credentials')
const refreshToken = createRefreshToken(user.id, request.headers['user-agent'], request.ip)
@ -217,6 +216,7 @@ function refreshRoute(server: FastifyInstance<Server, IncomingMessage, ServerRes
if ((tokenData.exp * 1000) > Date.now()) return badRequestError(reply, 'Token must be expired')
userId = tokenData.sub
} catch (err) {
request.log.error(err)
return badRequestError(reply, 'Invalid token')
}
@ -224,7 +224,8 @@ function refreshRoute(server: FastifyInstance<Server, IncomingMessage, ServerRes
const tokenItem = container.item(request.body.refresh, userId)
if (!tokenItem) return badRequestError(reply, 'Invalid refresh token')
const { resource: token } = await tokenItem.read<IUserToken>()
const { resource: token, requestCharge } = await tokenItem.read<IUserToken>()
request.log.trace('Get: %d', requestCharge)
if (token.expires < Date.now()) return badRequestError(reply, 'Refresh token expired')
@ -254,7 +255,7 @@ function selfRoute(server: FastifyInstance<Server, IncomingMessage, ServerRespon
if (!server.database) return serverError(reply)
if (!request.viewer) return unauthorizedError(reply)
const viewer = await getItem<IUser>(containerFor(server.database.client, 'Users'), request.viewer.id)
const viewer = await getItem<IUser>(containerFor(server.database.client, 'Users'), request.viewer.id, request.log)
if (!viewer) return unauthorizedError(reply)
return viewer

14
src/plugins/api/groups.ts

@ -51,7 +51,8 @@ function createRoute(server: FastifyInstance<Server, IncomingMessage, ServerResp
if (!request.viewer) return unauthorizedError(reply)
const viewerItem = containerFor(server.database.client, 'Users').item(request.viewer.id, request.viewer.id)
const { resource: viewer } = await viewerItem.read<IUser>()
const { resource: viewer, requestCharge } = await viewerItem.read<IUser>()
request.log.trace('Get: %d', requestCharge)
const groupContainer = containerFor(server.database.client, 'Groups')
@ -60,7 +61,7 @@ function createRoute(server: FastifyInstance<Server, IncomingMessage, ServerResp
const { name, about, open, requiresApproval } = request.body
const id = normalize(name)
const existingGroup = await getItem<IGroup>(groupContainer, id)
const existingGroup = await getItem<IGroup>(groupContainer, id, request.log)
if (existingGroup) return badRequestError(reply, 'Name already used')
const group: IGroup = {
@ -136,8 +137,7 @@ function blockRoute(server: FastifyInstance<Server, IncomingMessage, ServerRespo
if (!request.viewer) return unauthorizedError(reply)
const groupContainer = containerFor(server.database.client, 'Groups')
const group = await getItem<IGroup>(groupContainer, request.params.id)
const group = await getItem<IGroup>(groupContainer, request.params.id, request.log)
if (!group) return notFoundError(reply)
await containerFor(server.database.client, 'Users').items.create<IUserBlock>({
@ -184,7 +184,7 @@ function unblockRoute(server: FastifyInstance<Server, IncomingMessage, ServerRes
const userContainer = containerFor(server.database.client, 'Users')
const groupContainer = containerFor(server.database.client, 'Groups')
const group = await getItem<IGroup>(groupContainer, request.params.id)
const group = await getItem<IGroup>(groupContainer, request.params.id, request.log)
if (!group) return notFoundError(reply)
const userBlockQuery = createQuerySpec(`SELECT u.id FROM Users u WHERE u.partitionKey = @partitionKey AND u.blockedId = @blocked AND u.type = 'block'`, {
@ -192,7 +192,7 @@ function unblockRoute(server: FastifyInstance<Server, IncomingMessage, ServerRes
blocked: group.id,
})
const userBlocks = await queryItems<IUserBlock>(userContainer, userBlockQuery)
const userBlocks = await queryItems<IUserBlock>(userContainer, userBlockQuery, request.log)
for (const userBlock of userBlocks) {
await userContainer.item(userBlock.id!, request.viewer.id).delete()
}
@ -206,7 +206,7 @@ function unblockRoute(server: FastifyInstance<Server, IncomingMessage, ServerRes
}
)
const groupBlocks = await queryItems<IUserBlock>(groupContainer, groupBlockQuery)
const groupBlocks = await queryItems<IUserBlock>(groupContainer, groupBlockQuery, request.log)
for (const groupBlock of groupBlocks) {
await groupContainer.item(groupBlock.id!, group.id).delete()
}

4
src/plugins/api/index.ts

@ -55,8 +55,8 @@ const plugin: Plugin<Server, IncomingMessage, ServerResponse, PluginOptions> = a
id: data.sub
}
} catch (err) {
server.log.error('Unable to decode token')
server.log.error(err)
req.log.error('Unable to decode token')
req.log.error(err)
}
})

36
src/plugins/api/posts.ts

@ -89,11 +89,12 @@ function doPostRoute(server: FastifyInstance<Server, IncomingMessage, ServerResp
if (!request.viewer) return unauthorizedError(reply)
let newPostRelationship: IPostRelationship | undefined
const postContainer = containerFor(server.database.client, 'Posts')
const postRelationshipContainer = containerFor(server.database.client, 'PostRelationships')
const userContainer = containerFor(server.database.client, 'Users')
const viewer = await getItem<IUser>(userContainer, request.viewer.id)
const viewer = await getItem<IUser>(userContainer, request.viewer.id, request.log)
if (!viewer) return serverError(reply)
if (viewer.pending) return badRequestError(reply, 'User requires approval')
@ -102,10 +103,10 @@ function doPostRoute(server: FastifyInstance<Server, IncomingMessage, ServerResp
const postId = createPostId()
if (request.body.parent) {
const parent = await getItem<IPost>(postContainer, request.body.parent)
const parent = await getItem<IPost>(postContainer, request.body.parent, request.log)
if (!parent) return badRequestError(reply, 'Invalid parent', 'parent')
const parentRelationship = await getItem<IPostRelationship>(postRelationshipContainer, request.body.parent, parent.root)
const parentRelationship = await getItem<IPostRelationship>(postRelationshipContainer, request.body.parent, parent.root, request.log)
const parents = parentRelationship ? parentRelationship.parents : []
newPostRelationship = {
@ -144,7 +145,7 @@ function doPostRoute(server: FastifyInstance<Server, IncomingMessage, ServerResp
if (newPostRelationship) await postRelationshipContainer.items.create<IPostRelationship>(newPostRelationship)
const query = createQuerySpec(`SELECT u.id FROM Users u WHERE u.partitionKey = @partitionKey AND u.type = 'subscription'`, { partitionKey: request.viewer.id })
const subscribers = await queryItems<IUserSubscription>(userContainer, query)
const subscribers = await queryItems<IUserSubscription>(userContainer, query, request.log)
if (subscribers.length < 100) {
for (const subscriber of subscribers) {
@ -196,7 +197,7 @@ function postsByUserRoute(server: FastifyInstance<Server, IncomingMessage, Serve
const id = normalize(request.params.id)
const userContainer = containerFor(server.database.client, 'Users')
const user = await getItem<IUser>(userContainer, id)
const user = await getItem<IUser>(userContainer, id, request.log)
if (!user) return notFoundError(reply)
if (!user.group) return notFoundError(reply)
@ -206,13 +207,14 @@ function postsByUserRoute(server: FastifyInstance<Server, IncomingMessage, Serve
case 'private':
if (!request.viewer) return unauthorizedError(reply)
const subscriptions = await getSubscriptions(server.database.client, user.id, request.viewer.id)
const subscriptions = await getSubscriptions(server.database.client, user.id, request.viewer.id, request.log)
if (subscriptions.length === 0) return unauthorizedError(reply)
break
case 'group':
if (!request.viewer) return unauthorizedError(reply)
const { resource: viewer } = await userContainer.item(request.viewer.id, request.viewer.id).read<IUser>()
const viewer = await getItem<IUser>(userContainer, request.viewer.id, request.log)
if (!viewer) return serverError(reply)
if (!viewer.group) return unauthorizedError(reply)
if (viewer.group.id !== user.group.id) return unauthorizedError(reply)
@ -220,11 +222,11 @@ function postsByUserRoute(server: FastifyInstance<Server, IncomingMessage, Serve
}
if (request.viewer) {
const viewer = await getItem<IUser>(userContainer, request.viewer.id)
const viewer = await getItem<IUser>(userContainer, request.viewer.id, request.log)
if (!viewer) return serverError(reply)
if (!viewer.group) return unauthorizedError(reply)
const blocks = await getUserBlocks(server.database.client, user.id, [viewer.id, viewer.group.id])
const blocks = await getUserBlocks(server.database.client, user.id, [viewer.id, viewer.group.id], request.log)
if (blocks.length > 0) return unauthorizedError(reply)
}
@ -233,7 +235,7 @@ function postsByUserRoute(server: FastifyInstance<Server, IncomingMessage, Serve
const posts = await queryItems<IPost>(containerFor(server.database.client, 'Posts'), createQuerySpec('SELECT * FROM Posts p WHERE ARRAY_CONTAINS(@posts, p.id)', {
posts: userPosts.map(p => p.id!),
}))
}), request.log)
return {
user,
@ -282,7 +284,7 @@ function postRoute(server: FastifyInstance<Server, IncomingMessage, ServerRespon
if (!server.database) return serverError(reply)
const postContainer = containerFor(server.database.client, 'Posts')
const post = await getItem<IPost>(postContainer, request.params.id)
const post = await getItem<IPost>(postContainer, request.params.id, request.log)
if (!post) return notFoundError(reply)
const query = createQuerySpec('SELECT * FROM PostRelationships r WHERE r.partitionKey = @partitionKey AND ARRAY_CONTAINS(r.parents, @id)', {
@ -290,15 +292,15 @@ function postRoute(server: FastifyInstance<Server, IncomingMessage, ServerRespon
id: post.id,
})
const descendantRelationships = await queryItems<IPostRelationship>(containerFor(server.database.client, 'PostRelationships'), query)
const descendantRelationships = await queryItems<IPostRelationship>(containerFor(server.database.client, 'PostRelationships'), query, request.log)
const descendants = await queryItems<IPost>(postContainer, createQuerySpec('SELECT * FROM Posts p WHERE ARRAY_CONTAINS(@descendants, p.id)', {
descendants: descendantRelationships.map(r => r.id),
}))
}), request.log)
const ancestors = await queryItems<IPost>(postContainer, createQuerySpec('SELECT * FROM Posts p WHERE ARRAY_CONTAINS(@parents, p.id)', {
parents: post.parents,
}))
}), request.log)
const getUserId = (post: IPost) => post.userId
@ -308,10 +310,10 @@ function postRoute(server: FastifyInstance<Server, IncomingMessage, ServerRespon
getUserId(post),
]
const users = await getUsers(server.database.client, userIds)
const users = await getUsers(server.database.client, userIds, request.log)
if (request.viewer) {
const viewer = await getItem<IUser>(containerFor(server.database.client, 'Users'), request.viewer.id)
const viewer = await getItem<IUser>(containerFor(server.database.client, 'Users'), request.viewer.id, request.log)
if (!viewer) return serverError(reply)
if (!viewer.group) return unauthorizedError(reply)
@ -327,7 +329,7 @@ function postRoute(server: FastifyInstance<Server, IncomingMessage, ServerRespon
ids: userIds,
})
const blocks = await queryItems<IGroupBlock>(containerFor(server.database.client, 'Groups'), blockQuery)
const blocks = await queryItems<IGroupBlock>(containerFor(server.database.client, 'Groups'), blockQuery, request.log)
const blockedUserIds = blocks.map(b => b.userId)
if (blockedUserIds.includes(post.userId)) return unauthorizedError(reply)

61
src/plugins/api/users.ts

@ -10,10 +10,11 @@ import {
import { Server, IncomingMessage, ServerResponse } from 'http'
import { MAX_NAME_LENGTH } from '../../constants'
import { userSchema } from '../../schemas'
import { unauthorizedError, serverError, notFoundError, badRequestError } from '../../lib/errors'
import { containerFor, createQuerySpec, queryItems, getItem } from '../../lib/database'
import { IUser, IUserSubscription, IUserBlock, IGroupBlock } from '../../types/collections'
import { IUser, IUserSubscription, IUserBlock, IGroupBlock, IUserPrivacyType } from '../../types/collections'
interface PluginOptions {}
@ -25,6 +26,8 @@ function updateRoute(server: FastifyInstance<Server, IncomingMessage, ServerResp
interface Body {
name?: string
about?: string
requiresApproval?: boolean
privacy?: IUserPrivacyType
}
const options: RouteShorthandOptions = {
@ -38,8 +41,16 @@ function updateRoute(server: FastifyInstance<Server, IncomingMessage, ServerResp
body: {
type: 'object',
properties: {
name: { type: 'string' },
name: {
type: 'string',
maxLength: MAX_NAME_LENGTH,
},
about: { type: 'string' },
requiresApproval: { type: 'boolean' },
privacy: {
type: 'string',
enum: ['public', 'group', 'subscribers', 'private'],
},
},
},
response: {
@ -53,7 +64,8 @@ function updateRoute(server: FastifyInstance<Server, IncomingMessage, ServerResp
if (!request.viewer) return unauthorizedError(reply)
const viewerItem = containerFor(server.database.client, 'Users').item(request.viewer.id, request.viewer.id)
const { resource: viewer } = await viewerItem.read<IUser>()
const { resource: viewer, requestCharge } = await viewerItem.read<IUser>()
request.log.trace('Get: %d', requestCharge)
if (!viewer) return serverError(reply)
@ -71,6 +83,14 @@ function updateRoute(server: FastifyInstance<Server, IncomingMessage, ServerResp
}
}
if (request.body.requiresApproval !== undefined) {
viewer.requiresApproval = request.body.requiresApproval
}
if (request.body.privacy) {
viewer.privacy = request.body.privacy
}
await viewerItem.replace<IUser>(viewer)
return viewer
@ -94,7 +114,17 @@ function getRoute(server: FastifyInstance<Server, IncomingMessage, ServerRespons
}
server.post<DefaultQuery, Params, DefaultHeaders, DefaultBody>('/api/user/:id', options, async (request, reply) => {
if (!server.database) return serverError(reply)
const userContainer = containerFor(server.database.client, 'Users')
const user = await getItem<IUser>(userContainer, request.params.id, request.log)
if (!user) return notFoundError(reply)
switch (user.privacy) {
case 'private':
break
}
})
}
@ -121,8 +151,8 @@ function subscribeRoute(server: FastifyInstance<Server, IncomingMessage, ServerR
if (request.viewer.id === request.params.id) return badRequestError(reply)
const userContainer = containerFor(server.database.client, 'Users')
const user = await getItem<IUser>(userContainer, request.params.id)
const viewer = await getItem<IUser>(userContainer, request.viewer.id)
const user = await getItem<IUser>(userContainer, request.params.id, request.log)
const viewer = await getItem<IUser>(userContainer, request.viewer.id, request.log)
if (!user) return notFoundError(reply)
if (!viewer) return serverError(reply)
@ -133,7 +163,7 @@ function subscribeRoute(server: FastifyInstance<Server, IncomingMessage, ServerR
viewer: viewer.id,
})
const subscriptions = await queryItems<IUserSubscription>(userContainer, subscriptionQuery)
const subscriptions = await queryItems<IUserSubscription>(userContainer, subscriptionQuery, request.log)
if (subscriptions.length > 0) return badRequestError(reply, 'Already subscribed')
let pending = false
@ -143,7 +173,7 @@ function subscribeRoute(server: FastifyInstance<Server, IncomingMessage, ServerR
return unauthorizedError(reply)
case 'group':
if (user.group !== viewer.group) return unauthorizedError(reply)
case 'approve':
case 'subscribers':
pending = true
break
}
@ -159,7 +189,7 @@ function subscribeRoute(server: FastifyInstance<Server, IncomingMessage, ServerR
viewerGroup: viewer.group.id,
})
const blocks = await queryItems<IGroupBlock>(containerFor(server.database.client, 'Groups'), blockQuery)
const blocks = await queryItems<IGroupBlock>(containerFor(server.database.client, 'Groups'), blockQuery, request.log)
if (blocks.length > 0) return badRequestError(reply, 'Invalid operation')
await userContainer.items.create<IUserSubscription>({
@ -195,8 +225,8 @@ function unsubscribeRoute(server: FastifyInstance<Server, IncomingMessage, Serve
if (!request.viewer) return unauthorizedError(reply)
const userContainer = containerFor(server.database.client, 'Users')
const user = await getItem<IUser>(userContainer, request.params.id)
const viewer = await getItem<IUser>(userContainer, request.viewer.id)
const user = await getItem<IUser>(userContainer, request.params.id, request.log)
const viewer = await getItem<IUser>(userContainer, request.viewer.id, request.log)
if (!user) return notFoundError(reply)
if (!viewer) return serverError(reply)
@ -206,7 +236,7 @@ function unsubscribeRoute(server: FastifyInstance<Server, IncomingMessage, Serve
viewer: viewer.id,
})
const subscriptions = await queryItems<IUserSubscription>(userContainer, subscriptionQuery)
const subscriptions = await queryItems<IUserSubscription>(userContainer, subscriptionQuery, request.log)
for (const subscription of subscriptions) {
await userContainer.item(subscription.id!, viewer.id).delete()
}
@ -246,7 +276,7 @@ function blockRoute(server: FastifyInstance<Server, IncomingMessage, ServerRespo
if (!request.viewer) return unauthorizedError(reply)
const userContainer = containerFor(server.database.client, 'Users')
const user = await getItem<IUser>(userContainer, request.params.id)
const user = await getItem<IUser>(userContainer, request.params.id, request.log)
if (!user) return notFoundError(reply)
if (!user.group) return badRequestError(reply)
@ -295,7 +325,7 @@ function unblockRoute(server: FastifyInstance<Server, IncomingMessage, ServerRes
const userContainer = containerFor(server.database.client, 'Users')
const groupContainer = containerFor(server.database.client, 'Groups')
const user = await getItem<IUser>(userContainer, request.params.id)
const user = await getItem<IUser>(userContainer, request.params.id, request.log)
if (!user) return notFoundError(reply)
if (!user.group) return badRequestError(reply, 'Invalid operation')
@ -305,7 +335,7 @@ function unblockRoute(server: FastifyInstance<Server, IncomingMessage, ServerRes
blocked: user.id,
})
const userBlocks = await queryItems<IUserBlock>(userContainer, userBlockQuery)
const userBlocks = await queryItems<IUserBlock>(userContainer, userBlockQuery, request.log)
for (const userBlock of userBlocks) {
await userContainer.item(userBlock.id!, request.viewer.id).delete()
}
@ -319,7 +349,7 @@ function unblockRoute(server: FastifyInstance<Server, IncomingMessage, ServerRes
}
)
const groupBlocks = await queryItems<IGroupBlock>(groupContainer, groupBlockQuery)
const groupBlocks = await queryItems<IGroupBlock>(groupContainer, groupBlockQuery, request.log)
for (const groupBlock of groupBlocks) {
await groupContainer.item(groupBlock.id!, user.group.id).delete()
}
@ -330,6 +360,7 @@ function unblockRoute(server: FastifyInstance<Server, IncomingMessage, ServerRes
const plugin: Plugin<Server, IncomingMessage, ServerResponse, PluginOptions> = async server => {
updateRoute(server)
getRoute(server)
subscribeRoute(server)
unsubscribeRoute(server)
blockRoute(server)

3
src/types/collections.ts

@ -10,7 +10,7 @@
// - Partition Key: partitionKey (postId)
export type IUserItemType = 'user' | 'token' | 'post' | 'follow' | 'timeline'
export type IUserPrivacyType = 'public' | 'group' | 'approve' | 'private'
export type IUserPrivacyType = 'public' | 'group' | 'subscribers' | 'private'
export type IGroupItemType = 'group' | 'membership' | 'report' | 'block'
export type IGroupMembershipType = 'admin' | 'moderator' | 'member'
export type IReportStatus = 'pending' | 'complete'
@ -85,6 +85,7 @@ export interface IUser {
subscriberCount: number
subscribedCount: number
pending: boolean
requiresApproval: boolean
privacy: IUserPrivacyType
paid: boolean
created: number // Timestamp

Loading…
Cancel
Save