Convert tags to groups on demand (#784)
* Fix stuff to not prematurely initialize Firebase when imported * Add script to convert a tag to a group with the same contracts
This commit is contained in:
parent
f4ebb2b504
commit
2439317408
|
@ -23,13 +23,8 @@ type JwtCredentials = { kind: 'jwt'; data: admin.auth.DecodedIdToken }
|
||||||
type KeyCredentials = { kind: 'key'; data: string }
|
type KeyCredentials = { kind: 'key'; data: string }
|
||||||
type Credentials = JwtCredentials | KeyCredentials
|
type Credentials = JwtCredentials | KeyCredentials
|
||||||
|
|
||||||
const auth = admin.auth()
|
|
||||||
const firestore = admin.firestore()
|
|
||||||
const privateUsers = firestore.collection(
|
|
||||||
'private-users'
|
|
||||||
) as admin.firestore.CollectionReference<PrivateUser>
|
|
||||||
|
|
||||||
export const parseCredentials = async (req: Request): Promise<Credentials> => {
|
export const parseCredentials = async (req: Request): Promise<Credentials> => {
|
||||||
|
const auth = admin.auth()
|
||||||
const authHeader = req.get('Authorization')
|
const authHeader = req.get('Authorization')
|
||||||
if (!authHeader) {
|
if (!authHeader) {
|
||||||
throw new APIError(403, 'Missing Authorization header.')
|
throw new APIError(403, 'Missing Authorization header.')
|
||||||
|
@ -57,6 +52,8 @@ export const parseCredentials = async (req: Request): Promise<Credentials> => {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const lookupUser = async (creds: Credentials): Promise<AuthedUser> => {
|
export const lookupUser = async (creds: Credentials): Promise<AuthedUser> => {
|
||||||
|
const firestore = admin.firestore()
|
||||||
|
const privateUsers = firestore.collection('private-users')
|
||||||
switch (creds.kind) {
|
switch (creds.kind) {
|
||||||
case 'jwt': {
|
case 'jwt': {
|
||||||
if (typeof creds.data.user_id !== 'string') {
|
if (typeof creds.data.user_id !== 'string') {
|
||||||
|
@ -70,7 +67,7 @@ export const lookupUser = async (creds: Credentials): Promise<AuthedUser> => {
|
||||||
if (privateUserQ.empty) {
|
if (privateUserQ.empty) {
|
||||||
throw new APIError(403, `No private user exists with API key ${key}.`)
|
throw new APIError(403, `No private user exists with API key ${key}.`)
|
||||||
}
|
}
|
||||||
const privateUser = privateUserQ.docs[0].data()
|
const privateUser = privateUserQ.docs[0].data() as PrivateUser
|
||||||
return { uid: privateUser.id, creds: { privateUser, ...creds } }
|
return { uid: privateUser.id, creds: { privateUser, ...creds } }
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -21,6 +21,7 @@ const bodySchema = z.object({
|
||||||
})
|
})
|
||||||
|
|
||||||
export const creategroup = newEndpoint({}, async (req, auth) => {
|
export const creategroup = newEndpoint({}, async (req, auth) => {
|
||||||
|
const firestore = admin.firestore()
|
||||||
const { name, about, memberIds, anyoneCanJoin } = validate(
|
const { name, about, memberIds, anyoneCanJoin } = validate(
|
||||||
bodySchema,
|
bodySchema,
|
||||||
req.body
|
req.body
|
||||||
|
@ -67,7 +68,7 @@ export const creategroup = newEndpoint({}, async (req, auth) => {
|
||||||
return { status: 'success', group: group }
|
return { status: 'success', group: group }
|
||||||
})
|
})
|
||||||
|
|
||||||
const getSlug = async (name: string) => {
|
export const getSlug = async (name: string) => {
|
||||||
const proposedSlug = slugify(name)
|
const proposedSlug = slugify(name)
|
||||||
|
|
||||||
const preexistingGroup = await getGroupFromSlug(proposedSlug)
|
const preexistingGroup = await getGroupFromSlug(proposedSlug)
|
||||||
|
@ -75,9 +76,8 @@ const getSlug = async (name: string) => {
|
||||||
return preexistingGroup ? proposedSlug + '-' + randomString() : proposedSlug
|
return preexistingGroup ? proposedSlug + '-' + randomString() : proposedSlug
|
||||||
}
|
}
|
||||||
|
|
||||||
const firestore = admin.firestore()
|
|
||||||
|
|
||||||
export async function getGroupFromSlug(slug: string) {
|
export async function getGroupFromSlug(slug: string) {
|
||||||
|
const firestore = admin.firestore()
|
||||||
const snap = await firestore
|
const snap = await firestore
|
||||||
.collection('groups')
|
.collection('groups')
|
||||||
.where('slug', '==', slug)
|
.where('slug', '==', slug)
|
||||||
|
|
66
functions/src/scripts/convert-tag-to-group.ts
Normal file
66
functions/src/scripts/convert-tag-to-group.ts
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
// Takes a tag and makes a new group with all the contracts in it.
|
||||||
|
|
||||||
|
import * as admin from 'firebase-admin'
|
||||||
|
import { initAdmin } from './script-init'
|
||||||
|
import { isProd, log } from '../utils'
|
||||||
|
import { getSlug } from '../create-group'
|
||||||
|
import { Group } from '../../../common/group'
|
||||||
|
|
||||||
|
const getTaggedContractIds = async (tag: string) => {
|
||||||
|
const firestore = admin.firestore()
|
||||||
|
const results = await firestore
|
||||||
|
.collection('contracts')
|
||||||
|
.where('lowercaseTags', 'array-contains', tag.toLowerCase())
|
||||||
|
.get()
|
||||||
|
return results.docs.map((d) => d.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
const createGroup = async (
|
||||||
|
name: string,
|
||||||
|
about: string,
|
||||||
|
contractIds: string[]
|
||||||
|
) => {
|
||||||
|
const firestore = admin.firestore()
|
||||||
|
const creatorId = isProd()
|
||||||
|
? 'IPTOzEqrpkWmEzh6hwvAyY9PqFb2'
|
||||||
|
: '94YYTk1AFWfbWMpfYcvnnwI1veP2'
|
||||||
|
|
||||||
|
const slug = await getSlug(name)
|
||||||
|
const groupRef = firestore.collection('groups').doc()
|
||||||
|
const now = Date.now()
|
||||||
|
const group: Group = {
|
||||||
|
id: groupRef.id,
|
||||||
|
creatorId,
|
||||||
|
slug,
|
||||||
|
name,
|
||||||
|
about,
|
||||||
|
createdTime: now,
|
||||||
|
mostRecentActivityTime: now,
|
||||||
|
contractIds: contractIds,
|
||||||
|
anyoneCanJoin: true,
|
||||||
|
memberIds: [],
|
||||||
|
}
|
||||||
|
return await groupRef.create(group)
|
||||||
|
}
|
||||||
|
|
||||||
|
const convertTagToGroup = async (tag: string, groupName: string) => {
|
||||||
|
log(`Looking up contract IDs with tag ${tag}...`)
|
||||||
|
const contractIds = await getTaggedContractIds(tag)
|
||||||
|
log(`${contractIds.length} contracts found.`)
|
||||||
|
if (contractIds.length > 0) {
|
||||||
|
log(`Creating group ${groupName}...`)
|
||||||
|
const about = `Contracts that used to be tagged ${tag}.`
|
||||||
|
const result = await createGroup(groupName, about, contractIds)
|
||||||
|
log(`Done. Group: `, result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (require.main === module) {
|
||||||
|
initAdmin()
|
||||||
|
const args = process.argv.slice(2)
|
||||||
|
if (args.length != 2) {
|
||||||
|
console.log('Usage: convert-tag-to-group [tag] [group-name]')
|
||||||
|
} else {
|
||||||
|
convertTagToGroup(args[0], args[1]).catch((e) => console.error(e))
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user