Skip to content

Instantly share code, notes, and snippets.

@ewaldbenes
Created December 4, 2018 10:15
Show Gist options
  • Save ewaldbenes/6f41bd7fa081b17dc522e0c4e8141f47 to your computer and use it in GitHub Desktop.
Save ewaldbenes/6f41bd7fa081b17dc522e0c4e8141f47 to your computer and use it in GitHub Desktop.
Firebase user import from CSV using admin tools and RxJs
/**
* 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