diff options
author | Koren Lev <korenlev@gmail.com> | 2017-07-27 16:42:15 +0300 |
---|---|---|
committer | Koren Lev <korenlev@gmail.com> | 2017-07-27 16:42:15 +0300 |
commit | b88c78e3cf2bef22aa2f1c4d0bf305e303bc15f0 (patch) | |
tree | ffa30a6e1511d72562d8772b8700cda52b2752a1 /ui/imports/api | |
parent | b70483739d1f6f4f0d31987ed2e4d1e30d71d579 (diff) |
adding calipso ui
Change-Id: Ifa6f63daebb07f45580f747341960e898fdb00c4
Signed-off-by: Koren Lev <korenlev@gmail.com>
Diffstat (limited to 'ui/imports/api')
67 files changed, 4154 insertions, 0 deletions
diff --git a/ui/imports/api/accounts/methods.js b/ui/imports/api/accounts/methods.js new file mode 100644 index 0000000..4e1c40a --- /dev/null +++ b/ui/imports/api/accounts/methods.js @@ -0,0 +1,196 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others / +// / +// All rights reserved. This program and the accompanying materials / +// are made available under the terms of the Apache License, Version 2.0 / +// which accompanies this distribution, and is available at / +// http://www.apache.org/licenses/LICENSE-2.0 / +///////////////////////////////////////////////////////////////////////////////////////// +import { ValidatedMethod } from 'meteor/mdg:validated-method'; +import { SimpleSchema } from 'meteor/aldeed:simple-schema'; +import * as R from 'ramda'; +import { Roles } from 'meteor/alanning:roles'; +import { Environments } from '/imports/api/environments/environments'; + +let userSchema = new SimpleSchema({ + _id: { type: String }, + username: { type: String }, + password: { type: String }, + viewEnvs: { type: [ String ] }, + editEnvs: { type: [ String ] }, +}); + +export const insert = new ValidatedMethod({ + name: 'accounts.insert', + validate: userSchema + .pick([ + 'username', + 'password', + 'viewEnvs', + 'viewEnvs.$', + 'editEnvs', + 'editEnvs.$', + ]).validator({ clean: true, filter: false }), + run({ + username, + password, + viewEnvs, + editEnvs, + }) { + if (! Roles.userIsInRole(Meteor.userId(), 'manage-users', Roles.GLOBAL_GROUP)) { + throw new Meteor.Error('unauthorized for removing users'); + } + + let userId = Accounts.createUser({ + username: username, + password: password + }); + + addRole(viewEnvs, 'view-env', userId); + addRole(editEnvs, 'edit-env', userId); + } +}); + + + +export const update = new ValidatedMethod({ + name: 'accounts.update', + validate: userSchema + .pick([ + '_id', + // 'password', + 'viewEnvs', + 'viewEnvs.$', + 'editEnvs', + 'editEnvs.$', + ]).validator({ clean: true, filter: false }), + run({ + _id, + //_password, + viewEnvs, + editEnvs, + }) { + console.log('accounts - methods - update - start'); + //throw new Meteor.Error('unimplemented'); + if (! Roles.userIsInRole(Meteor.userId(), 'manage-users', Roles.GLOBAL_GROUP)) { + throw new Meteor.Error('unauthorized for updating users'); + } + + /* + let item = Meteor.users.findOne({ _id: _id }); + console.log('user for update: ', item); + + item = R.merge(R.pick([ + 'password', + ], item), { + password + }); + */ + + /* + let item = { + //password + }; + + Meteor.users.update({ _id: _id }, { $set: item }); + */ + + let currentViewEnvs = R.map((env) => { + return env.name; + }, Environments.find({ 'auth.view-env': { $in: [ _id ] }}).fetch()); + + let viewEnvsForDelete = R.difference(currentViewEnvs, viewEnvs); + let viewEnvsForAdd = R.difference(viewEnvs, currentViewEnvs); + + removeRole(viewEnvsForDelete, 'view-env', _id); + addRole(viewEnvsForAdd, 'view-env', _id); + + // + + let currentEditEnvs = R.map((env) => { + return env.name; + }, Environments.find({ 'auth.edit-env': { $in: [ _id ] }}).fetch()); + + let editEnvsForDelete = R.difference(currentEditEnvs, editEnvs); + let editEnvsForAdd = R.difference(editEnvs, currentEditEnvs); + + removeRole(editEnvsForDelete, 'edit-env', _id); + addRole(editEnvsForAdd, 'edit-env', _id); + + console.log('accounts - methods - update - end'); + } +}); + +export const remove = new ValidatedMethod({ + name: 'accounts.remove', + validate: userSchema + .pick([ + '_id', + ]).validator({ clean: true, filter: false }), + run({ + _id + }) { + if (! Roles.userIsInRole(Meteor.userId(), 'manage-users', Roles.GLOBAL_GROUP)) { + throw new Meteor.Error('unauthorized for removing users'); + } + + let user = Meteor.users.findOne({ _id: _id }); + console.log('user for remove: ', user); + + Meteor.users.remove({ _id: _id }); + } +}); + +function removeRole(rolesForRemoval, roleName, userId) { + R.forEach((envName) => { + let env = Environments.findOne({ name: envName }); + let auth = env.auth; + if (R.isNil(auth)) { auth = { }; } + if (R.isNil(R.path([roleName], auth))) { + auth = R.assoc(roleName, [], auth); + } + auth = R.assoc(roleName, R.reject(R.equals(userId), auth[roleName]), auth); + + updateEnv(auth, env); + //let newEnv = R.merge(env, { auth: auth }); + + }, rolesForRemoval); +} + +function addRole(rolesForAdd, roleName, userId) { + R.forEach((envName) => { + let env = Environments.findOne({ name: envName }); + let auth = env.auth; + if (R.isNil(auth)) { auth = { }; } + if (R.isNil(R.path([roleName], auth))) { + auth = R.assoc(roleName, [], auth); + } + auth = R.assoc(roleName, R.append(userId, auth[roleName]), auth); + + updateEnv(auth, env); + //let newEnv = R.merge(env, { auth: auth }); + + }, rolesForAdd); +} + +function updateEnv(auth, env) { + console.log('update env. set: ' + R.toString(auth)); + try { + Environments.update(env._id, { + $set: { + auth: auth, + configuration: env.configuration, + //distribution: distribution, + //name: name, + type_drivers: env.type_drivers, + mechanism_drivers: env.mechanism_drivers, + listen: env.listen, + enable_monitoring: env.enable_monitoring, + } + }); + } catch(e) { + console.error('error in update: ' + R.toString(e)); + throw new Meteor.Error('enviornment update error', + `unable to update ACL for environment - ${env.name}. Please check envrironment info. ${e.message}`); + } +} diff --git a/ui/imports/api/accounts/server/publications.js b/ui/imports/api/accounts/server/publications.js new file mode 100644 index 0000000..47718d3 --- /dev/null +++ b/ui/imports/api/accounts/server/publications.js @@ -0,0 +1,29 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others / +// / +// All rights reserved. This program and the accompanying materials / +// are made available under the terms of the Apache License, Version 2.0 / +// which accompanies this distribution, and is available at / +// http://www.apache.org/licenses/LICENSE-2.0 / +///////////////////////////////////////////////////////////////////////////////////////// +import { Meteor } from 'meteor/meteor'; +//import * as R from 'ramda'; +//import { Environments } from '/imports/api/environments/environments'; +//import { Roles } from 'meteor/alanning:roles'; + +Meteor.publish('users', function () { + console.log('server subscribtion to: users'); + /* + let that = this; + + let query = {}; + + if (! Roles.userIsInRole(that.userId, 'manage-users', 'default-group')) { + query = { + _id: that.userId + }; + } + */ + + return Meteor.users.find({}); +}); diff --git a/ui/imports/api/attributes_for_hover_on_data/attributes_for_hover_on_data.js b/ui/imports/api/attributes_for_hover_on_data/attributes_for_hover_on_data.js new file mode 100644 index 0000000..ec2f6cd --- /dev/null +++ b/ui/imports/api/attributes_for_hover_on_data/attributes_for_hover_on_data.js @@ -0,0 +1,12 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others / +// / +// All rights reserved. This program and the accompanying materials / +// are made available under the terms of the Apache License, Version 2.0 / +// which accompanies this distribution, and is available at / +// http://www.apache.org/licenses/LICENSE-2.0 / +///////////////////////////////////////////////////////////////////////////////////////// +import { Mongo } from 'meteor/mongo'; + +export const NodeHoverAttr = new Mongo.Collection( + 'attributes_for_hover_on_data', { idGeneration: 'MONGO' }); diff --git a/ui/imports/api/attributes_for_hover_on_data/methods.js b/ui/imports/api/attributes_for_hover_on_data/methods.js new file mode 100644 index 0000000..1eda375 --- /dev/null +++ b/ui/imports/api/attributes_for_hover_on_data/methods.js @@ -0,0 +1,8 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others / +// / +// All rights reserved. This program and the accompanying materials / +// are made available under the terms of the Apache License, Version 2.0 / +// which accompanies this distribution, and is available at / +// http://www.apache.org/licenses/LICENSE-2.0 / +///////////////////////////////////////////////////////////////////////////////////////// diff --git a/ui/imports/api/attributes_for_hover_on_data/server/publications.js b/ui/imports/api/attributes_for_hover_on_data/server/publications.js new file mode 100644 index 0000000..bc42d58 --- /dev/null +++ b/ui/imports/api/attributes_for_hover_on_data/server/publications.js @@ -0,0 +1,25 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others / +// / +// All rights reserved. This program and the accompanying materials / +// are made available under the terms of the Apache License, Version 2.0 / +// which accompanies this distribution, and is available at / +// http://www.apache.org/licenses/LICENSE-2.0 / +///////////////////////////////////////////////////////////////////////////////////////// +import { Meteor } from 'meteor/meteor'; + +import { NodeHoverAttr } from '../attributes_for_hover_on_data.js'; + +Meteor.publish('attributes_for_hover_on_data', function () { + console.log('server subscribtion to: attributes_for_hover_on_data'); + //return Inventory.find({$where: 'this.id_path.match('^/WebEX-Mirantis@Cisco/')'}); + return NodeHoverAttr.find({}); +}); + +Meteor.publish('attributes_for_hover_on_data?type', function (type) { + console.log('server subscribtion to: attributes_for_hover_on_data?type'); + console.log('- type: ' + type); + + //return Inventory.find({$where: 'this.id_path.match('^/WebEX-Mirantis@Cisco/')'}); + return NodeHoverAttr.find({ 'type': type}); +}); diff --git a/ui/imports/api/clique-constraints/clique-constraints.js b/ui/imports/api/clique-constraints/clique-constraints.js new file mode 100644 index 0000000..8641715 --- /dev/null +++ b/ui/imports/api/clique-constraints/clique-constraints.js @@ -0,0 +1,48 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others / +// / +// All rights reserved. This program and the accompanying materials / +// are made available under the terms of the Apache License, Version 2.0 / +// which accompanies this distribution, and is available at / +// http://www.apache.org/licenses/LICENSE-2.0 / +///////////////////////////////////////////////////////////////////////////////////////// +import { Mongo } from 'meteor/mongo'; +import { SimpleSchema } from 'meteor/aldeed:simple-schema'; +import * as R from 'ramda'; +import { Constants } from '/imports/api/constants/constants'; + +export const CliqueConstraints = new Mongo.Collection( + 'clique_constraints', { idGeneration: 'MONGO' }); + +let schema = { + _id: { type: { _str: { type: String, regEx: SimpleSchema.RegEx.Id } } }, + + focal_point_type: { + type: String, + custom: function () { + let that = this; + let values = Constants.findOne({ name: 'object_types_for_links' }).data; + + if (R.isNil(R.find(R.propEq('value', that.value), values))) { + return 'notAllowed'; + } + } + }, + + constraints: { + type: [String], + minCount: 1, + custom: function () { + let that = this; + let objectTypes = Constants.findOne({ name: 'object_types_for_links' }).data; + + let findResult = R.intersection(that.value, R.pluck('value', objectTypes)); + if (findResult.length !== that.value.length) { return 'notAllowed'; } + + return; + }, + }, +}; + +CliqueConstraints.schema = new SimpleSchema(schema); +CliqueConstraints.attachSchema(CliqueConstraints.schema); diff --git a/ui/imports/api/clique-constraints/methods.js b/ui/imports/api/clique-constraints/methods.js new file mode 100644 index 0000000..c9ae997 --- /dev/null +++ b/ui/imports/api/clique-constraints/methods.js @@ -0,0 +1,99 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others / +// / +// All rights reserved. This program and the accompanying materials / +// are made available under the terms of the Apache License, Version 2.0 / +// which accompanies this distribution, and is available at / +// http://www.apache.org/licenses/LICENSE-2.0 / +///////////////////////////////////////////////////////////////////////////////////////// +import { ValidatedMethod } from 'meteor/mdg:validated-method'; +import * as R from 'ramda'; +import { Roles } from 'meteor/alanning:roles'; + +import { CliqueConstraints } from './clique-constraints'; + +export const insert = new ValidatedMethod({ + name: 'clique_constraints.insert', + validate: CliqueConstraints.simpleSchema() + .pick([ +// 'environment', + 'focal_point_type', + 'constraints', + 'constraints.$', + ]).validator({ clean: true, filter: false }), + run({ + // environment, + focal_point_type, + constraints, + }) { + if (! Roles.userIsInRole(Meteor.userId(), 'manage-clique-constraints', Roles.GLOBAL_GROUP)) { + throw new Meteor.Error('unauthorized for inserting clique constraints'); + } + + let cliqueConstraint = CliqueConstraints.schema.clean({}); + + cliqueConstraint = R.merge(cliqueConstraint, { + // environment, + focal_point_type, + constraints, + }); + + CliqueConstraints.insert(cliqueConstraint); + } +}); + +export const remove = new ValidatedMethod({ + name: 'clique_constraints.remove', + validate: CliqueConstraints.simpleSchema() + .pick([ + '_id', + ]).validator({ clean: true, filter: false }), + run({ + _id + }) { + if (! Roles.userIsInRole(Meteor.userId(), 'manage-clique-constraints', Roles.DEFAULT_GROUP)) { + throw new Meteor.Error('unauthorized for removing clique constraints'); + } + + let cliqueConstraint = CliqueConstraints.findOne({ _id: _id }); + console.log('clique constraint for remove: ', cliqueConstraint); + + CliqueConstraints.remove({ _id: _id }); + } +}); + +export const update = new ValidatedMethod({ + name: 'clique_constraints.update', + validate: CliqueConstraints.simpleSchema() + .pick([ + '_id', + 'focal_point_type', + 'constraints', + 'constraints.$', + ]).validator({ clean: true, filter: false }), + run({ + _id, + focal_point_type, + constraints, + }) { + + if (! Roles.userIsInRole(Meteor.userId(), 'manage-clique-constraints', Roles.DEFAULT_GROUP)) { + throw new Meteor.Error('unauthorized for removing clique constraints'); + } + + let item = CliqueConstraints.findOne({ _id: _id }); + console.log('clique constraints for update: ', item); + console.log('current user', Meteor.userId()); + + item = R.merge( + R.pick([ + 'focal_point_type', + 'constraints', + ], item), { + focal_point_type, + constraints, + }); + + CliqueConstraints.update({ _id: _id }, { $set: item }); + } +}); diff --git a/ui/imports/api/clique-constraints/server/publications.js b/ui/imports/api/clique-constraints/server/publications.js new file mode 100644 index 0000000..6e4ae1a --- /dev/null +++ b/ui/imports/api/clique-constraints/server/publications.js @@ -0,0 +1,30 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others / +// / +// All rights reserved. This program and the accompanying materials / +// are made available under the terms of the Apache License, Version 2.0 / +// which accompanies this distribution, and is available at / +// http://www.apache.org/licenses/LICENSE-2.0 / +///////////////////////////////////////////////////////////////////////////////////////// +import { Meteor } from 'meteor/meteor'; + +import { CliqueConstraints } from '../clique-constraints.js'; + +Meteor.publish('clique_constraints', function () { + console.log('server subscribtion: clique_constraints'); + + //let that = this; + + let query = {}; + return CliqueConstraints.find(query); +}); + +Meteor.publish('clique_constraints?_id', function (_id) { + console.log('server subscribtion: clique_constraints?_id'); + console.log(_id); + + //let that = this; + + let query = { _id: _id }; + return CliqueConstraints.find(query); +}); diff --git a/ui/imports/api/clique-types/clique-types.js b/ui/imports/api/clique-types/clique-types.js new file mode 100644 index 0000000..852c319 --- /dev/null +++ b/ui/imports/api/clique-types/clique-types.js @@ -0,0 +1,107 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others / +// / +// All rights reserved. This program and the accompanying materials / +// are made available under the terms of the Apache License, Version 2.0 / +// which accompanies this distribution, and is available at / +// http://www.apache.org/licenses/LICENSE-2.0 / +///////////////////////////////////////////////////////////////////////////////////////// +import { Mongo } from 'meteor/mongo'; +import { SimpleSchema } from 'meteor/aldeed:simple-schema'; +import * as R from 'ramda'; +import { Constants } from '/imports/api/constants/constants'; +import { Environments } from '/imports/api/environments/environments'; +import { LinkTypes } from '/imports/api/link-types/link-types'; + +export const CliqueTypes = new Mongo.Collection( + 'clique_types', { idGeneration: 'MONGO' }); + +let schema = { + _id: { type: { _str: { type: String, regEx: SimpleSchema.RegEx.Id } } }, + + environment: { + type: String, + custom: function () { + let that = this; + let env = Environments.findOne({ name: that.value }); + + if (R.isNil(env)) { + return 'notAllowed'; + } + } + }, + + focal_point_type: { + type: String, + custom: function () { + let that = this; + let values = Constants.findOne({ name: 'object_types_for_links' }).data; + + if (R.isNil(R.find(R.propEq('value', that.value), values))) { + return 'notAllowed'; + } + } + }, + + link_types: { + type: [String], + minCount: 1, + custom: function () { + let that = this; + let findResult = R.all(function (pLinkType) { + if (R.isNil(LinkTypes.findOne({ type: pLinkType }))) { + return false; + } + + return true; + }, that.value); + + if (! findResult) { return 'notAllowed'; } + + return; + }, + }, + + name: { + type: String + }, +}; + +let simpleSchema = new SimpleSchema(schema); + +simpleSchema.addValidator(function () { + let that = this; + + let existing = CliqueTypes.findOne({ + environment: that.field('environment').value, + focal_point_type: that.field('focal_point_type').value + }); + + if (R.allPass([ + R.pipe(R.isNil, R.not), + R.pipe(R.propEq('_id', that.docId), R.not) + ])(existing)) { + + return 'alreadyExists'; + } +}); + +simpleSchema.addValidator(function () { + let that = this; + + let existing = CliqueTypes.findOne({ + environment: that.field('environment').value, + name: that.field('name').value + }); + + if (R.allPass([ + R.pipe(R.isNil, R.not), + R.pipe(R.propEq('_id', that.docId), R.not) + ])(existing)) { + + return 'alreadyExists'; + } +}); + +CliqueTypes.schema = simpleSchema; +CliqueTypes.attachSchema(CliqueTypes.schema); diff --git a/ui/imports/api/clique-types/methods.js b/ui/imports/api/clique-types/methods.js new file mode 100644 index 0000000..a62c22f --- /dev/null +++ b/ui/imports/api/clique-types/methods.js @@ -0,0 +1,108 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others / +// / +// All rights reserved. This program and the accompanying materials / +// are made available under the terms of the Apache License, Version 2.0 / +// which accompanies this distribution, and is available at / +// http://www.apache.org/licenses/LICENSE-2.0 / +///////////////////////////////////////////////////////////////////////////////////////// +import { ValidatedMethod } from 'meteor/mdg:validated-method'; +import * as R from 'ramda'; +import { Roles } from 'meteor/alanning:roles'; + +import { CliqueTypes } from './clique-types'; + +export const insert = new ValidatedMethod({ + name: 'clique_types.insert', + validate: CliqueTypes.simpleSchema() + .pick([ + 'environment', + 'focal_point_type', + 'link_types', + 'link_types.$', + 'name', + ]).validator({ clean: true, filter: false }), + run({ + environment, + focal_point_type, + link_types, + name, + }) { + if (! Roles.userIsInRole(Meteor.userId(), 'manage-clique-types', Roles.DEFAULT_GROUP)) { + throw new Meteor.Error('unauthorized for adding clique type'); + } + + let cliqueType = CliqueTypes.schema.clean({}); + + cliqueType = R.merge(cliqueType, { + environment, + focal_point_type, + link_types, + name, + }); + + CliqueTypes.insert(cliqueType); + } +}); + +export const remove = new ValidatedMethod({ + name: 'clique_types.remove', + validate: CliqueTypes.simpleSchema() + .pick([ + '_id', + ]).validator({ clean: true, filter: false }), + run({ + _id + }) { + + if (! Roles.userIsInRole(Meteor.userId(), 'manage-clique-types', Roles.DEFAULT_GROUP)) { + throw new Meteor.Error('unauthorized for removing clique type'); + } + + let cliqueType = CliqueTypes.findOne({ _id: _id }); + console.log('clique type for remove: ', cliqueType); + + CliqueTypes.remove({ _id: _id }); + } +}); + +export const update = new ValidatedMethod({ + name: 'clique_types.update', + validate: CliqueTypes.simpleSchema() + .pick([ + '_id', + 'environment', + 'focal_point_type', + 'link_types', + 'link_types.$', + 'name', + ]).validator({ clean: true, filter: false }), + run({ + _id, + environment, + focal_point_type, + link_types, + name, + }) { + if (! Roles.userIsInRole(Meteor.userId(), 'manage-clique-types', Roles.DEFAULT_GROUP)) { + throw new Meteor.Error('unauthorized for updating clique type'); + } + + let cliqueType = CliqueTypes.findOne({ _id: _id }); + console.log('clique type for remove: ', cliqueType); + + cliqueType = R.merge(R.pick([ + 'environment', + 'focal_point_type', + 'link_types', + 'name', ], + cliqueType), { + environment, + focal_point_type, + link_types, + name, + }); + + CliqueTypes.update({ _id: _id }, { $set: cliqueType }); + } +}); diff --git a/ui/imports/api/clique-types/server/publications.js b/ui/imports/api/clique-types/server/publications.js new file mode 100644 index 0000000..95274b9 --- /dev/null +++ b/ui/imports/api/clique-types/server/publications.js @@ -0,0 +1,34 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others / +// / +// All rights reserved. This program and the accompanying materials / +// are made available under the terms of the Apache License, Version 2.0 / +// which accompanies this distribution, and is available at / +// http://www.apache.org/licenses/LICENSE-2.0 / +///////////////////////////////////////////////////////////////////////////////////////// +import { Meteor } from 'meteor/meteor'; +import * as R from 'ramda'; + +import { CliqueTypes } from '../clique-types.js'; + +Meteor.publish('clique_types?env*', function (env) { + console.log('server subscribtion: clique_types?env*'); + console.log(env); + + //let that = this; + + let query = {}; + if (! R.isNil(env)) { query = R.assoc('environment', env, query); } + console.log('-query: ', query); + return CliqueTypes.find(query); +}); + +Meteor.publish('clique_types?_id', function (_id) { + console.log('server subscribtion: clique_types?_id'); + console.log(_id); + + //let that = this; + + let query = { _id: _id }; + return CliqueTypes.find(query); +}); diff --git a/ui/imports/api/cliques/cliques.js b/ui/imports/api/cliques/cliques.js new file mode 100644 index 0000000..78fb7ad --- /dev/null +++ b/ui/imports/api/cliques/cliques.js @@ -0,0 +1,12 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others / +// / +// All rights reserved. This program and the accompanying materials / +// are made available under the terms of the Apache License, Version 2.0 / +// which accompanies this distribution, and is available at / +// http://www.apache.org/licenses/LICENSE-2.0 / +///////////////////////////////////////////////////////////////////////////////////////// +import { Mongo } from 'meteor/mongo'; + +export const Cliques = new Mongo.Collection( + 'cliques', { idGeneration: 'MONGO' }); diff --git a/ui/imports/api/cliques/methods.js b/ui/imports/api/cliques/methods.js new file mode 100644 index 0000000..1eda375 --- /dev/null +++ b/ui/imports/api/cliques/methods.js @@ -0,0 +1,8 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others / +// / +// All rights reserved. This program and the accompanying materials / +// are made available under the terms of the Apache License, Version 2.0 / +// which accompanies this distribution, and is available at / +// http://www.apache.org/licenses/LICENSE-2.0 / +///////////////////////////////////////////////////////////////////////////////////////// diff --git a/ui/imports/api/cliques/server/publications.js b/ui/imports/api/cliques/server/publications.js new file mode 100644 index 0000000..16a4644 --- /dev/null +++ b/ui/imports/api/cliques/server/publications.js @@ -0,0 +1,33 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others / +// / +// All rights reserved. This program and the accompanying materials / +// are made available under the terms of the Apache License, Version 2.0 / +// which accompanies this distribution, and is available at / +// http://www.apache.org/licenses/LICENSE-2.0 / +///////////////////////////////////////////////////////////////////////////////////////// +import { Meteor } from 'meteor/meteor'; + +import { Cliques } from '../cliques.js'; + +Meteor.publish('cliques', function () { + console.log('server subscribtion to: cliques'); + //return Inventory.find({$where: 'this.id_path.match('^/WebEX-Mirantis@Cisco/')'}); + return Cliques.find({}); +}); + +Meteor.publish('cliques?focal_point', function (objId) { + var query = { + focal_point: new Mongo.ObjectID(objId) + }; +/* + var counterName = 'inventory?env+type!counter?env=' + env + '&type=' + type; + + console.log('server subscribing to counter: ' + counterName); + Counts.publish(this, counterName, Inventory.find(query)); +*/ + + console.log('server subscribtion to: cliques?focal_point'); + console.log('- focal_point: ' + objId); + return Cliques.find(query); +}); diff --git a/ui/imports/api/constants/constants.js b/ui/imports/api/constants/constants.js new file mode 100644 index 0000000..b3f0407 --- /dev/null +++ b/ui/imports/api/constants/constants.js @@ -0,0 +1,22 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others / +// / +// All rights reserved. This program and the accompanying materials / +// are made available under the terms of the Apache License, Version 2.0 / +// which accompanies this distribution, and is available at / +// http://www.apache.org/licenses/LICENSE-2.0 / +///////////////////////////////////////////////////////////////////////////////////////// +import { Mongo } from 'meteor/mongo'; +import { SimpleSchema } from 'meteor/aldeed:simple-schema'; +//import * as R from 'ramda'; + +export const Constants = new Mongo.Collection('constants', { idGeneration: 'MONGO' }); + +let schema = { + _id: { type: { _str: { type: String, regEx: SimpleSchema.RegEx.Id } } }, + name: { type: String }, + data: { type: [Object], blackbox: true }, +}; + +Constants.schema = schema; +Constants.attachSchema(schema); diff --git a/ui/imports/api/constants/data/distributions.js b/ui/imports/api/constants/data/distributions.js new file mode 100644 index 0000000..97ecdb4 --- /dev/null +++ b/ui/imports/api/constants/data/distributions.js @@ -0,0 +1,64 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others / +// / +// All rights reserved. This program and the accompanying materials / +// are made available under the terms of the Apache License, Version 2.0 / +// which accompanies this distribution, and is available at / +// http://www.apache.org/licenses/LICENSE-2.0 / +///////////////////////////////////////////////////////////////////////////////////////// +export const Distributions = [{ + label: 'Mirantis-6.0', + value: 'Mirantis-6.0', +}, { + label: 'Mirantis-7.0', + value: 'Mirantis-7.0', +}, { + label: 'Mirantis-8.0', + value: 'Mirantis-8.0', +}, { + label: 'Mirantis-9.0', + value: 'Mirantis-9.0', +}, { + label: 'RDO-Mitaka', + value: 'RDO-Mitaka', +}, { + label: 'RDO-Liberty', + value: 'RDO-Liberty', +}, { + label: 'RDO-Juno', + value: 'RDO-Juno', +}, { + label: 'RDO-kilo', + value: 'RDO-kilo', +}, { + label: 'devstack-liberty', + value: 'devstack-liberty', +}, { + label: 'Canonical-icehouse', + value: 'Canonical-icehouse', +}, { + label: 'Canonical-juno', + value: 'Canonical-juno', +}, { + label: 'Canonical-liberty', + value: 'Canonical-liberty', +}, { + label: 'Canonical-mitaka', + value: 'Canonical-mitaka', +}, { + label: 'Apex-Mitaka', + value: 'Apex-Mitaka', +}, { + label: 'Devstack-Mitaka', + value: 'Devstack-Mitaka', +}, { + label: 'packstack-7.0.0-0.10.dev1682', + value: 'packstack-7.0.0-0.10.dev1682', +}, { + label: 'Stratoscale-v2.1.6', + value: 'Stratoscale-v2.1.6', +}, { + label: 'Mirantis-9.1', + value: 'Mirantis-9.1', +} +]; diff --git a/ui/imports/api/constants/data/env-types.js b/ui/imports/api/constants/data/env-types.js new file mode 100644 index 0000000..00b0aaf --- /dev/null +++ b/ui/imports/api/constants/data/env-types.js @@ -0,0 +1,15 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others / +// / +// All rights reserved. This program and the accompanying materials / +// are made available under the terms of the Apache License, Version 2.0 / +// which accompanies this distribution, and is available at / +// http://www.apache.org/licenses/LICENSE-2.0 / +///////////////////////////////////////////////////////////////////////////////////////// +export const EnvTypes = [{ + label: 'Production', + value: 'production', +}, { + label: 'Development', + value: 'development', +}]; diff --git a/ui/imports/api/constants/data/environment-monitoring-types.js b/ui/imports/api/constants/data/environment-monitoring-types.js new file mode 100644 index 0000000..e3a573a --- /dev/null +++ b/ui/imports/api/constants/data/environment-monitoring-types.js @@ -0,0 +1,12 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others / +// / +// All rights reserved. This program and the accompanying materials / +// are made available under the terms of the Apache License, Version 2.0 / +// which accompanies this distribution, and is available at / +// http://www.apache.org/licenses/LICENSE-2.0 / +///////////////////////////////////////////////////////////////////////////////////////// +export const EnvironmentMonitoringTypes = [{ + label: 'Sensu', + value: 'Sensu', +}]; diff --git a/ui/imports/api/constants/data/environment-provision-types.js b/ui/imports/api/constants/data/environment-provision-types.js new file mode 100644 index 0000000..5139266 --- /dev/null +++ b/ui/imports/api/constants/data/environment-provision-types.js @@ -0,0 +1,21 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others / +// / +// All rights reserved. This program and the accompanying materials / +// are made available under the terms of the Apache License, Version 2.0 / +// which accompanies this distribution, and is available at / +// http://www.apache.org/licenses/LICENSE-2.0 / +///////////////////////////////////////////////////////////////////////////////////////// +export const EnvProvisionTypes = [{ + label: 'None', + value: 'None', +}, { + label: 'Deploy', + value: 'Deploy', +}, { + label: 'Files', + value: 'Files', +}, { + label: 'DB', + value: 'DB', +}]; diff --git a/ui/imports/api/constants/data/log-levels.js b/ui/imports/api/constants/data/log-levels.js new file mode 100644 index 0000000..dee6b6d --- /dev/null +++ b/ui/imports/api/constants/data/log-levels.js @@ -0,0 +1,27 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others / +// / +// All rights reserved. This program and the accompanying materials / +// are made available under the terms of the Apache License, Version 2.0 / +// which accompanies this distribution, and is available at / +// http://www.apache.org/licenses/LICENSE-2.0 / +///////////////////////////////////////////////////////////////////////////////////////// +export const LogLevels = [{ + label: 'CRITICAL', + value: 'critical', +}, { + label: 'ERROR', + value: 'error', +}, { + label: 'WARNING', + value: 'warning', +}, { + label: 'INFO', + value: 'info', +}, { + label: 'DEBUG', + value: 'debug', +}, { + label: 'NOTSET', + value: 'notset', +}]; diff --git a/ui/imports/api/constants/data/mechanism-drivers.js b/ui/imports/api/constants/data/mechanism-drivers.js new file mode 100644 index 0000000..afa8b01 --- /dev/null +++ b/ui/imports/api/constants/data/mechanism-drivers.js @@ -0,0 +1,24 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others / +// / +// All rights reserved. This program and the accompanying materials / +// are made available under the terms of the Apache License, Version 2.0 / +// which accompanies this distribution, and is available at / +// http://www.apache.org/licenses/LICENSE-2.0 / +///////////////////////////////////////////////////////////////////////////////////////// +export const MechanismDrivers = [{ + 'label' : 'ovs', + 'value' : 'ovs' +}, { + 'label' : 'vpp', + 'value' : 'vpp' +}, { + 'label' : 'lxb', + 'value' : 'lxb' +}, { + 'label' : 'Arista', + 'value' : 'Arista' +}, { + 'label' : 'Nexus', + 'value' : 'Nexus' +}]; diff --git a/ui/imports/api/constants/data/message-source-systems.js b/ui/imports/api/constants/data/message-source-systems.js new file mode 100644 index 0000000..77ec901 --- /dev/null +++ b/ui/imports/api/constants/data/message-source-systems.js @@ -0,0 +1,15 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others / +// / +// All rights reserved. This program and the accompanying materials / +// are made available under the terms of the Apache License, Version 2.0 / +// which accompanies this distribution, and is available at / +// http://www.apache.org/licenses/LICENSE-2.0 / +///////////////////////////////////////////////////////////////////////////////////////// +export const MessageSourceSystems = [{ + label: 'OpenStack', + value: 'OpenStack', +}, { + label: 'OSDNA_Sensu', + value: 'OSDNA_Sensu', +}]; diff --git a/ui/imports/api/constants/data/network-plugins.js b/ui/imports/api/constants/data/network-plugins.js new file mode 100644 index 0000000..c89be26 --- /dev/null +++ b/ui/imports/api/constants/data/network-plugins.js @@ -0,0 +1,15 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others / +// / +// All rights reserved. This program and the accompanying materials / +// are made available under the terms of the Apache License, Version 2.0 / +// which accompanies this distribution, and is available at / +// http://www.apache.org/licenses/LICENSE-2.0 / +///////////////////////////////////////////////////////////////////////////////////////// +export const NetworkPlugins = [{ + label: 'OVS', + value: 'OVS', +}, { + label: 'VPP', + value: 'VPP', +}]; diff --git a/ui/imports/api/constants/data/object-types-for-links.js b/ui/imports/api/constants/data/object-types-for-links.js new file mode 100644 index 0000000..35f1805 --- /dev/null +++ b/ui/imports/api/constants/data/object-types-for-links.js @@ -0,0 +1,39 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others / +// / +// All rights reserved. This program and the accompanying materials / +// are made available under the terms of the Apache License, Version 2.0 / +// which accompanies this distribution, and is available at / +// http://www.apache.org/licenses/LICENSE-2.0 / +///////////////////////////////////////////////////////////////////////////////////////// +export const ObjectTypesForLinks = [{ + label: 'vnic', + value: 'vnic', +}, { + label: 'vconnector', + value: 'vconnector', +}, { + label: 'vedge', + value: 'vedge', +}, { + label: 'instance', + value: 'instance', +}, { + label: 'vservice', + value: 'vservice', +}, { + label: 'pnic', + value: 'pnic', +}, { + label: 'network', + value: 'network', +}, { + label: 'port', + value: 'port', +}, { + label: 'otep', + value: 'otep', +}, { + label: 'agent', + value: 'agent', +}]; diff --git a/ui/imports/api/constants/data/scans-statuses.js b/ui/imports/api/constants/data/scans-statuses.js new file mode 100644 index 0000000..778f256 --- /dev/null +++ b/ui/imports/api/constants/data/scans-statuses.js @@ -0,0 +1,30 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others / +// / +// All rights reserved. This program and the accompanying materials / +// are made available under the terms of the Apache License, Version 2.0 / +// which accompanies this distribution, and is available at / +// http://www.apache.org/licenses/LICENSE-2.0 / +///////////////////////////////////////////////////////////////////////////////////////// +export const Statuses = [{ + value: 'draft', + label: 'Draft', +}, { + value: 'pending', + label: 'Pending', +}, { + value: 'running', + label: 'Running', +}, { + value: 'completed', + label: 'Completed', +}, { + value: 'failed', + label: 'Failed', +}, { + value: 'aborted', + label: 'Aborted', +} +]; + +export const StatusesInOperation = ['pending', 'running']; diff --git a/ui/imports/api/constants/data/type-drivers.js b/ui/imports/api/constants/data/type-drivers.js new file mode 100644 index 0000000..efc7f7d --- /dev/null +++ b/ui/imports/api/constants/data/type-drivers.js @@ -0,0 +1,24 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others / +// / +// All rights reserved. This program and the accompanying materials / +// are made available under the terms of the Apache License, Version 2.0 / +// which accompanies this distribution, and is available at / +// http://www.apache.org/licenses/LICENSE-2.0 / +///////////////////////////////////////////////////////////////////////////////////////// +export const TypeDrivers = [{ + 'label' : 'local', + 'value' : 'local' +}, { + 'label' : 'vlan', + 'value' : 'vlan' +}, { + 'label' : 'vxlan', + 'value' : 'vxlan' +}, { + 'label' : 'gre', + 'value' : 'gre' +}, { + 'label' : 'flat', + 'value' : 'flat' +}]; diff --git a/ui/imports/api/constants/server/publications.js b/ui/imports/api/constants/server/publications.js new file mode 100644 index 0000000..3ace17f --- /dev/null +++ b/ui/imports/api/constants/server/publications.js @@ -0,0 +1,16 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others / +// / +// All rights reserved. This program and the accompanying materials / +// are made available under the terms of the Apache License, Version 2.0 / +// which accompanies this distribution, and is available at / +// http://www.apache.org/licenses/LICENSE-2.0 / +///////////////////////////////////////////////////////////////////////////////////////// +import { Meteor } from 'meteor/meteor'; + +import { Constants } from '../constants.js'; + +Meteor.publish('constants', function () { + console.log('server subscribtion to: constants'); + return Constants.find({}); +}); diff --git a/ui/imports/api/environments/configuration-groups/aci-configuration.js b/ui/imports/api/environments/configuration-groups/aci-configuration.js new file mode 100644 index 0000000..10b749e --- /dev/null +++ b/ui/imports/api/environments/configuration-groups/aci-configuration.js @@ -0,0 +1,29 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others / +// / +// All rights reserved. This program and the accompanying materials / +// are made available under the terms of the Apache License, Version 2.0 / +// which accompanies this distribution, and is available at / +// http://www.apache.org/licenses/LICENSE-2.0 / +///////////////////////////////////////////////////////////////////////////////////////// +import { SimpleSchema } from 'meteor/aldeed:simple-schema'; + +export const AciSchema = new SimpleSchema({ + name: { + type: String, + autoValue: function () { return 'ACI'; } + }, + host: { + type: String, + regEx: SimpleSchema.RegEx.IP, + defaultValue: '10.56.0.104', + }, + user: { + type: String, + defaultValue: 'admin' + }, + pwd: { + type: String, + defaultValue: 'C1sco12345' + }, +}); diff --git a/ui/imports/api/environments/configuration-groups/amqp-configuration.js b/ui/imports/api/environments/configuration-groups/amqp-configuration.js new file mode 100644 index 0000000..83a15cf --- /dev/null +++ b/ui/imports/api/environments/configuration-groups/amqp-configuration.js @@ -0,0 +1,29 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others / +// / +// All rights reserved. This program and the accompanying materials / +// are made available under the terms of the Apache License, Version 2.0 / +// which accompanies this distribution, and is available at / +// http://www.apache.org/licenses/LICENSE-2.0 / +///////////////////////////////////////////////////////////////////////////////////////// +import { SimpleSchema } from 'meteor/aldeed:simple-schema'; +import { portRegEx } from '/imports/lib/general-regex'; + +export const AMQPSchema = new SimpleSchema({ + name: { type: String, autoValue: function () { return 'AMQP'; } }, + host: { + type: String, + regEx: SimpleSchema.RegEx.IP, + defaultValue: '10.0.0.1', + }, + port: { + type: String, + regEx: portRegEx, + defaultValue: '5673', + }, + user: { + type: String, + defaultValue: 'rabbitmquser' + }, + password: { type: String }, +}); diff --git a/ui/imports/api/environments/configuration-groups/cli-configuration.js b/ui/imports/api/environments/configuration-groups/cli-configuration.js new file mode 100644 index 0000000..c651359 --- /dev/null +++ b/ui/imports/api/environments/configuration-groups/cli-configuration.js @@ -0,0 +1,69 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others / +// / +// All rights reserved. This program and the accompanying materials / +// are made available under the terms of the Apache License, Version 2.0 / +// which accompanies this distribution, and is available at / +// http://www.apache.org/licenses/LICENSE-2.0 / +///////////////////////////////////////////////////////////////////////////////////////// +import * as R from 'ramda'; +import { SimpleSchema } from 'meteor/aldeed:simple-schema'; +import { pathRegEx } from '/imports/lib/general-regex'; + +export const CLISchema = new SimpleSchema({ + name: { type: String, autoValue: function () { return 'CLI'; } }, + host: { + type: String, + defaultValue: '10.0.0.1' + }, + key: { + type: String, + regEx: pathRegEx, + optional: true + }, + user: { + type: String, + defaultValue: 'sshuser' + }, + pwd: { + type: String, + optional: true + }, +}); + +CLISchema.addValidator(function () { + let that = this; + + let conf = {}; + if (isConfEmpty(conf)) { + return; + } + + let validationResult = R.find((validationFn) => { + return validationFn(that).isError; + }, [ keyPasswordValidation ]); + + if (R.isNil(validationResult)) { return; } + + throw validationResult(that); +}); + +function keyPasswordValidation(schemaItem) { + let password = schemaItem.field('pwd'); + let key = schemaItem.field('key'); + + if (key.value || password.value) { return { isError: false }; } + + return { + isError: true, + type: 'subGroupError', + data: [], + message: 'Master Host Group: At least one required: key or password' + }; +} + +function isConfEmpty(conf) { + return R.find((key) => { + return !(R.isNil(conf[key])); + }, R.keys(conf)); +} diff --git a/ui/imports/api/environments/configuration-groups/monitoring-configuration.js b/ui/imports/api/environments/configuration-groups/monitoring-configuration.js new file mode 100644 index 0000000..2b27f8a --- /dev/null +++ b/ui/imports/api/environments/configuration-groups/monitoring-configuration.js @@ -0,0 +1,119 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others / +// / +// All rights reserved. This program and the accompanying materials / +// are made available under the terms of the Apache License, Version 2.0 / +// which accompanies this distribution, and is available at / +// http://www.apache.org/licenses/LICENSE-2.0 / +///////////////////////////////////////////////////////////////////////////////////////// +import { SimpleSchema } from 'meteor/aldeed:simple-schema'; +import * as R from 'ramda'; +import { Constants } from '/imports/api/constants/constants'; +import { portRegEx } from '/imports/lib/general-regex'; +import { hostnameRegex } from '/imports/lib/general-regex'; +import { ipAddressRegex } from '/imports/lib/general-regex'; +import { pathRegEx } from '/imports/lib/general-regex'; + +export const MonitoringSchema = new SimpleSchema({ + name: { type: String, autoValue: function () { return 'Monitoring'; } }, + //app_path: { type: String, autoValue: function () { return '/etc/calipso/monitoring'; } }, + + config_folder: { + type: String, + defaultValue: '/local_dir/sensu_config', + regEx: pathRegEx, + }, + + env_type: { + type: String, + defaultValue: 'production', + custom: function () { + let that = this; + let EnvTypesRec = Constants.findOne({ name: 'env_types' }); + + if (R.isNil(EnvTypesRec.data)) { return 'notAllowed'; } + let EnvTypes = EnvTypesRec.data; + + if (R.isNil(R.find(R.propEq('value', that.value), EnvTypes))) { + return 'notAllowed'; + } + }, + }, + + rabbitmq_port: { + type: String, + defaultValue: '5671', + regEx: portRegEx, + }, + + rabbitmq_user: { + type: String, + defaultValue: 'sensu' + }, + + rabbitmq_pass: { type: String }, + + server_ip: { + type: String, + regEx: new RegExp(hostnameRegex.source + '|' + ipAddressRegex.soure), + defaultValue: '10.0.0.1', + }, + + server_name: { + type: String, + defaultValue: 'sensu_server', + }, + + type: { + type: String, + defaultValue: 'Sensu', + custom: function () { + let that = this; + let values = Constants.findOne({ name: 'environment_monitoring_types' }).data; + + if (R.isNil(values)) { return 'notAllowed'; } + + if (R.isNil(R.find(R.propEq('value', that.value), values))) { + return 'notAllowed'; + } + }, + }, + + provision: { + type: String, + defaultValue: 'None', + custom: function () { + let that = this; + let values = Constants.findOne({ name: 'environment_provision_types' }).data; + + if (R.isNil(values)) { return 'notAllowed'; } + + if (R.isNil(R.find(R.propEq('value', that.value), values))) { + return 'notAllowed'; + } + }, + }, + + ssh_port: { + type: String, + defaultValue: '20022', + optional: true + }, + + ssh_user: { + type: String, + defaultValue: 'root', + optional: true + }, + + ssh_password: { + type: String, + defaultValue: 'calipso', + optional: true + }, + + api_port: { + type: Number, + defaultValue: 4567, + }, +}); diff --git a/ui/imports/api/environments/configuration-groups/mysql-configuration.js b/ui/imports/api/environments/configuration-groups/mysql-configuration.js new file mode 100644 index 0000000..1921432 --- /dev/null +++ b/ui/imports/api/environments/configuration-groups/mysql-configuration.js @@ -0,0 +1,33 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others / +// / +// All rights reserved. This program and the accompanying materials / +// are made available under the terms of the Apache License, Version 2.0 / +// which accompanies this distribution, and is available at / +// http://www.apache.org/licenses/LICENSE-2.0 / +///////////////////////////////////////////////////////////////////////////////////////// +import { SimpleSchema } from 'meteor/aldeed:simple-schema'; +import { portRegEx } from '/imports/lib/general-regex'; + +export const MysqlSchema = new SimpleSchema({ + name: { + type: String, + autoValue: function () { return 'mysql'; } + }, + host: { + type: String, + regEx: SimpleSchema.RegEx.IP, + defaultValue: '10.0.0.1' + }, + password: { type: String }, + port: { + type: String, + regEx: portRegEx, + defaultValue: '3307' + }, + user: { + type: String, + min: 3, + defaultValue: 'mysqluser' + }, +}); diff --git a/ui/imports/api/environments/configuration-groups/nfv-provider-configuration.js b/ui/imports/api/environments/configuration-groups/nfv-provider-configuration.js new file mode 100644 index 0000000..3638e3b --- /dev/null +++ b/ui/imports/api/environments/configuration-groups/nfv-provider-configuration.js @@ -0,0 +1,25 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others / +// / +// All rights reserved. This program and the accompanying materials / +// are made available under the terms of the Apache License, Version 2.0 / +// which accompanies this distribution, and is available at / +// http://www.apache.org/licenses/LICENSE-2.0 / +///////////////////////////////////////////////////////////////////////////////////////// +import { SimpleSchema } from 'meteor/aldeed:simple-schema'; +import { portRegEx } from '/imports/lib/general-regex'; + +export const NfvProviderSchema = new SimpleSchema({ + name: { type: String, autoValue: function () { return 'NFV_provider'; } }, + host: { + type: String, + regEx: SimpleSchema.RegEx.IP, + }, + nfv_token: { type: String }, + port: { + type: String, + regEx: portRegEx + }, + user: { type: String }, + pwd: { type: String }, +}); diff --git a/ui/imports/api/environments/configuration-groups/open-stack-configuration.js b/ui/imports/api/environments/configuration-groups/open-stack-configuration.js new file mode 100644 index 0000000..a0d710f --- /dev/null +++ b/ui/imports/api/environments/configuration-groups/open-stack-configuration.js @@ -0,0 +1,30 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others / +// / +// All rights reserved. This program and the accompanying materials / +// are made available under the terms of the Apache License, Version 2.0 / +// which accompanies this distribution, and is available at / +// http://www.apache.org/licenses/LICENSE-2.0 / +///////////////////////////////////////////////////////////////////////////////////////// +import { SimpleSchema } from 'meteor/aldeed:simple-schema'; +import { portRegEx } from '/imports/lib/general-regex'; + +export const OpenStackSchema = new SimpleSchema({ + name: { type: String, autoValue: function () { return 'OpenStack'; } }, + host: { + type: String, + regEx: SimpleSchema.RegEx.IP, + defaultValue: '10.0.0.1', + }, + admin_token: { type: String }, + port: { + type: String, + regEx: portRegEx, + defaultValue: '5000', + }, + user: { + type: String, + defaultValue: 'adminuser' + }, + pwd: { type: String }, +}); diff --git a/ui/imports/api/environments/environments.js b/ui/imports/api/environments/environments.js new file mode 100644 index 0000000..d616960 --- /dev/null +++ b/ui/imports/api/environments/environments.js @@ -0,0 +1,457 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others / +// / +// All rights reserved. This program and the accompanying materials / +// are made available under the terms of the Apache License, Version 2.0 / +// which accompanies this distribution, and is available at / +// http://www.apache.org/licenses/LICENSE-2.0 / +///////////////////////////////////////////////////////////////////////////////////////// +import { Mongo } from 'meteor/mongo'; +import { SimpleSchema } from 'meteor/aldeed:simple-schema'; +import * as R from 'ramda'; +import { Constants } from '/imports/api/constants/constants'; +import { MysqlSchema } from './configuration-groups/mysql-configuration'; +import { OpenStackSchema } from './configuration-groups/open-stack-configuration'; +import { MonitoringSchema } from './configuration-groups/monitoring-configuration'; +import { CLISchema } from './configuration-groups/cli-configuration'; +import { AMQPSchema } from './configuration-groups/amqp-configuration'; +//import { NfvProviderSchema } from './configuration-groups/nfv-provider-configuration'; +import { AciSchema } from './configuration-groups/aci-configuration'; +import { + isMonitoringSupported, + isListeningSupported, +} from '/imports/api/supported_environments/supported_environments'; + +export const Environments = new Mongo.Collection( + 'environments_config', { idGeneration: 'MONGO' }); + +export const requiredConfGroups = [ + 'mysql', + 'OpenStack', + 'CLI', +]; + +export const optionalConfGroups = [ + // 'NFV_provider', + 'AMQP', + 'Monitoring', + 'ACI', +]; + +let simpleSchema = new SimpleSchema({ + _id: { type: { _str: { type: String, regEx: SimpleSchema.RegEx.Id } } }, + auth: { + type: Object, + blackbox: true, + defaultValue: { + 'view-env': [ + ], + 'edit-env': [ + ] + } + }, + configuration: { + type: [Object], + blackbox: true, + autoValue: function () { + console.log('start - autovalue - environment - configuration'); + //console.log(this); + let that = this; + + if (that.isSet) { + let confGroups = that.value; + + let { + isMonitoringSupportedRes, + isListeningSupportedRes, + enable_monitoring, + listen + } = extractCalcEnvSupportedRelatedValues(that); + let dbNode = getDbNode(that); + let aci = extractValue('aci', that, dbNode); + + if (enable_monitoring && isMonitoringSupportedRes) { + if (! R.find(R.propEq('name', 'Monitoring'), confGroups)) { + confGroups = R.append(createNewConfGroup('Monitoring'), confGroups); + } + } else { + console.log('env - configurations - autovalue - monitoring not supported'); + confGroups = R.reject(R.propEq('name', 'Monitoring'), confGroups); + } + + if (listen && isListeningSupportedRes) { + if (! R.find(R.propEq('name', 'AMQP'), confGroups)) { + confGroups = R.append(createNewConfGroup('AMQP'), confGroups); + } + } else { + console.log('env - configurations - autovalue - listening not supported'); + confGroups = R.reject(R.propEq('name', 'AMQP'), confGroups); + } + + if (aci) { + if (! R.find(R.propEq('name', 'ACI'), confGroups)) { + confGroups = R.append(createNewConfGroup('ACI'), confGroups); + } + } else { + console.log('env - configurations - autovalue - aci not requested'); + confGroups = R.reject(R.propEq('name', 'ACI'), confGroups); + } + + confGroups = cleanOptionalGroups(confGroups, optionalConfGroups); + console.log('env - configurations - autovalue - after clean optional groups'); + + let newValue = R.map(function(confGroup) { + let schema = getSchemaForGroupName(confGroup.name); + return schema.clean(confGroup); + }, confGroups); + + console.log('end - autovalue - environment - configurations'); + console.log(newValue); + return newValue; + + } else { + console.log('env - configurations - autovalue - is not set'); + let newValue = R.map((confName) => { + let schema = getSchemaForGroupName(confName); + return schema.clean({}); + }, requiredConfGroups); + console.log('end - autovalue - environment - configurations'); + console.log(newValue); + return newValue; + } + }, + custom: function () { + console.log('start - custom - environment - configurations'); + //console.log(this); + let that = this; + let configurationGroups = that.value; + + let subErrors = []; + + let { + isMonitoringSupportedRes, + isListeningSupportedRes, + enable_monitoring, + listen + } = extractCalcEnvSupportedRelatedValues(that); + + let requiredConfGroupsTemp = R.clone(requiredConfGroups); + if (enable_monitoring && isMonitoringSupportedRes) { + requiredConfGroupsTemp = R.append('Monitoring', requiredConfGroupsTemp); + } + if (listen && isListeningSupportedRes) { + requiredConfGroupsTemp = R.append('AMQP', requiredConfGroupsTemp); + } + + console.log('env - configurations - custom - after mon & listen check'); + + let invalidResult = R.find(function(groupName) { + subErrors = checkGroup(groupName, configurationGroups, true); + if (subErrors.length > 0) { return true; } + return false; + }, requiredConfGroupsTemp); + + console.log(`env - configurations - custom - after require groups check`); + + if (R.isNil(invalidResult)) { + invalidResult = R.find(function(groupName) { + subErrors = checkGroup(groupName, configurationGroups, false); + if (subErrors.length > 0) { return true; } + return false; + }, optionalConfGroups); + } + + console.log(`env - configurations - custom - after optional groups check`); + + if (! R.isNil(invalidResult)) { + console.log(`env - configrations - custom - invalid result end: ${R.toString(subErrors)}`); + throw { + isError: true, + type: 'subGroupError', + data: subErrors, + message: constructSubGroupErrorMessage(subErrors) + }; + } + }, + + }, + user: { + type: String, + }, + distribution: { + type: String, + defaultValue: 'Mirantis-8.0', + custom: function () { + let that = this; + let constsDist = Constants.findOne({ name: 'distributions' }); + + if (R.isNil(constsDist.data)) { return 'notAllowed'; } + let distributions = constsDist.data; + + if (R.isNil(R.find(R.propEq('value', that.value), distributions))) { + return 'notAllowed'; + } + }, + }, + last_scanned: { + type: String, defaultValue: '' + }, + name: { + type: String, + defaultValue: 'MyEnvironmentName', + min: 6, + }, + type_drivers: { + type: String, + defaultValue: 'gre', + custom: function () { + let that = this; + let TypeDriversRec = Constants.findOne({ name: 'type_drivers' }); + + if (R.isNil(TypeDriversRec.data)) { return 'notAllowed'; } + let TypeDrivers = TypeDriversRec.data; + + if (R.isNil(R.find(R.propEq('value', that.value), TypeDrivers))) { + return 'notAllowed'; + } + }, + }, + + mechanism_drivers: { + type: [String], + defaultValue: ['ovs'], + minCount: 1, + custom: function () { + let that = this; + let consts = Constants.findOne({ name: 'mechanism_drivers' }); + + if (R.isNil(consts.data)) { return 'notAllowed'; } + let mechanismDrivers = consts.data; + + let result = R.find((driver) => { + if (R.find(R.propEq('value', driver), mechanismDrivers)) { + return false; + } + return true; + }, that.value); + + if (result) { return 'notAllowed'; } + + }, + }, + + operational: { + type: String, + allowedValues: ['stopped', 'running', 'error'], + defaultValue: 'stopped' + }, + + scanned: { type: Boolean, defaultValue: false }, + + type: { + type: String, + autoValue: function () { + return 'environment'; + }, + }, + + app_path: { + type: String, + autoValue: function () { + return '/home/scan/calipso_prod/app'; + } + }, + + listen: { + type: Boolean, + autoValue: function () { + console.log('env - listen - autoValue - start'); + let that = this; + let newValue = that.value; + console.log(`- current value: ${R.toString(newValue)}`); + + let { isListeningSupportedRes } = extractCalcEnvSupportedRelatedValues(that); + + if (!isListeningSupportedRes) { + console.log('* listening not supported'); + console.log(`* ${R.toString(isListeningSupportedRes)}`); + newValue = false; + } + + return newValue; + }, + }, + + enable_monitoring: { + type: Boolean, + autoValue: function () { + console.log('env - enable_monitoring - autoValue - start'); + let that = this; + let newValue = that.value; + console.log(`- current value: ${R.toString(newValue)}`); + + let { isMonitoringSupportedRes } = extractCalcEnvSupportedRelatedValues(that); + + if (!isMonitoringSupportedRes) { + console.log('* monitoring not supported'); + console.log(`* ${R.toString(isMonitoringSupportedRes)}`); + newValue = false; + } + + return newValue; + }, + }, + aci: { + type: Boolean, + defaultValue: false, + }, +}); + +/* +simpleSchema.addValidator(function () { + //let that = this; +}); +*/ + +// Bug in simple schema. cant add custom message to instance specific +// schema. +// https://github.com/aldeed/meteor-simple-schema/issues/559 +// Version 2 fixes it but it is rc. +//Environments.schema.messages({ +SimpleSchema.messages({ + confGroupInvalid: 'Configuration group is invalid.' +}); + +Environments.schema = simpleSchema; +Environments.attachSchema(Environments.schema); + +function getSchemaForGroupName(groupName) { + switch (groupName) { + case 'mysql': + return MysqlSchema; + case 'OpenStack': + return OpenStackSchema; + case 'CLI': + return CLISchema; + case 'AMQP': + return AMQPSchema; +// case 'NFV_provider': +// return NfvProviderSchema; + case 'ACI': + return AciSchema; + case 'Monitoring': + return MonitoringSchema; + default: + throw 'group name is not recognized. group: ' + groupName; + } +} + +function constructSubGroupErrorMessage(errors) { + let message = 'Validation errors on sub groups:'; + message = message + R.reduce((acc, item) => { + return acc + '\n- ' + item.group + ': ' + item.message; + }, '', errors); + + return message; +} + +function checkGroup(groupName, configurationGroups, groupRequired) { + let subErrors = []; + let confGroup = R.find(R.propEq('name', groupName), configurationGroups); + + if (R.isNil(confGroup)) { + if (groupRequired) { + subErrors = R.append({ + field: 'configuration', + group: groupName, + message: 'group ' + groupName + ' is required' + }, subErrors); + } + return subErrors; + } + + let validationContext = getSchemaForGroupName(groupName).newContext(); + + if (! validationContext.validate(confGroup)) { + subErrors = R.reduce(function (acc, invalidField) { + return R.append({ + field: invalidField, + group: groupName, + message: validationContext.keyErrorMessage(invalidField.name), + }, acc); + }, [], validationContext.invalidKeys()); + + return subErrors; + } + + return subErrors; +} + +export function createNewConfGroup(groupName) { + let schema = getSchemaForGroupName(groupName); + return schema.clean({}); +} + +function cleanOptionalGroups(confGroups, optionalConfGroups) { + return R.filter((conf) => { + if (R.contains(conf.name, optionalConfGroups)) { + return !isConfEmpty(conf); + } + + return true; + }, confGroups); +} + +function isConfEmpty(conf) { + return ! R.any((key) => { + if (key === 'name') { return false; } // We ignore the key 'name'. It is a 'type' key. + let val = conf[key]; + return ! ( R.isNil(val) || R.isEmpty(val)); + })(R.keys(conf)); +} + +function extractValue(name, schemaValidator, dbNode) { + console.log('env - extract value'); + console.log(`-name: ${R.toString(name)}`); + //console.log(`-schemaValidator: ${R.toString(schemaValidator)}`); + console.log(`-dbNode: ${R.toString(dbNode)}`); + + let field = schemaValidator.field(name); + let value = field.value; + + console.log(`extract value - schema value: ${R.toString(value)}`); + + if (R.isNil(field.value) && !field.isSet && dbNode) { + console.log(`extract value - db value: ${R.toString(dbNode[name])}`); + value = dbNode[name]; + } + + console.log(`extract value - result: ${R.toString(value)}`); + return value; +} + +function getDbNode(schemaHelper) { + let _id = R.defaultTo(schemaHelper.docId, R.path(['value'], schemaHelper.field('_id'))); + let dbNode = R.defaultTo(null, Environments.findOne({ _id: _id })); + return dbNode; +} + +function extractCalcEnvSupportedRelatedValues(schemaHelper) { + let dbNode = getDbNode(schemaHelper); + + let dist = extractValue('distribution', schemaHelper, dbNode); + let typeDrivers = extractValue('type_drivers', schemaHelper, dbNode); + let mechDrivers = extractValue('mechanism_drivers', schemaHelper, dbNode); + let enable_monitoring = extractValue('enable_monitoring', schemaHelper, dbNode); + let listen = extractValue('listen', schemaHelper, dbNode); + + let isMonitoringSupportedRes = isMonitoringSupported(dist, typeDrivers, mechDrivers); + let isListeningSupportedRes = isListeningSupported(dist, typeDrivers, mechDrivers); + + return { + enable_monitoring, + listen, + isMonitoringSupportedRes, + isListeningSupportedRes, + }; +} diff --git a/ui/imports/api/environments/methods.js b/ui/imports/api/environments/methods.js new file mode 100644 index 0000000..22a1e8b --- /dev/null +++ b/ui/imports/api/environments/methods.js @@ -0,0 +1,154 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others / +// / +// All rights reserved. This program and the accompanying materials / +// are made available under the terms of the Apache License, Version 2.0 / +// which accompanies this distribution, and is available at / +// http://www.apache.org/licenses/LICENSE-2.0 / +///////////////////////////////////////////////////////////////////////////////////////// +//import { Meteor } from 'meteor/meteor'; +import * as R from 'ramda'; +import { ValidatedMethod } from 'meteor/mdg:validated-method'; + +//import { SimpleSchema } from 'meteor/aldeed:simple-schema'; + +import { Environments } from './environments'; +import { Inventory } from '/imports/api/inventories/inventories'; +import { Links } from '/imports/api/links/links'; +import { Cliques } from '/imports/api/cliques/cliques'; +import { CliqueTypes } from '/imports/api/clique-types/clique-types'; +import { Messages } from '/imports/api/messages/messages'; +import { Scans } from '/imports/api/scans/scans'; +import { Roles } from 'meteor/alanning:roles'; + +export const insert = new ValidatedMethod({ + name: 'environments.insert', + validate: Environments.simpleSchema() + .pick([ + 'configuration', + 'configuration.$', + 'distribution', + 'name', + 'type_drivers', + 'mechanism_drivers', + 'mechanism_drivers.$', + 'listen', + 'enable_monitoring', + 'aci', + ]).validator({ clean: true, filter: false }), + //validate: null, + run({ + configuration, + distribution, + name, + type_drivers, + mechanism_drivers, + listen, + enable_monitoring, + aci, + }) { + // todo: create clean object instance. + let environment = Environments.schema.clean({ + user: Meteor.userId() + }); + + let auth = { + 'view-env': [ + Meteor.userId() + ], + 'edit-env': [ + Meteor.userId() + ] + }; + + environment = R.merge(environment, { + configuration, + distribution, + name, + type_drivers, + mechanism_drivers, + listen, + enable_monitoring, + auth, + aci, + }); + + Environments.insert(environment); + }, +}); + +export const update = new ValidatedMethod({ + name: 'environments.update', + validate: Environments.simpleSchema().pick([ + '_id', + 'configuration', + 'configuration.$', + //'distribution', + //'name', + 'type_drivers', + 'mechanism_drivers', + 'mechanism_drivers.$', + 'listen', + 'enable_monitoring', + 'aci', + ]).validator({ clean: true, filter: false }), + run({ + _id, + configuration, + //distribution, + //name, + type_drivers, + mechanism_drivers, + listen, + enable_monitoring, + aci, + }) { + let env = Environments.findOne({ _id: _id }); + + if (! Roles.userIsInRole(Meteor.userId(), 'edit-env', 'default-group')) { + if (! R.contains(Meteor.userId(), R.path(['auth', 'edit-env'], env) )) { + throw new Meteor.Error('not-auth', 'unauthorized for updating env'); + } + } + + Environments.update(_id, { + $set: { + configuration: configuration, + //distribution: distribution, + //name: name, + type_drivers, + mechanism_drivers, + listen, + enable_monitoring, + aci, + }, + }); + } +}); + +export const remove = new ValidatedMethod({ + name: 'environments.remove', + validate: Environments.simpleSchema().pick([ + '_id', + ]).validator({ clean: true, filter: false }), + run({ + _id, + }) { + const env = Environments.findOne({ _id: _id }); + console.log('environment for remove: ', env); + + if (! Roles.userIsInRole(Meteor.userId(), 'edit-env', 'default-group')) { + if (! R.contains(Meteor.userId(), R.path(['auth', 'edit-env'], env) )) { + throw new Meteor.Error('not-auth', 'unauthorized for updating env'); + } + } + + Inventory.remove({ environment: env.name }); + Links.remove({ environment: env.name }); + Cliques.remove({ environment: env.name }); + CliqueTypes.remove({ environment: env.name }); + Messages.remove({ environment: env.name }); + Scans.remove({ environment: env.name }); + Environments.remove({ _id: _id }); + } +}); diff --git a/ui/imports/api/environments/server/publications.js b/ui/imports/api/environments/server/publications.js new file mode 100644 index 0000000..667ee8e --- /dev/null +++ b/ui/imports/api/environments/server/publications.js @@ -0,0 +1,102 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others / +// / +// All rights reserved. This program and the accompanying materials / +// are made available under the terms of the Apache License, Version 2.0 / +// which accompanies this distribution, and is available at / +// http://www.apache.org/licenses/LICENSE-2.0 / +///////////////////////////////////////////////////////////////////////////////////////// +import { Meteor } from 'meteor/meteor'; +import * as R from 'ramda'; +import { Roles } from 'meteor/alanning:roles'; + +import { Environments } from '../environments.js'; + +Meteor.publish('environments_config', function () { + console.log('server subscribtion to: environments_config'); + let userId = this.userId; + + let query = { + type: 'environment', + }; + + if (! Roles.userIsInRole(userId, 'view-env', null)) { + query = R.merge(query, { + 'auth.view-env': { + $in: [ userId ] + } + }); + } + + console.log('-query: ', R.toString(query)); + return Environments.find(query); +}); + +const subsEnvViewEnvUserId = 'environments.view-env&userId'; +Meteor.publish(subsEnvViewEnvUserId, function (userId) { + console.log(`subscription - ${subsEnvViewEnvUserId} `); + console.log(`-userId: ${R.toString(userId)}`); + + let query = {}; + + let currentUser = this.userId; + if (! Roles.userIsInRole(currentUser, 'manage-users', Roles.GLOBAL_GROUP)) { + console.log(`* error: unauth`); + console.log(`- currentUser: ${R.toString(currentUser)}`); + this.error('unauthorized for this subscription'); + return; + } + + query = R.merge(query, { + 'auth.view-env': { + $in: [ userId ] + } + }); + + console.log(`* query: ${R.toString(query)}`); + return Environments.find(query); +}); + +const subsEnvEditEnvUserId = 'environments.edit-env&userId'; +Meteor.publish(subsEnvEditEnvUserId, function (userId) { + console.log(`subscription - ${subsEnvEditEnvUserId} `); + console.log(`-userId: ${R.toString(userId)}`); + let query = {}; + + let currentUser = this.userId; + if (! Roles.userIsInRole(currentUser, 'manage-users', Roles.GLOBAL_GROUP)) { + console.log(`* error: unauth`); + console.log(`- currentUser: ${R.toString(currentUser)}`); + this.error('unauthorized for this subscription'); + return; + } + + query = R.merge(query, { + 'auth.edit-env': { + $in: [ userId ] + } + }); + + console.log(`* query: ${R.toString(query)}`); + return Environments.find(query); +}); + +Meteor.publish('environments?name', function (name) { + console.log('server subscribtion to: environments?name=' + name.toString()); + let query = { + name: name, + user: this.userId + }; + return Environments.find(query); +}); + +Meteor.publish('environments?_id', function (_id) { + console.log('server subscribtion to: environments?_id'); + console.log('-_id: ', R.toString(_id)); + + let query = { + _id: _id, + user: this.userId + }; + return Environments.find(query); +}); diff --git a/ui/imports/api/inventories/inventories.js b/ui/imports/api/inventories/inventories.js new file mode 100644 index 0000000..114f5ef --- /dev/null +++ b/ui/imports/api/inventories/inventories.js @@ -0,0 +1,11 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others / +// / +// All rights reserved. This program and the accompanying materials / +// are made available under the terms of the Apache License, Version 2.0 / +// which accompanies this distribution, and is available at / +// http://www.apache.org/licenses/LICENSE-2.0 / +///////////////////////////////////////////////////////////////////////////////////////// +import { Mongo } from 'meteor/mongo'; + +export const Inventory = new Mongo.Collection('inventory', { idGeneration: 'MONGO' }); diff --git a/ui/imports/api/inventories/server/methods.js b/ui/imports/api/inventories/server/methods.js new file mode 100644 index 0000000..ec2f27d --- /dev/null +++ b/ui/imports/api/inventories/server/methods.js @@ -0,0 +1,151 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others / +// / +// All rights reserved. This program and the accompanying materials / +// are made available under the terms of the Apache License, Version 2.0 / +// which accompanies this distribution, and is available at / +// http://www.apache.org/licenses/LICENSE-2.0 / +///////////////////////////////////////////////////////////////////////////////////////// +import { check } from 'meteor/check'; +import * as R from 'ramda'; +import { Inventory } from '../inventories'; +import { Environments } from '/imports/api/environments/environments'; +import { regexEscape } from '/imports/lib/regex-utils'; +import { NodeHoverAttr } from '/imports/api/attributes_for_hover_on_data/attributes_for_hover_on_data'; +const AUTO_COMPLETE_RESULTS_LIMIT = 15; + +Meteor.methods({ + 'inventorySearch': function(searchTerm, envId, opCounter) { + console.log('inventorySearch'); + console.log('searchTerm', R.toString(searchTerm)); + console.log('envId', R.toString(envId)); + console.log('opCounter', R.toString(opCounter)); + + this.unblock(); + + if (R.anyPass([R.isNil, R.isEmpty])(searchTerm)) { + return { + searchResults: [], + opCounter: opCounter + }; + } + + let searchExp = new RegExp(regexEscape(searchTerm), 'i'); + + let query = { + name: searchExp + }; + + if (! R.isNil(envId)) { + let env = Environments.findOne({ _id: envId }); + query = R.merge(query, { + environment: env.name + }); + } + + let searchResults = Inventory.find(query, { + limit: AUTO_COMPLETE_RESULTS_LIMIT + }).fetch(); + + searchResults = R.map((inventory) => { + console.log('search result'); + console.log(R.toString(inventory)); + + let itemEnv = Environments.findOne({ name: inventory.environment }); + + return R.merge(inventory, { + _envId: itemEnv._id + }); + }, searchResults); + + return { + opCounter: opCounter, + searchResults: searchResults, + }; + }, + + 'expandNodePath': function(nodeId) { + console.log('method server: expandNodePath', R.toString(nodeId)); + + //check(nodeId, MongoI); + this.unblock(); + + let node = Inventory.findOne({ _id: nodeId }); + if (R.isNil(node)) { + console.log('method server: expandNodePath - no node'); + return null; + } + + let idList = R.pipe(R.split('/'), R.drop(2))(node.id_path); + let result = R.map((partId) => { + return Inventory.findOne({ environment: node.environment, id: partId }); + }, idList); + + console.log('method server: expandNodePath - results', result); + return result; + }, + + 'inventoryFindNode?type&env&name': function(type, envName, nodeName) { + console.log('method server: inventoryFindNode', + R.toString(type), R.toString(envName), R.toString(nodeName)); + + check(envName, String); + check(nodeName, String); + this.unblock(); + + let query = { type: type, environment: envName, name: nodeName }; + let node = Inventory.findOne(query); + + return { + node: node + }; + }, + + 'inventoryFindNode?env&id': function (envName, nodeId) { + console.log('method server: inventoryFindNode?env&id', + R.toString(envName), R.toString(nodeId)); + + check(envName, String); + check(nodeId, String); + this.unblock(); + + let query = { environment: envName, id: nodeId }; + let node = Inventory.findOne(query); + + return { + node: node + }; + }, + + 'inventoryFindNode?DataAndAttrs': function (nodeId) { + console.log(`method server: inventoryFindNode?DataAndAttrs. ${R.toString(nodeId)}`); + //check(nodeId, ObjectId); + this.unblock(); + + let query = { _id: nodeId }; + let node = Inventory.findOne(query); + let attrsDefs = NodeHoverAttr.findOne({ 'type': node.type }); + let attributes = calcAttrsForNode(node, attrsDefs); + + return { + node: node, + nodeName: node.name, + attributes: attributes + }; + }, +}); + +function calcAttrsForNode(node, attrsDefsRec) { + if (R.isNil(attrsDefsRec)) { + return []; + } + + let attrsDefs = attrsDefsRec.attributes; + + return R.reduce((acc, attrDef) => { + return R.ifElse(R.isNil, + R.always(acc), + (attrVal) => R.append(R.assoc(attrDef, attrVal, {}), acc) + )(R.prop(attrDef, node)); + }, [], attrsDefs); +} diff --git a/ui/imports/api/inventories/server/publications.js b/ui/imports/api/inventories/server/publications.js new file mode 100644 index 0000000..f35ff30 --- /dev/null +++ b/ui/imports/api/inventories/server/publications.js @@ -0,0 +1,250 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others / +// / +// All rights reserved. This program and the accompanying materials / +// are made available under the terms of the Apache License, Version 2.0 / +// which accompanies this distribution, and is available at / +// http://www.apache.org/licenses/LICENSE-2.0 / +///////////////////////////////////////////////////////////////////////////////////////// +import { Meteor } from 'meteor/meteor'; +import { Counts } from 'meteor/tmeasday:publish-counts'; +import { check } from 'meteor/check'; +import * as R from 'ramda'; + +import { Inventory } from '../inventories.js'; +import { regexEscape } from '/imports/lib/regex-utils'; + +Meteor.publish('inventory', function () { + console.log('server subscribtion to: inventory'); + //return Inventory.find({$where: 'this.id_path.match('^/WebEX-Mirantis@Cisco/')'}); + //return Inventory.find({ 'show_in_tree': true }); + return Inventory.find({}); +}); + +Meteor.publish('inventory?_id', function (_id) { + console.log('server subscribtion to: inventory?_id'); + console.log('_id:', R.toString(_id)); + + return Inventory.find({ _id: _id }); +}); + +Meteor.publish('inventory?id', function (id) { + console.log('server subscribtion to: inventory?id'); + return Inventory.find({id: id}); +}); + +Meteor.publish('inventory?env&id', function (env, id) { + console.log('server subscribtion to: inventory?env&id'); + console.log(`-env: ${R.toString(env)}`); + console.log(`-id: ${R.toString(id)}`); + + return Inventory.find({environment: env, id: id}); +}); + +Meteor.publish('inventory?id_path', function (id_path) { + console.log('server subscribtion to: inventory?id_path'); + return Inventory.find({id_path: id_path}); +}); + +Meteor.publish('inventory?name&env&type', function (name, env, type) { + console.log('server subscribtion to: inventory?name&env&type'); + console.log('-name:', R.toString(name)); + console.log('-env:', R.toString(env)); + console.log('-type:', R.toString(type)); + + let query = { + name: name, + environment: env, + type: type + }; + + console.log('query', R.toString(query)); + return Inventory.find(query); +}); + +Meteor.publish('inventory?_id-in', function (idsList) { + var query = { + _id: { $in: idsList } + }; + /* + var counterName = 'inventory?env+type!counter?env=' + env + '&type=' + type; + + console.log('server subscribing to counter: ' + counterName); + Counts.publish(this, counterName, Inventory.find(query)); + */ + console.log('server subscribtion to: inventory?_id-in'); + console.log('- id-in: ' + idsList); + + return Inventory.find(query); +}); + +Meteor.publish('inventory?env+type', function (env, type) { + var query = { + environment: env, + type: type + }; + var counterName = 'inventory?env+type!counter?env=' + env + '&type=' + type; + + console.log('server subscribing to counter: ' + counterName); + Counts.publish(this, counterName, Inventory.find(query)); + + console.log('server subscribtion to: inventory-by-env-and-type'); + console.log('-env: ' + env); + console.log('-type: ' + type); + + return Inventory.find(query); +}); + +Meteor.publish('inventory?env&binding:host_id&type', function (env, host_id, type) { + var query = { + environment: env, + 'binding:host_id': host_id, + type: type + }; + console.log('server subscribtion to: inventory?env&binding:host_id&type'); + console.log('-env: ' + env); + console.log('-binding:host_id: ' + host_id); + console.log('-type: ' + type); + + return Inventory.find(query); +}); + +Meteor.publish('inventory?env+name', function (env, name) { + var query = { + name: name, + environment: env + }; + + console.log('server subscribtion to: inventory?env+name'); + console.log('- name: ' + name); + console.log('- env: ' + env); + + return Inventory.find(query); +}); + +Meteor.publish('inventory?type+host', function (type, host) { + var query = { + type: type, + host: host + }; +/* + var counterName = 'inventory?env+type!counter?env=' + env + '&type=' + type; + + console.log('server subscribing to counter: ' + counterName); + Counts.publish(this, counterName, Inventory.find(query)); +*/ + + console.log('server subscribtion to: inventory?type+host'); + console.log('- type: ' + type); + console.log('- host: ' + host); + return Inventory.find(query); +}); + +Meteor.publish('inventory?id_path_start&type', function (id_path, type) { + check(id_path, String); + check(type, String); + + let idPathExp = new RegExp(`^${regexEscape(id_path)}`); + + let query = { + id_path: idPathExp, + type: type + }; + + var counterName = 'inventory?id_path_start&type!counter?id_path_start=' + + id_path + '&type=' + type; + + console.log('server subscribing to counter: ' + counterName); + Counts.publish(this, counterName, Inventory.find(query)); + + console.log('server subscribtion to: inventory?id_path_start&type'); + console.log('-id_path_start: ' + id_path); + console.log('-type: ' + type); + return Inventory.find(query); +}); + + +Meteor.publish('inventory.children', function (id, type, name, env) { + console.log('server subscribtion to: inventory.children'); + console.log('node id: ' + R.toString(id)); + console.log('node type: ' + R.toString(type)); + console.log('node name: ' + R.toString(name)); + console.log('node env: ' + R.toString(env)); + + let query = { + $or: + [ + { + environment: env, + parent_id: id + }, + ] + }; + + if (R.equals('host_ref', type)) { + let realParent = Inventory.findOne({ + name: name, + environment: env, + type: 'host' + }); + + query = R.merge(query, { + $or: R.append({ + environment: env, + parent_id: realParent.id + }, query.$or) + }); + } + + console.log('query: ', R.toString(query)); + + return Inventory.find(query); +}); + +Meteor.publish('inventory.first-child', function (id, type, name, env) { + console.log('server subscribing to: inventory.first-child'); + console.log('node id: ' + R.toString(id)); + console.log('node type: ' + R.toString(type)); + console.log('node name: ' + R.toString(name)); + console.log('node env: ' + R.toString(env)); + + var counterName = 'inventory.first-child!counter!id=' + id; + var query = { + $or: [ + { + environment: env, + parent_id: id + } + ] + }; + + if (R.equals('host_ref', type)) { + let realParent = Inventory.findOne({ + name: name, + environment: env, + type: 'host' + }); + + query = R.merge(query, { + $or: R.append({ + environment: env, + parent_id: realParent.id + }, query.$or) + }); + } + + Counts.publish(this, counterName, Inventory.find(query, { limit: 1 })); + console.log('server subscribing to counter: ' + counterName); + +// todo: eyaltask: all criteria + console.log('query: ', R.toString(query)); + return Inventory.find(query, { limit: 1 }); +}); + +Meteor.publish('inventoryByEnv', function (env) { + console.log('server subscribtion to: inventoryByEnv'); + //return Inventory.find({$where: 'this.id_path.match('^/WebEX-Mirantis@Cisco/')'}); + //return Inventory.find({ 'show_in_tree': true }); + return Inventory.find({'environment':env}); +}); + diff --git a/ui/imports/api/link-types/link-types.js b/ui/imports/api/link-types/link-types.js new file mode 100644 index 0000000..94d6ddd --- /dev/null +++ b/ui/imports/api/link-types/link-types.js @@ -0,0 +1,86 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others / +// / +// All rights reserved. This program and the accompanying materials / +// are made available under the terms of the Apache License, Version 2.0 / +// which accompanies this distribution, and is available at / +// http://www.apache.org/licenses/LICENSE-2.0 / +///////////////////////////////////////////////////////////////////////////////////////// +import { Mongo } from 'meteor/mongo'; +import { SimpleSchema } from 'meteor/aldeed:simple-schema'; +import * as R from 'ramda'; +import { Constants } from '/imports/api/constants/constants'; +//import { Environments } from '/imports/api/environments/environments'; + +export const LinkTypes = new Mongo.Collection( + 'link_types', { idGeneration: 'MONGO' }); + +let schema = { + _id: { type: { _str: { type: String, regEx: SimpleSchema.RegEx.Id } } }, + description: { + type: String + }, + type: { + type: String + }, + endPointA: { + type: String, + custom: function () { + let that = this; + let values = Constants.findOne({ name: 'object_types_for_links' }).data; + + if (R.isNil(R.find(R.propEq('value', that.value), values))) { + return 'notAllowed'; + } + } + }, + endPointB: { + type: String, + custom: function () { + let that = this; + let values = Constants.findOne({ name: 'object_types_for_links' }).data; + + if (R.isNil(R.find(R.propEq('value', that.value), values))) { + return 'notAllowed'; + } + } + } +}; + +let simpleSchema = new SimpleSchema(schema); + +simpleSchema.addValidator(function () { + let that = this; + + let existing = LinkTypes.findOne({ + _id: { $ne: that.docId }, + endPointA: that.field('endPointA').value, + endPointB: that.field('endPointB').value + }); + + if (R.allPass([ + R.pipe(R.isNil, R.not), + R.pipe(R.propEq('_id', that.docId), R.not) + ])(existing)) { + + return 'alreadyExists'; + } + + existing = LinkTypes.findOne({ + _id: { $ne: that.docId }, + endPointA: that.field('endPointB').value, + endPointB: that.field('endPointA').value + }); + + if (R.allPass([ + R.pipe(R.isNil, R.not), + R.pipe(R.propEq('_id', that.docId), R.not) + ])(existing)) { + + return 'alreadyExists'; + } +}); + +LinkTypes.schema = simpleSchema; + +LinkTypes.attachSchema(LinkTypes.schema); diff --git a/ui/imports/api/link-types/methods.js b/ui/imports/api/link-types/methods.js new file mode 100644 index 0000000..846c28b --- /dev/null +++ b/ui/imports/api/link-types/methods.js @@ -0,0 +1,114 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others / +// / +// All rights reserved. This program and the accompanying materials / +// are made available under the terms of the Apache License, Version 2.0 / +// which accompanies this distribution, and is available at / +// http://www.apache.org/licenses/LICENSE-2.0 / +///////////////////////////////////////////////////////////////////////////////////////// +import { ValidatedMethod } from 'meteor/mdg:validated-method'; +import * as R from 'ramda'; +import { Roles } from 'meteor/alanning:roles'; + +import { LinkTypes } from './link-types'; + +export const insert = new ValidatedMethod({ + name: 'links_types.insert', + validate: LinkTypes.simpleSchema() + .pick([ + //'environment', + 'description', + 'endPointA', + 'endPointB', + ]).validator({ clean: true, filter: false }), + run({ + //environment, + description, + endPointA, + endPointB + }) { + if (! Roles.userIsInRole(Meteor.userId(), 'manage-link-types', Roles.GLOBAL_GROUP)) { + throw new Meteor.Error('unauthorized for inserting link type'); + } + + let linkType = LinkTypes.schema.clean({ + }); + + let type = calcTypeFromEndPoints(endPointA, endPointB); + + linkType = R.merge(linkType, { + description, + endPointA, + endPointB, + type + }); + + LinkTypes.insert(linkType); + } +}); + +export const remove = new ValidatedMethod({ + name: 'links_types.remove', + validate: LinkTypes.simpleSchema() + .pick([ + '_id', + ]).validator({ clean: true, filter: false }), + run({ + _id + }) { + if (! Roles.userIsInRole(Meteor.userId(), 'manage-link-types', Roles.DEFAULT_GROUP)) { + throw new Meteor.Error('unauthorized for removing link type'); + } + + let linkType = LinkTypes.findOne({ _id: _id }); + console.log('link type for remove: ', linkType); + console.log('current user', Meteor.userId()); + + LinkTypes.remove({ _id: _id }); + } +}); + +export const update = new ValidatedMethod({ + name: 'links_types.update', + validate: LinkTypes.simpleSchema() + .pick([ + '_id', + 'description', + 'endPointA', + 'endPointB', + ]).validator({ clean: true, filter: false }), + run({ + _id, + description, + endPointA, + endPointB + }) { + if (! Roles.userIsInRole(Meteor.userId(), 'manage-link-types', Roles.DEFAULT_GROUP)) { + throw new Meteor.Error('unauthorized for updating link type'); + } + + let linkType = LinkTypes.findOne({ _id: _id }); + console.log('link type for update: ', linkType); + console.log('current user', Meteor.userId()); + + let type = calcTypeFromEndPoints(endPointA, endPointB); + + linkType = R.merge(R.pick([ + 'description', + 'endPointA', + 'endPointB', + 'type' + ], linkType), { + description, + endPointA, + endPointB, + type + }); + + LinkTypes.update({ _id: _id }, { $set: linkType }); + } +}); + +function calcTypeFromEndPoints(endPointA, endPointB) { + return `${endPointA}-${endPointB}`; +} diff --git a/ui/imports/api/link-types/server/publications.js b/ui/imports/api/link-types/server/publications.js new file mode 100644 index 0000000..6c6278f --- /dev/null +++ b/ui/imports/api/link-types/server/publications.js @@ -0,0 +1,46 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others / +// / +// All rights reserved. This program and the accompanying materials / +// are made available under the terms of the Apache License, Version 2.0 / +// which accompanies this distribution, and is available at / +// http://www.apache.org/licenses/LICENSE-2.0 / +///////////////////////////////////////////////////////////////////////////////////////// +import { Meteor } from 'meteor/meteor'; +import * as R from 'ramda'; + +import { LinkTypes } from '../link-types.js'; + +Meteor.publish('link_types', function () { + console.log('server subscribtion: link_types'); + + //let that = this; + + let query = {}; + return LinkTypes.find(query); +}); + +Meteor.publish('link_types?env*', function (env) { + console.log('server subscribtion: link_types?env*'); + console.log(env); + + //let that = this; + + let query = {}; + if (! R.isNil(env)) { query = R.assoc('environment', env, query); } + console.log('-query: ', query); + return LinkTypes.find(query); +}); + +Meteor.publish('link_types?_id', function (_id) { + console.log('server subscribtion: link_types?_id'); + console.log(_id); + + //let that = this; + + let query = { + _id: _id, + }; + console.log('-query: ', query); + return LinkTypes.find(query); +}); diff --git a/ui/imports/api/links/links.js b/ui/imports/api/links/links.js new file mode 100644 index 0000000..2baf58c --- /dev/null +++ b/ui/imports/api/links/links.js @@ -0,0 +1,11 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others / +// / +// All rights reserved. This program and the accompanying materials / +// are made available under the terms of the Apache License, Version 2.0 / +// which accompanies this distribution, and is available at / +// http://www.apache.org/licenses/LICENSE-2.0 / +///////////////////////////////////////////////////////////////////////////////////////// +import { Mongo } from 'meteor/mongo'; + +export const Links = new Mongo.Collection('links', { idGeneration: 'MONGO' }); diff --git a/ui/imports/api/links/methods.js b/ui/imports/api/links/methods.js new file mode 100644 index 0000000..1eda375 --- /dev/null +++ b/ui/imports/api/links/methods.js @@ -0,0 +1,8 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others / +// / +// All rights reserved. This program and the accompanying materials / +// are made available under the terms of the Apache License, Version 2.0 / +// which accompanies this distribution, and is available at / +// http://www.apache.org/licenses/LICENSE-2.0 / +///////////////////////////////////////////////////////////////////////////////////////// diff --git a/ui/imports/api/links/server/publications.js b/ui/imports/api/links/server/publications.js new file mode 100644 index 0000000..78d0c26 --- /dev/null +++ b/ui/imports/api/links/server/publications.js @@ -0,0 +1,32 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others / +// / +// All rights reserved. This program and the accompanying materials / +// are made available under the terms of the Apache License, Version 2.0 / +// which accompanies this distribution, and is available at / +// http://www.apache.org/licenses/LICENSE-2.0 / +///////////////////////////////////////////////////////////////////////////////////////// +import { Meteor } from 'meteor/meteor'; +import { Links } from '../links.js'; + +Meteor.publish('links', function () { + console.log('server subscribtion to: links'); + //return Inventory.find({$where: 'this.id_path.match('^/WebEX-Mirantis@Cisco/')'}); + return Links.find({}); +}); + +Meteor.publish('links?_id-in', function (idsList) { + var query = { + _id: { $in: idsList} + }; +/* + var counterName = 'inventory?env+type!counter?env=' + env + '&type=' + type; + + console.log('server subscribing to counter: ' + counterName); + Counts.publish(this, counterName, Inventory.find(query)); +*/ + + console.log('server subscribtion to: links?_id-in'); + console.log('- _id-in: ' + idsList); + return Links.find(query); +}); diff --git a/ui/imports/api/messages/messages.js b/ui/imports/api/messages/messages.js new file mode 100644 index 0000000..5a028b0 --- /dev/null +++ b/ui/imports/api/messages/messages.js @@ -0,0 +1,125 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others / +// / +// All rights reserved. This program and the accompanying materials / +// are made available under the terms of the Apache License, Version 2.0 / +// which accompanies this distribution, and is available at / +// http://www.apache.org/licenses/LICENSE-2.0 / +///////////////////////////////////////////////////////////////////////////////////////// +import { Mongo } from 'meteor/mongo'; +import { SimpleSchema } from 'meteor/aldeed:simple-schema'; +import * as R from 'ramda'; +import { Environments } from '/imports/api/environments/environments'; +import { Constants } from '/imports/api/constants/constants'; + +export const Messages = new Mongo.Collection('messages', { idGeneration: 'MONGO' }); + +let schema = { + _id: { type: { _str: { type: String, regEx: SimpleSchema.RegEx.Id } } }, + + environment: { + type: String, + custom: function () { + let that = this; + let env = Environments.findOne({ name: that.value }); + + if (R.isNil(env)) { + return 'notAllowed'; + } + } + }, + + id: { + type: String + }, + + viewed: { + type: Boolean, + defaultValue: false + }, + + display_context: { + type: String + }, + + message: { + type: Object, + blackbox: true + }, + + source_system: { + type: String, + custom: function () { + let that = this; + let values = Constants.findOne({ name: 'message_source_systems' }).data; + + if (R.isNil(R.find(R.propEq('value', that.value), values))) { + return 'notAllowed'; + } + } + }, + + level: { + type: String + }, + + timestamp: { + type: Date + }, + + related_object_type: { + type: String + }, + + related_object: { + type: String + }, + + scan_id: { + type: Date + } +}; + +let simpleSchema = new SimpleSchema(schema); + +Messages.schema = simpleSchema; +Messages.attachSchema(Messages.schema); + +export function calcIconForMessageLevel(level) { + switch (level) { + case 'info': + return 'notifications'; + case 'warning': + return 'warning'; + case 'error': + return 'error'; + default: + return 'notifications'; + } +} + +export function lastMessageTimestamp (level, envName) { + let query = { level: level }; + query = R.ifElse(R.isNil, R.always(query), R.assoc('environment', R.__, query))(envName); + + let message = Messages.findOne(query, { + sort: { timestamp: -1 } + }); + + let res = R.path(['timestamp'], message); + if (R.isNil(res)) { return null; } + return (res instanceof String) ? res : res.toString(); +} + +export function calcColorClassForMessagesInfoBox(level) { + switch (level) { + case 'info': + return 'green-text'; + case 'warning': + return 'orange-text'; + case 'error': + return 'red-text'; + default: + return 'green-text'; + } +} diff --git a/ui/imports/api/messages/methods.js b/ui/imports/api/messages/methods.js new file mode 100644 index 0000000..1eda375 --- /dev/null +++ b/ui/imports/api/messages/methods.js @@ -0,0 +1,8 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others / +// / +// All rights reserved. This program and the accompanying materials / +// are made available under the terms of the Apache License, Version 2.0 / +// which accompanies this distribution, and is available at / +// http://www.apache.org/licenses/LICENSE-2.0 / +///////////////////////////////////////////////////////////////////////////////////////// diff --git a/ui/imports/api/messages/server/methods.js b/ui/imports/api/messages/server/methods.js new file mode 100644 index 0000000..119e6b0 --- /dev/null +++ b/ui/imports/api/messages/server/methods.js @@ -0,0 +1,49 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others / +// / +// All rights reserved. This program and the accompanying materials / +// are made available under the terms of the Apache License, Version 2.0 / +// which accompanies this distribution, and is available at / +// http://www.apache.org/licenses/LICENSE-2.0 / +///////////////////////////////////////////////////////////////////////////////////////// +import * as R from 'ramda'; +import { Messages } from '/imports/api/messages/messages'; + +Meteor.methods({ + 'messages/get?level&env&page&amountPerPage&sortField&sortDirection': function ( + level, env, page, amountPerPage, sortField, sortDirection) { + + logMethodCall('messages/get?level&env&page&amountPerPage&sortField&sortDirection', + {level, env, page, amountPerPage}); + + this.unblock(); + + let skip = (page - 1) * amountPerPage; + + let query = {}; + let sortParams = {}; + + query = R.ifElse(R.isNil, R.always(query),R.assoc('environment', R.__, query))(env); + query = R.ifElse(R.isNil, R.always(query),R.assoc('level', R.__, query))(level); + + sortParams = R.ifElse(R.isNil, R.always(sortParams), + R.assoc(R.__, sortDirection, sortParams))(sortField); + + console.log('sort params:', sortParams); + + let qParams = { + limit: amountPerPage, + skip: skip, + sort: sortParams, + }; + + return Messages.find(query, qParams).fetch(); + } +}); + +function logMethodCall(name, args) { + console.log(`method call: ${name}`); + R.forEachObjIndexed((value, key) => { + console.log(`${key}: ${R.toString(value)}`); + }, args); +} diff --git a/ui/imports/api/messages/server/publications.js b/ui/imports/api/messages/server/publications.js new file mode 100644 index 0000000..13c7c50 --- /dev/null +++ b/ui/imports/api/messages/server/publications.js @@ -0,0 +1,98 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others / +// / +// All rights reserved. This program and the accompanying materials / +// are made available under the terms of the Apache License, Version 2.0 / +// which accompanies this distribution, and is available at / +// http://www.apache.org/licenses/LICENSE-2.0 / +///////////////////////////////////////////////////////////////////////////////////////// +import { Meteor } from 'meteor/meteor'; +//import { Counts } from 'meteor/tmeasday:publish-counts'; +import { Counter } from 'meteor/natestrauser:publish-performant-counts'; +import { Messages } from '../messages.js'; +import * as R from 'ramda'; + +Meteor.publish('messages', function () { + console.log('server subscribtion to: messages'); + //return Inventory.find({$where: 'this.id_path.match('^/WebEX-Mirantis@Cisco/')'}); + //return Inventory.find({ 'show_in_tree': true }); + return Messages.find({}); +}); + +Meteor.publish('messages?_id', function (_id) { + console.log('server subscribtion to: messages?_id'); + console.log('_id', _id); + + let query = { _id: _id }; + return Messages.find(query); +}); + +Meteor.publish('messages?level', function (level) { + var query = { + level: level + }; + + /* + var counterName = 'messages?level!counter?' + + 'level=' + level; + + console.log('server subscription to: ' + counterName); + Counts.publish(this, counterName, Messages.find(query)); + */ + + console.log('server subscribtion to: messages?level'); + console.log('- level: ' + level); + return Messages.find(query); +}); + +Meteor.publish('messages?env+level', function (env, level) { + var query = { + environment: env, + level: level + }; + /* + var counterName = 'messages?env+level!counter?env=' + + env + '&level=' + level; + + console.log('server subscription to: messages - counter'); + console.log(' - name: ' + counterName); + Counts.publish(this, counterName, Messages.find(query)); + */ + + console.log('server subscribtion to: messages'); + console.log('- env: ' + env); + console.log('- level: ' + level); + return Messages.find(query); +}); + +Meteor.publish('messages/count', function () { + const counterName = `messages/count`; + console.log(`subscribe - counter: ${counterName}`); + + return new Counter(counterName, Messages.find({ })); +}); + +Meteor.publish('messages/count?env', function (env) { + const counterName = `messages/count?env`; + console.log(`subscribe - counter: ${counterName}`); + + let query = {}; + query = R.ifElse(R.isNil, R.always(query), R.assoc('environment', R.__, query))(env); + return new Counter(counterName, Messages.find(query)); +}); + +Meteor.publish('messages/count?level', function (level) { + const counterName = `messages/count?level=${level}`; + console.log(`subscribe - counter: ${counterName}`); + + return new Counter(counterName, Messages.find({ level: level })); +}); + +Meteor.publish('messages/count?level&env', function (level, env) { + const counterName = `messages/count?level=${level}&env=${env}`; + console.log(`subscribe - counter: ${counterName}`); + + let query = { level: level }; + query = R.ifElse(R.isNil, R.always(query), R.assoc('environment', R.__, query))(env); + + return new Counter(counterName, Messages.find(query)); }); diff --git a/ui/imports/api/migrations/migrations.js b/ui/imports/api/migrations/migrations.js new file mode 100644 index 0000000..79411b1 --- /dev/null +++ b/ui/imports/api/migrations/migrations.js @@ -0,0 +1,20 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others / +// / +// All rights reserved. This program and the accompanying materials / +// are made available under the terms of the Apache License, Version 2.0 / +// which accompanies this distribution, and is available at / +// http://www.apache.org/licenses/LICENSE-2.0 / +///////////////////////////////////////////////////////////////////////////////////////// +import { CliqueTypes } from '/imports/api/clique-types/clique-types'; + +Migrations.add({ + version: 1, + up: () => { + console.log('migrating: add clique type constaints for env+name, env+focal_point_type'); + CliqueTypes._ensureIndex({ environment: 1, name: 1 }); + CliqueTypes._ensureIndex({ environment: 1, focal_point_type: 1 }); + }, + down: () => { + } +}); diff --git a/ui/imports/api/scans/methods.js b/ui/imports/api/scans/methods.js new file mode 100644 index 0000000..82af820 --- /dev/null +++ b/ui/imports/api/scans/methods.js @@ -0,0 +1,55 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others / +// / +// All rights reserved. This program and the accompanying materials / +// are made available under the terms of the Apache License, Version 2.0 / +// which accompanies this distribution, and is available at / +// http://www.apache.org/licenses/LICENSE-2.0 / +///////////////////////////////////////////////////////////////////////////////////////// +import { ValidatedMethod } from 'meteor/mdg:validated-method'; +import * as R from 'ramda'; + +import { Scans } from './scans'; + +export const insert = new ValidatedMethod({ + name: 'scans.insert', + validate: Scans.simpleSchema() + .pick([ + 'environment', + 'object_id', + 'log_level', + 'clear', + 'loglevel', + 'scan_only_inventory', + 'scan_only_links', + 'scan_only_cliques', + ]).validator({ clean: true, filter: false }), + run({ + environment, + object_id, + log_level, + clear, + loglevel, + scan_only_inventory, + scan_only_links, + scan_only_cliques, + }) { + let scan = Scans.schema.clean({ + status: 'pending' + }); + scan = R.merge(scan, { + environment, + object_id, + log_level, + clear, + loglevel, + scan_only_inventory, + scan_only_links, + scan_only_cliques, + submit_timestamp: Date.now() + }); + + Scans.insert(scan); + }, + +}); diff --git a/ui/imports/api/scans/scans.js b/ui/imports/api/scans/scans.js new file mode 100644 index 0000000..857c2ea --- /dev/null +++ b/ui/imports/api/scans/scans.js @@ -0,0 +1,159 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others / +// / +// All rights reserved. This program and the accompanying materials / +// are made available under the terms of the Apache License, Version 2.0 / +// which accompanies this distribution, and is available at / +// http://www.apache.org/licenses/LICENSE-2.0 / +///////////////////////////////////////////////////////////////////////////////////////// +import { Mongo } from 'meteor/mongo'; +import { SimpleSchema } from 'meteor/aldeed:simple-schema'; +import * as R from 'ramda'; + +import { Constants } from '/imports/api/constants/constants'; +import { StatusesInOperation } from '/imports/api/constants/data/scans-statuses'; + +export const Scans = new Mongo.Collection('scans', { idGeneration: 'MONGO' }); + +Scans.schemaRelated = { + environment: { + label: 'Environment', + description: 'Name of environment to scan', + disabled: true, + }, + status: { + label: 'Status', + description: 'Scan lifecycle status', + subtype: 'select', + options: 'scans_statuses', + disabled: true, + }, + object_id: { + label: 'Scan specific object', + description: 'Object ID', + }, + log_level: { + label: 'Log level', + description: 'logging level', + subtype: 'select', + options: 'log_levels', + }, + clear: { + label: 'Clear data', + description: 'clear all data prior to scanning', + }, + scan_only_inventory: { + label: 'Scan only inventory', + description: 'do only scan to inventory', + }, + scan_only_links: { + label: 'Scan only links', + description: 'do only links creation', + }, + scan_only_cliques: { + label: 'Scan only cliques', + description: 'do only cliques creation', + }, +}; + +Scans.scansOnlyFields = ['scan_only_inventory', 'scan_only_links', 'scan_only_cliques']; + +let schema = { + _id: { type: { _str: { type: String, regEx: SimpleSchema.RegEx.Id } } }, + environment: { + type: String + }, + status: { + type: String, + defaultValue: 'draft', + custom: function () { + let that = this; + let statuses = Constants.findOne({ name: 'scans_statuses' }).data; + + if (R.isNil(R.find(R.propEq('value', that.value), statuses))) { + return 'notAllowed'; + } + }, + }, + object_id: { + type: String, + optional: true, + }, + log_level: { + type: String, + defaultValue: 'warning', + custom: function () { + let that = this; + let logLevels = Constants.findOne({ name: 'log_levels' }).data; + + if (R.isNil(R.find(R.propEq('value', that.value), logLevels))) { + return 'notAllowed'; + } + }, + }, + clear: { + type: Boolean, + defaultValue: true, + }, + scan_only_inventory: { + type: Boolean, + defaultValue: false, + }, + scan_only_links: { + type: Boolean, + defaultValue: false, + }, + scan_only_cliques: { + type: Boolean, + defaultValue: false, + }, + submit_timestamp: { + type: Date, + defaultValue: null + }, + +}; + +Scans.schema = new SimpleSchema(schema); +Scans.schema.addValidator(function () { + let that = this; + let env = that.field('environment').value; + + let currentScansCount = Scans.find({ + environment: env, + status: { $in: StatusesInOperation } + }).count(); + + if (currentScansCount > 0) { + throw { + isError: true, + type: 'notUinque', + data: [], + message: 'There is already a scan in progress.' + }; + } + + let scanOnlyFields = R.filter( f => that.field(f).value, Scans.scansOnlyFields); + + if(scanOnlyFields.length > 1) { + throw { + isError: true, + type: 'conflict', + data: scanOnlyFields, + message: 'Only one of the scan only fields can be selected' + }; + } + +}); + +Scans.attachSchema(Scans.schema); + +Scans.schemaRelated = R.mapObjIndexed((relatedItem, key) => { + return R.merge(relatedItem, { + type: schema[key].type + }); + +}, Scans.schemaRelated); + +export const subsScansEnvPageAmountSorted = 'scans?env*&page&amount&sortField&sortDirection'; +export const subsScansEnvPageAmountSortedCounter = `${subsScansEnvPageAmountSorted}!counter`; diff --git a/ui/imports/api/scans/server/methods.js b/ui/imports/api/scans/server/methods.js new file mode 100644 index 0000000..0fe43c2 --- /dev/null +++ b/ui/imports/api/scans/server/methods.js @@ -0,0 +1,44 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others / +// / +// All rights reserved. This program and the accompanying materials / +// are made available under the terms of the Apache License, Version 2.0 / +// which accompanies this distribution, and is available at / +// http://www.apache.org/licenses/LICENSE-2.0 / +///////////////////////////////////////////////////////////////////////////////////////// +import { check } from 'meteor/check'; +import * as R from 'ramda'; +import { Scans } from '../scans'; +import { Environments } from '/imports/api/environments/environments'; + +Meteor.methods({ + 'scansFind?start-timestamp-before': function (startTimestamp) { + console.log('method server: scanFind?start-timestamp-before', + R.toString(startTimestamp)); + + check(startTimestamp, Date); + this.unblock(); + + let query = { start_timestamp: { $lt: startTimestamp }}; + let scan = Scans.findOne(query, { + sort: { start_timestamp: -1 } + }); + + let environment = R.ifElse( + R.isNil, + R.always(null), + (scan) => { + console.log('finding environment:', scan.environment); + let env = Environments.findOne({ name: scan.environment }); + console.log('found env:', env); + return env; + })(scan); + + console.log('found scan', scan); + + return { + environment: environment, + scan: scan, + }; + }, +}); diff --git a/ui/imports/api/scans/server/publications.js b/ui/imports/api/scans/server/publications.js new file mode 100644 index 0000000..774fe3d --- /dev/null +++ b/ui/imports/api/scans/server/publications.js @@ -0,0 +1,82 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others / +// / +// All rights reserved. This program and the accompanying materials / +// are made available under the terms of the Apache License, Version 2.0 / +// which accompanies this distribution, and is available at / +// http://www.apache.org/licenses/LICENSE-2.0 / +///////////////////////////////////////////////////////////////////////////////////////// +import { Meteor } from 'meteor/meteor'; +import * as R from 'ramda'; +import { Counts } from 'meteor/tmeasday:publish-counts'; + +import { Scans, + subsScansEnvPageAmountSorted, + subsScansEnvPageAmountSortedCounter, +} from '../scans.js'; + +Meteor.publish('scans?env', function (env_name) { + console.log('server subscribtion: scans?env'); + console.log(env_name); + + return Scans.find({ + environment: env_name, + }); +}); + +Meteor.publish('scans?env*', function (env) { + console.log('server subscribtion: scans?env*'); + console.log(env); + + //let that = this; + + let query = {}; + if (! R.isNil(env)) { query = R.assoc('environment', env, query); } + console.log('-query: ', query); + return Scans.find(query); +}); + +Meteor.publish(subsScansEnvPageAmountSorted, function ( + env, page, amountPerPage, sortField, sortDirection) { + + console.log(`server subscribtion: ${subsScansEnvPageAmountSorted}`); + console.log(env); + console.log('page: ', page); + console.log('amount: ', amountPerPage); + console.log('sortField: ', sortField, R.isNil(sortField)); + console.log('sortDirection: ', sortDirection); + + let skip = (page - 1) * amountPerPage; + + let query = {}; + if (! R.isNil(env)) { query = R.assoc('environment', env, query); } + console.log('-query: ', query); + let sortParams = {}; + + sortParams = R.ifElse(R.isNil, R.always(sortParams), + R.assoc(R.__, sortDirection, sortParams))(sortField); + + console.log('sort params:', sortParams); + + let qParams = { + limit: amountPerPage, + skip: skip, + sort: sortParams, + }; + + Counts.publish(this, subsScansEnvPageAmountSortedCounter, Scans.find(query), { + noReady: true + }); + + return Scans.find(query, qParams); +}); + +Meteor.publish('scans?id', function (id) { + console.log('server subscribtion: scans?id'); + console.log('-id: ', id); + + //let that = this; + + let query = { _id: id }; + return Scans.find(query); +}); diff --git a/ui/imports/api/scheduled-scans/methods.js b/ui/imports/api/scheduled-scans/methods.js new file mode 100644 index 0000000..22f8110 --- /dev/null +++ b/ui/imports/api/scheduled-scans/methods.js @@ -0,0 +1,131 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others / +// / +// All rights reserved. This program and the accompanying materials / +// are made available under the terms of the Apache License, Version 2.0 / +// which accompanies this distribution, and is available at / +// http://www.apache.org/licenses/LICENSE-2.0 / +///////////////////////////////////////////////////////////////////////////////////////// +import { ValidatedMethod } from 'meteor/mdg:validated-method'; +import * as R from 'ramda'; + +import { ScheduledScans } from './scheduled-scans'; + +export const insert = new ValidatedMethod({ + name: 'scheduled-scans.insert', + validate: ScheduledScans.simpleSchema() + .pick([ + 'environment', + 'object_id', + 'log_level', + 'clear', + 'loglevel', + 'scan_only_inventory', + 'scan_only_links', + 'scan_only_cliques', + 'freq', + ]).validator({ clean: true, filter: false }), + run({ + environment, + object_id, + log_level, + clear, + loglevel, + scan_only_inventory, + scan_only_links, + scan_only_cliques, + freq, + }) { + let scan = ScheduledScans.schema.clean({ }); + + scan = R.merge(scan, { + environment, + object_id, + log_level, + clear, + loglevel, + scan_only_inventory, + scan_only_links, + scan_only_cliques, + freq, + submit_timestamp: Date.now() + }); + + ScheduledScans.insert(scan); + }, + +}); + +export const update = new ValidatedMethod({ + name: 'scheduled_scans.update', + validate: ScheduledScans.simpleSchema() + .pick([ + '_id', + 'environment', + 'object_id', + 'log_level', + 'clear', + 'loglevel', + 'scan_only_inventory', + 'scan_only_links', + 'scan_only_cliques', + 'freq', + ]).validator({ clean: true, filter: false }), + run({ + _id, + environment, + object_id, + log_level, + clear, + loglevel, + scan_only_inventory, + scan_only_links, + scan_only_cliques, + freq, + }) { + let item = ScheduledScans.findOne({ _id: _id }); + console.log('scheduled scan for update: ', item); + + item = R.merge(R.pick([ + 'environment', + 'object_id', + 'log_level', + 'clear', + 'loglevel', + 'scan_only_inventory', + 'scan_only_links', + 'scan_only_cliques', + 'submit_timestamp', + 'freq', + ], item), { + environment, + object_id, + log_level, + clear, + loglevel, + scan_only_inventory, + scan_only_links, + scan_only_cliques, + freq, + submit_timestamp: Date.now() + }); + + ScheduledScans.update({ _id: _id }, { $set: item }); + } +}); + +export const remove = new ValidatedMethod({ + name: 'scheduled_scans.remove', + validate: ScheduledScans.simpleSchema() + .pick([ + '_id', + ]).validator({ clean: true, filter: false }), + run({ + _id + }) { + let item = ScheduledScans.findOne({ _id: _id }); + console.log('scheduled scan for remove: ', item); + + ScheduledScans.remove({ _id: _id }); + } +}); diff --git a/ui/imports/api/scheduled-scans/scheduled-scans.js b/ui/imports/api/scheduled-scans/scheduled-scans.js new file mode 100644 index 0000000..66ae5d1 --- /dev/null +++ b/ui/imports/api/scheduled-scans/scheduled-scans.js @@ -0,0 +1,91 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others / +// / +// All rights reserved. This program and the accompanying materials / +// are made available under the terms of the Apache License, Version 2.0 / +// which accompanies this distribution, and is available at / +// http://www.apache.org/licenses/LICENSE-2.0 / +///////////////////////////////////////////////////////////////////////////////////////// +import { Mongo } from 'meteor/mongo'; +import { SimpleSchema } from 'meteor/aldeed:simple-schema'; +import { Constants } from '/imports/api/constants/constants'; +import * as R from 'ramda'; + +export const ScheduledScans = new Mongo.Collection('scheduled_scans', { idGeneration: 'MONGO' }); + +export const scansOnlyFields = ['scan_only_inventory', 'scan_only_links', 'scan_only_cliques']; + +let schema = new SimpleSchema({ + _id: { type: { _str: { type: String, regEx: SimpleSchema.RegEx.Id } } }, + environment: { + type: String + }, + object_id: { + type: String, + optional: true, + }, + log_level: { + type: String, + defaultValue: 'warning', + custom: function () { + let that = this; + let logLevels = Constants.findOne({ name: 'log_levels' }).data; + + if (R.isNil(R.find(R.propEq('value', that.value), logLevels))) { + return 'notAllowed'; + } + }, + }, + clear: { + type: Boolean, + defaultValue: true, + }, + scan_only_inventory: { + type: Boolean, + defaultValue: true, + }, + scan_only_links: { + type: Boolean, + defaultValue: false, + }, + scan_only_cliques: { + type: Boolean, + defaultValue: false, + }, + freq: { + type: String, + defaultValue: 'WEEKLY', + }, + submit_timestamp: { + type: Date, + defaultValue: null + }, + scheduled_timestamp: { + type: Date, + defaultValue: null, + optional: true, + } +}); + +schema.addValidator(function () { + let that = this; + let currentScansOnlyFields = + R.reject( f => that.field(f).value == false, scansOnlyFields); + + if(currentScansOnlyFields.length > 1) { + throw { + isError: true, + type: 'conflict', + data: currentScansOnlyFields, + message: `Only one of the scan only fields can be selected. ${R.toString(currentScansOnlyFields)}` + }; + } +}); + +ScheduledScans.schema = schema; +ScheduledScans.attachSchema(ScheduledScans.schema); + +export const subsScheduledScansPageAmountSorted = 'scheduled_scans?page&amount&sortField&sortDirection'; +export const subsScheduledScansPageAmountSortedCounter = `${subsScheduledScansPageAmountSorted}!counter`; + +export const subsScheduledScansId = 'scheduled_scans?_id'; diff --git a/ui/imports/api/scheduled-scans/server/methods.js b/ui/imports/api/scheduled-scans/server/methods.js new file mode 100644 index 0000000..17ed990 --- /dev/null +++ b/ui/imports/api/scheduled-scans/server/methods.js @@ -0,0 +1,27 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others / +// / +// All rights reserved. This program and the accompanying materials / +// are made available under the terms of the Apache License, Version 2.0 / +// which accompanies this distribution, and is available at / +// http://www.apache.org/licenses/LICENSE-2.0 / +///////////////////////////////////////////////////////////////////////////////////////// +import { check } from 'meteor/check'; +import * as R from 'ramda'; +import { ScheduledScans } from '../scheduled-scans'; + +Meteor.methods({ + 'scheduledScansFind?env': function (env) { + console.log('method server: scheduledScansFind?env', R.toString(env)); + + check(env, String); + this.unblock(); + + let query = { environment: env }; + let scheduledScan = ScheduledScans.findOne(query, {}); + + return { + item: scheduledScan + }; + } +}); diff --git a/ui/imports/api/scheduled-scans/server/publications.js b/ui/imports/api/scheduled-scans/server/publications.js new file mode 100644 index 0000000..97acc21 --- /dev/null +++ b/ui/imports/api/scheduled-scans/server/publications.js @@ -0,0 +1,60 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others / +// / +// All rights reserved. This program and the accompanying materials / +// are made available under the terms of the Apache License, Version 2.0 / +// which accompanies this distribution, and is available at / +// http://www.apache.org/licenses/LICENSE-2.0 / +///////////////////////////////////////////////////////////////////////////////////////// +import { Meteor } from 'meteor/meteor'; +import * as R from 'ramda'; +import { Counts } from 'meteor/tmeasday:publish-counts'; + +import { ScheduledScans, + subsScheduledScansPageAmountSorted, + subsScheduledScansPageAmountSortedCounter, + subsScheduledScansId, +} from '../scheduled-scans.js'; + +Meteor.publish(subsScheduledScansPageAmountSorted, function ( + page, amountPerPage, sortField, sortDirection) { + + console.log(`server subscribtion: ${subsScheduledScansPageAmountSorted}`); + console.log('page: ', page); + console.log('amount: ', amountPerPage); + console.log('sortField: ', sortField, R.isNil(sortField)); + console.log('sortDirection: ', sortDirection); + + let skip = (page - 1) * amountPerPage; + + let query = {}; + console.log('-query: ', query); + let sortParams = {}; + + sortParams = R.ifElse(R.isNil, R.always(sortParams), + R.assoc(R.__, sortDirection, sortParams))(sortField); + + console.log('sort params:', sortParams); + + let qParams = { + limit: amountPerPage, + skip: skip, + sort: sortParams, + }; + + Counts.publish(this, subsScheduledScansPageAmountSortedCounter, ScheduledScans.find(query), { + noReady: true + }); + + return ScheduledScans.find(query, qParams); +}); + +Meteor.publish(subsScheduledScansId, function (_id) { + console.log(`server subscribtion: ${subsScheduledScansId}`); + console.log('-id: ', _id); + + //let that = this; + + let query = { _id: _id }; + return ScheduledScans.find(query); +}); diff --git a/ui/imports/api/simple-schema.init.js b/ui/imports/api/simple-schema.init.js new file mode 100644 index 0000000..4f5addb --- /dev/null +++ b/ui/imports/api/simple-schema.init.js @@ -0,0 +1,13 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others / +// / +// All rights reserved. This program and the accompanying materials / +// are made available under the terms of the Apache License, Version 2.0 / +// which accompanies this distribution, and is available at / +// http://www.apache.org/licenses/LICENSE-2.0 / +///////////////////////////////////////////////////////////////////////////////////////// +import { SimpleSchema } from 'meteor/aldeed:simple-schema'; + +SimpleSchema.messages({ + 'alreadyExists': 'item already exists' +}); diff --git a/ui/imports/api/statistics/helpers.js b/ui/imports/api/statistics/helpers.js new file mode 100644 index 0000000..7cb78e8 --- /dev/null +++ b/ui/imports/api/statistics/helpers.js @@ -0,0 +1,64 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others / +// / +// All rights reserved. This program and the accompanying materials / +// are made available under the terms of the Apache License, Version 2.0 / +// which accompanies this distribution, and is available at / +// http://www.apache.org/licenses/LICENSE-2.0 / +///////////////////////////////////////////////////////////////////////////////////////// +import * as R from 'ramda'; + +export function createGraphQuerySchema( + env, + object_id, + type, + flowType, + timeStart, + timeEnd, + sourceMacAddress, + destinationMacAddress, + sourceIPv4Address, + destinationIPv4Address) { + + let schema = { + environment: env, + object_id: object_id, + type: type, + flowType: flowType, + /* + averageArrivalNanoSeconds: { + $gte: timeStart, + //$lt: timeEnd + } + */ + data_arrival_avg: { + $gte: timeStart, + } + }; + + if (! R.isNil(timeEnd)) { + //schema = R.assocPath(['averageArrivalNanoSeconds', '$lt'], timeEnd, schema); + schema = R.assocPath(['data_arrival_avg', '$lt'], timeEnd, schema); + } + + switch (flowType) { + case 'L2': + schema = R.merge(schema, { + sourceMacAddress: sourceMacAddress, + destinationMacAddress: destinationMacAddress + }); + break; + + case 'L3': + schema = R.merge(schema, { + sourceIPv4Address: sourceIPv4Address, + destinationIPv4Address: destinationIPv4Address + }); + break; + + default: + break; + } + + return schema; +} diff --git a/ui/imports/api/statistics/methods.js b/ui/imports/api/statistics/methods.js new file mode 100644 index 0000000..23a216d --- /dev/null +++ b/ui/imports/api/statistics/methods.js @@ -0,0 +1,159 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others / +// / +// All rights reserved. This program and the accompanying materials / +// are made available under the terms of the Apache License, Version 2.0 / +// which accompanies this distribution, and is available at / +// http://www.apache.org/licenses/LICENSE-2.0 / +///////////////////////////////////////////////////////////////////////////////////////// +import * as R from 'ramda'; +import { Statistics } from './statistics'; +import { createGraphQuerySchema } from './helpers'; + +Meteor.methods({ + 'statistics.flowTypes?env&object_id&type'({ env, object_id, type}) { + console.log('subscribe: statistics.flowTypes?env&object_id&type'); + console.log(`- env: ${env}`); + console.log(`- object_id: ${object_id}`); + console.log(`- type: ${type}`); + + let pipeline = [{ + $match: { + environment: env, + object_id: object_id, + type: type + } + }, { + $group: { + _id: { flowType: '$flowType' }, + flowType: { $first: '$flowType' } + } + }]; + + return Statistics.aggregate(pipeline); + }, + + 'statistics.srcMacAddresses?env&object_id&type&flowType'( + { env, object_id, type, flowType }) { + + let pipeline = [{ + $match: { + environment: env, + object_id: object_id, + type: type, + flowType: flowType + } + }, { + $group: { + _id: { sourceMacAddress: '$sourceMacAddress' }, + sourceMacAddress: { $first: '$sourceMacAddress' } + } + }]; + + return Statistics.aggregate(pipeline); + }, + + 'statistics.dstMacAddresses?env&object_id&type&flowType'( + { env, object_id, type, flowType }) { + + let pipeline = [{ + $match: { + environment: env, + object_id: object_id, + type: type, + flowType: flowType + } + }, { + $group: { + _id: { destinationMacAddress: '$destinationMacAddress' }, + destinationMacAddress: { $first: '$destinationMacAddress' } + } + }]; + + return Statistics.aggregate(pipeline); + }, + + 'statistics.srcIPv4Addresses?env&object_id&type&flow_typw'( + { env, object_id, type, flowType }) { + let pipeline = [{ + $match: { + environment: env, + object_id: object_id, + type: type, + flowType: flowType + } + }, { + $group: { + _id: { sourceIPv4Address: '$sourceIPv4Address' }, + sourceIPv4Address: { $first: '$sourceIPv4Address' } + } + }]; + + return Statistics.aggregate(pipeline); + }, + + 'statistics.dstIPv4Addresses?env&object_id&type&flowType'( + { env, object_id, type, flowType }) { + let pipeline = [{ + $match: { + environment: env, + object_id: object_id, + type: type, + flowType: flowType + } + }, { + $group: { + _id: { destinationIPv4Address: '$destinationIPv4Addres' }, + destinationIPv4Address: { $first: '$destinationIPv4Addres' } + } + }]; + + return Statistics.aggregate(pipeline); + }, + + 'statistics!graph-frames'({ + env, + object_id, + type, + flowType, + timeStart, + timeEnd, + sourceMacAddress, + destinationMacAddress, + sourceIPv4Address, + destinationIPv4Address + }) { + let schema = createGraphQuerySchema( + env, + object_id, + type, + flowType, + timeStart, + timeEnd, + sourceMacAddress, + destinationMacAddress, + sourceIPv4Address, + destinationIPv4Address); + + console.log('statistics!graph-frames'); + console.log(`- env: ${env}`); + console.log(`- object_id: ${object_id}`); + console.log(`- type: ${type}`); + console.log(`- flowType: ${flowType}`); + console.log(`- timeStart: ${timeStart}`); + console.log(`- timeEnd: ${timeEnd}`); + console.log(`- sourceMacAddress: ${sourceMacAddress}`); + console.log(`- destinationMacAddress: ${destinationMacAddress}`); + console.log(`- sourceIPv4Address: ${sourceIPv4Address}`); + console.log(`- destinationIPv4Address: ${destinationIPv4Address}`); + + //let data = Statistics.find(schema).fetch(); + let data = Statistics.findOne(schema); + console.log(`- averageArrivalNanoSeconds: ${R.path([0, 'averageArrivalNanoSeconds'], data)}`); + + return data; + } +}); + + + diff --git a/ui/imports/api/statistics/server/publications.js b/ui/imports/api/statistics/server/publications.js new file mode 100644 index 0000000..f69be56 --- /dev/null +++ b/ui/imports/api/statistics/server/publications.js @@ -0,0 +1,52 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others / +// / +// All rights reserved. This program and the accompanying materials / +// are made available under the terms of the Apache License, Version 2.0 / +// which accompanies this distribution, and is available at / +// http://www.apache.org/licenses/LICENSE-2.0 / +///////////////////////////////////////////////////////////////////////////////////////// +import { Meteor } from 'meteor/meteor'; +//import { Counts } from 'meteor/tmeasday:publish-counts'; +import { Statistics } from '../statistics.js'; +import { createGraphQuerySchema } from '../helpers'; + +Meteor.publish('statistics!graph-frames', function ({ + env, + object_id, + type, + flowType, + timeStart, + sourceMacAddress, + destinationMacAddress, + sourceIPv4Address, + destinationIPv4Address +}) { + console.log('server subscribe: statistics?graph-frames'); + + let schema = createGraphQuerySchema( + env, + object_id, + type, + flowType, + timeStart, + null, + sourceMacAddress, + destinationMacAddress, + sourceIPv4Address, + destinationIPv4Address); + + console.log('statistics!graph-frames'); + console.log(`- env: ${env}`); + console.log(`- object_id: ${object_id}`); + console.log(`- type: ${type}`); + console.log(`- flowType: ${flowType}`); + console.log(`- timeStart: ${timeStart}`); + console.log(`- sourceMacAddress: ${sourceMacAddress}`); + console.log(`- destinationMacAddress: ${destinationMacAddress}`); + console.log(`- sourceIPv4Address: ${sourceIPv4Address}`); + console.log(`- destinationIPv4Address: ${destinationIPv4Address}`); + + return Statistics.find(schema); +}); + diff --git a/ui/imports/api/statistics/statistics.js b/ui/imports/api/statistics/statistics.js new file mode 100644 index 0000000..3391933 --- /dev/null +++ b/ui/imports/api/statistics/statistics.js @@ -0,0 +1,14 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others / +// / +// All rights reserved. This program and the accompanying materials / +// are made available under the terms of the Apache License, Version 2.0 / +// which accompanies this distribution, and is available at / +// http://www.apache.org/licenses/LICENSE-2.0 / +///////////////////////////////////////////////////////////////////////////////////////// +import { Mongo } from 'meteor/mongo'; +//import { SimpleSchema } from 'meteor/aldeed:simple-schema'; +//import * as R from 'ramda'; + +export const Statistics = new Mongo.Collection( + 'statistics', { idGeneration: 'MONGO' }); diff --git a/ui/imports/api/supported_environments/methods.js b/ui/imports/api/supported_environments/methods.js new file mode 100644 index 0000000..1eda375 --- /dev/null +++ b/ui/imports/api/supported_environments/methods.js @@ -0,0 +1,8 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others / +// / +// All rights reserved. This program and the accompanying materials / +// are made available under the terms of the Apache License, Version 2.0 / +// which accompanies this distribution, and is available at / +// http://www.apache.org/licenses/LICENSE-2.0 / +///////////////////////////////////////////////////////////////////////////////////////// diff --git a/ui/imports/api/supported_environments/server/publications.js b/ui/imports/api/supported_environments/server/publications.js new file mode 100644 index 0000000..8fef880 --- /dev/null +++ b/ui/imports/api/supported_environments/server/publications.js @@ -0,0 +1,17 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others / +// / +// All rights reserved. This program and the accompanying materials / +// are made available under the terms of the Apache License, Version 2.0 / +// which accompanies this distribution, and is available at / +// http://www.apache.org/licenses/LICENSE-2.0 / +///////////////////////////////////////////////////////////////////////////////////////// +import { Meteor } from 'meteor/meteor'; +import { SupportedEnvironments, + subsNameSupportedEnvs +} from '../supported_environments.js'; + +Meteor.publish(subsNameSupportedEnvs, function () { + console.log(`server subscribtion to: ${subsNameSupportedEnvs}`); + return SupportedEnvironments.find({}); +}); diff --git a/ui/imports/api/supported_environments/supported_environments.js b/ui/imports/api/supported_environments/supported_environments.js new file mode 100644 index 0000000..55c5745 --- /dev/null +++ b/ui/imports/api/supported_environments/supported_environments.js @@ -0,0 +1,49 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others / +// / +// All rights reserved. This program and the accompanying materials / +// are made available under the terms of the Apache License, Version 2.0 / +// which accompanies this distribution, and is available at / +// http://www.apache.org/licenses/LICENSE-2.0 / +///////////////////////////////////////////////////////////////////////////////////////// +import { Mongo } from 'meteor/mongo'; +import * as R from 'ramda'; + +export const SupportedEnvironments = new Mongo.Collection( + 'supported_environments', { idGeneration: 'MONGO' }); + +export const subsNameSupportedEnvs = 'supported-environments'; + +export function isMonitoringSupported(distribution, type_drivers, mechanism_drivers) { + console.log('isMonitoringSupported'); + console.log(`distribution: ${R.toString(distribution)}`); + console.log(`type_drivers: ${R.toString(type_drivers)}`); + console.log(`mechanism_drivers: ${R.toString(mechanism_drivers)}`); + + let result = SupportedEnvironments.find({ + 'environment.distribution': distribution, + 'environment.type_drivers': type_drivers, + 'environment.mechanism_drivers': { $in: mechanism_drivers }, + 'features.monitoring': true + }).count() > 0; + + console.log(`result: ${R.toString(result)}`); + return result; +} + +export function isListeningSupported(distribution, type_drivers, mechanism_drivers) { + console.log('isListeningSupported'); + console.log(`distribution: ${R.toString(distribution)}`); + console.log(`type_drivers: ${R.toString(type_drivers)}`); + console.log(`mechanism_drivers: ${R.toString(mechanism_drivers)}`); + + let result = SupportedEnvironments.find({ + 'environment.distribution': distribution, + 'environment.type_drivers': type_drivers, + 'environment.mechanism_drivers': { $in: mechanism_drivers }, + 'features.listening': true + }).count() > 0; + + console.log(`result: ${R.toString(result)}`); + return result; +} |