2022-06-22 16:35:50 +00:00
|
|
|
import * as admin from 'firebase-admin'
|
|
|
|
|
|
|
|
import { getUser } from './utils'
|
|
|
|
import { Contract } from '../../common/contract'
|
|
|
|
import { slugify } from '../../common/util/slugify'
|
|
|
|
import { randomString } from '../../common/util/random'
|
|
|
|
import {
|
|
|
|
Group,
|
|
|
|
MAX_ABOUT_LENGTH,
|
|
|
|
MAX_GROUP_NAME_LENGTH,
|
|
|
|
MAX_ID_LENGTH,
|
|
|
|
} from '../../common/group'
|
|
|
|
import { APIError, newEndpoint, validate } from '../../functions/src/api'
|
|
|
|
import { z } from 'zod'
|
|
|
|
|
|
|
|
const bodySchema = z.object({
|
|
|
|
name: z.string().min(1).max(MAX_GROUP_NAME_LENGTH),
|
|
|
|
memberIds: z.array(z.string().min(1).max(MAX_ID_LENGTH)),
|
|
|
|
anyoneCanJoin: z.boolean(),
|
|
|
|
about: z.string().min(1).max(MAX_ABOUT_LENGTH).optional(),
|
|
|
|
})
|
|
|
|
|
2022-06-29 23:47:06 +00:00
|
|
|
export const creategroup = newEndpoint({}, async (req, auth) => {
|
2022-06-22 16:35:50 +00:00
|
|
|
const { name, about, memberIds, anyoneCanJoin } = validate(
|
|
|
|
bodySchema,
|
|
|
|
req.body
|
|
|
|
)
|
|
|
|
|
|
|
|
const creator = await getUser(auth.uid)
|
|
|
|
if (!creator)
|
|
|
|
throw new APIError(400, 'No user exists with the authenticated user ID.')
|
|
|
|
|
|
|
|
// Add creator id to member ids for convenience
|
|
|
|
if (!memberIds.includes(creator.id)) memberIds.push(creator.id)
|
|
|
|
|
|
|
|
console.log(
|
|
|
|
'creating group for',
|
|
|
|
creator.username,
|
|
|
|
'named',
|
|
|
|
name,
|
|
|
|
'about',
|
|
|
|
about,
|
|
|
|
'other member ids',
|
|
|
|
memberIds
|
|
|
|
)
|
|
|
|
|
|
|
|
const slug = await getSlug(name)
|
|
|
|
|
|
|
|
const groupRef = firestore.collection('groups').doc()
|
|
|
|
|
|
|
|
const group: Group = {
|
|
|
|
id: groupRef.id,
|
|
|
|
creatorId: creator.id,
|
|
|
|
slug,
|
|
|
|
name,
|
|
|
|
about: about ?? '',
|
|
|
|
createdTime: Date.now(),
|
|
|
|
mostRecentActivityTime: Date.now(),
|
|
|
|
// TODO: allow users to add contract ids on group creation
|
|
|
|
contractIds: [],
|
|
|
|
anyoneCanJoin,
|
|
|
|
memberIds,
|
|
|
|
}
|
|
|
|
|
|
|
|
await groupRef.create(group)
|
|
|
|
|
|
|
|
return { status: 'success', group: group }
|
|
|
|
})
|
|
|
|
|
|
|
|
const getSlug = async (name: string) => {
|
|
|
|
const proposedSlug = slugify(name)
|
|
|
|
|
|
|
|
const preexistingGroup = await getGroupFromSlug(proposedSlug)
|
|
|
|
|
|
|
|
return preexistingGroup ? proposedSlug + '-' + randomString() : proposedSlug
|
|
|
|
}
|
|
|
|
|
|
|
|
const firestore = admin.firestore()
|
|
|
|
|
|
|
|
export async function getGroupFromSlug(slug: string) {
|
|
|
|
const snap = await firestore
|
|
|
|
.collection('groups')
|
|
|
|
.where('slug', '==', slug)
|
|
|
|
.get()
|
|
|
|
|
|
|
|
return snap.empty ? undefined : (snap.docs[0].data() as Contract)
|
|
|
|
}
|