Created
December 4, 2018 10:15
-
-
Save ewaldbenes/6f41bd7fa081b17dc522e0c4e8141f47 to your computer and use it in GitHub Desktop.
Firebase user import from CSV using admin tools and RxJs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Written in Typescript (v3+). | |
* | |
* Dependencies: | |
* - rxjs >= 6 | |
* - firebase-tools >= 6 | |
* | |
* Have fun! | |
* | |
*/ | |
import { auth } from 'firebase-admin'; | |
import { ReadLine, createInterface } from 'readline'; | |
import { from, Observable, empty } from 'rxjs'; | |
import { catchError, mergeMap, map } from 'rxjs/operators'; | |
export class FirebaseUsers { | |
constructor(private auth: auth.Auth, private ignoreFirstLine: boolean) {} | |
/** | |
* Import all users found inside the CSV stream into Firebase Authentication. | |
* | |
* Note: Lines that cannot be parsed are skipped. Also users that cannot be imported | |
* because they exist already or do not meet other criterias are skipped over as well. | |
* Errors are written to the console. | |
* | |
* @param stream to parse the CSV from | |
* @returns string observable delivering user names | |
*/ | |
create(stream: NodeJS.ReadableStream): Observable<string> { | |
return new Observable<User>(obs => { | |
const lineReader = createInterface(stream); | |
let isFirstLine = true; | |
lineReader.on('line', (line: string) => { | |
if (isFirstLine && this.ignoreFirstLine) { | |
isFirstLine = false; | |
return; | |
} | |
const user = parseUserFromCsvLine(line); | |
obs.next(user); | |
}); | |
lineReader.on('close', () => obs.complete()); | |
}).pipe( | |
mergeMap(user => { | |
return from(this.auth.createUser(user)) | |
.pipe(catchError(err => { | |
console.error(`Cannot create user "${user.email}". ${err.errorInfo.message}`); | |
return empty(); | |
})); | |
}), | |
map(userRecord => userRecord.email), | |
); | |
} | |
} | |
/** | |
* Parses either colon or semicolon separated values (4 columns) from a text line. | |
* Windows, Linux and OSX line endings do work automatically. | |
*/ | |
export function parseUserFromCsvLine(line: string): User { | |
let lineItems = line.split(';'); | |
if (lineItems.length < 4) { | |
lineItems = line.split(','); | |
if (lineItems.length < 4) | |
throw new Error('Cannot parse user. No ; line separator found.'); | |
} | |
if (lineItems[2].indexOf(' ') > -1) | |
throw new Error('Cannot parse user. User name column 3 must not contain space.'); | |
return { | |
email: `${lineItems[2]}@team-challenge.at`, | |
password: lineItems[3] | |
}; | |
} | |
/** | |
* The user object that gets parsed from the CSV file and eventually | |
* is imported into Firebase Authentication. | |
*/ | |
export interface User { | |
email: string; | |
password: string; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment