blob: b9ee9defeee16c17b2e2467cb8dd7138e58e675a [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
'use strict';
const fs = require('fs');
const _ = require('lodash');
const mongoose = require('mongoose');
// Fire me up!
/**
* Module mongo schema.
*/
module.exports = {
implements: 'mongo',
inject: ['settings', 'schemas']
};
const defineSchema = (schemas) => {
const result = { connection: mongoose.connection };
result.ObjectId = mongoose.Types.ObjectId;
result.errCodes = {
DUPLICATE_KEY_ERROR: 11000,
DUPLICATE_KEY_UPDATE_ERROR: 11001
};
// Define models.
_.forEach(schemas, (schema, name) => {
result[name] = mongoose.model(name, schema);
});
result.handleError = function(res, err) {
// TODO IGNITE-843 Send error to admin
res.status(err.code || 500).send(err.message);
};
return result;
};
const upgradeAccounts = (mongo, activation) => {
if (activation) {
return mongo.Account.find({
$or: [{activated: false}, {activated: {$exists: false}}],
activationToken: {$exists: false}
}, '_id').lean().exec()
.then((accounts) => {
const conditions = _.map(accounts, (account) => ({session: {$regex: `"${account._id}"`}}));
return mongoose.connection.db.collection('sessions').deleteMany({$or: conditions});
});
}
return mongo.Account.updateMany({activated: false}, {$unset: {activationSentAt: '', activationToken: ''}}).exec();
};
module.exports.factory = function(settings, schemas) {
// Use native promises
mongoose.Promise = global.Promise;
console.log(settings.mongoUrl, 'Trying to connect to local MongoDB...');
// Connect to mongoDB database.
return mongoose.connect(settings.mongoUrl, {useNewUrlParser: true, useCreateIndex: true})
.then(() => defineSchema(schemas))
.catch(() => {
console.log(`Failed to connect to MongoDB with connection string: "${settings.mongoUrl}", will try to download and start embedded MongoDB`);
const dbDir = `${process.cwd()}/user_data`;
if (!fs.existsSync(dbDir))
fs.mkdirSync(dbDir);
const {MongodHelper} = require('mongodb-prebuilt');
const {MongoDBDownload} = require('mongodb-download');
const helper = new MongodHelper(['--port', '27017', '--dbpath', dbDir]);
helper.mongoBin.mongoDBPrebuilt.mongoDBDownload = new MongoDBDownload({
downloadDir: `${process.cwd()}/libs/mongodb`,
version: '4.0.9'
});
let mongodRun;
if (settings.packaged) {
mongodRun = new Promise((resolve, reject) => {
helper.resolveLink = resolve;
helper.rejectLink = reject;
helper.mongoBin.runCommand()
.then(() => {
helper.mongoBin.childProcess.removeAllListeners('close');
helper.mongoBin.childProcess.stderr.on('data', (data) => helper.stderrHandler(data));
helper.mongoBin.childProcess.stdout.on('data', (data) => helper.stdoutHandler(data));
helper.mongoBin.childProcess.on('close', (code) => helper.closeHandler(code));
});
});
}
else
mongodRun = helper.run();
return mongodRun
.catch((err) => {
console.log('Failed to start embedded MongoDB', err);
return Promise.reject(err);
})
.then(() => {
console.log('Embedded MongoDB successfully started');
return mongoose.connect(settings.mongoUrl, {useNewUrlParser: true, useCreateIndex: true})
.catch((err) => {
console.log('Failed to connect to embedded MongoDB', err);
return Promise.reject(err);
});
})
.then(() => defineSchema(schemas))
.then((mongo) => {
if (settings.packaged) {
return mongo.Account.count()
.then((count) => {
if (count === 0) {
return Promise.all([
mongo.Account.create({
_id: '59fc0c25e145c32be0f83b33',
salt: '7b4ccb9e375508a8f87c8f347083ce98cb8785d857dd18208f9a480e992a26bb',
hash: '909d5ed6e0b0a656ef542e2e8e851e9eb00cfb77984e0a6b4597c335d1436a577b3b289601eb8d1f3646e488cd5ea2bbb3e97fcc131cd6a9571407a45b1817bf1af1dd0ccdd070f07733da19e636ff9787369c5f38f86075f78c60809fe4a52288a68ca38aae0ad2bd0cc77b4cae310abf260e9523d361fd9be60e823a7d8e73954ddb18091e668acd3f57baf9fa7db4267e198d829761997a4741734335589ab62793ceb089e8fffe6e5b0e86f332b33a3011ba44e6efd29736f31cbd2b2023e5173baf517f337eb7a4321ea2b67ec827cffa271d26d3f2def93b5efa3ae7e6e327e55feb121ee96b8ff5016527cc7d854a9b49b44c993387c1093705cb26b1802a2e4c1d34508fb93d051d7e5e2e6cc65b6048a999f94c369973b46b204295f0b2f23f8e30723f9e984ddb2c53dcbf0a77a6d0795d44c3ad97a4ae49d6767db9630e2ef76c2069da87088f1400b1292df9bd787122b2cfef1f26a884a298a0bab3d6e6b689381cf6389d2f019e6cd19e82c84048bacfdd1bee946f9d40dda040be426e583abf92529a1c4f032d5058a9799a77e6642312b8d231d79300d5d0d3f74d62797f9d192e8581698e9539812a539ef1b9fbf718f44dd549896ea9449f6ea744586222e5fc29dfcd5eb79e7646ad3d37868f5073833c554853dee6b067bf2bbfab44c011f2de98a8570292f8109b6bde11e3be51075a656c32b521b7',
email: 'admin@admin',
firstName: 'admin',
lastName: 'admin',
company: 'admin',
country: 'United States',
admin: true,
token: 'ruQvlWff09zqoVYyh6WJ',
attempts: 0,
resetPasswordToken: 'O2GWgOkKkhqpDcxjYnSP',
activated: true
}),
mongo.Space.create({
_id: '59fc0c26e145c32be0f83b34',
name: 'Personal space',
owner: '59fc0c25e145c32be0f83b33',
usedBy: [],
demo: false
})
]);
}
})
.then(() => mongo)
.catch(() => mongo);
}
return mongo;
});
})
.then((mongo) => {
return upgradeAccounts(mongo, settings.activation.enabled)
.then(() => mongo)
.catch(() => mongo);
});
};