Skip to content

Commit

Permalink
Merge pull request #643 from noire-munich/firebase_generator
Browse files Browse the repository at this point in the history
Firebase generator
  • Loading branch information
peterp committed Jun 15, 2020
2 parents 84727f3 + 39f2e0d commit 50bf2be
Show file tree
Hide file tree
Showing 6 changed files with 90 additions and 14 deletions.
31 changes: 20 additions & 11 deletions packages/cli/src/commands/generate/auth/auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,31 @@ import c from 'src/lib/colors'

const API_GRAPHQL_PATH = path.join(getPaths().api.functions, 'graphql.js')
const API_SRC_PATH = path.join(getPaths().api.src)
const TEMPLATE_PATH = path.resolve(__dirname, 'templates', 'auth.js.template')
const TEMPLATE = fs.readFileSync(TEMPLATE_PATH).toString()
const TEMPLATES = fs
.readdirSync(path.resolve(__dirname, 'templates'))
.reduce((templates, file) => {
if (file === 'auth.js.template') {
return { ...templates, base: path.resolve(__dirname, 'templates', file) }
} else {
const provider = file.replace('.auth.js.template', '')
return {
...templates,
[provider]: path.resolve(__dirname, 'templates', file),
}
}
}, {})
const OUTPUT_PATH = path.join(getPaths().api.lib, 'auth.js')
const WEB_SRC_INDEX_PATH = path.join(getPaths().web.src, 'index.js')
const SUPPORTED_PROVIDERS = fs
.readdirSync(path.resolve(__dirname, 'providers'))
.map((file) => path.basename(file, '.js'))
.filter((file) => file !== 'README.md')

// returns the content of index.js with import statements added
const addWebImports = (content, imports) => {
const importStatements = imports.map((imp) => {
return `import ${imp.import} from '${imp.from}'`
})

return (
`import { AuthProvider } from '@redwoodjs/auth'\n` +
importStatements.join('\n') +
imports.join('\n') +
'\n' +
content
)
Expand Down Expand Up @@ -60,9 +68,10 @@ const addWebRender = (content, authProvider) => {
}

// the files to create to support auth
export const files = () => {
export const files = (provider) => {
const template = TEMPLATES[provider] ?? TEMPLATES.base
return {
[OUTPUT_PATH]: TEMPLATE,
[OUTPUT_PATH]: fs.readFileSync(template).toString(),
}
}

Expand Down Expand Up @@ -114,7 +123,7 @@ export const description = 'Generate an auth configuration'
export const builder = (yargs) => {
yargs
.positional('provider', {
choices: ['netlify', 'auth0', 'magic-link'],
choices: SUPPORTED_PROVIDERS,
description: 'Auth provider to configure',
type: 'string',
})
Expand Down Expand Up @@ -162,7 +171,7 @@ export const handler = async ({ provider, force }) => {
title: 'Generating auth lib...',
task: (_ctx, task) => {
if (apiSrcDoesExist()) {
return writeFilesTask(files(), { overwriteExisting: force })
return writeFilesTask(files(provider), { overwriteExisting: force })
} else {
task.skip('api/src not found, skipping')
}
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/commands/generate/auth/providers/auth0.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// the lines that need to be added to index.js
export const config = {
imports: [{ import: '{ Auth0Client }', from: '@auth0/auth0-spa-js' }],
imports: [`import { Auth0Client } from '@auth0/auth0-spa-js'`],
init: `const auth0 = new Auth0Client({
domain: process.env.AUTH0_DOMAIN,
client_id: process.env.AUTH0_CLIENT_ID,
Expand Down
30 changes: 30 additions & 0 deletions packages/cli/src/commands/generate/auth/providers/firebase.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
export const config = {
imports: [
`import * as firebase from 'firebase/app'`,
`import 'firebase/auth'`,
],
init: `const firebaseClientConfig = {
apiKey: process.env.FIREBASE_API_KEY,
authDomain: process.env.FIREBASE_AUTH_DOMAIN,
databaseURL: process.env.FIREBASE_DATABASE_URL,
projectId: process.env.FIREBASE_PROJECT_ID,
storageBucket: process.env.FIREBASE_STORAGE_BUCKET,
messagingSenderId: process.env.FIREBASE_MESSAGING_SENDER_ID,
appId: process.env.FIREBASE_APP_ID,
}
const firebaseClient = ((config) => {
firebase.initializeApp(config)
return firebase
})(firebaseClientConfig)
`,
authProvider: { client: 'firebaseClient', type: 'firebase' },
}

export const packages = ['firebase']

export const notes = [
'You will need to create several environment variables with your Firebase config options.',
'Check out web/src/index.js for the variables you need to add.',
'See: https://firebase.google.com/docs/web/setup#config-object',
]
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export const config = {
imports: [{ import: '{ Magic }', from: 'magic-sdk' }],
imports: [`import { Magic } from 'magic-sdk'`],
init: 'const m = new Magic(process.env.MAGICLINK_PUBLIC)',
authProvider: {
client: 'm',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// the lines that need to be added to index.js
export const config = {
imports: [{ import: 'netlifyIdentity', from: 'netlify-identity-widget' }],
imports: [`import netlifyIdentity from 'netlify-identity-widget'`],
init: 'netlifyIdentity.init()',
authProvider: {
client: 'netlifyIdentity',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Define what you want `currentUser` to return throughout your app. For example,
// to return a real user from your database, you could do something like:
//
// export const getCurrentUser = async ({ email }) => {
// return await db.user.findOne({ where: { email } })
// }

import { AuthenticationError } from '@redwoodjs/api'
import admin from 'firebase-admin'

import { db } from './db'

const config = {
apiKey: process.env.FIREBASE_API_KEY,
authDomain: process.env.FIREBASE_AUTH_DOMAIN,
databaseURL: process.env.FIREBASE_DATABASE_URL,
projectId: process.env.FIREBASE_PROJECT_ID,
storageBucket: process.env.FIREBASE_STORAGE_BUCKET,
messagingSenderId: process.env.FIREBASE_MESSAGING_SENDER_ID,
appId: process.env.FIREBASE_APP_ID,
}

const adminApp = admin.initializeApp(config)

export const getCurrentUser = async (token) => {
const { email, uid } = await adminApp.auth().verifyToken(token)
return { email, uid }
}

// Use this function in your services to check that a user is logged in, and
// optionally raise an error if they're not.

export const requireAuth = () => {
if (!context.currentUser) {
throw new AuthenticationError("You don't have permission to do that.")
}
}

0 comments on commit 50bf2be

Please sign in to comment.