You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
188 lines
6.1 KiB
188 lines
6.1 KiB
// collections.ts
|
|
// Copyright (C) 2020 Dwayne Harris
|
|
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
import { CosmosClient, Item } from '@azure/cosmos'
|
|
import { Logger } from 'fastify'
|
|
import compact from 'lodash/compact'
|
|
import uniq from 'lodash/uniq'
|
|
|
|
import { containerFor, createQuerySpec, queryItems, getItem } from './database'
|
|
import { USER_LISTING_PARTITION_KEY } from '../constants'
|
|
import { DatabaseItem } from '../types'
|
|
import { User, UserSubscription, UserBlock, Group, GroupMembership, UserItemType, GroupItemType, UserListing } from '../types/collections'
|
|
|
|
export async function getUser(client: CosmosClient, id: string): Promise<User | undefined> {
|
|
const user = await getItem<User>({
|
|
container: containerFor(client, 'Users'),
|
|
id,
|
|
})
|
|
|
|
if (!user) return
|
|
|
|
const getGroup = async (id: string) => {
|
|
return await getItem<Group>({
|
|
container: containerFor(client, 'Groups'),
|
|
id,
|
|
})
|
|
}
|
|
|
|
return {
|
|
...user,
|
|
group: user.groupId ? await getGroup(user.groupId) : undefined,
|
|
}
|
|
}
|
|
|
|
export async function getUsers(client: CosmosClient, ids: string[], logger?: Logger): Promise<User[]> {
|
|
const users = await queryItems<User>({
|
|
container: containerFor(client, 'Users'),
|
|
query: createQuerySpec(
|
|
'SELECT u.id, u.name, u.imageUrl, u.coverImageUrl, u.groupId, u.created FROM Users u WHERE ARRAY_CONTAINS(@ids, u.id)',
|
|
{ ids: uniq(ids) }
|
|
),
|
|
logger,
|
|
})
|
|
|
|
const groups = await queryItems<Group>({
|
|
container: containerFor(client, 'Groups'),
|
|
query: createQuerySpec(
|
|
'SELECT g.id, g.name, g.imageUrl, g.coverImageUrl, g.iconImageUrl, g.created FROM Groups g WHERE ARRAY_CONTAINS(@ids, g.id)',
|
|
{ ids: uniq(compact(users.map(u => u.groupId))) }
|
|
),
|
|
logger,
|
|
})
|
|
|
|
return users.map(user => {
|
|
return {
|
|
...user,
|
|
group: groups.find(group => group.id === user.groupId),
|
|
groupId: undefined
|
|
}
|
|
})
|
|
}
|
|
|
|
export async function getUsersFromItems<T extends DatabaseItem>(client: CosmosClient, items: T[], logger?: Logger): Promise<User[]> {
|
|
return await getUsers(client, items.map(i => i.id), logger)
|
|
}
|
|
|
|
export async function updateItem<T>(item: Item, updates: Partial<T>) {
|
|
const { resource } = await item.read<T>()
|
|
await item.replace<T>({
|
|
...resource,
|
|
...updates,
|
|
})
|
|
}
|
|
|
|
export async function getApprovedSubscriptions(client: CosmosClient, from: string, to: string, logger?: Logger): Promise<UserSubscription[]> {
|
|
return await queryItems<UserSubscription>({
|
|
container: containerFor(client, 'Users'),
|
|
query: createQuerySpec(
|
|
`SELECT u.id FROM Users u WHERE
|
|
u.userId = @to
|
|
u.pk = @from AND
|
|
u.t = @type AND
|
|
u.pending = false`,
|
|
{ from, to, type: UserItemType.Subscription }
|
|
),
|
|
logger,
|
|
})
|
|
}
|
|
|
|
export async function getUserBlocks(client: CosmosClient, from: string, to: string[], logger?: Logger): Promise<UserBlock[]> {
|
|
return await queryItems<UserBlock>({
|
|
container: containerFor(client, 'Users'),
|
|
query: createQuerySpec(
|
|
`SELECT u.id FROM Users u WHERE
|
|
u.pk = @from
|
|
AND u.t = @type
|
|
AND ARRAY_CONTAINS(@to, u.blockedId)`,
|
|
{ from, to, type: UserItemType.Block }
|
|
),
|
|
logger,
|
|
})
|
|
}
|
|
|
|
export async function getUserMembership(client: CosmosClient, userId: string, logger?: Logger) {
|
|
const user = await getItem<User>({
|
|
container: containerFor(client, 'Users'),
|
|
id: userId,
|
|
})
|
|
|
|
if (!user) return
|
|
if (!user.groupId) return
|
|
|
|
const memberships = await queryItems<GroupMembership>({
|
|
container: containerFor(client, 'Groups'),
|
|
query: createQuerySpec(
|
|
`SELECT * FROM Groups g WHERE
|
|
g.pk = @pk AND
|
|
g.t = @type AND
|
|
g.userId = @user
|
|
`,
|
|
{
|
|
pk: user.groupId,
|
|
type: GroupItemType.Membership,
|
|
user: user.id,
|
|
}
|
|
),
|
|
logger,
|
|
})
|
|
|
|
if (memberships.length > 0) return memberships[0]
|
|
}
|
|
|
|
export async function getUserIdFromEmail(client: CosmosClient, email: string, logger?: Logger) {
|
|
const listings = await queryItems<UserListing>({
|
|
container: containerFor(client, 'Directory'),
|
|
query: createQuerySpec('SELECT d.id FROM Directory d WHERE d.pk = @pk AND d.email = @email', {
|
|
pk: USER_LISTING_PARTITION_KEY,
|
|
email,
|
|
}),
|
|
logger,
|
|
})
|
|
|
|
const listing = listings[0]
|
|
if (listing) return listing.id
|
|
}
|
|
|
|
export async function getUserIdFromPhone(client: CosmosClient, phone: string, logger?: Logger) {
|
|
const listings = await queryItems<UserListing>({
|
|
container: containerFor(client, 'Directory'),
|
|
query: createQuerySpec('SELECT d.id FROM Directory d WHERE d.pk = @pk AND d.phone = @phone', {
|
|
pk: USER_LISTING_PARTITION_KEY,
|
|
phone,
|
|
}),
|
|
logger,
|
|
})
|
|
|
|
const listing = listings[0]
|
|
if (listing) return listing.id
|
|
}
|
|
|
|
export function userIsValid(user?: User) {
|
|
if (!user) return false
|
|
if (user.pending) return false
|
|
if (!user.groupId) return false
|
|
if (!user.active) return false
|
|
|
|
return true
|
|
}
|
|
|
|
export async function userIdIsValid(client: CosmosClient, id: string) {
|
|
return userIsValid(await getItem<User>({
|
|
container: containerFor(client, 'Users'),
|
|
id,
|
|
}))
|
|
}
|