change user info cloud function and script; move cleanUsername to common

This commit is contained in:
mantikoros 2022-01-26 14:19:32 -06:00
parent 55dabd2dc9
commit a60c495c8a
6 changed files with 160 additions and 8 deletions

View File

@ -0,0 +1,7 @@
export const cleanUsername = (name: string) => {
return name
.replace(/\s+/g, '')
.normalize('NFD') // split an accented letter in the base letter and the acent
.replace(/[\u0300-\u036f]/g, '') // remove all previously split accents
.replace(/[^A-Za-z0-9_]/g, '') // remove all chars not letters, numbers and underscores
}

View File

@ -0,0 +1,92 @@
import * as functions from 'firebase-functions'
import * as admin from 'firebase-admin'
import { getUser, getUserByUsername, removeUndefinedProps } from './utils'
import { Contract } from '../../common/contract'
import { Comment } from '../../common/comment'
import { User } from '../../common/user'
import { cleanUsername } from '../../common/util/clean-username'
export const changeUserInfo = functions
.runWith({ minInstances: 1 })
.https.onCall(
async (
data: {
username?: string
name?: string
avatarUrl?: string
},
context
) => {
const userId = context?.auth?.uid
if (!userId) return { status: 'error', message: 'Not authorized' }
const user = await getUser(userId)
if (!user) return { status: 'error', message: 'User not found' }
const { username, name, avatarUrl } = data
return await changeUser(user, { username, name, avatarUrl })
.then(() => {
console.log('succesfully changed', user.username, 'to', data)
return { status: 'success' }
})
.catch((e) => {
console.log('Error', e.message)
return { status: 'error', message: e.message }
})
}
)
export const changeUser = async (
user: User,
update: {
username?: string
name?: string
avatarUrl?: string
}
) => {
if (update.username) {
update.username = cleanUsername(update.username)
if (!update.username) {
throw new Error('Invalid username')
}
const sameNameUser = await getUserByUsername(update.username)
if (sameNameUser) {
throw new Error('Username already exists')
}
}
const userRef = firestore.collection('users').doc(user.id)
const userUpdate: Partial<User> = removeUndefinedProps(update)
await userRef.update(userUpdate)
const contractSnap = await firestore
.collection('contracts')
.where('creatorId', '==', user.id)
.get()
const contractUpdate: Partial<Contract> = removeUndefinedProps({
creatorName: update.name,
creatorUsername: update.username,
creatorAvatarUrl: update.avatarUrl,
})
await Promise.all(contractSnap.docs.map((d) => d.ref.update(contractUpdate)))
const commentSnap = await firestore
.collectionGroup('comments')
.where('userUsername', '==', user.username)
.get()
const commentUpdate: Partial<Comment> = removeUndefinedProps({
userName: update.name,
userUsername: update.username,
userAvatarUrl: update.avatarUrl,
})
await Promise.all(commentSnap.docs.map((d) => d.ref.update(commentUpdate)))
}
const firestore = admin.firestore()

View File

@ -9,6 +9,7 @@ import {
} from '../../common/user'
import { getUser, getUserByUsername } from './utils'
import { randomString } from '../../common/util/random'
import { cleanUsername } from '../../common/util/clean-username'
export const createUser = functions
.runWith({ minInstances: 1 })
@ -77,14 +78,6 @@ export const createUser = functions
return { status: 'success', user }
})
const cleanUsername = (name: string) => {
return name
.replace(/\s+/g, '')
.normalize('NFD') // split an accented letter in the base letter and the acent
.replace(/[\u0300-\u036f]/g, '') // remove all previously split accents
.replace(/[^A-Za-z0-9_]/g, '') // remove all chars not letters, numbers and underscores
}
const firestore = admin.firestore()
const isPrivateUserWithDeviceToken = async (deviceToken: string) => {

View File

@ -15,3 +15,4 @@ export * from './unsubscribe'
export * from './update-contract-metrics'
export * from './update-user-metrics'
export * from './backup-db'
export * from './change-user-info'

View File

@ -0,0 +1,49 @@
import * as admin from 'firebase-admin'
import * as _ from 'lodash'
// Generate your own private key, and set the path below:
// https://console.firebase.google.com/u/0/project/mantic-markets/settings/serviceaccounts/adminsdk
const serviceAccount = require('../../../../../../Downloads/dev-mantic-markets-firebase-adminsdk-sir5m-b2d27f8970.json')
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
})
import { getUserByUsername } from '../utils'
import { changeUser } from '../change-user-info'
async function main() {
const username = process.argv[2]
const name = process.argv[3]
const avatarUrl = process.argv[4]
const newUsername = process.argv[5]
if (process.argv.length < 4) {
console.log(
'syntax: node change-user-info.js [current username] [new name] [new avatar] [new username]'
)
return
}
const user = await getUserByUsername(username)
if (!user) {
console.log('username', username, 'could not be found')
return
}
await changeUser(user, { username, name, avatarUrl })
.then(() =>
console.log(
'succesfully changed',
user.username,
'to',
name,
avatarUrl,
newUsername
)
)
.catch((e) => console.log(e.message))
}
if (require.main === module) main().then(() => process.exit())

View File

@ -77,3 +77,13 @@ export const chargeUser = (userId: string, charge: number) => {
return updateUserBalance(userId, -charge)
}
export const removeUndefinedProps = <T>(obj: T): T => {
let newObj: any = {}
for (let key of Object.keys(obj)) {
if ((obj as any)[key] !== undefined) newObj[key] = (obj as any)[key]
}
return newObj
}