summaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorChristian Hofmaier2018-08-05 01:48:06 +0200
committerChristian Hofmaier2018-08-05 01:48:06 +0200
commit0d653469ea504bd8f638d0534e20b69ce977d319 (patch)
tree54125f18c9400052b8fd3b9635c6f362b8647d9d /server
parent[permissions] add permission management (diff)
parent[webapp/groups] add generic table actions component for search and pagination... (diff)
downloadbas-0d653469ea504bd8f638d0534e20b69ce977d319.tar.gz
bas-0d653469ea504bd8f638d0534e20b69ce977d319.tar.xz
bas-0d653469ea504bd8f638d0534e20b69ce977d319.zip
merge
Diffstat (limited to 'server')
-rw-r--r--server/.eslintrc.js3
-rw-r--r--server/.gitignore3
-rw-r--r--server/api/backends.js113
-rw-r--r--server/api/clients.js63
-rw-r--r--server/api/groups.js124
-rw-r--r--server/api/ipxe-loader.js42
-rw-r--r--server/api/ipxe.js54
-rw-r--r--server/app.js5
-rw-r--r--server/ipxe/main.ipxe2
-rw-r--r--server/lib/external-backends/backends/another-backend.js8
-rw-r--r--server/lib/external-backends/backends/dummy-backend.js4
-rw-r--r--server/lib/external-backends/backends/idoit-backend.js166
-rw-r--r--server/lib/external-backends/backends/template-backend.js13
-rw-r--r--server/lib/external-backends/external-backends.js17
-rw-r--r--server/lib/shell.js2
-rw-r--r--server/migrations/20180715193710-create-backend.js17
-rw-r--r--server/migrations/20180717132233-create-group.js3
-rw-r--r--server/migrations/20180717132333-create-client.js3
-rw-r--r--server/migrations/20180717202333-create-group_x_group.js2
-rw-r--r--server/migrations/20180717202533-create-group_x_client.js2
-rw-r--r--server/models/backend.js19
-rw-r--r--server/models/client.js5
-rw-r--r--server/models/group.js10
-rw-r--r--server/package-lock.json22
-rw-r--r--server/package.json1
-rw-r--r--server/router.js57
26 files changed, 603 insertions, 157 deletions
diff --git a/server/.eslintrc.js b/server/.eslintrc.js
new file mode 100644
index 0000000..b6351b0
--- /dev/null
+++ b/server/.eslintrc.js
@@ -0,0 +1,3 @@
+module.exports = {
+ "extends": "standard"
+};
diff --git a/server/.gitignore b/server/.gitignore
index 251d1ad..3e9d832 100644
--- a/server/.gitignore
+++ b/server/.gitignore
@@ -19,5 +19,4 @@ yarn-error.log*
*.suo
*.ntvs*
*.njsproj
-*.sln
-*.eslintrc.js
+*.sln \ No newline at end of file
diff --git a/server/api/backends.js b/server/api/backends.js
index b744bd2..ff165a4 100644
--- a/server/api/backends.js
+++ b/server/api/backends.js
@@ -3,7 +3,8 @@ const path = require('path')
const ExternalBackends = require(path.join(__appdir, 'lib', 'external-backends', 'external-backends.js'))
var db = require(path.join(__appdir, 'lib', 'sequelize'))
-module.exports = {
+// GET requests
+module.exports.get = {
getCredentialsByType: function (req, res) {
const backendType = req.query.type
const b = new ExternalBackends()
@@ -14,7 +15,7 @@ module.exports = {
res.status(200).send(instance.getCredentials())
},
- getBackendInfoById: function (req, res) {
+ getInfoById: function (req, res) {
const backendId = req.query.id
db.backend.findOne({ where: { id: backendId } }).then(backend => {
const b = {
@@ -27,7 +28,7 @@ module.exports = {
})
},
- getBackendTypes: function (req, res) {
+ getTypes: function (req, res) {
const backends = new ExternalBackends()
var files = backends.getBackends()
@@ -39,7 +40,7 @@ module.exports = {
res.status(200).send(files)
},
- getBackendList: function (req, res) {
+ getList: function (req, res) {
db.backend.findAll({
attributes: ['id', 'name', 'type']
}).then(function (backends) {
@@ -47,44 +48,106 @@ module.exports = {
})
},
- checkConnection: function (req, res) {
- var x = Math.floor(Math.random() * Math.floor(2))
- var y = ''
- if (x === 0) {
- y = 'success'
- } else {
- y = 'error'
- }
- var w = 'Oh noes! An error occurred.'
- var z = Math.floor(Math.random() * Math.floor(5000))
-
-
- setTimeout(function() { res.status(200).send({ status: y, msg: w }) }, 0)
+ getObject: function (req, res) {
+ const id = req.query.id
+ const oid = req.query.oid
+ db.backend.findOne({ where: { id: id } }).then(backend => {
+ const ba = new ExternalBackends()
+ const instance = ba.getInstance(backend.type)
+ instance.getRoomdata(backend.credentials, oid).then(result => {
+ res.status(200).send(result)
+ })
+ })
+ },
+
+ getObjectTypes: function (req, res) {
+ const id = req.query.id
+ db.backend.findOne({ where: { id: id } }).then(backend => {
+ const ba = new ExternalBackends()
+ const instance = ba.getInstance(backend.type)
+ instance.getObjectTypes(backend.credentials).then(result => {
+ res.status(200).send(result)
+ })
+ })
+ },
+
+ getSyncSettings: function (req, res) {
+ const id = req.query.id
+ var types = {}
+ db.backend.findOne({ where: { id: id } }).then(backend => {
+ types.groups = JSON.parse(backend.groups)
+ types.clients = JSON.parse(backend.clients)
+ types.sync = backend.sync
+ res.status(200).send(types)
+ })
},
- // POST REQUESTS
- saveBackend: function (req, res) {
+ getSyncTypes: function (req, res) {
+ const id = req.query.id
+ db.backend.findOne({ where: { id: id } }).then(backend => {
+ const ba = new ExternalBackends()
+ const instance = ba.getInstance(backend.type)
+ res.status(200).send(instance.getSyncTypes())
+ })
+ }
+}
+
+// POST requests
+module.exports.post = {
+ save: function (req, res) {
// Save credentials in the db.
- const formData = req.body
- const credentialString = JSON.stringify(formData.backendCredentials)
+ const backend = req.body
+ const credentialString = JSON.stringify(backend.credentials)
- if (formData.backendId === 0) {
+ if (backend.id === 0) {
// Insert new backend in the db.
- db.backend.create({ name: formData.backendName, type: formData.backendType, credentials: credentialString })
+ db.backend.create({ name: backend.name, type: backend.type, credentials: credentialString })
} else {
// Update an existing backend in the db.
- db.backend.update({ name: formData.backendName, type: formData.backendType, credentials: credentialString }, { where: { id: formData.backendId } })
+ db.backend.update({ name: backend.name, type: backend.type, credentials: credentialString }, { where: { id: backend.id } })
}
// db.backend.findOne({})
res.status(200).send('success')
},
- deleteBackends: function (req, res) {
+ delete: function (req, res) {
const backendIds = req.body.id
db.backend.destroy({ where: { id: backendIds } }).then(function () {
res.status(200).send('success')
})
+ },
+
+ // If id is set the backend connection in the db is testest.
+ // Else backendinfo has to be set manually, to test unsaved connections.
+ checkConnection: function (req, res) {
+ const id = req.body.id
+
+ var getBackend = null
+ if (id) getBackend = db.backend.findOne({ where: { id: id } })
+ else getBackend = new Promise(resolve => resolve(req.body))
+
+ getBackend.then(backend => {
+ // Creating the backend instance and calling the specific checkConnection.
+ const b = new ExternalBackends()
+ const instance = b.getInstance(backend.type)
+ instance.checkConnection(backend.credentials).then(connection => {
+ res.status(200).send({ success: connection.success, msg: connection.msg })
+ })
+ })
+ },
+
+ // Saves the group / clients assigned object types in the database and sync type.
+ saveSyncSettings: function (req, res) {
+ const id = req.body.id
+ const groups = JSON.stringify(req.body.groups)
+ const clients = JSON.stringify(req.body.clients)
+ const sync = req.body.sync
+ db.backend.findOne({ where: { id: id } }).then(backend => {
+ db.backend.update({ groups: groups, clients: clients, sync: sync }, { where: { id: id } }).then(() => {
+ res.status(200).send()
+ })
+ })
}
}
diff --git a/server/api/clients.js b/server/api/clients.js
index aeb4673..046bced 100644
--- a/server/api/clients.js
+++ b/server/api/clients.js
@@ -2,19 +2,60 @@
var path = require('path')
var db = require(path.join(__appdir, 'lib', 'sequelize'))
-module.exports = {
- get: function (req, res) {
- switch (req.query.action) {
- case 'getInfo':
- db.client.findOne({ where: { id: req.query.id }}).then(client => {
- res.send(client)
- })
- break
- default:
- res.end()
+// GET Requests
+module.exports.get = {
+ getList: function (req, res) {
+ db.client.findAll({ attributes: ['id', 'name'], order: [['name', 'ASC']] }).then(list => {
+ res.send(list)
+ })
+ },
+
+ // get all groups
+ getAll: function (req, res) {
+ db.client.findAll().then(list => {
+ res.send(list)
+ })
+ },
+
+ // get all clients that have no groups
+ getTopLevel: function (req, res) {
+ db.client.findAll({ where: { '$groups.id$': null }, include: ['groups'] }).then(clients => {
+ res.send(clients)
+ })
+ },
+
+ // get name, description, ip, mac and uuid of a client (by id)
+ getClient: function (req, res) {
+ db.client.findOne({ where: { id: req.query.id }, include: ['groups'] }).then(client => {
+ if (client) res.send(client)
+ else res.status(404).end()
+ })
+ }
+}
+
+// POST Requests
+module.exports.post = {
+ // create client or update information of a client (returns id)
+ save: function (req, res) {
+ const id = req.body.id > 0 ? req.body.id : null
+ if (id) {
+ db.client.findOne({ where: { id } }).then(client => {
+ if (client) {
+ var promises = []
+ if (req.body.info) promises.push([client.update(req.body.info)])
+ if (req.body.groupIds) promises.push(client.setGroups(req.body.groupIds))
+ Promise.all(promises).then(() => { res.send({ id }) })
+ } else { res.status(404).end() }
+ })
+ } else {
+ db.client.create(req.body.info).then(client => {
+ if (req.body.groupIds) client.setGroups(req.body.groupIds).then(() => { res.send({ id: client.id }) })
+ })
}
},
- post: function (req, res) {
+ // delete clients
+ delete: function (req, res) {
+ db.client.destroy({ where: { id: req.body.ids } }).then(count => { res.send({ count }) })
}
}
diff --git a/server/api/groups.js b/server/api/groups.js
index 8158d1c..02bfa25 100644
--- a/server/api/groups.js
+++ b/server/api/groups.js
@@ -2,41 +2,97 @@
var path = require('path')
var db = require(path.join(__appdir, 'lib', 'sequelize'))
-module.exports = {
- get: function (req, res) {
- var id = req.query.id > 0 ? req.query.id : null
- switch (req.query.action) {
- case 'getParents':
- db.group.findOne({ where: { id: req.query.id }, include: ['parents']}).then(group => {
- group.getParents().then(parents => {
- res.send(parents.map(x => ({ id: x.id, name: x.name })))
- })
- })
- break
- case 'getSubGroups':
- db.group.findAll({ where: { '$parents.id$': id }, include: ['parents'] }).then(result => {
- res.send(result)
- })
- break
- case 'getClients':
- db.client.findAll({ where: { '$groups.id$': id }, include: ['groups'] }).then(result => {
- res.send(result)
- })
- break
- default:
- res.end()
- }
+// GET Requests
+module.exports.get = {
+ // get a list containing id and name of all groups
+ getList: function (req, res) {
+ db.group.findAll({ attributes: ['id', 'name'], order: [['name', 'ASC']] }).then(list => {
+ res.send(list)
+ })
+ },
+
+ // get all groups
+ getAll: function (req, res) {
+ db.group.findAll().then(list => {
+ res.send(list)
+ })
+ },
+
+ // get all groups that have no parents
+ getTopLevel: function (req, res) {
+ db.group.findAll({ where: { '$parents.id$': null }, include: ['parents'] }).then(groups => {
+ res.send(groups)
+ })
},
- post: function (req, res) {
- var id = req.body.id > 0 ? req.body.id : null
- switch (req.body.action) {
- case 'update':
- if (!id) res.end()
- db.group.update({ name: req.body.name }, { where: { id: id } })
- res.end()
- break
- default:
- res.end()
+
+ // get name, description, parents, subgroups and clients of a group (by id)
+ getGroup: function (req, res) {
+ db.group.findOne({ where: { id: req.query.id }, include: ['parents', 'subgroups', 'clients'] }).then(group => {
+ if (group) res.send(group)
+ else res.status(404).end()
+ })
+ }
+}
+
+// POST Requests
+module.exports.post = {
+ // create group or update information of a group (returns id)
+ save: function (req, res) {
+ const id = req.body.id > 0 ? req.body.id : null
+ if (id) {
+ db.group.findOne({ where: { id } }).then(group => {
+ if (group) {
+ var promises = []
+ if (req.body.info) promises.push([group.update(req.body.info)])
+ if (req.body.parentIds) promises.push(group.setParents(req.body.parentIds))
+ Promise.all(promises).then(() => { res.send({id}) })
+ } else { res.status(404).end() }
+ })
+ } else {
+ db.group.create(req.body.info).then(group => {
+ if (req.body.parentIds) group.setParents(req.body.parentIds).then(() => { res.send({ id: group.id }) })
+ })
}
+ },
+
+ // delete groups
+ delete: function (req, res) {
+ db.group.destroy({ where: { id: req.body.ids } }).then(count => { res.send({ count }) })
+ },
+
+ // remove subgroups from a group
+ removeSubgroups: function (req, res) {
+ db.group.findOne({ where: { id: req.body.id } }).then(group => {
+ if (group) {
+ group.removeSubgroups(req.body.ids).then(() => { res.end() })
+ } else { res.status(404).end() }
+ })
+ },
+
+ // remove clients from a group
+ removeClients: function (req, res) {
+ db.group.findOne({ where: { id: req.body.id } }).then(group => {
+ if (group) {
+ group.removeClients(req.body.ids).then(() => { res.end() })
+ } else { res.status(404).end() }
+ })
+ },
+
+ // add subgroups to a group
+ addSubgroups: function (req, res) {
+ db.group.findOne({ where: { id: req.body.id } }).then(group => {
+ if (group) {
+ group.addSubgroups(req.body.ids).then(() => { res.end() })
+ } else { res.status(404).end() }
+ })
+ },
+
+ // add clients to a group
+ addClients: function (req, res) {
+ db.group.findOne({ where: { id: req.body.id } }).then(group => {
+ if (group) {
+ group.addClients(req.body.ids).then(() => { res.end() })
+ } else { res.status(404).end() }
+ })
}
}
diff --git a/server/api/ipxe-loader.js b/server/api/ipxe-loader.js
deleted file mode 100644
index e75ce72..0000000
--- a/server/api/ipxe-loader.js
+++ /dev/null
@@ -1,42 +0,0 @@
-module.exports = {
- loadScript: function (req, res) {
- res.setHeader('content-type', 'text/plain')
- res.status(200).send(`#!ipxe
-dhcp
-
-:start
-menu Please choose a webserver to load the ipxe menu:
-item pxelnx PxeLinux
-item exit Exit
-item exit0 Exit0
-item exit1 Exit1
-item sh [Shell]
-choose target && goto \${target}
-
-:exit
-exit
-:exit0
-exit 0
-:exit1
-exit 1
-:pxelnx
-# set 210:string https://bas.stfu-kthx.net:8888/
-# chain \${210:string}pxelinux.0 || goto start
-#chain https://bas.stfu-kthx.net:8888/pxelinux.0
-# set next-server bas-stfu-kthx.net:8888
-# set 209:string https://bas.stfu-kthx.net:8888/pxelinux.cfg
-#imgload pxelinux.0
-#boot pxelinux.0
-
-set 209:string pxelinux.cfg/default
-set 210:string bas.stfu-kthx.net
-# chain tftp://bas.stfu-kthx.net/pxelinux.0 || goto start
-kernel tftp://bas.stfu-kthx.net/ldlinux.c32
-imgload tftp://bas.stfu-kthx.net/pxelinux.0
-boot
-
-:sh
-shell
-goto start`)
- }
-}
diff --git a/server/api/ipxe.js b/server/api/ipxe.js
new file mode 100644
index 0000000..3e8dd9a
--- /dev/null
+++ b/server/api/ipxe.js
@@ -0,0 +1,54 @@
+/* global __appdir */
+var path = require('path')
+var shell = require(path.join(__appdir, 'lib', 'shell'))
+
+module.exports.get = {
+ build: function (req, res) {
+ shell.buildIpxe(req, res)
+ },
+ loadScript: function (req, res) {
+ res.setHeader('content-type', 'text/plain')
+ res.status(200).send(`#!ipxe
+dhcp
+
+:start
+menu Please choose a webserver to load the ipxe menu:
+item pxelnx PxeLinux
+item c32boot C32Boot
+item exit Exit
+item exit0 Exit0
+item exit1 Exit1
+item sh [Shell]
+choose target && goto \${target}
+
+:exit
+exit
+:exit0
+exit 0
+:exit1
+exit 1
+:pxelnx
+# set 210:string https://bas.stfu-kthx.net:8888/
+# chain \${210:string}pxelinux.0 || goto start
+# chain https://bas.stfu-kthx.net:8888/pxelinux.0
+# set next-server bas-stfu-kthx.net:8888
+# set 209:string https://bas.stfu-kthx.net:8888/pxelinux.cfg
+# imgload pxelinux.0
+set net0/next-server 192.52.3.91 ||
+set netX/next-server 192.52.3.91 ||
+set next-server 192.52.3.91 ||
+# set 209:string pxelinux.cfg/default
+# set 210:string bas.stfu-kthx.net
+# shell ||
+boot tftp://bas.stfu-kthx.net/pxelinux.0 || goto start
+:c32boot
+set net0/next-server 192.52.3.91 ||
+set netX/next-server 192.52.3.91 ||
+set next-server 192.52.3.91 ||
+boot tftp://bas.stfu-kthx.net/chain.c32 || goto start
+
+:sh
+shell
+goto start`)
+ }
+}
diff --git a/server/app.js b/server/app.js
index d98c0ce..cc5cd21 100644
--- a/server/app.js
+++ b/server/app.js
@@ -27,11 +27,12 @@ app.use(cookieParser())
// ############################################################################
// ########################### setup routes ##################################
-app.use(express.static('public'))
-
var apiRouter = require(path.join(__dirname, 'router'))
app.use('/api', apiRouter)
+app.use(express.static('public'))
+app.use('*', express.static('public'))
+
// ############################################################################
// ######################### handle http errors ###############################
diff --git a/server/ipxe/main.ipxe b/server/ipxe/main.ipxe
index fa1f492..763725a 100644
--- a/server/ipxe/main.ipxe
+++ b/server/ipxe/main.ipxe
@@ -15,7 +15,7 @@ choose target && goto ${target}
:js
set crosscert http://ca.ipxe.org/auto/
-chain https://bas.stfu-kthx.net/api/ipxe-loader/load-script
+chain https://bas.stfu-kthx.net:8888/api/ipxe/loadScript ||
goto start
:uw
chain http://10.4.9.115/boot.php
diff --git a/server/lib/external-backends/backends/another-backend.js b/server/lib/external-backends/backends/another-backend.js
index eb329ae..8f6b717 100644
--- a/server/lib/external-backends/backends/another-backend.js
+++ b/server/lib/external-backends/backends/another-backend.js
@@ -4,6 +4,14 @@ class AnotherBackend extends ExternalBackends {
getCredentials () {
return [{ type: 'text', id: 1, name: 'text 1' }, { type: 'text', id: 2, name: 'text 2' }, { type: 'password', id: 3, name: 'password 1', show: false }, { type: 'password', id: 4, name: 'password 2', show: true }, { type: 'password', id: 5, name: 'password 3', show: false }]
}
+
+ async checkConnection (backend) {
+ return { success: true }
+ }
+
+ getSyncTypes () {
+ return ['THERE', 'ARE', 'NO', 'SYNC', 'TYPES']
+ }
}
module.exports = AnotherBackend
diff --git a/server/lib/external-backends/backends/dummy-backend.js b/server/lib/external-backends/backends/dummy-backend.js
index 6052953..a1704e3 100644
--- a/server/lib/external-backends/backends/dummy-backend.js
+++ b/server/lib/external-backends/backends/dummy-backend.js
@@ -4,6 +4,10 @@ class DummyBackend extends ExternalBackends {
getCredentials () {
return [{ type: 'switch', id: 1, name: 'switch 1', value: false }, { type: 'switch', id: 2, name: 'switch 2', value: false }, { type: 'switch', id: 3, name: 'switch 3', value: true }, { type: 'select', id: 4, name: 'selection 1', items: ['wasd', 'asdf', 'qwertz'] }, { type: 'select', id: 5, name: 'selection 2', items: ['1', '2', '3'] }]
}
+
+ async checkConnection (backend) {
+ return { success: false, msg: 'This is a test where success was intentionally set to false!' }
+ }
}
module.exports = DummyBackend
diff --git a/server/lib/external-backends/backends/idoit-backend.js b/server/lib/external-backends/backends/idoit-backend.js
new file mode 100644
index 0000000..b282c6b
--- /dev/null
+++ b/server/lib/external-backends/backends/idoit-backend.js
@@ -0,0 +1,166 @@
+var ExternalBackends = require('../external-backends.js')
+var axios = require('axios')
+
+class IdoitBackend extends ExternalBackends {
+ // Needed functions
+ getCredentials () {
+ // I do it only needs the API-key.
+ return [
+ { type: 'text', id: 1, name: 'API url', icon: 'link' },
+ { type: 'password', id: 2, name: 'API token', icon: 'vpn_key', show: false },
+ {
+ type: 'switch',
+ id: 3,
+ name: 'Login',
+ icon: 'lock_open',
+ elements: [
+ { type: 'text', id: 4, name: 'username', icon: 'person_outline' },
+ { type: 'password', id: 5, name: 'password', icon: 'lock', show: false }
+ ]
+ }
+ ]
+ }
+
+ async checkConnection (credentials) {
+ var c = this.mapCredentials(credentials)
+ return this.getSession(c)
+ }
+
+ // Return the list of object types created in iDoIT.
+ async getObjectTypes (credentials) {
+ var c = this.mapCredentials(credentials)
+ var login = await this.getSession(c)
+ var sid = login.data.result['session-id']
+
+ // Headers
+ var headers = {
+ 'X-RPC-Auth-Session': sid
+ }
+
+ // Params
+ var params = {
+ 'apikey': c.apikey,
+ 'language': 'en'
+ }
+
+ var result = {}
+ result.types = await this.axiosRequest(c.url, 'cmdb.object_types', params, headers)
+ result.types = result.types.data.result
+
+ var types = []
+ result.types.forEach(type => {
+ types.push({ id: type.id, title: type.title })
+ })
+
+ return types
+ }
+
+ getSyncTypes () {
+ return ['None', 'Two-Way', 'Upload Only', 'Upload Then Delete', 'Upload Mirror', 'Download Only', 'Download Then Delete', 'Download Mirror']
+ }
+
+ // Optional functions e.g. helperfunctions or testing stuff.
+
+ // Helper function, to map the array of credential objects into a single js object.
+ mapCredentials (credentials) {
+ const c = JSON.parse(credentials)
+ const login = c.find(x => x.id === 3)
+ var mapped = {
+ url: c.find(x => x.id === 1).value,
+ apikey: c.find(x => x.id === 2).value,
+ login: login.value
+ }
+
+ if (mapped.login) {
+ mapped.username = login.elements.find(x => x.id === 4).value
+ mapped.password = login.elements.find(x => x.id === 5).value
+ }
+ return mapped
+ }
+
+ async getRoomdata (credentials, oid) {
+ var c = this.mapCredentials(credentials)
+ var login = await this.getSession(c)
+ var sid = login.data.result['session-id']
+
+ // Headers
+ var headers = {
+ 'X-RPC-Auth-Session': sid
+ }
+
+ // Params
+ var params = {
+ 'id': oid,
+ 'apikey': c.apikey,
+ 'language': 'en'
+ }
+
+ var result = {}
+ result.object = await this.axiosRequest(c.url, 'cmdb.object.read', params, headers)
+ result.childs = await this.axiosRequest(c.url, 'cmdb.location_tree', params, headers)
+ result.object = result.object.data.result
+ result.childs = result.childs.data.result
+
+ return result
+ }
+
+ // Username and password are optional.
+ async getSession (credentials) {
+ // Headers
+ var headers = {}
+ // Optional credentials
+ if (credentials.login) {
+ headers['X-RPC-Auth-Username'] = credentials.username
+ headers['X-RPC-Auth-Password'] = credentials.password
+ }
+
+ // Params
+ var params = {
+ 'apikey': credentials.apikey,
+ 'language': 'en'
+ }
+
+ // Make a login request and see if we are authenticated.
+ return this.axiosRequest(credentials.url, 'idoit.login', params, headers)
+ }
+
+ // Helper function to make the axios http/https requests to reduced copy pasta code in this backend. Including the error handling.
+ async axiosRequest (url, method, params, headers) {
+ const body = {
+ 'version': '2.0',
+ 'method': method,
+ 'params': params,
+ 'id': 1
+ }
+
+ var config = {
+ timeout: 30000,
+ headers: headers
+ }
+ config.headers['Content-Type'] = 'application/json'
+
+ var response = await axios.post(url, body, config)
+ .then(response => {
+ return response
+ })
+ .catch(error => {
+ console.log(error)
+ return error.response ? error.response : { status: 900, statusText: 'Request failed timeout' }
+ })
+ // Axios error handling
+ if (response.status !== 200) {
+ return { success: false, error: response.status, msg: response.statusText }
+ }
+
+ // iDoIT error handling.
+ if (response.data.result) {
+ return { success: true, data: response.data }
+ } else if (response.data.error) {
+ return { success: false, error: response.data.error.message, msg: response.data.error.data.error }
+ } else {
+ return { success: false, msg: 'UNNOWN ERROR' }
+ }
+ }
+}
+
+module.exports = IdoitBackend
diff --git a/server/lib/external-backends/backends/template-backend.js b/server/lib/external-backends/backends/template-backend.js
index 19f1d76..4e5098d 100644
--- a/server/lib/external-backends/backends/template-backend.js
+++ b/server/lib/external-backends/backends/template-backend.js
@@ -4,6 +4,19 @@ class TemplateBackend extends ExternalBackends {
getCredentials () {
return [{ type: 'text', id: 1, name: 'text test', icon: 'bug_report' }, { type: 'password', id: 2, name: 'password test', show: true }, { type: 'password', id: 3, name: 'password test nr2', show: false }, { type: 'switch', id: 4, name: 'bool test', value: false }, { type: 'select', id: 5, name: 'selection test', items: ['wasd', 'asdf', 'qwertz'] }]
}
+
+ async checkConnection (backend) {
+ var result = await x()
+ return result
+ }
+}
+
+function x () {
+ return new Promise(resolve => {
+ setTimeout(() => {
+ resolve({ success: true })
+ }, 5000)
+ })
}
module.exports = TemplateBackend
diff --git a/server/lib/external-backends/external-backends.js b/server/lib/external-backends/external-backends.js
index 0bf891e..be32c13 100644
--- a/server/lib/external-backends/external-backends.js
+++ b/server/lib/external-backends/external-backends.js
@@ -9,7 +9,8 @@ class ExternalBackends {
}
getCredentials () {
- return 'If this method gets called the backend class has NOT IMPLEMENTED the getCredentials method!'
+ console.log('If this method gets called the backend class has NOT IMPLEMENTED the getCredentials method!')
+ return null
}
getInstance (type) {
@@ -25,6 +26,20 @@ class ExternalBackends {
const backend = new (require(path.join(__appdir, 'lib', 'external-backends', 'backends', bType)))()
return backend
}
+
+ getSyncTypes () {
+ return []
+ }
+
+ async checkConnection (backend) {
+ console.log('If this method gets called the backend class has NOT IMPLEMENTED the checkConnection method!')
+ return null
+ }
+
+ // Return an empty array [] if the backends doesn't have such a function.
+ async getObjectTypes (credentials) {
+ return []
+ }
}
module.exports = ExternalBackends
diff --git a/server/lib/shell.js b/server/lib/shell.js
index 311af1d..e0782f1 100644
--- a/server/lib/shell.js
+++ b/server/lib/shell.js
@@ -4,7 +4,7 @@ var shell = require('shelljs')
var ipxeGIT = 'git://git.ipxe.org/ipxe.git'
module.exports = {
- buildIPXE: function (req, res) {
+ buildIpxe: function (req, res) {
if (!shell.which('git')) {
return res.status(500).send({ status: 'GIT_MISSING', error_message: 'Please install git on the server.' })
}
diff --git a/server/migrations/20180715193710-create-backend.js b/server/migrations/20180715193710-create-backend.js
index e89362e..98f5476 100644
--- a/server/migrations/20180715193710-create-backend.js
+++ b/server/migrations/20180715193710-create-backend.js
@@ -15,7 +15,22 @@ module.exports = {
type: Sequelize.STRING
},
credentials: {
- type: Sequelize.STRING(2048)
+ allowNull: false,
+ type: Sequelize.STRING(2048),
+ defaultValue: '[]'
+ },
+ groups: {
+ allowNull: false,
+ type: Sequelize.STRING(4096),
+ defaultValue: '[]'
+ },
+ clients: {
+ allowNull: false,
+ type: Sequelize.STRING(4096),
+ defaultValue: '[]'
+ },
+ sync: {
+ type: Sequelize.STRING(1024)
}
})
},
diff --git a/server/migrations/20180717132233-create-group.js b/server/migrations/20180717132233-create-group.js
index 720a1e7..49088dd 100644
--- a/server/migrations/20180717132233-create-group.js
+++ b/server/migrations/20180717132233-create-group.js
@@ -10,6 +10,9 @@ module.exports = {
},
name: {
type: Sequelize.STRING
+ },
+ description: {
+ type: Sequelize.STRING(2048)
}
})
},
diff --git a/server/migrations/20180717132333-create-client.js b/server/migrations/20180717132333-create-client.js
index 79552c4..d374b22 100644
--- a/server/migrations/20180717132333-create-client.js
+++ b/server/migrations/20180717132333-create-client.js
@@ -11,6 +11,9 @@ module.exports = {
name: {
type: Sequelize.STRING
},
+ description: {
+ type: Sequelize.STRING(2048)
+ },
ip: {
type: Sequelize.STRING
},
diff --git a/server/migrations/20180717202333-create-group_x_group.js b/server/migrations/20180717202333-create-group_x_group.js
index 4263f9a..298c2fb 100644
--- a/server/migrations/20180717202333-create-group_x_group.js
+++ b/server/migrations/20180717202333-create-group_x_group.js
@@ -6,6 +6,7 @@ module.exports = {
primaryKey: true,
allowNull: false,
type: Sequelize.INTEGER,
+ onDelete: 'cascade',
references: {
model: 'groups',
key: 'id'
@@ -15,6 +16,7 @@ module.exports = {
primaryKey: true,
allowNull: false,
type: Sequelize.INTEGER,
+ onDelete: 'cascade',
references: {
model: 'groups',
key: 'id'
diff --git a/server/migrations/20180717202533-create-group_x_client.js b/server/migrations/20180717202533-create-group_x_client.js
index e3bd490..7564618 100644
--- a/server/migrations/20180717202533-create-group_x_client.js
+++ b/server/migrations/20180717202533-create-group_x_client.js
@@ -6,6 +6,7 @@ module.exports = {
primaryKey: true,
allowNull: false,
type: Sequelize.INTEGER,
+ onDelete: 'cascade',
references: {
model: 'groups',
key: 'id'
@@ -15,6 +16,7 @@ module.exports = {
primaryKey: true,
allowNull: false,
type: Sequelize.INTEGER,
+ onDelete: 'cascade',
references: {
model: 'clients',
key: 'id'
diff --git a/server/models/backend.js b/server/models/backend.js
index 4ed5fce..62b936a 100644
--- a/server/models/backend.js
+++ b/server/models/backend.js
@@ -9,7 +9,24 @@ module.exports = (sequelize, DataTypes) => {
},
name: DataTypes.STRING,
type: DataTypes.STRING,
- credentials: DataTypes.STRING(2048)
+ credentials: {
+ allowNull: false,
+ type: DataTypes.STRING(2048),
+ defaultValue: '[]'
+ },
+ groups: {
+ allowNull: false,
+ type: DataTypes.STRING(4096),
+ defaultValue: '[]'
+ },
+ clients: {
+ allowNull: false,
+ type: DataTypes.STRING(4096),
+ defaultValue: '[]'
+ },
+ sync: {
+ type: DataTypes.STRING(1024)
+ }
}, {
timestamps: false
})
diff --git a/server/models/client.js b/server/models/client.js
index ad3bc28..5789788 100644
--- a/server/models/client.js
+++ b/server/models/client.js
@@ -8,15 +8,16 @@ module.exports = (sequelize, DataTypes) => {
type: DataTypes.INTEGER
},
name: DataTypes.STRING,
+ description: DataTypes.STRING(2048),
ip: DataTypes.STRING,
mac: DataTypes.STRING,
uuid: DataTypes.STRING
}, {
timestamps: false
})
- var GroupXClient = sequelize.define('group_x_client', {}, { timestamps: false, freezeTableName: true })
client.associate = function (models) {
- client.belongsToMany(models.group, { as: 'groups', through: GroupXClient, foreignKey: 'clientId', otherKey: 'groupId'})
+ var GroupXClient = sequelize.define('group_x_client', {}, { timestamps: false, freezeTableName: true })
+ client.belongsToMany(models.group, { as: 'groups', through: GroupXClient, foreignKey: 'clientId', otherKey: 'groupId' })
}
return client
}
diff --git a/server/models/group.js b/server/models/group.js
index 9151db5..62a5665 100644
--- a/server/models/group.js
+++ b/server/models/group.js
@@ -7,13 +7,17 @@ module.exports = (sequelize, DataTypes) => {
primaryKey: true,
type: DataTypes.INTEGER
},
- name: DataTypes.STRING
+ name: DataTypes.STRING,
+ description: DataTypes.STRING(2048)
}, {
timestamps: false
})
- var GroupXGroup = sequelize.define('group_x_group', {}, { timestamps: false, freezeTableName: true })
group.associate = function (models) {
- group.belongsToMany(group, { as: 'parents', through: GroupXGroup, foreignKey: 'childId', otherKey: 'parentId'})
+ var GroupXGroup = sequelize.define('group_x_group', {}, { timestamps: false, freezeTableName: true })
+ var GroupXClient = sequelize.define('group_x_client', {}, { timestamps: false, freezeTableName: true })
+ group.belongsToMany(group, { as: 'parents', through: GroupXGroup, foreignKey: 'childId', otherKey: 'parentId' })
+ group.belongsToMany(group, { as: 'subgroups', through: GroupXGroup, foreignKey: 'parentId', otherKey: 'childId' })
+ group.belongsToMany(models.client, { as: 'clients', through: GroupXClient, foreignKey: 'groupId', otherKey: 'clientId' })
}
return group
}
diff --git a/server/package-lock.json b/server/package-lock.json
index 96ee9be..3af2294 100644
--- a/server/package-lock.json
+++ b/server/package-lock.json
@@ -129,6 +129,15 @@
"resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
"integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0="
},
+ "axios": {
+ "version": "0.18.0",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-0.18.0.tgz",
+ "integrity": "sha1-MtU+SFHv3AoRmTts0AB4nXDAUQI=",
+ "requires": {
+ "follow-redirects": "^1.3.0",
+ "is-buffer": "^1.1.5"
+ }
+ },
"babel-code-frame": {
"version": "6.26.0",
"resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz",
@@ -1125,6 +1134,14 @@
"write": "^0.2.1"
}
},
+ "follow-redirects": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.1.tgz",
+ "integrity": "sha512-v9GI1hpaqq1ZZR6pBD1+kI7O24PhDvNGNodjS3MdcEqyrahCp8zbtpv+2B/krUnSmUH80lbAS7MrdeK5IylgKg==",
+ "requires": {
+ "debug": "^3.1.0"
+ }
+ },
"foreach": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz",
@@ -1363,6 +1380,11 @@
"resolved": "https://registry.npmjs.org/is-bluebird/-/is-bluebird-1.0.2.tgz",
"integrity": "sha1-CWQ5Bg9KpBGr7hkUOoTWpVNG1uI="
},
+ "is-buffer": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
+ },
"is-builtin-module": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz",
diff --git a/server/package.json b/server/package.json
index 247a12e..0ad1ccc 100644
--- a/server/package.json
+++ b/server/package.json
@@ -7,6 +7,7 @@
"start": "node ./bin/www"
},
"dependencies": {
+ "axios": "^0.18.0",
"compression": "^1.7.2",
"cookie-parser": "^1.4.3",
"debug": "^3.1.0",
diff --git a/server/router.js b/server/router.js
index bde35a8..53caca8 100644
--- a/server/router.js
+++ b/server/router.js
@@ -10,45 +10,40 @@ router.post('/signup', auth.signup)
router.post('/logout', auth.logout)
router.post('/changepassword', auth.changePassword)
+// Public callable functions.
+var ipxe = require(path.join(__dirname, 'api', 'ipxe'))
+router.get('/ipxe/loadScript', ipxe.get.loadScript)
+
+// ############ Legacy Code: TODO(Chris): Rework to api and get/post or delete! ############
// User API
var user = require(path.join(__dirname, 'api', 'user'))
router.get('/user/info', auth.verifyToken, user.info)
-// Groups API
-var groups = require(path.join(__dirname, 'api', 'groups'))
-router.get('/groups', groups.get)
-router.post('/groups', groups.post)
-
-// Clients API
-var clients = require(path.join(__dirname, 'api', 'clients'))
-router.get('/clients', clients.get)
-router.post('/clients', clients.post)
-
// Permissions API
var permissions = require(path.join(__dirname, 'api', 'permissions'))
router.get('/getRolesByUserid', permissions.getRolesByUserid)
router.post('/getRoleById', auth.verifyToken, permissions.getRoleById)
-// Shell API
-var shell = require(path.join(__dirname, 'lib', 'shell'))
-router.get('/shell/buildipxe', shell.buildIPXE)
-
-// Nodemailer API
-var nodemailer = require(path.join(__dirname, 'lib', 'nodemailer'))
-router.get('/mail/send', nodemailer.sendMail)
-
-// External backends API
-var backends = require(path.join(__dirname, 'api', 'backends'))
-router.get('/backends/getCredentialsByType', auth.verifyToken, backends.getCredentialsByType)
-router.get('/backends/getBackendInfoById', auth.verifyToken, backends.getBackendInfoById)
-router.get('/backends/getBackendList', auth.verifyToken, backends.getBackendList)
-router.get('/backends/getBackendTypes', backends.getBackendTypes)
-router.get('/backends/checkConnection', auth.verifyToken, backends.checkConnection)
-router.post('/backends/saveBackend', auth.verifyToken, backends.saveBackend)
-router.post('/backends/deleteBackends', auth.verifyToken, backends.deleteBackends)
-
-// Load ipxe scipts API
-var ipxeloader = require(path.join(__dirname, 'api', 'ipxe-loader'))
-router.get('/ipxe-loader/load-script', ipxeloader.loadScript)
+// ############################################################################
+
+// Dynamic API routes
+function mapApi (method) {
+ return function (req, res) {
+ var api = require(path.join(__dirname, 'api', req.params.api))
+ if (method in api && req.params.action in api[method]) {
+ api[method][req.params.action](req, res)
+ } else {
+ res.status(501).end()
+ }
+ }
+}
+
+// Every API can be called with /<api>/<action>
+router.get('/:api/:action', auth.verifyToken, mapApi('get'))
+router.post('/:api/:action', auth.verifyToken, mapApi('post'))
+
+router.use('*', (req, res) => {
+ res.status(404).end()
+})
module.exports = router