diff --git a/app/client/templates/profile.html b/app/client/templates/profile.html index 93e9e86..4ce5f1b 100644 --- a/app/client/templates/profile.html +++ b/app/client/templates/profile.html @@ -23,6 +23,16 @@

My emails ({{emails.length}})

{{/with}} +

My MAC addresses

+
+
+ {{#each macs localIPCandidates}} +
{{MAC}} {{name}}
+ {{/each}} +
+
+ +

My addresses

My public IP address: {{remoteIPAddress}}
diff --git a/app/client/templates/profile.js b/app/client/templates/profile.js index 42acbd9..b623e9f 100644 --- a/app/client/templates/profile.js +++ b/app/client/templates/profile.js @@ -1,2 +1,25 @@ -Template.profile.events({ +Template.profile.onCreated(function () { + Meteor.subscribe('Meteor.arptable'); + Meteor.subscribe('Meteor.users'); +}); + +Template.profile.helpers({ + macs: function(IP){ + cursor = App.Collections.ARPEntries.find({"IP" : IP[0]}); + result = []; + + cursor.map(entry => { + //TODO: use proper projection + var user = Meteor.users.findOne({'profile.devices.MAC': entry.MAC }); + var name; + user.profile.devices.map(MACentry => { + if(MACentry.MAC == entry.MAC){ + name = MACentry.name; + } + }) + result.push({'MAC': entry.MAC, 'name': name}); + }); + + return result; + } }); \ No newline at end of file diff --git a/app/client/templates/whosthere.js b/app/client/templates/whosthere.js index 2a49a2a..be96eb5 100644 --- a/app/client/templates/whosthere.js +++ b/app/client/templates/whosthere.js @@ -1,6 +1,17 @@ Template.whosthere.onCreated(function () { + Meteor.subscribe('Meteor.arptable'); +}); + +Template.whosthere.onRendered(function() { + + this.$('.ui.dropdown') + .dropdown(); +}); + + +Template.whosthere.helpers({ - this.connectedMembers = function () { + connectedMembers: function() { var ARPentries = App.Collections.ARPEntries.find(); var i = 0; @@ -21,20 +32,6 @@ Template.whosthere.onCreated(function () { unknown: user ? false : true }; }), 'name'), 'order'); - }; -}); - -Template.whosthere.onRendered(function() { - - this.$('.ui.dropdown') - .dropdown(); -}); - - -Template.whosthere.helpers({ - - connectedMembers: function() { - return Template.instance().connectedMembers(); }, unknownMemberClass: function() { diff --git a/app/imports/server/api/endpoints.app-test.js b/app/imports/server/api/endpoints.app-test.js index c3f6725..51c604e 100644 --- a/app/imports/server/api/endpoints.app-test.js +++ b/app/imports/server/api/endpoints.app-test.js @@ -4,16 +4,14 @@ import { chai } from 'meteor/practicalmeteor:chai'; var assert = chai.assert, expect = chai.expect; -const NoEntries = 'IP address HW type Flags HW address Mask Device'; -const ThreeEntries = 'IP address HW type Flags HW address Mask Device\r\n192.168.1.11 0x1 0x2 8c:3a:e3:93:83:93 * br0\r\n192.168.1.50 0x1 0x2 00:26:bb:07:54:80 * br0\r\n192.168.1.18 0x1 0x2 3c:15:c2:cc:dc:2a * br0'; -const TwoEntries = 'IP address HW type Flags HW address Mask Device\r\n192.168.1.11 0x1 0x2 8c:3a:e3:93:83:93 * br0\r\n192.168.1.50 0x1 0x2 00:26:bb:07:54:80 * br0'; +const testFilesPath = 'test/arpTable/'; describe('API', function() { it('accepts correct call', function() { HTTP.call( 'POST', - Meteor.absoluteUrl() + 'routerapi/v1/arp/candra', { headers: { 'Authorization': 'Bearer abcd' }, data: { arpTable: ThreeEntries } }, + Meteor.absoluteUrl() + 'routerapi/v1/arp/candra', { headers: { 'Authorization': 'Bearer abcd' }, data: { arpTable: Assets.getText(testFilesPath + 'threeEntries.txt') } }, function(error, result) { assert(!error, 'there was an error: \n' + error); assert(result.statusCode == 200, 'Status code didn\'t match 200 it was ' + result.statusCode); @@ -82,12 +80,12 @@ describe('API', function() { it('removes old MAC addresses', function() { HTTP.call( 'POST', - Meteor.absoluteUrl() + 'routerapi/v1/arp/candra', { headers: { 'Authorization': 'Bearer abcd' }, data: { arpTable: ThreeEntries } } + Meteor.absoluteUrl() + 'routerapi/v1/arp/candra', { headers: { 'Authorization': 'Bearer abcd' }, data: { arpTable: Assets.getText(testFilesPath + 'threeEntries.txt') } } ); var entriesBefore = App.Collections.ARPEntries.find().count(); result = HTTP.call( 'POST', - Meteor.absoluteUrl() + 'routerapi/v1/arp/candra', { headers: { 'Authorization': 'Bearer abcd' }, data: { arpTable: TwoEntries } } + Meteor.absoluteUrl() + 'routerapi/v1/arp/candra', { headers: { 'Authorization': 'Bearer abcd' }, data: { arpTable: Assets.getText(testFilesPath + 'twoEntries.txt') } } ); assert.equal(App.Collections.ARPEntries.find().count(), entriesBefore - 1); }); diff --git a/app/imports/server/api/getEntries.test.js b/app/imports/server/api/getEntries.test.js index a4697f8..bfc2b81 100644 --- a/app/imports/server/api/getEntries.test.js +++ b/app/imports/server/api/getEntries.test.js @@ -1,61 +1,49 @@ import { Meteor } from 'meteor/meteor'; import { chai } from 'meteor/practicalmeteor:chai'; import { getEntries } from '../../../server/api/arpTable.js'; +import { processedThreeEntries, processedRealARP } from '../api/processed.js'; var assert = chai.assert, expect = chai.expect; -const NoEntries = 'IP address HW type Flags HW address Mask Device'; -const ThreeEntries = 'IP address HW type Flags HW address Mask Device\r\n192.168.1.11 0x1 0x2 8c:3a:e3:93:83:93 * br0\r\n192.168.1.50 0x1 0x2 00:26:bb:07:54:80 * br0\r\n192.168.1.18 0x1 0x2 3c:15:c2:cc:dc:2a * br0'; - -const DoubleIP = 'IP address HW type Flags HW address Mask Device\r\n192.168.1.11 0x1 0x2 8c:3a:e3:93:83:93 * br0 192.168.1.17'; -const DoubleMAC = 'IP address HW type Flags HW address Mask Device\r\n192.168.1.11 0x1 0x2 8d:3a:e3:93:83:93 * br0 8c:3a:e3:93:83:93'; -const NoMAC = 'IP address HW type Flags HW address Mask Device\r\n192.168.1.11 0x1 0x2 * br0 192.168.1.11 '; -const NoIP = 'IP address HW type Flags HW address Mask Device\r\n192.168 0x1 0x2 * br0 8c:3a:e3:93:83:93'; -const NoIPnorMAC = 'IP address HW type Flags HW address Mask Device\r\n192.168 0x1 0x2 * br0 '; -const ReUsedMAC = 'IP address HW type Flags HW address Mask Device\r\n192.168.1.11 0x1 0x2 8c:3a:e3:93:83:93 * br0\r\n192.168.1.50 0x1 0x2 8c:3a:e3:93:83:93 * br0\r\n192.168.1.18 0x1 0x2 8c:3a:e3:93:83:93 * br0'; -const ReUsedIP = 'IP address HW type Flags HW address Mask Device\r\n192.168.1.50 0x1 0x2 8c:3a:e3:93:83:93 * br0\r\n192.168.1.50 0x1 0x2 8c:3a:e3:93:83:94 * br0\r\n192.168.1.50 0x1 0x2 8c:3a:e3:93:83:92 * br0'; -const ReUsedIPandMAC = 'IP address HW type Flags HW address Mask Device\r\n192.168.1.50 0x1 0x2 8c:3a:e3:93:83:93 * br0\r\n192.168.1.50 0x1 0x2 8c:3a:e3:93:83:93 * br0\r\n192.168.1.50 0x1 0x2 8c:3a:e3:93:83:93 * br0'; - -const processedThreeEntries = [{ - IP: '192.168.1.11', - MAC: '8C:3A:E3:93:83:93' -}, { - IP: '192.168.1.50', - MAC: '00:26:BB:07:54:80' -}, { - IP: '192.168.1.18', - MAC: '3C:15:C2:CC:DC:2A' -}]; +const testFilesPath = 'test/arpTable/'; describe('arpTable', function() { it('processes correct arpTables', function() { - var result = getEntries(ThreeEntries); + var result = getEntries(Assets.getText(testFilesPath + 'threeEntries.txt')); for (var i = result.length - 1; i >= 0; i--) { delete result[i].updatedAt; } assert.deepEqual(result, processedThreeEntries); }); + it('processes another correct arpTables', function() { + var result = getEntries(Assets.getText(testFilesPath + 'realARP.txt')); + for (var i = result.length - 1; i >= 0; i--) { + delete result[i].updatedAt; + } + assert.deepEqual(result, processedRealARP); + }); + it('processes empty arpTables', function() { - assert.deepEqual(getEntries(NoEntries), []); + assert.deepEqual(getEntries(Assets.getText(testFilesPath + 'noEntries.txt')), []); }); it('does not allow no MAC address in entry', function() { assert.throws(function(){ - getEntries(NoMAC); + getEntries(Assets.getText(testFilesPath + 'noMAC.txt')); }, Error, 'no MAC') }); it('does not allow no IP address in entry', function() { assert.throws(function(){ - getEntries(NoIP); + getEntries(Assets.getText(testFilesPath + 'noIP.txt')); }, Error, 'no IP') }); it('does not allow no IP nor MAC address in entry', function() { assert.throws(function(){ - getEntries(NoIPnorMAC); + getEntries(Assets.getText(testFilesPath + 'noIPnorMAC.txt')); }, Error, 'no IP') }); diff --git a/app/imports/server/api/processed.js b/app/imports/server/api/processed.js new file mode 100644 index 0000000..8789459 --- /dev/null +++ b/app/imports/server/api/processed.js @@ -0,0 +1,42 @@ +export const processedThreeEntries = [{ + IP: '192.168.1.11', + MAC: '8C:3A:E3:93:83:93' +}, { + IP: '192.168.1.50', + MAC: '00:26:BB:07:54:80' +}, { + IP: '192.168.1.18', + MAC: '3C:15:C2:CC:DC:2A' +}]; + +export const processedRealARP = [{ + IP: '192.168.1.132', + MAC: 'B0:E2:35:70:61:A9' +},{ + IP: '192.168.1.172', + MAC: 'AC:72:89:6A:B4:D6' +},{ + IP: '192.168.1.203', + MAC: 'FC:C2:DE:7A:E7:6F' +},{ + IP: '192.168.1.90', + MAC: 'D8:50:E6:BD:A0:0F' +},{ + IP: '192.168.1.125', + MAC: '74:A5:28:74:73:76' +},{ + IP: '192.168.1.231', + MAC: '44:82:E5:9E:87:C9' +},{ + IP: '192.168.1.178', + MAC: 'C0:EE:FB:27:16:DB' +},{ + IP: '192.168.1.81', + MAC: '6C:40:08:A9:1B:A0' +},{ + IP: '10.1.2.1', + MAC: '30:85:A9:E7:1A:B8' +},{ + IP: '192.168.1.84', + MAC: '3C:15:C2:CC:DC:2A' +}]; \ No newline at end of file diff --git a/app/lib/collections/Users.js b/app/lib/collections/Users.js index dd4afd5..88d7cc0 100644 --- a/app/lib/collections/Users.js +++ b/app/lib/collections/Users.js @@ -41,7 +41,7 @@ var UserProfileSchema = new SimpleSchema({ optional: true }, devices: { - type: new SimpleSchema({ + type: [new SimpleSchema({ name: { type: String, optional: true @@ -50,7 +50,7 @@ var UserProfileSchema = new SimpleSchema({ type: String, optional: true } - }), + })], optional: true } }); diff --git a/app/lib/methods/users.js b/app/lib/methods/users.js index 755a7ce..c362069 100644 --- a/app/lib/methods/users.js +++ b/app/lib/methods/users.js @@ -1,30 +1,28 @@ Meteor.methods({ - 'user/updateProfilePicture': function(picture) { + 'user/updateProfilePicture': function(picture) { - check(picture, String); - Meteor.users.update(this.userId, {$set: {'profile.picture': picture}}); + check(picture, String); + Meteor.users.update(this.userId, { $set: { 'profile.picture': picture } }); - return true; - }, + return true; + }, - 'user/updateDevice': function (MAC, name, userId) { + 'user/updateDevice': function(MAC, name) { - check(userId, String); - check(MAC, String); - check(name, Match.Optional(name)); + userId = Meteor.userId(); - if (!userId) { - userId = Meteor.userId(); - } + check(userId, String); + check(MAC, String); + check(name, Match.Optional(name)); - App.Services.Users.updateDevice(userId, {MAC: MAC, name: name}); - }, + App.Services.Users.updateDevice(userId, { MAC: MAC, name: name }); + }, - 'user/getRemoteIPAddress': function() { + 'user/getRemoteIPAddress': function() { - if (this.isSimulation) return; + if (this.isSimulation) return; - var clientIP = this.connection.clientAddress; - return clientIP; - } + var clientIP = this.connection.clientAddress; + return clientIP; + } }); diff --git a/app/private/test/arpTable/doubleIP.txt b/app/private/test/arpTable/doubleIP.txt new file mode 100644 index 0000000..cadae75 --- /dev/null +++ b/app/private/test/arpTable/doubleIP.txt @@ -0,0 +1,2 @@ +IP address HW type Flags HW address Mask Device +192.168.1.11 0x1 0x2 8c:3a:e3:93:83:93 * br0 192.168.1.17 \ No newline at end of file diff --git a/app/private/test/arpTable/doubleMAC.txt b/app/private/test/arpTable/doubleMAC.txt new file mode 100644 index 0000000..7e81c37 --- /dev/null +++ b/app/private/test/arpTable/doubleMAC.txt @@ -0,0 +1,2 @@ +IP address HW type Flags HW address Mask Device\r\n +192.168.1.11 0x1 0x2 8d:3a:e3:93:83:93 * br0 8c:3a:e3:93:83:93 diff --git a/app/private/test/arpTable/noEntries.txt b/app/private/test/arpTable/noEntries.txt new file mode 100644 index 0000000..206eb71 --- /dev/null +++ b/app/private/test/arpTable/noEntries.txt @@ -0,0 +1 @@ +IP address HW type Flags HW address Mask Device \ No newline at end of file diff --git a/app/private/test/arpTable/noIP.txt b/app/private/test/arpTable/noIP.txt new file mode 100644 index 0000000..591ccfd --- /dev/null +++ b/app/private/test/arpTable/noIP.txt @@ -0,0 +1,2 @@ +IP address HW type Flags HW address Mask Device +192.168 0x1 0x2 * br0 8c:3a:e3:93:83:93 diff --git a/app/private/test/arpTable/noIPnorMAC.txt b/app/private/test/arpTable/noIPnorMAC.txt new file mode 100644 index 0000000..41a9489 --- /dev/null +++ b/app/private/test/arpTable/noIPnorMAC.txt @@ -0,0 +1,2 @@ +IP address HW type Flags HW address Mask Device +92.168 0x1 0x2 * br0 diff --git a/app/private/test/arpTable/noMAC.txt b/app/private/test/arpTable/noMAC.txt new file mode 100644 index 0000000..b2d6460 --- /dev/null +++ b/app/private/test/arpTable/noMAC.txt @@ -0,0 +1,2 @@ +IP address HW type Flags HW address Mask Device +192.168.1.11 0x1 0x2 * br0 192.168.1.11 diff --git a/app/private/test/arpTable/realARP.txt b/app/private/test/arpTable/realARP.txt new file mode 100644 index 0000000..860a24f --- /dev/null +++ b/app/private/test/arpTable/realARP.txt @@ -0,0 +1,11 @@ +IP address HW type Flags HW address Mask Device +192.168.1.132 0x1 0x2 B0:E2:35:70:61:A9 * br0 +192.168.1.172 0x1 0x2 AC:72:89:6A:B4:D6 * br0 +192.168.1.203 0x1 0x2 FC:C2:DE:7A:E7:6F * br0 +192.168.1.90 0x1 0x2 D8:50:E6:BD:A0:0F * br0 +192.168.1.125 0x1 0x2 74:A5:28:74:73:76 * br0 +192.168.1.231 0x1 0x2 44:82:E5:9E:87:C9 * br0 +192.168.1.178 0x1 0x2 C0:EE:FB:27:16:DB * br0 +192.168.1.81 0x1 0x2 6C:40:08:A9:1B:A0 * br0 +10.1.2.1 0x1 0x2 30:85:A9:E7:1A:B8 * eth0 +192.168.1.84 0x1 0x2 3C:15:C2:CC:DC:2A * br0 \ No newline at end of file diff --git a/app/private/test/arpTable/threeEntries.txt b/app/private/test/arpTable/threeEntries.txt new file mode 100644 index 0000000..a0be4c4 --- /dev/null +++ b/app/private/test/arpTable/threeEntries.txt @@ -0,0 +1,4 @@ +IP address HW type Flags HW address Mask Device +192.168.1.11 0x1 0x2 8c:3a:e3:93:83:93 * br0 +192.168.1.50 0x1 0x2 00:26:bb:07:54:80 * br0 +192.168.1.18 0x1 0x2 3c:15:c2:cc:dc:2a * br0 diff --git a/app/private/test/arpTable/twoEntries.txt b/app/private/test/arpTable/twoEntries.txt new file mode 100644 index 0000000..ddccb96 --- /dev/null +++ b/app/private/test/arpTable/twoEntries.txt @@ -0,0 +1,3 @@ +IP address HW type Flags HW address Mask Device +192.168.1.11 0x1 0x2 8c:3a:e3:93:83:93 * br0 +192.168.1.50 0x1 0x2 00:26:bb:07:54:80 * br0 diff --git a/app/server/api/arpTable.js b/app/server/api/arpTable.js index 1cfbdee..b34d9e2 100644 --- a/app/server/api/arpTable.js +++ b/app/server/api/arpTable.js @@ -12,7 +12,7 @@ var getEntries = function(arpTable) { var rows = arpTable.split("\n"); rows.forEach((row, index) => { - if (index === 0) + if (index === 0 || row.length === 0) return; row = row.toUpperCase(); diff --git a/app/server/api/users.js b/app/server/api/users.js index 154a3fe..c1c019a 100644 --- a/app/server/api/users.js +++ b/app/server/api/users.js @@ -4,6 +4,7 @@ import { UserSchema, UserProfileSchema } from '../../lib/collections/Users.js'; Meteor.methods({ 'users.insert'(doc) { + doc.createdAt = new Date(); check(doc, UserSchema); Meteor.users.insert(doc); }, diff --git a/app/server/init.js b/app/server/init.js index b6c853c..ae8b75e 100644 --- a/app/server/init.js +++ b/app/server/init.js @@ -15,36 +15,46 @@ function oauthConfig(service, clientId, secret) { } function initOrgs() { - var directory = Meteor.http.call("GET", "http://spaceapi.net/directory.json?api=0.13"); - var urls = Object.keys(directory.data).map(function(k) { - if (!App.Collections.Orgs.findOne({ space: k })) { - var url = directory.data[k]; - Meteor.defer(function() { - var newLog; - try { - var result = Meteor.http.call("GET", url); - newLog = logs.createNewSuccessLog(url, JSON.parse(result.content)); - } catch (e) { - newLog = logs.createNewErrorLog(url, e); - } - logs.createOrUpdateLog(newLog); + try{ + var directory = Meteor.http.call("GET", "http://spaceapi.net/directory.json?api=0.13"); + console.log('fetching spaceAPI.'); + var urls = Object.keys(directory.data).map(function(k) { + if (!App.Collections.Orgs.findOne({ space: k })) { + var url = directory.data[k]; + Meteor.defer(function() { + var newLog; + try { + var result = Meteor.http.call("GET", url); + newLog = logs.createNewSuccessLog(url, JSON.parse(result.content)); + } catch (e) { + newLog = logs.createNewErrorLog(url, e); + } + logs.createOrUpdateLog(newLog); - return url; - }); - } else { - return ''; - } - }); + return url; + }); + } else { + return ''; + } + }); - return _.compact(urls); + return _.compact(urls); + } catch (e){ + console.log('fetching spaceAPI has failed, error:'); + console.log(e); + } } Meteor.startup(function() { var config = getCurrentConfiguration(); console.log(config); - if (config.github) { - console.log("Github login configured"); - oauthConfig('github', config.github.clientId, config.github.secret); + if(config.environment == "local" && config.github.local){ + console.log("Github Local login configured"); + oauthConfig('github', config.github.local.clientId, config.github.local.secret); + } + if(config.environment == "develop" && config.github.develop){ + console.log("Github Develop login configured"); + oauthConfig('github', config.github.develop.clientId, config.github.develop.secret); } if (config.google) { @@ -74,3 +84,8 @@ Meteor.publish("Meteor.users", function() { Meteor.publish("Meteor.orgLogs", function() { return App.Collections.OrgLogs.find({}); }); + +Meteor.publish("Meteor.arptable", function() { + return App.Collections.ARPEntries.find({}); +}); +