db backup function

This commit is contained in:
Chris\Laptop
2018-11-21 12:31:56 +01:00
parent ae7c12135a
commit 88ee4c9d2c
6 changed files with 74 additions and 12012 deletions

1
functions-cron Submodule

Submodule functions-cron added at 18009b3c48

View File

@@ -11,14 +11,14 @@
},
"main": "lib/index.js",
"dependencies": {
"axios": "^0.18.0",
"body-parser": "^1.18.3",
"cors": "^2.8.5",
"express": "^4.16.4",
"firebase-admin": "~6.0.0",
"firebase-functions": "^2.1.0",
"google-auth-library": "^2.0.1",
"googleapis": "^35.0.0",
"request-promise": "^4.2.2"
"googleapis": "^35.0.0"
},
"devDependencies": {
"tslint": "~5.8.0",

View File

@@ -1,12 +1,14 @@
import { pubsub } from 'firebase-functions'
// import { pubsub } from 'firebase-functions'
import { JWT } from 'google-auth-library'
import * as admin from 'firebase-admin'
// import * as rp from 'request-promise'
import * as devKey from './config/dev-service-account-key.json'
import * as config from './config/dev-service-account-key.json'
import Axios from 'axios'
const PROJECT_ID = 'test'
/* Cloud function to automatically backup the firebase database adapted from:
https://thatweirddeveloper.com/how-to-back-up-cloud-firestore-periodically
*/
admin.initializeApp()
const PROJECT_ID = config.project_id
// authorise application using JWT, requires key file defined above as dev key
// see config/readme for more info
@@ -16,17 +18,15 @@ const getAccessToken = async () => {
'https://www.googleapis.com/auth/cloud-platform',
]
const jwtClient = new JWT(
devKey.client_email,
config.client_email,
null,
devKey.private_key,
config.private_key,
scopes,
)
try {
const authorization = await jwtClient.authorize()
console.log('authorisation successful', authorization)
return authorization.access_token
} catch (error) {
console.error(error)
return null
}
}
@@ -36,19 +36,35 @@ export const AuthTest = async () => {
return token
}
export const DatabaseBackup = async () =>
pubsub.topic('firebase-backup').onPublish(async (message, context) => {
console.log('executing database backup')
const accessToken = await getAccessToken()
console.log('access token received', accessToken)
const url = `https://firestore.googleapis.com/v1beta1/projects/${PROJECT_ID}/databases/(default):exportDocuments`
// return rp.post(url, {
// headers: {
// Authorization: `Bearer ${accessToken}`,
// },
// json: true,
// body: {
// outputUriPrefix: `gs://${PROJECT_ID}-backups`,
// },
// })
})
// rest reference: https://cloud.google.com/firestore/docs/reference/rest/v1beta2/projects.databases/exportDocuments
export const BackupDatabase = async () => {
console.log('executing database backup')
const accessToken = await getAccessToken()
console.log('access token received', accessToken)
const url = `https://firestore.googleapis.com/v1beta1/projects/${PROJECT_ID}/databases/(default):exportDocuments`
// use axios to send post request as promise
console.log('posting', url)
const timestamp: string = new Date().toString()
let res
try {
res = await Axios({
url: url,
method: 'post',
headers: {
Authorization: `Bearer ${accessToken}`,
},
data: {
outputUriPrefix: `gs://${PROJECT_ID}.appspot.com/backups/${timestamp}`,
},
})
} catch (error) {
res = 404
}
return res
}
// const createSub = async () => {
// pubsub
// .topic('firebase-backup')
// .onPublish(async (message, context) => BackupDatabase)
// }

View File

@@ -3,17 +3,19 @@ import * as bodyParser from 'body-parser'
import * as cors from 'cors'
import * as express from 'express'
import * as functions from 'firebase-functions'
import * as admin from 'firebase-admin'
admin.initializeApp()
// custom module imports
import * as DB from './databaseBackup'
// dev only
const buildNumber = 1
const app = express()
// update on change logging purposes
const buildNumber = 1.03
// express settings to handle api
const app = express()
// Automatically allow cross-origin requests
app.use(cors({ origin: true }))
// use bodyparse to create json object from body
app.use(
bodyParser.json({
@@ -23,13 +25,11 @@ app.use(
app.use(bodyParser.urlencoded({ extended: false }))
/************ GET and POST requests ************************************************
Redirect requests so that if a custom endpoint function exists on koboApi call it,
otherwise pipe request directly to kobo native API
Redirect requests so that if a custom endpoint function exists we can call them
at /api/[endpoint]
************************************************************************************/
app.all('*', async (req, res, next) => {
// log the version number for dev / tracking:
console.log('api build number', buildNumber)
// get the endpoint based on the request path
const endpoint = req.path.split('/')[1]
// *** NOTE currently all request types handled the same, i.e. GET/POST
@@ -38,17 +38,35 @@ app.all('*', async (req, res, next) => {
case 'db-test':
const token = await DB.AuthTest()
res.send(token)
break
case 'backup':
const response = await DB.BackupDatabase()
res.send(response)
break
default:
res.send('invalid api endpoint')
}
})
// Expose Express API as a single Cloud Function:
exports.api = functions.https.onRequest(app)
app.listen(3000, 'localhost', listen => {
console.log('API listening on port 3000')
console.log(`API v${buildNumber} listening on port 3000`)
})
/************ Cron tasks ***********************************************************
Use pubsub to automatically subscribe to messages sent from cron.
Add/change schedule from `./functions-cron/appengine/cron.yaml`
************************************************************************************/
exports.backupFirestore = functions.pubsub
.topic('firebase-backup')
.onPublish(async (message, context) => {
console.log('initiating backup')
// run our daily db backup task
const backup = await DB.BackupDatabase()
console.log('backup:', backup)
return true
})
// add export so can be used by test
export default app

11974
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -32,6 +32,7 @@
"src/setupTests.ts",
"config/*.js",
"config/jest/*.js",
"functions-cron",
"functions"
]
}