diff --git a/.travis.yml b/.travis.yml index 68c654c..ab08c0e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,6 +11,7 @@ addons: services: - mysql - postgresql + - elasticsearch env: global: @@ -42,6 +43,7 @@ install: - luarocks install luacov - luarocks install luacov-coveralls - luarocks make rockspecs/sailor-current-1.rockspec + - luarocks install --server=http://luarocks.org/dev elasticsearch before_script: - source .travis/setdatabases.sh diff --git a/docs/admin_center.md b/docs/admin_center.md new file mode 100644 index 0000000..79d8920 --- /dev/null +++ b/docs/admin_center.md @@ -0,0 +1,36 @@ +##Admin Center + +The controller and views for admin center are pre loaded with the blank-app. So, when you create a new app using `sailor create "app_name"` these files are within the new folders. + +###Admin center structure + +There is one controller named `admin.lua` and a views folder named "admin" inside which are three files. One is `dashboard.lp` which is the views file for the autogen and config editor functions. `index.lp` is for logging into the admin center. Third file is `error.lp`. + +###Getting started +First open `conf/conf.lua`. Change these two parameters: + + -- the default value for this is "false" + enable_admin = "true" + + -- the defaullt password is empty + admin_password = "someDifficultPassword" + +After running the `start-server.lua`, visit here. Enter the password set it in the config file in the above setup. You would be +re-directed to `localhost:8000/?r=admin/dashboard`. +The autogen functions are located on the left and the fields from the config file are on the right. You can edit any of the config editor values and then press `submit` button +at the bottom of the screen. + +###Autogen Functions + +The first autogen function is to Generate a model based on a table existing in the database. This is a very handy function to automatically generate the model file. +Enter the table name and press enter. + +There would be a success message ` Model generated with success.`. +To create the methods for CRUD operations in the controller, use the next autogen function. +To Generate CRUD, enter the name of the `model` created in the previous step. This would be same as the name of the table. + +###Config editor + +Config editor is basically a long form which when saved, writes data into the config file. The existing values can be edited and then saved at the end. The main file edited here is `conf/conf.lua`. + +After making necessary changes, don't forget to logout and also disable admin in production servers. diff --git a/docs/manual_ES_model.md b/docs/manual_ES_model.md new file mode 100644 index 0000000..b7e2d8c --- /dev/null +++ b/docs/manual_ES_model.md @@ -0,0 +1,147 @@ +##Reference Manual +### Elastic Search Model + +This module makes it possible to store, retrieve and search data from Elasticsearch . It uses the elasticsearch-lua client for Lua. Refer the client here to know the parameters which can be sent through the model functions if any. Return responses are also same as the one offered by this client. + +###Installation and getting started. + +To get started, install the elasticsearch-lua rock using + + luarocks install --server=http://luarocks.org/dev elasticsearch + +Make sure you have elasticsearch installed and running. Refer to the instructions given on the official website. + +The `es_model.lua` file is the main module. After importing "es_model" we proceed to create a new instance of the model. There should be a file inside models/ which contains the keys and types defined for the particular model. + + local es_model = require "sailor.es_model" + -- test.lua should be inside models/ folder. + local contact = es.model.new("test") + +Now, you can assign attributes to `contact` like + + contact.name = "test name" + contact.email = "test@test.com" + +And save it using, + + msg , code = contact.save{id = 1} + +The `arg` represented here is named arguments which have to be passed into the function. For list of args that can be passed check the elasticsearch-lua reference. + +The return value for these functions is same as elasticsearch-lua. +Example: + + local msg , err = contact.save{id = 2, routing = "test.com", timout = "2m"} + +If the call succeeds then `msg` contains the result table and `err` contains the status code. +If the call fails then `msg` contains `nil` and `err` contains the error message. + +###Elasticsearch administration + +To use administrative functionalities, + + local es_model = require("sailor.db.es_model") + -- To use the namespaces + local res, err = es_model.client.cluster:stats() + +Check this page for more functions. + +###model.save(arg) + +This function takes a list of paramters which would be same as for the elasticsearch-lua client. It saves the attributes assigned to the model if the `body` parameter is not present. Else it just saves the array passsed in the body parameter. The below example saves the `name` attribute into the ES + + contact.name = "test" + contact.save = {id = 1} + +The index can be preset in the config file which can also be over written when passing the parameters. + +###model.getCount() + +This functions returns the number of documents present in the given index and type. You don't need to pass any parameter. +Example: + + local count = contact.getCount() + +###model.getAll() + +This function returns a table of all the documents present in the given index and type. No parameter is required. It uses the `client:search()` function from elasticsearch-lua on the inside. + + local data, err = contact.getAll() + +###model.update(arg) + +This is used for updating documents already in the index. The id has to be specified. + + contact.update{id = 1, body = {doc = { name = "new name" }}} + +###model.delete(arg) + +Deletes a particular document with the given id. + + contact.delete{id = 1} + +###model.search(arg) + +Search the given index and type. The arg list supports a lot of parameters. Read more about it here. + + contact.search{q = "queryString", size = 15} + +###model.get(arg) + +Get's documents from the database based on the parameters provided. Full list of args can be found here. + + contact.get{id = 1, fields = {name, email}} + +###model.bulkIndex(arg) + +For indexing multiple documents at once. Uses `client:bulk()`. The index and type have to set in the parameters. For a list of parameters check here. + + contact.bulkIndex{ + body = { + -- First action + { + index = { + ["_index"] = "my_index1", + ["_type"] = "my_type1" + } + }, + -- First body + { + my_key1 = "my_value1", + }, + -- Second action + { + index = { + ["_index"] = "my_index2", + ["_type"] = "my_type2" + } + }, + -- Second body + { + my_key2 = "my_value2", + } + } + } + +###model.mget(arg) + +You can get multiple documents in the form of nested table using the `client:mget()`. The allowed parameters are here. + + contact.mget{ + body = { + docs = { + -- First document + { + ["_index"] = "my_index1", + ["_type"] = "my_type1", + ["_id"] = "my_id1" + }, + -- Second document + { + ["_index"] = "my_index2", + ["_type"] = "my_type2", + ["_id"] = "my_id2" + } + } + } + } \ No newline at end of file diff --git a/docs/tutorial_testing.md b/docs/tutorial_testing.md index 084c65a..cb60137 100644 --- a/docs/tutorial_testing.md +++ b/docs/tutorial_testing.md @@ -51,7 +51,7 @@ Let's suppose we have a User model and we want to unit test some of the User met The fixture is a regular Lua script that will be required. This for multiple possibilities, such as making loops for inserting many entries, as long as in the end you return a table containing samples of your model. -After creating your fixture, you must add this on the bottom of your bootstrap file so they are loaded before running your tests. +After creating your fixture, you must add this on the bottom of your bootstrap file so they are loaded before running your tests. Also don't forget to set the package.path to the sailor directory you want to test. --/tests/bootstrap.lua ... diff --git a/rockspecs/sailor-current-1.rockspec b/rockspecs/sailor-current-1.rockspec index 8929ca2..8af26da 100644 --- a/rockspecs/sailor-current-1.rockspec +++ b/rockspecs/sailor-current-1.rockspec @@ -33,9 +33,10 @@ build = { modules = { sailor = "src/sailor.lua", ['sailor.access'] = "src/sailor/access.lua", - ['sailor.autogen'] = "src/sailor/autogen.lua", ['sailor.cookie'] = "src/sailor/cookie.lua", ['sailor.db'] = "src/sailor/db.lua", + ['sailor.autogen'] = "src/sailor/autogen.lua", + ['sailor.db.es_model'] = "src/sailor/db/es_model.lua", ['sailor.db.resty_mysql'] = "src/sailor/db/resty_mysql.lua", ['sailor.db.luasql_common'] = "src/sailor/db/luasql_common.lua", ['sailor.blank-app.conf.conf'] = "src/sailor/blank-app/conf/conf.lua", diff --git a/src/sailor.lua b/src/sailor.lua index 8e07f36..fef242c 100755 --- a/src/sailor.lua +++ b/src/sailor.lua @@ -103,17 +103,6 @@ function sailor.init(r) return p end - --- Auxiliary function to open the autogen page for models and CRUDs --- page: our page object -local function autogen(page) - local autogen = require "sailor.autogen" - - local src = autogen.gen() - src = lp.translate(src) - page:render('sailor/autogen',{page=page},src) -end - -- Gets parameter from url query and made by mod rewrite and reassembles into page.GET -- TODO - improve local function apache_friendly_url(page) @@ -174,14 +163,6 @@ function sailor.route(page) controller, action = match(route_name, "([^/]+)/?([^/]*)") end - if controller == "autogen" then - if conf.sailor.enable_autogen then - local _,res = xpcall(function () autogen(page) end, error_handler) - return res or httpd.OK or page.r.status or 200 - end - return error_404() - end - local ctr local _, res = xpcall(function() ctr = require("controllers."..controller) end, error_handler) if ctr then diff --git a/src/sailor/access.lua b/src/sailor/access.lua index ac62aec..975d077 100644 --- a/src/sailor/access.lua +++ b/src/sailor/access.lua @@ -104,4 +104,8 @@ function access.logout() return session.destroy(sailor.r) end +function access.is_loggedin(login) + if (session.data.login == login) then return true else return false end +end + return access diff --git a/src/sailor/autogen.lua b/src/sailor/autogen.lua index 3a3d615..47d7e8f 100644 --- a/src/sailor/autogen.lua +++ b/src/sailor/autogen.lua @@ -9,50 +9,6 @@ local lfs = require "lfs" local M = {} ---The code for the autogen page -function M.gen() - local code = [[ - - -

Generate model

- -
- - -
- - Model generated with success! - -

- -

Generate CRUD

- -
- - -
- - CRUD generated with success! - -]] - return code -end - -- The code for the generated controller -- model: the model from which the generated CRUD will refer to function M.generate_controller(model) diff --git a/src/sailor/blank-app/conf/conf.lua b/src/sailor/blank-app/conf/conf.lua index 91d3982..9741315 100755 --- a/src/sailor/blank-app/conf/conf.lua +++ b/src/sailor/blank-app/conf/conf.lua @@ -9,11 +9,12 @@ local conf = { layout = 'main', route_parameter = 'r', default_error404 = 'error/404', - enable_autogen = false, -- default is false, should be true only in development environment friendly_urls = false, - max_upload = 1024 * 1024, + max_upload = 1024 * 1024, environment = "development", -- this will use db configuration named development - hide_stack_trace = false -- false recommended for development, true recommended for production + hide_stack_trace = false, -- false recommended for development, true recommended for production + enable_admin=false, -- set true only in development. Set password below too. + admin_password="" }, db = { @@ -28,8 +29,8 @@ local conf = { smtp = { server = '', - user = '', - pass = '', + smtpuser = '', + smtppass = '', from = '' }, diff --git a/src/sailor/blank-app/controllers/admin.lua b/src/sailor/blank-app/controllers/admin.lua new file mode 100644 index 0000000..308df56 --- /dev/null +++ b/src/sailor/blank-app/controllers/admin.lua @@ -0,0 +1,153 @@ +local access = require "sailor.access" +local conf = require "conf.conf" +local sailor = require "sailor" +local model = require "sailor.model" + +local admin={} + +function admin.index(page) + if conf.sailor.enable_admin then + local msg = "" + if next(page.POST) then + access.settings{default_password = conf.sailor.admin_password} + local login, err = access.login('admin', page.POST.password) + if login then + page:redirect('admin/dashboard') + else + msg = err + end + end + page:render('index' ,{msg = msg}) + else + page:render('error') + end +end + +function admin.logout( page ) + if access.logout() then + page:redirect('admin') + end +end + +function admin.dashboard(page) + local testmsg ="" + local mogelgen = false + local crudgen = false + if not access.is_loggedin('admin') then + page:redirect('admin') + else + if next(page.POST) then + if (page.POST.table_name or page.POST.model_name) then + if page.POST.table_name then + modelgen = model.generate_model(page.POST.table_name) + page:render('dashboard',{modelgen=modelgen}) + end + + if page.POST.model_name then + crudgen = model.generate_crud(page.POST.model_name) + page:render('dashboard', {crudgen=crudgen}) + end + end + + local path = sailor.path..'/conf/conf.lua' + + local t={} + local string1 =[[local conf = { + sailor = { + + ]] + + table.insert(t,string1) + local name= "app_name = " .."\""..page.POST.app_name.."\""..",\n" + table.insert(t,name) + local password = "admin_password = " .."\""..page.POST.admin_password.."\""..",\n" + table.insert(t, password) + local theme ="theme = " .."\""..page.POST.theme.."\""..",\n" + table.insert(t,theme) + local layout = "layout = " .."\""..page.POST.layout.."\""..",\n" + table.insert(t,layout) + local parameter = "route_parameter = " .."\""..page.POST.route_parameter.."\""..",\n" + table.insert(t, parameter) + local error = "default_error404 = " .."\""..page.POST.default_error404.."\""..",\n" + table.insert(t, error) + local environment = "environment = " .."\""..page.POST.environment.."\""..",\n" + table.insert(t, environment) + local controller = "default_controller = " .."\""..page.POST.default_controller.."\""..",\n" + table.insert(t, controller) + local action = "default_action = " .."\""..page.POST.default_action.."\""..",\n" + table.insert(t, action) + local static = "default_static="..tostring(page.POST.default_static)..",\n" + table.insert(t, static) + local urls = "friendly_urls="..tostring(page.POST.friendly_urls)..",\n" + table.insert(t, urls) + local trace = "hide_stack_trace="..page.POST.hide_stack_trace..",\n" + table.insert(t, trace) + local adminc = "enable_admin="..tostring(page.POST.enable_admin).."},\n" + table.insert(t, adminc) + + + local string2 = [=[ + db = { ]=] + table.insert(t,string2) + local env = conf.sailor.environment.." = { " + table.insert(t,env) + + local driver = "driver = " .."\""..tostring(page.POST.driver).."\""..",\n" + table.insert(t, driver) + local host = "host = " .."\""..tostring(page.POST.host).."\""..",\n" + table.insert(t, host) + local user = "user = " .."\""..tostring(page.POST.user).."\""..",\n" + table.insert(t, user) + local pass = "pass = " .."\""..tostring(page.POST.pass).."\""..",\n" + table.insert(t, pass) + local name = "name = " .."\""..tostring(page.POST.name).."\"".."}},\n" + table.insert(t, name) + + local string3 = [==[ + smtp = { + ]==] + + table.insert(t,string3) + local smtpserver = "server = " .."\""..tostring(page.POST.server).."\""..",\n" + table.insert(t, smtpserver) + local smtpuser = "smtpuser = " .."\""..tostring(page.POST.smtpuser).."\""..",\n" + table.insert(t, smtpuser) + local smtppass = "smtppass = " .."\""..tostring(page.POST.smtppass).."\""..",\n" + table.insert(t, smtppass) + local smtpfrom = "from = " .."\""..tostring(page.POST.from).."\"".."},\n" + table.insert(t, smtpfrom) + + local string4="lua_at_client = {" + table.insert(t, string4) + + local vm = "vm = " .."\""..page.POST.lua_at_client.."\""..",},\n" + table.insert(t, vm) + + local string5 = "debug = { \n" + table.insert(t, string5) + + local debug = "inspect = "..page.POST.debug.."}}\n" + table.insert(t, debug) + + local string6 = "return conf" + table.insert(t, string6) + + local file = io.open(path, "w") + local writeconf = file:write(table.concat(t)) + file:close() + + if writeconf then + testmsg = "Write Success" + else + testmsg = "Error in writing" + end + + + + end + + page:render('dashboard',{test = testmsg, modelgen=modelgen,crudgen=crudgen}) + end +end + +return admin \ No newline at end of file diff --git a/src/sailor/blank-app/views/admin/dashboard.lp b/src/sailor/blank-app/views/admin/dashboard.lp new file mode 100644 index 0000000..9b1ad88 --- /dev/null +++ b/src/sailor/blank-app/views/admin/dashboard.lp @@ -0,0 +1,97 @@ + + + diff --git a/src/sailor/blank-app/views/admin/error.lp b/src/sailor/blank-app/views/admin/error.lp new file mode 100644 index 0000000..30fe2dc --- /dev/null +++ b/src/sailor/blank-app/views/admin/error.lp @@ -0,0 +1 @@ +

Enable Admin first in the config file

\ No newline at end of file diff --git a/src/sailor/blank-app/views/admin/index.lp b/src/sailor/blank-app/views/admin/index.lp new file mode 100644 index 0000000..279af29 --- /dev/null +++ b/src/sailor/blank-app/views/admin/index.lp @@ -0,0 +1,28 @@ + + +
+
+
+ +
+
+ + +
+
+
diff --git a/src/sailor/db/es_model.lua b/src/sailor/db/es_model.lua new file mode 100644 index 0000000..e3b274e --- /dev/null +++ b/src/sailor/db/es_model.lua @@ -0,0 +1,114 @@ +------------------------------------------------------------------------------------------- +-- es_model.lua: DB module for connecting, querying and serching through elasticsearch +-- This file is a part of Sailor project +-- Copyright (c) 2016 Nikhil. R +-- License: MIT +-- http://sailorproject.org +------------------------------------------------------------------------------------------- + +local es_model = {} +local elasticsearch = require "elasticsearch" +local main_conf = require "conf.conf" +local elastic_conf = main_conf.search[main_conf.sailor.search_engine] + +local client = elasticsearch.client{ + hosts=elastic_conf.hosts, + params = elastic_conf.params +} + +es_model.client = client + +es_model.new = function(model_name) + + local self = {} + local ob = require("models."..model_name) + es_type = ob.type + keys = ob.keys + local attributes={} + + -- Function for indexing data into ES. If doc is not set, then attributes is saved into the index. + -- It uses named arguments to support optional parameters + self.save = function(arg) + arg.index = arg.index or elastic_conf.index + arg.type = es_type + if arg.body == nil then + arg.body = attributes + return client:index(arg) + else + return client:index(arg) + end + end + -- Function for getting data from ES + self.get = function(arg) + arg.index = arg.index or elastic_conf.index + arg.type = es_type + return client:get(arg) + end + -- Function for searching ES + self.search = function(arg) + arg.index = arg.index or elastic_conf.index + arg.type = es_type + return client:search(arg) + end + -- Function for delete documents in ES + self.delete = function(arg) + arg.index = arg.index or elastic_conf.index + arg.type = es_type + return client:delete(arg) + end + -- Function for updating documents in ES + self.update = function(arg) + arg.index = arg.index or elastic_conf.index + arg.type = es_type + return client:update(arg) + end + -- Function to find number of documents given the index and type; uses client:search + self.getCount = function() + local arg = {} + arg.index = arg.index or elastic_conf.index + arg.type = es_type + local data, err = client:search(arg) + if data ~=nil then return data.hits.total, err else return err end + end + -- Get an array of all documents in the given index and type + self.getAll = function() + local arg ={} + arg.index = arg.index or elastic_conf.index + arg.type = es_type + local data,err = client:search(arg) + if data ~=nil then return data.hits.hits, err else return err end + end + -- Bulk Indexing documents. Both index and type have to be specified in the parameters. + self.bulkIndex = function(arg) + return client:bulk(arg) + end + -- For getting multiple documents at once. + self.mget = function(arg) + return client:mget(arg) + end +-- Metamethod for storing attributes. Checks first if it's defined in the model. + + setmetatable(self, { + __newindex = function(table, key, value) + local found = false + for _,attrs in pairs(keys) do + if attrs == key then + attributes[key] = value + found = true + end + end + if not found then + error(tostring(key).." is not a valid attribute for this model.") + end + end, +-- The fallback table is also attributes. + __index = attributes + + }) + + + return self + +end + +return es_model diff --git a/src/sailor/page.lua b/src/sailor/page.lua index be3210f..7e9d38d 100644 --- a/src/sailor/page.lua +++ b/src/sailor/page.lua @@ -91,7 +91,6 @@ end -- parms: table, vars being passed ahead. function Page:render(filename,parms,src) parms = parms or {} - if src ~= nil then return render_page(filename,parms,src) end -- shortcut for autogen module local src local filepath diff --git a/test/dev-app/conf/conf.lua b/test/dev-app/conf/conf.lua index 514c8a5..cfbc815 100755 --- a/test/dev-app/conf/conf.lua +++ b/test/dev-app/conf/conf.lua @@ -21,8 +21,12 @@ local conf = { default_error404 = 'error/404', enable_autogen = true, -- default is false, should be true only in development environment friendly_urls = false, + hide_stack_trace = false, max_upload = 1024 * 1024, environment = "test", -- this will use db configuration named test + search_engine = "elasticsearch", + enable_admin = false, + admin_password = "" }, db = { @@ -32,13 +36,34 @@ local conf = { user = db_user or '', pass = db_pass or '', dbname = db_name or '' - } + }, + + }, + search ={ + elasticsearch={ + hosts={ + { + protocol ="http", + host ="localhost", + port=9200 + } + }, + params={ + pingTimeout = 1, + selector = 'RoundRobinSelector', + connectionPool = 'StaticConnectionPool', + maxRetryCount = 5, + logLevel = 'WARN' + }, + index = "test" + } + }, smtp = { server = '', - user = '', - pass = '', + smtpuser = '', + smtppass = '', from = '' }, diff --git a/test/dev-app/controllers/admin.lua b/test/dev-app/controllers/admin.lua new file mode 100644 index 0000000..0f1bc71 --- /dev/null +++ b/test/dev-app/controllers/admin.lua @@ -0,0 +1,176 @@ +local access = require "sailor.access" +local conf = require "conf.conf" +local sailor = require "sailor" +local model = require "sailor.model" + +local admin={} + +function admin.index(page) + if conf.sailor.enable_admin then + local msg = "" + if next(page.POST) then + access.settings{default_password = conf.sailor.admin_password} + local login, err = access.login('admin', page.POST.password) + if login then + page:redirect('admin/dashboard') + else + msg = err + end + end + page:render('index' ,{msg = msg}) + else + page:render('error') + end +end + +function admin.logout( page ) + if access.logout() then + page:redirect('admin') + end +end + +function admin.dashboard(page) + local testmsg ="" + local mogelgen = false + local crudgen = false + if not access.is_loggedin('admin') then + page:redirect('admin') + else + if next(page.POST) then + if (page.POST.table_name or page.POST.model_name) then + if page.POST.table_name then + modelgen = model.generate_model(page.POST.table_name) + page:render('dashboard',{modelgen=modelgen}) + end + + if page.POST.model_name then + crudgen = model.generate_crud(page.POST.model_name) + page:render('dashboard', {crudgen=crudgen}) + end + end + + local path = sailor.path..'/conf/conf.lua' + + local t={} + local string1 =[[local conf = { + sailor = { + + ]] + + table.insert(t,string1) + local name= "app_name = " .."\""..page.POST.app_name.."\""..",\n" + table.insert(t,name) + local password = "admin_password = " .."\""..page.POST.admin_password.."\""..",\n" + table.insert(t, password) + local theme ="theme = " .."\""..page.POST.theme.."\""..",\n" + table.insert(t,theme) + local layout = "layout = " .."\""..page.POST.layout.."\""..",\n" + table.insert(t,layout) + local parameter = "route_parameter = " .."\""..page.POST.route_parameter.."\""..",\n" + table.insert(t, parameter) + local error = "default_error404 = " .."\""..page.POST.default_error404.."\""..",\n" + table.insert(t, error) + local environment = "environment = " .."\""..page.POST.environment.."\""..",\n" + table.insert(t, environment) + local controller = "default_controller = " .."\""..page.POST.default_controller.."\""..",\n" + table.insert(t, controller) + local action = "default_action = " .."\""..page.POST.default_action.."\""..",\n" + table.insert(t, action) + local static = "default_static="..tostring(page.POST.default_static)..",\n" + table.insert(t, static) + local urls = "friendly_urls="..tostring(page.POST.friendly_urls)..",\n" + table.insert(t, urls) + local trace = "hide_stack_trace="..page.POST.hide_stack_trace..",\n" + table.insert(t, trace) + table.insert(t, "search_engine = " .."\""..tostring(page.POST.search_engine).."\""..",\n") + local adminc = "enable_admin="..tostring(page.POST.enable_admin).."},\n" + table.insert(t, adminc) + + + local string2 = [=[ + db = { ]=] + table.insert(t,string2) + local env = conf.sailor.environment.." = { " + table.insert(t,env) + + local driver = "driver = " .."\""..tostring(page.POST.driver).."\""..",\n" + table.insert(t, driver) + local host = "host = " .."\""..tostring(page.POST.host[1]).."\""..",\n" + table.insert(t, host) + local user = "user = " .."\""..tostring(page.POST.user).."\""..",\n" + table.insert(t, user) + local pass = "pass = " .."\""..tostring(page.POST.pass).."\""..",\n" + table.insert(t, pass) + local name = "name = " .."\""..tostring(page.POST.name).."\"".."}},\n" + table.insert(t, name) + + local string3 = [==[ + smtp = { + ]==] + + table.insert(t,string3) + local smtpserver = "server = " .."\""..tostring(page.POST.server).."\""..",\n" + table.insert(t, smtpserver) + local smtpuser = "smtpuser = " .."\""..tostring(page.POST.smtpuser).."\""..",\n" + table.insert(t, smtpuser) + local smtppass = "smtppass = " .."\""..tostring(page.POST.smtppass).."\""..",\n" + table.insert(t, smtppass) + local smtpfrom = "from = " .."\""..tostring(page.POST.from).."\"".."},\n" + table.insert(t, smtpfrom) + + local string7 = [==[ + search = { + elasticsearch = { + hosts = {{ + + ]==] + table.insert(t, string7) + table.insert(t, "protocol = " .."\""..tostring(page.POST.protocol).."\""..",\n") + table.insert(t, "host = " .."\""..tostring(page.POST.host[2]).."\""..",\n") + table.insert(t, "port = " .."\""..tostring(page.POST.port).."\"".."}},\n") + local string8 = [=[ + params = { + ]=] + table.insert(t, string8) + table.insert(t, "pingTimeout = " .."\""..tostring(page.POST.pingTimeout).."\""..",\n") + table.insert(t, "selector = " .."\""..tostring(page.POST.selector).."\""..",\n") + table.insert(t, "connectionPool = " .."\""..tostring(page.POST.connectionPool).."\""..",\n") + table.insert(t, "maxRetryCount = " .."\""..tostring(page.POST.maxRetryCount).."\""..",\n") + table.insert(t, "logLevel = " .."\""..tostring(page.POST.logLevel).."\"".."},\n") + + table.insert(t, "index = ".."\""..tostring(page.POST.index).."\"".."}},\n") + + local string4="lua_at_client = {" + table.insert(t, string4) + + local vm = "vm = " .."\""..page.POST.lua_at_client.."\""..",},\n" + table.insert(t, vm) + + local string5 = "debug = { \n" + table.insert(t, string5) + + local debug = "inspect = "..page.POST.debug.."}}\n" + table.insert(t, debug) + + local string6 = "return conf" + table.insert(t, string6) + + local file = io.open(path, "w") + local writeconf = file:write(table.concat(t)) + file:close() + + if writeconf then + testmsg = "Write Success" + else + testmsg = "Error in writing" + end + + + + end + + page:render('dashboard',{test = testmsg, modelgen=modelgen,crudgen=crudgen}) + end +end + +return admin \ No newline at end of file diff --git a/test/dev-app/controllers/category.lua b/test/dev-app/controllers/category.lua index 8116b03..7d1fdee 100644 --- a/test/dev-app/controllers/category.lua +++ b/test/dev-app/controllers/category.lua @@ -1,14 +1,12 @@ -local sailor = require "sailor" - local M = {} function M.index(page) - local categorys = sailor.model("category"):find_all() + local categorys = require "sailor.model"("category"):find_all() page:render('index',{categorys = categorys}) end function M.create(page) - local category = sailor.model("category"):new() + local category = require "sailor.model"("category"):new() local saved if next(page.POST) then category:get_post(page.POST) @@ -21,7 +19,7 @@ function M.create(page) end function M.update(page) - local category = sailor.model("category"):find_by_id(page.GET.id) + local category = require "sailor.model"("category"):find_by_id(page.GET.id) if not category then return 404 end @@ -37,7 +35,7 @@ function M.update(page) end function M.view(page) - local category = sailor.model("category"):find_by_id(page.GET.id) + local category = require "sailor.model"("category"):find_by_id(page.GET.id) if not category then return 404 end @@ -45,7 +43,7 @@ function M.view(page) end function M.delete(page) - local category = sailor.model("category"):find_by_id(page.GET.id) + local category = require "sailor.model"("category"):find_by_id(page.GET.id) if not category then return 404 end diff --git a/test/dev-app/controllers/test.lua b/test/dev-app/controllers/test.lua index d8c3012..b43165d 100755 --- a/test/dev-app/controllers/test.lua +++ b/test/dev-app/controllers/test.lua @@ -2,6 +2,7 @@ local session = require "sailor.session" local validation = require "valua" local form = require "sailor.form" local sailor = require "sailor" +local es_model = require ('sailor.db.es_model') local test = {} @@ -14,6 +15,61 @@ function test.index(page) page:render('index',{stringVariable = stringVariable,anotherVar = anotherVar}) end +function test.elasticfunctions(page) + + function table.val_to_str ( v ) + + if "string" == type( v ) then + v = string.gsub( v, "\n", "\\n" ) + + if string.match( string.gsub(v,"[^'\"]",""), '^"+$' ) then + return "'" .. v .. "'" + end + return '"' .. string.gsub(v,'"', '\\"' ) .. '"' + else + return "table" == type( v ) and table.tostring( v ) or + tostring( v ) + end + + end + + function table.key_to_str ( k ) + if "string" == type( k ) and string.match( k, "^[_%a][_%a%d]*$" ) then + return k + else + return "[" .. table.val_to_str( k ) .. "]" + end + end + + function table.tostring( tbl ) + local result, done = {}, {} + for k, v in ipairs( tbl ) do + table.insert( result, table.val_to_str( v ) ) + done[ k ] = true + end + + for k, v in pairs( tbl ) do + if not done[ k ] then + table.insert( result, + table.key_to_str( k ) .. "=" .. table.val_to_str( v ) ) + end + end + + return "{" .. table.concat( result, "," ) .. "}" + end + + local doc = {name = "test"} + local contact = es_model.new("test") + contact.name = "Tester 123" + local msg = contact.save{id = 101, body = doc, routing = "routing@test.com"} + if (page.POST) then msg = contact.search{q = page.POST.search} end + if type(msg) == "table" then + page:render('elastic',{ msg = table.tostring(msg) }) + else + page:render('elastic',{ msg = msg }) + end +end + --This will be recovered once I reorganize the mailer module --[[ function test.mailer(page) @@ -247,4 +303,6 @@ function test.cookie_get(page) page:write("Getting cookie:".. (data or "no data")) end + + return test diff --git a/test/dev-app/models/category.lua b/test/dev-app/models/category.lua index b0fb2d8..0ff4f3f 100644 --- a/test/dev-app/models/category.lua +++ b/test/dev-app/models/category.lua @@ -15,8 +15,7 @@ M.db = { table = 'category' } -M.relations = { - posts = {relation = "MANY_MANY", model = "post", table = "post_category", attributes = {"category_id","post_id"}} -} +M.relations = {} return M + diff --git a/test/dev-app/models/test.lua b/test/dev-app/models/test.lua new file mode 100644 index 0000000..9406c86 --- /dev/null +++ b/test/dev-app/models/test.lua @@ -0,0 +1,10 @@ +local test ={} + +test.type = "testing" + +test.keys = { + "name", "email" +} + +return test + diff --git a/test/dev-app/tests/functional/admin.lua b/test/dev-app/tests/functional/admin.lua new file mode 100644 index 0000000..13e5280 --- /dev/null +++ b/test/dev-app/tests/functional/admin.lua @@ -0,0 +1,69 @@ +local access = require "sailor.access" +local conf = require "conf.conf" +local test = require "sailor.test" +local lfs = require "lfs" + +describe("Testing Admin", function () + + it("Admin Page should not open", function() + conf.sailor.enable_admin = false + local res = test.request('admin') + assert.truthy(res.body:match('Enable Admin first in the config file')) + end) + + it("Admin page should not open", function() + conf.sailor.enable_admin = true + conf.sailor.admin_password = "test" + local res = test.request('admin', {post={password = "random123"}}) + assert.truthy(res.body:match("Invalid username or password.")) + end) + + + it("Admin page should open", function() + conf.sailor.enable_admin = true + conf.sailor.admin_password = "test" + local res = test.request('admin',{post={password = "test"}}) + assert.is_true(res:redirected('admin/dashboard')) + end) + + + it("should not generate model", function() + local res = test.request('admin/dashboard',{post={table_name ='asdasd'}}) + assert.falsy(res.body:match('Model generated with success')) + end) + + it("should generate model", function() + local path = 'models/category.lua' + os.remove(path) + local res = test.request('admin/dashboard',{post={table_name ='category'}}) + assert.truthy(res.body:match('Model generated with success')) + assert.truthy(lfs.attributes(path)) + end) + + it("should not generate CRUD", function() + local res = test.request('admin/dashboard',{post={model_name ='asdasd'}}) + assert.falsy(res.body:match('CRUD generated with success')) + end) + + it("should generate CRUD", function() + local paths = { + 'controllers/category.lua', + 'views/category/create.lp', + 'views/category/index.lp', + 'views/category/update.lp', + 'views/category/view.lp' + } + for _,f in ipairs(paths) do + os.remove(f) + end + + local res = test.request('admin/dashboard',{post={model_name ='category'}}) + assert.truthy(res.body:match('CRUD generated with success')) + for _,f in ipairs(paths) do + assert.truthy(lfs.attributes(f)) + end + end) + +end) + + diff --git a/test/dev-app/tests/functional/autogen.lua b/test/dev-app/tests/functional/autogen.lua deleted file mode 100644 index 02f011f..0000000 --- a/test/dev-app/tests/functional/autogen.lua +++ /dev/null @@ -1,64 +0,0 @@ -local test = require "sailor.test" -local lfs = require "lfs" -local conf = require "conf.conf" -local model = require "sailor.model" - - -local db = require "sailor.db" -local helper = require "tests.helper" - - - -describe("Testing #Autogen", function() - - it("should not open autogen page", function() - conf.sailor.enable_autogen = false - local res = test.request('autogen') - assert.truthy(res.body:match('Error')) - end) - - it("should open autogen page", function() - conf.sailor.enable_autogen = true - local res = test.request('autogen') - assert.same(200,res.status) - assert.truthy(res.body:match('Generate CRUD')) - end) - - it("should not generate model", function() - local res = test.request('autogen',{post={table_name ='asdasd'}}) - assert.falsy(res.body:match('Model generated with success')) - end) - - it("should generate model", function() - local path = 'models/category.lua' - os.remove(path) - local res = test.request('autogen',{post={table_name ='category'}}) - assert.truthy(res.body:match('Model generated with success')) - assert.truthy(lfs.attributes(path)) - end) - - it("should not generate CRUD", function() - local res = test.request('autogen',{post={model_name ='asdasd'}}) - assert.falsy(res.body:match('CRUD generated with success')) - end) - - it("should generate CRUD", function() - local paths = { - 'controllers/category.lua', - 'views/category/create.lp', - 'views/category/index.lp', - 'views/category/update.lp', - 'views/category/view.lp' - } - for _,f in ipairs(paths) do - os.remove(f) - end - - local res = test.request('autogen',{post={model_name ='category'}}) - assert.truthy(res.body:match('CRUD generated with success')) - for _,f in ipairs(paths) do - assert.truthy(lfs.attributes(f)) - end - end) - -end) \ No newline at end of file diff --git a/test/dev-app/tests/unit/access.lua b/test/dev-app/tests/unit/access.lua index 8d856c4..102496d 100644 --- a/test/dev-app/tests/unit/access.lua +++ b/test/dev-app/tests/unit/access.lua @@ -27,6 +27,10 @@ describe("Testing #UserController", function() assert.is_true(User.authenticate(fixtures[1].username,fixtures[1].password,false)) end) + it("should check which user is logged in", function() + assert.is_true(access.is_loggedin("serena")) + end) + it("should know the user is logged in", function() assert.is_false(access.is_guest()) end) @@ -64,5 +68,11 @@ describe("Testing #UserController", function() assert.is_false(access.login('admin','demon')) assert.is_true(access.is_guest()) end) + + it('access logged in fucntion', function () + access.settings({model = false, hashing = false, default_login = 'admin', default_password = 'demo'}) + assert.is_true(access.login('admin', 'demo')) + assert.is_true(access.is_loggedin('admin')) + end) end) diff --git a/test/dev-app/tests/unit/elasticsearch.lua b/test/dev-app/tests/unit/elasticsearch.lua new file mode 100644 index 0000000..226bd2c --- /dev/null +++ b/test/dev-app/tests/unit/elasticsearch.lua @@ -0,0 +1,164 @@ +local es_model = require ('sailor.db.es_model') +local fixtures = require "tests.fixtures.user" or {} + +describe("Testing Elasticsearch Models", function() + local user = es_model.new("test") + user.name = "Test User" + user.email = "test@test.com" + user.save{id = 1} + user.save{id = 3, body = {doc = { name = "new test2"}}} + local count_before + + + it("Should create different objects", function() + local u1 = es_model.new("test") + u1.name = fixtures[1].username + u1.save{id = "a"} + local u2 = es_model.new("test") + u2.name = fixtures[2].username + u2.save{id = "b"} + assert.is_equal(u1.get{id = "a"}._source.name, fixtures[1].username) + assert.is_equal(u2.get{id = "b"}._source.name, fixtures[2].username) + + end) + + it("Should count objects", function() + assert.is_equal(#user.getAll(), user.getCount()) + end) + + it("Should not assign attributes that don't defined in the model file", function() + assert.has_error(function() user.blahblah = "hey" end, "blahblah is not a valid attribute for this model.") + end) + + it("should not access attributes that don't exist", function() + assert.falsy(user.blahblah) + end) + + it("should save object", function() + user.delete{id = 2} + -- Give some time for it to index + local ntime = os.time() + 1 + repeat until os.time() > ntime + count_before = user.getCount() + local doc = {test = "random"} + local _,code = user.save{id = 2 , body = doc} + local ntime = os.time() + 1 + repeat until os.time() > ntime + assert.is_equal(code, 201) + assert.is_equal(user.getCount(), count_before + 1) + end) + + it("should update object", function() + local _,code = user.update{id = 1, body = {doc = {name = "New name"}}} + assert.is_equal(code, 200) + assert.is_equal(user.get{id =1}._source.name, "New name") + end) + + it("should delete object", function() + count_before = user.getCount() + local _,code = user.delete{id = "a"} + local ntime = os.time() + 1 + repeat until os.time() > ntime + assert.is_equal(code, 200) + assert.is_equal(user.getCount(), count_before - 1) + + end) + + it("should find by id", function() + local data, err = user.get{id = "b"} + assert.is_equal(data._source.name, fixtures[2].username) + end) + + it("should not find by id", function() + local data,err = user.get{id = "randomid"} + local value + if data == nil then value = false end + assert.is_false(value) + end) + + it("should find all objects", function() + assert.is_equal(user.getCount(), #user.getAll()) + + end) + + it("should find some objects", function() + local count = user.search{q = "name"}.hits.total + assert.is_equal(1, count) + end) + + it("should find one object", function() + local count = user.search{q = "test:random"}.hits.total + assert.is_equal(1, count) + end) + + it("shold create objects and then rollback", function() + local data, status = user.save{id = 4, body = {doc = { name = "new test4"}}} + assert.truthy(data) + local ntime = os.time() + 1 + repeat until os.time() > ntime + assert.is_equal(5, user.getCount()) + user.delete{id = 4} + local ntime = os.time() + 1 + repeat until os.time() > ntime + data, status = user.get{id = 4} + assert.falsy(data) + local ntime = os.time() + 1 + repeat until os.time() > ntime + assert.is_equal(4, user.getCount()) + end) + + it("should bulk index", function() + local data, status = user.bulkIndex{ + body = { + -- First action + { + index = { + ["_index"] = "my_index1", + ["_type"] = "my_type1" + } + }, + -- First body + { + my_key1 = "my_value1", + }, + -- Second action + { + index = { + ["_index"] = "my_index2", + ["_type"] = "my_type2" + } + }, + -- Second body + { + my_key2 = "my_value2", + } + } + } + + assert.is_equal(status, 200) + end) + + it("should get multiple documents at once", function() + local data, status = user.mget{ + body = { + docs = { + -- First document + { + ["_index"] = "my_index1", + ["_type"] = "my_type1", + ["_id"] = "my_id1" + }, + -- Second document + { + ["_index"] = "my_index2", + ["_type"] = "my_type2", + ["_id"] = "my_id2" + } + } + } + } + + assert.is_equal(status, 200) + + end) +end) \ No newline at end of file diff --git a/test/dev-app/views/admin/dashboard.lp b/test/dev-app/views/admin/dashboard.lp new file mode 100644 index 0000000..3307c75 --- /dev/null +++ b/test/dev-app/views/admin/dashboard.lp @@ -0,0 +1,130 @@ + + + diff --git a/test/dev-app/views/admin/error.lp b/test/dev-app/views/admin/error.lp new file mode 100644 index 0000000..30fe2dc --- /dev/null +++ b/test/dev-app/views/admin/error.lp @@ -0,0 +1 @@ +

Enable Admin first in the config file

\ No newline at end of file diff --git a/test/dev-app/views/admin/index.lp b/test/dev-app/views/admin/index.lp new file mode 100644 index 0000000..279af29 --- /dev/null +++ b/test/dev-app/views/admin/index.lp @@ -0,0 +1,28 @@ + + +
+
+
+ +
+
+ + +
+
+
diff --git a/test/dev-app/views/category/create.lp b/test/dev-app/views/category/create.lp index 4eed4fe..2fba66d 100644 --- a/test/dev-app/views/category/create.lp +++ b/test/dev-app/views/category/create.lp @@ -3,18 +3,18 @@ There was an error while saving. -
-
+ +
- - + <%= form.text(category,'id', 'class="form-control" placeholder="id"') %> + <%= category.errors.id or '' %>
-
+
- - + <%= form.text(category,'name', 'class="form-control" placeholder="name"') %> + <%= category.errors.name or '' %>
- +
-<- Back to View All +<- Back to View All diff --git a/test/dev-app/views/category/index.lp b/test/dev-app/views/category/index.lp index 1de627f..eb85bb7 100644 --- a/test/dev-app/views/category/index.lp +++ b/test/dev-app/views/category/index.lp @@ -4,17 +4,17 @@ }

View all

- - - - +
idname
+ + + - - - + + + - -
idname
<%= v.id %> <%= v.name %>
+ +
-Create new category +Create new category diff --git a/test/dev-app/views/category/update.lp b/test/dev-app/views/category/update.lp index abba556..922e7ab 100644 --- a/test/dev-app/views/category/update.lp +++ b/test/dev-app/views/category/update.lp @@ -3,16 +3,16 @@ There was an error while saving. -
-
+ +
- + <%= form.text(category,'id', 'class="form-control" placeholder="id"') %>
-
+
- + <%= form.text(category,'name', 'class="form-control" placeholder="name"') %>

-<- Back to View All +<- Back to View All diff --git a/test/dev-app/views/category/view.lp b/test/dev-app/views/category/view.lp index 0753f4b..50eca19 100644 --- a/test/dev-app/views/category/view.lp +++ b/test/dev-app/views/category/view.lp @@ -1,11 +1,11 @@

- View category # - (update) - (delete) + View category #<%= category.id %> + (update) + (delete)

- - - -
id
name
+ + + +
id<%= category.id %>
name<%= category.name %>

-<- Back to View All +<- Back to View All diff --git a/test/dev-app/views/test/elastic.lp b/test/dev-app/views/test/elastic.lp new file mode 100644 index 0000000..aaf63d3 --- /dev/null +++ b/test/dev-app/views/test/elastic.lp @@ -0,0 +1,11 @@ + + +
+

Search box

+ + +
+ +