From e5e3675bebd2a6fbb5b5ffaf4403c4039b25a5ea Mon Sep 17 00:00:00 2001
From: Student User <student@workstation.lab.example.com>
Date: Fri, 02 Aug 2019 21:48:17 +0200
Subject: [PATCH] add sample for ch10s03 lab

---
 todo-backend/controllers/items.js      |  131 +++++++++++++++++++++
 todo-backend/models/items.js           |  127 +++++++++++++++++++++
 todo-backend/controllers/serverinfo.js |   29 ++++
 todo-backend/package.json              |   16 ++
 todo-backend/models/db.js              |   10 +
 todo-backend/app.js                    |   36 ++++++
 6 files changed, 349 insertions(+), 0 deletions(-)

diff --git a/todo-backend/app.js b/todo-backend/app.js
new file mode 100644
index 0000000..af05312
--- /dev/null
+++ b/todo-backend/app.js
@@ -0,0 +1,36 @@
+var restify = require('restify');
+
+var controller = require('./controllers/items');
+var serverinfo = require('./controllers/serverinfo');
+
+var db = require('./models/db');
+var model = require('./models/items');
+
+model.connect(db.params, function(err) {
+    if (err) throw err;
+});
+
+var server = restify.createServer() 
+    .use(restify.fullResponse())
+    .use(restify.queryParser())
+    .use(restify.bodyParser())
+    .use(restify.CORS());;
+    
+controller.context(server, '/todo/api', model); 
+serverinfo.context(server, '/todo/api');
+
+var port = process.env.PORT || 8080;
+server.listen(port, function (err) {
+    if (err)
+        console.error(err);
+    else
+        console.log('App is ready at : ' + port);
+});
+
+
+/* 
+process.on('uncaughtException', function (err) {
+    console.error(JSON.parse(JSON.stringify(err, ['stack', 'message', 'inner'], 2)))
+});
+*/    
+
diff --git a/todo-backend/controllers/items.js b/todo-backend/controllers/items.js
new file mode 100644
index 0000000..3a6eeb2
--- /dev/null
+++ b/todo-backend/controllers/items.js
@@ -0,0 +1,131 @@
+
+var model = undefined;
+
+exports.context = function(server, path, itemsModel) {
+    if (!server)
+        done('has to provide a restify server object');
+        
+    var context = "/items";
+    if (path)
+        context = path + context;
+        
+    server.get(context + '/', this.list);
+    server.get(context + '/:id', this.read);
+    server.get(context + '-count', this.count);
+    server.post(context + '/', this.save);
+    server.del(context + '/:id', this.destroy);
+    
+    model = itemsModel;
+};
+
+exports.list = function(req, res, next) {
+    var page_no = req.query.page || 1;
+    var sortField = req.query.sortFields || "id";
+    var sortDirection = req.query.sortDirections || "asc";
+
+    model.listAll(page_no, sortField, sortDirection, function(err, items) {
+        if (err) {
+            res.send(err);
+        }
+        else {
+            if (items) {
+                model.countAll(function(err, n) {
+                    if (err) {
+                        res.send(err);
+                    }
+                    else {
+                        if (n) {
+                            var page = { 
+                                "currentPage" : page_no,
+                                "list" : items,
+                                "pageSize" : 10,
+                                "sortDirections" : sortDirection,
+                                "sortFields" : sortField,
+                                "totalResults" : n
+                            };
+                            res.json(page);
+                            next();
+                        }
+                    }
+                });
+            }
+            else {
+                res.send(err);
+            }
+        }
+    })
+};
+
+exports.read = function(req, res, next) {
+    var key = req.params.id;
+    model.read(key, function(err, item) {
+        if (err) {
+            res.send(err);
+        }
+        else {
+            if (item) {
+                res.json(item);
+                next();
+            }
+            else {
+                res.send(err);
+            }
+        }
+    })
+};
+
+
+exports.count = function(req, res, next) {
+    model.countAll(function(err, n) {
+        if (err) {
+            res.send(err);
+        } 
+        else {
+            var page = { 
+              count: n
+            };
+            res.json(page)
+            next();
+        }
+    })
+};
+
+
+exports.save = function(req, res, next) {
+    if (req.params.id) {
+        model.update(req.params.id, req.params.description, req.params.done, function(err, item) {
+            if (err) {
+                res.send(err);
+            }
+            else {
+                res.json(item);
+                next();
+            }
+        });
+    }
+    else {
+        model.create(req.params.description, req.params.done, function(err, item) {
+            if (err) {
+                res.send(err);
+            }
+            else {
+                res.json(item);
+                next();
+            }
+        });
+    }
+};
+
+
+exports.destroy = function(req, res, next) {
+    if (req.params.id) {
+        model.destroy(req.params.id, function(err, item) {
+            if (err) {
+                res.send(err);
+            }
+            else {
+                res.json(item);
+            }
+        });
+    }
+}
diff --git a/todo-backend/controllers/serverinfo.js b/todo-backend/controllers/serverinfo.js
new file mode 100644
index 0000000..00f4b58
--- /dev/null
+++ b/todo-backend/controllers/serverinfo.js
@@ -0,0 +1,29 @@
+var os = require('os');
+
+exports.context = function(server, path) {
+    if (!server)
+        done('has to provide a restify server object');
+        
+    server.get(path + '/host', this.serverInfo);
+};
+
+exports.serverInfo = function(req, res, next) {
+    var address;
+    var ifaces = os.networkInterfaces();
+
+    for (var dev in ifaces) {
+        var iface = ifaces[dev].filter(function(details) {
+            return details.family === 'IPv4' && details.internal === false;
+        });
+        if (iface.length > 0)
+            address = iface[0].address;
+    }
+
+    var reply = {
+        ip: address,
+        hostname: os.hostname()
+    };
+    res.json(reply);
+    next();
+};
+
diff --git a/todo-backend/models/db.js b/todo-backend/models/db.js
new file mode 100644
index 0000000..1135d1d
--- /dev/null
+++ b/todo-backend/models/db.js
@@ -0,0 +1,10 @@
+
+module.exports.params = {
+  dbname: process.env.DATABASE_NAME,
+  username: process.env.DATABASE_USER,
+  password: process.env.DATABASE_PASSWORD,
+  params: {
+      host: process.env.DATABASE_SVC,
+      dialect: 'mysql',
+  }
+};
diff --git a/todo-backend/models/items.js b/todo-backend/models/items.js
new file mode 100644
index 0000000..ef35e81
--- /dev/null
+++ b/todo-backend/models/items.js
@@ -0,0 +1,127 @@
+var Sequelize = require("sequelize");
+
+var Item = undefined;
+
+module.exports.connect = function(params, callback) {
+    var sequlz = new Sequelize(
+        params.dbname, params.username, params.password,
+        params.params);
+    Item = sequlz.define('Item', {
+        id: { type: Sequelize.BIGINT,
+            primaryKey: true, unique: true, allowNull: false,
+            autoIncrement: true },
+        description: { type: Sequelize.STRING,
+            allowNull: true },
+        done: { type: Sequelize.BOOLEAN,
+            allowNull: true }
+    }, {
+        timestamps: false,
+        freezeTableName: true
+    });
+    
+    if (process.env.DATABASE_INIT == 'true') {
+        Item.sync({ force: true }).then(function() {
+            callback();
+        }).catch(function(err) {
+            callback(err);
+        });
+    }
+}
+
+exports.disconnect = function(callback) {
+    //XXX shouln'd to something to close or release the db connection?
+    callback();
+}
+
+exports.create = function(description, done, callback) {
+    Item.create({
+        //id: id,
+        description: description,
+        done: (done) ? true : false
+    }).then(function(item) {
+        callback(null, item);
+    }).catch(function(err) {
+        callback(err);
+    });
+}
+
+exports.update = function(key, description, done, callback) {
+    Item.find({ where:{ id: key } }).then(function(item) {
+        if (!item) {
+            callback(new Error("Nothing found for key " + key));
+        }
+        else {
+            item.updateAttributes({
+                description: description,
+                done: (done) ? true : false
+            }).then(function() {
+                callback(null, item);
+            }).error(function(err) {
+                callback(err);
+            });
+        }
+    }).catch(function(err) {
+        callback(err);
+    });
+}
+
+
+exports.read = function(key, callback) {
+    Item.find({ where:{ id: key } }).then(function(item) {
+        if (!item) {
+            callback(new Error("Nothing found for key " + key));
+        }
+        else {
+            //XXX why recreating the item object?
+            callback(null, {
+                id: item.id,
+                description: item.description,
+                done: item.done
+            });
+        }
+    }).catch(function(err) {
+        callback(err);
+    });
+}
+
+exports.destroy = function(key, callback) {
+    Item.find({ where:{ id: key } }).then(function(item) {
+        if (!item) {
+            callback(new Error("Nothing found for " + key));
+        }
+        else {
+            item.destroy().then(function() {
+                callback(null, item);
+            }).error(function(err) {
+                callback(err);
+            });
+        }
+    }).catch(function(err) {
+        callback(err);
+    });
+}
+
+exports.countAll = function(callback) {
+    Item.findAll({
+        attributes: [[Sequelize.fn('COUNT', Sequelize.col('id')), 'no_items']]
+    }).then(function(n) {
+        callback(null, n[0].get('no_items'));
+    }).catch(function(err) {
+        callback(err);
+    });
+}
+
+exports.listAll = function(page, sortField, sortDirection, callback) {
+    Item.findAll({ offset: 10 * (page - 1), limit: 10,  order: [[sortField, sortDirection]] }).then(function(items) {
+        var theitems = [];
+        items.forEach(function(item) {
+            //XXX why recreating the item objects for theitems?
+            theitems.push({
+                id: item.id, description: item.description, done: item.done });
+        });
+        callback(null, theitems);
+    }).catch(function(err) {
+        callback(err);
+    });
+}
+
diff --git a/todo-backend/package.json b/todo-backend/package.json
new file mode 100644
index 0000000..1d197b2
--- /dev/null
+++ b/todo-backend/package.json
@@ -0,0 +1,16 @@
+{
+  "name": "todo-single",
+  "description": "single container version of the todoapp",
+  "version": "0.0.2",
+  "private": true,
+  "author": "Red Hat Training",
+  "license": "ASL",
+  "scripts": {
+    "start": "node app.js"
+  },
+  "dependencies": {
+    "restify": "4.0.3",
+    "sequelize": "3.14.2",
+    "mysql": "2.9.0"
+  }
+}

--
Gitblit v1.9.3