├── .gitignore ├── CREDITS.txt ├── LICENSE.txt ├── README.md ├── bin ├── autowire.lua └── unix │ ├── build.lua │ ├── octopus.service │ ├── server.sh │ └── ssl_certificate │ ├── server.crt │ └── server.key └── extensions ├── baseline ├── config.lua ├── src │ ├── BaselineHtmlTemplate.lua │ └── widget │ │ ├── nav.css │ │ ├── popup │ │ ├── InfoPopup.js │ │ ├── OneFieldPopup.js │ │ ├── Popup.css │ │ ├── Popup.js │ │ ├── QuestionPopup.js │ │ ├── ThreeFieldsPopup.js │ │ └── TwoFieldsPopup.js │ │ └── style.css └── static │ ├── css │ └── font-awesome.min.css │ ├── fonts │ ├── FontAwesome.otf │ ├── fontawesome-webfont.eot │ ├── fontawesome-webfont.svg │ ├── fontawesome-webfont.ttf │ ├── fontawesome-webfont.woff │ └── fontawesome-webfont.woff2 │ └── js │ ├── diff_match_patch.js │ ├── difflib.js │ ├── diffview.css │ ├── diffview.js │ ├── html5shiv.js │ ├── init-baseline.js │ ├── init-shop.js │ ├── jquery.min.js │ ├── jquery.pretty-text-diff.js │ ├── skel-layers.min.js │ ├── skel.css │ └── skel.min.js ├── config.lua ├── core ├── config.lua └── src │ ├── builder.lua │ ├── cookie.lua │ ├── crypto.lua │ ├── database.lua │ ├── date.lua │ ├── eval.lua │ ├── exception.lua │ ├── exit.lua │ ├── fileutil.lua │ ├── http.lua │ ├── http_headers.lua │ ├── js │ ├── parse.js │ └── widget.js │ ├── json.lua │ ├── param.lua │ ├── parse.lua │ ├── persistence.lua │ ├── resty │ ├── README.md │ ├── md5.lua │ ├── mysql.lua │ ├── resty.sh │ ├── rsa.lua │ ├── sha.lua │ ├── sha1.lua │ └── sha256.lua │ ├── rocky │ ├── README.md │ ├── certificate.lua │ ├── crypto.lua │ ├── luaorm.lua │ ├── ngx.lua │ ├── ngxssl.lua │ ├── postgresql.lua │ ├── socket.lua │ └── typedef.lua │ ├── stacktrace.lua │ ├── template.lua │ ├── upload.lua │ ├── utf8.lua │ ├── utf8data.lua │ ├── util.lua │ └── uuid.lua ├── database ├── config.lua ├── src │ ├── controller │ │ ├── DatabaseAddController.lua │ │ ├── DatabaseAddReferenceController.lua │ │ ├── DatabaseController.lua │ │ ├── DatabaseDeleteAllReferencesController.lua │ │ ├── DatabaseDeleteController.lua │ │ ├── DatabaseDeleteReferenceController.lua │ │ ├── DatabaseEditController.lua │ │ ├── DatabaseExecuteController.lua │ │ ├── DatabaseSaveController.lua │ │ ├── DatabaseTemplate.css │ │ └── DatabaseTemplate.js │ ├── filter │ │ ├── DatabaseRedirectOnSessionTimeoutFilter.lua │ │ └── DatabaseThrowErrorOnSessionTimeoutFilter.lua │ └── widget │ │ ├── DatabaseEditObject.js │ │ ├── DatabaseEditor.js │ │ ├── DatabaseHeader.css │ │ ├── DatabaseHeader.js │ │ ├── DatabaseNavigation.css │ │ ├── DatabaseNavigation.js │ │ ├── DatabaseResult.js │ │ └── DatabaseTabs.js └── static │ └── database-favicon.ico ├── demo ├── config.lua ├── src │ ├── controller │ │ ├── HelloWorldController.lua │ │ ├── IndexController.lua │ │ └── ProductDetailController.lua │ ├── module │ │ └── DemoProductService.lua │ └── widget │ │ ├── DemoError.js │ │ ├── DemoFooter.js │ │ ├── DemoHeader.js │ │ ├── DemoProductDetail.js │ │ ├── DemoTemplate1.lua │ │ └── DemoTemplate2.lua └── static │ ├── box.jpg │ └── stars-5.png ├── editor ├── config.lua ├── src │ ├── controller │ │ ├── CompareController.lua │ │ ├── CryptographyController.lua │ │ ├── EditorController.lua │ │ ├── EditorDownloadFileController.lua │ │ ├── EditorEditFileController.lua │ │ ├── EditorSearchController.lua │ │ ├── EditorSearchTemplate.js │ │ ├── EditorTemplate.css │ │ ├── EditorTemplate.js │ │ ├── EditorUploadFileController.lua │ │ └── operation │ │ │ ├── CreateDirectoryController.lua │ │ │ ├── CreateFileController.lua │ │ │ ├── DirectoryController.lua │ │ │ ├── FileContentController.lua │ │ │ ├── RemoveController.lua │ │ │ ├── RenameController.lua │ │ │ └── SaveController.lua │ ├── filter │ │ ├── EditorRedirectOnSessionTimeoutFilter.lua │ │ └── EditorThrowErrorOnSessionTimeoutFilter.lua │ ├── module │ │ ├── Directory.lua │ │ └── Editor.lua │ └── widget │ │ ├── CompareEditor.js │ │ ├── CompareHeader.js │ │ ├── CompareTabs.js │ │ ├── CryptographyTabs.js │ │ ├── Editor.js │ │ ├── EditorHeader.css │ │ ├── EditorHeader.js │ │ ├── EditorNavigation.css │ │ ├── EditorNavigation.js │ │ ├── EditorSearchHeader.js │ │ ├── EditorSearchPopup.js │ │ ├── EditorSearchResult.js │ │ └── UploadResult.js └── static │ ├── editor-favicon.ico │ └── search-favicon.ico ├── orm ├── config.lua └── src │ ├── database.lua │ └── db │ ├── api │ ├── common.lua │ ├── mysql.lua │ └── postgres.lua │ └── driver │ ├── mysql.lua │ └── postgres.lua ├── repository ├── config.lua ├── src │ ├── controller │ │ ├── RepositoryCommitHistoryController.lua │ │ ├── RepositoryFileHistoryController.lua │ │ ├── RepositoryLogHistoryController.lua │ │ ├── RepositoryStatusController.lua │ │ ├── RepositoryTemplate.css │ │ ├── RepositoryTemplate.js │ │ └── operation │ │ │ ├── AddController.lua │ │ │ ├── CommitController.lua │ │ │ ├── DeleteController.lua │ │ │ ├── FileDiffController.lua │ │ │ ├── FileRevisionContentController.lua │ │ │ ├── MergeController.lua │ │ │ ├── RefreshController.lua │ │ │ ├── RevertController.lua │ │ │ └── UpdateController.lua │ ├── module │ │ ├── GIT.lua │ │ └── SVN.lua │ └── widget │ │ ├── RepositoryDiff.js │ │ ├── RepositoryFileHistoryHeader.js │ │ ├── RepositoryFileHistoryNavigation.js │ │ ├── RepositoryLog.js │ │ ├── RepositoryPatch.js │ │ ├── RepositoryStatusHeader.js │ │ └── RepositoryStatusNavigation.js └── static │ └── repository-favicon.ico ├── security ├── config.lua └── src │ ├── controller │ ├── SecurityLoginPageController.lua │ ├── SecurityLoginUserController.lua │ ├── SecurityRegisterPageController.lua │ └── SecurityRegisterUserController.lua │ ├── import.lua │ ├── module │ └── UserService.lua │ ├── types.lua │ └── widget │ ├── LoginForm.js │ └── RegisterForm.js └── shop ├── config.lua ├── src ├── controller │ ├── ChangeCountryController.lua │ ├── ChangeLanguageController.lua │ ├── HomePageController.lua │ ├── account │ │ ├── AccountAddUpdateAddressController.lua │ │ ├── AccountAddressPageController.lua │ │ ├── AccountAddressesPageController.lua │ │ ├── AccountOrderPageController.lua │ │ ├── AccountOrdersPageController.lua │ │ ├── AccountPageController.lua │ │ ├── AccountRemoveAddressController.lua │ │ ├── LoginPageController.lua │ │ └── RegisterPageController.lua │ ├── catalog │ │ ├── CategoryPageController.lua │ │ └── ProductPageController.lua │ └── checkout │ │ ├── AddToCartController.lua │ │ ├── CartPageController.lua │ │ ├── CheckoutAddAddressController.lua │ │ ├── CheckoutAddressPageController.lua │ │ ├── CheckoutAddressesPageController.lua │ │ ├── CheckoutConfirmationPageController.lua │ │ ├── CheckoutDeliveryMethodPageController.lua │ │ ├── CheckoutPageController.lua │ │ ├── CheckoutPaymentMethodPageController.lua │ │ ├── CheckoutPlaceOrderController.lua │ │ ├── CheckoutReviewOrderPageController.lua │ │ ├── CheckoutSetAddressController.lua │ │ ├── CheckoutSetDeliveryMethodController.lua │ │ ├── CheckoutSetPaymentMethodController.lua │ │ └── UpdateProductEntryController.lua ├── filter │ ├── ShopRedirectOnSessionTimeoutFilter.lua │ └── ShopThrowErrorOnSessionTimeoutFilter.lua ├── import.lua ├── module │ ├── CartService.lua │ ├── CountryService.lua │ ├── ExceptionHandler.lua │ ├── LocaleService.lua │ └── PriceService.lua ├── types.lua └── widget │ ├── account │ ├── AccountOptions.js │ ├── AddressForm.js │ ├── Addresses.js │ ├── Order.js │ ├── Orders.js │ └── RegisterForm.js │ ├── catalog │ ├── HorizontalNavigation.css │ ├── HorizontalNavigation.js │ ├── ProductAttributeFilter.js │ ├── ProductDetail.js │ └── ProductsGrid.js │ ├── checkout │ ├── Cart.css │ ├── Cart.js │ ├── DeliveryMethodForm.js │ └── PaymentMethodForm.js │ └── header │ ├── Background.js │ ├── CallUs.js │ ├── Error.js │ ├── Logo.js │ ├── MiniCart.js │ ├── RegBackgroundWithPicture.css │ ├── Search.js │ └── ShopHeader.js └── static ├── bg_flag.gif ├── favicon.ico ├── logo.png ├── p1.jpg ├── p2.jpg ├── p3.jpg ├── p4.jpg ├── p5.jpg ├── p6.jpg ├── stars-5.png ├── style.css └── uk_flag.gif /.gitignore: -------------------------------------------------------------------------------- 1 | extensions/baseline/static/ace/ 2 | extensions/build/ 3 | bin/unix/downloads/ 4 | bin/unix/html/ 5 | bin/unix/lib/ 6 | bin/unix/logs/ 7 | bin/unix/luajit/ 8 | bin/unix/fastcgi.conf 9 | bin/unix/fastcgi.conf.default 10 | bin/unix/fastcgi_params 11 | bin/unix/fastcgi_params.default 12 | bin/unix/koi-utf 13 | bin/unix/koi-win 14 | bin/unix/mime.types 15 | bin/unix/mime.types.default 16 | bin/unix/nginx 17 | bin/unix/nginx.conf 18 | bin/unix/nginx.conf.default 19 | bin/unix/nginx.config.* 20 | bin/unix/nginx.pid 21 | bin/unix/nginx.old 22 | bin/unix/server.reload 23 | bin/unix/scgi_params 24 | bin/unix/scgi_params.default 25 | bin/unix/uwsgi_params 26 | bin/unix/uwsgi_params.default 27 | bin/unix/win-utf 28 | bin/unix/profiles.lua -------------------------------------------------------------------------------- /CREDITS.txt: -------------------------------------------------------------------------------- 1 | lua | http://www.lua.org/ | Copyright © 1994–2015 Lua.org, PUC-Rio. 2 | luajit | http://luajit.org/ | Copyright © 2005-2015 Mike Pall 3 | nginx | http://nginx.org/ | Copyright (C) 2011-2015 Nginx, Inc. 4 | openssl | https://www.openssl.org/ | Copyright (c) 1998-2016 The OpenSSL Project | Copyright (c) 1995-1998 Eric A. Young, Tim J. Hudson 5 | lua-nginx-module | https://github.com/openresty/lua-nginx-module | Copyright (C) 2009-2015, by Yichun "agentzh" Zhang (章亦春) agentzh@gmail.com, CloudFlare Inc. 6 | lua-resty-mysql | https://github.com/openresty/lua-resty-mysql | Copyright (C) 2012-2013, by Yichun "agentzh" Zhang (章亦春) agentzh@gmail.com, CloudFlare Inc. 7 | lua-resty-postgres | https://github.com/azurewang/lua-resty-postgres | Copyright (C) 2013 Azure Wang(azure1st@gmail.com) 8 | lfs | https://github.com/keplerproject/luafilesystem | Copyright © 2003-2014 Kepler Project. 9 | persistence | http://the-color-black.net/blog/LuaTablePersistence | Copyright (c) 2010 Gerhard Roethlin 10 | dkjson | http://dkolf.de/src/dkjson-lua.fsl/home | Copyright (C) 2010-2013 David Heiko Kolf 11 | uuid | https://github.com/Tieske/uuid | Copyright 2012 Rackspace (original), 2013 Thijs Schreijer (modifications) 12 | date | https://github.com/Tieske/date | Copyright (C) 2006, by Jas Latrix (jastejada@yahoo.com)| Copyright (C) 2013-2014, by Thijs Schreijer 13 | utf8 | Copyright (c) 2006-2007, Kyle Smith | Copyright (C) 2016, StrumaSoft 14 | lua-resty-http | https://github.com/pintsized/lua-resty-http | Copyright (c) 2013, James Hurst 15 | lua-resty-cookie | https://github.com/cloudflare/lua-resty-cookie | Copyright (C) 2013 Jiale Zhi (calio), Cloudflare Inc. 16 | lua-resty-upload | https://github.com/openresty/lua-resty-upload | Copyright (C) Yichun Zhang (agentzh) 17 | skel | https://github.com/n33/skel | Copyright (c) n33 18 | ace | https://github.com/ajaxorg/ace | Copyright (c) 2010, Ajax.org B.V. 19 | google-diff-match-patch | https://code.google.com/p/google-diff-match-patch/ | Apache License 2.0 20 | jQuery.PrettyTextDiff | https://github.com/arnab/jQuery.PrettyTextDiff | Copyright (c) 2013 Arnab Deka. 21 | jsdifflib | https://github.com/cemerick/jsdifflib | Copyright (c) 2007, Snowtide Informatics Systems, Inc. -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (C) 2015-2021, StrumaSoft 2 | 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, 6 | are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 17 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 | IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 19 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 24 | EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | -------------------------------------------------------------------------------- /bin/autowire.lua: -------------------------------------------------------------------------------- 1 | -- save old require 2 | local oldRequire = require 3 | 4 | 5 | package.loaded.MODULES = {} 6 | local function configuration (moduleName) 7 | local MODULES = package.loaded.MODULES 8 | local octopusHostDir = ngx.var.octopusHostDir 9 | 10 | if MODULES[octopusHostDir] then 11 | return MODULES[octopusHostDir][moduleName] 12 | else 13 | local modulesConfig = dofile(octopusHostDir .. "/build/src/module.lua") 14 | MODULES[octopusHostDir] = modulesConfig 15 | return modulesConfig[moduleName] 16 | end 17 | end 18 | 19 | 20 | local function newRequire (moduleName, newModule) 21 | if not moduleName then return nil end 22 | 23 | local scripts = configuration(moduleName) 24 | if scripts then 25 | local key 26 | if scripts[1]["extensionDir"]:find(ngx.var.octopusExtensionsDir, 1, true) then 27 | key = "octopus." .. moduleName 28 | elseif moduleName:find("global.", 1, true) then 29 | key = moduleName 30 | else 31 | key = ngx.var.octopusHostDir .. ":" .. moduleName 32 | end 33 | 34 | if newModule then 35 | package.loaded[key] = newModule 36 | return 37 | end 38 | 39 | local cached = package.loaded[key] 40 | if cached then return cached end 41 | 42 | local lastModule, tempModule 43 | for i=#scripts, 2, -1 do -- first script holds metadata 44 | local scriptModule = dofile(scripts[i]) 45 | 46 | if i == #scripts then 47 | lastModule = scriptModule 48 | tempModule = lastModule 49 | else 50 | local nonLastModule = scriptModule 51 | local mt = getmetatable(tempModule) or {} 52 | mt.__index = nonLastModule 53 | setmetatable(tempModule, mt) 54 | tempModule = nonLastModule 55 | end 56 | end 57 | 58 | package.loaded[key] = lastModule 59 | return lastModule 60 | end 61 | 62 | return oldRequire(moduleName) 63 | end 64 | 65 | 66 | -- return new require 67 | return newRequire -------------------------------------------------------------------------------- /bin/unix/octopus.service: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # cp octopus.service /etc/init.d/octopus 4 | # sudo systemctl daemon-reload 5 | # sudo service octopus restart 6 | 7 | ### BEGIN INIT INFO 8 | # Provides: octopus 9 | # Required-Start: $all 10 | # Required-Stop: 11 | # Default-Start: 2 3 4 5 12 | # Default-Stop: 13 | # Short-Description: octopus the lua web framework 14 | # Description: octopus the lua web framework 15 | ### END INIT INFO 16 | 17 | . /lib/lsb/init-functions 18 | 19 | cd /octopus/bin/unix 20 | 21 | case "$1" in 22 | build) 23 | ./server.sh build 24 | ;; 25 | start) 26 | ./server.sh build 27 | ./server.sh start 28 | ;; 29 | stop) 30 | ./server.sh stop 31 | ;; 32 | restart) 33 | ./server.sh build 34 | ./server.sh stop 35 | ./server.sh start 36 | ;; 37 | reload) 38 | ./server.sh stop 39 | ./server.sh start 40 | ;; 41 | status) 42 | ;; 43 | *) 44 | echo "Usage: $0 {start|stop|status|restart|reload|build}" 45 | esac 46 | 47 | exit 0 -------------------------------------------------------------------------------- /bin/unix/ssl_certificate/server.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIICoTCCAYmgAwIBAgIBATANBgkqhkiG9w0BAQsFADAUMRIwEAYDVQQDDAlsb2Nh 3 | bGhvc3QwHhcNMjQwMjA3MDY0MzMzWhcNMjUwMjA2MDY0MzMzWjAUMRIwEAYDVQQD 4 | DAlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC76UEA 5 | db3IfdLHAjN5fTUHH6DjY/ZaQodFCGFqMKkwJKXYIIv6rHHlEIHK6yyM739024HE 6 | Atd8xB4XkAld9fL3QtZHbewPhR5PlWvGFi3t3UBJZH93Nn8lVL9clRHIZw4KZi9l 7 | 81cS7M1DUzfR3xP5KlAcleeLffGVCvXsZdCvuuhiEly5VFuwmfk7kSyru26ym/N0 8 | wF9xmS6MDJvad93RV3eJYPtTqbR5KA4Pn78UtawN3vyL3t8K0CbqsX45Zalzf1lq 9 | cGX4ky7V2Ah3oZ5ZgEPmuwv7UcI4UzIm3CXik1miw30o7LFRqO2BXQ1iD+0lYPOk 10 | kyehEMAzWa0i0DzbAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAKL5G2WY6D+ntmIq 11 | k25pjOL2wu2b01UR+68DzSS21fBSq5jknJZ8hw6Q/IlSaGth9FVgaUJiBNBG62HV 12 | eZ/sf4nw5UJ5c7McbkCz3xYLe/wto2pAg4gtQYVZ+OpRQwDUhbV38b7WodxgZKhl 13 | cTCJLBqgaARnUbVaLhw4SJ1kzIPXpLB8WwkLZCbsicEb5WHOqNNICHKJkCcsD3zg 14 | 8VPQr14OOG8HzTngYLYjNPlGz5N6aBWmDw8Eo1njxUrrUfkcYeOjsuYvnglsCLOT 15 | er1qBbh50WoArVI6t4UlpwZaAkkY15Vvobdig6JIFE07L2FrvtLrqpm1OZVNck1t 16 | VVUnNmE= 17 | -----END CERTIFICATE----- 18 | -------------------------------------------------------------------------------- /bin/unix/ssl_certificate/server.key: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC76UEAdb3IfdLH 3 | AjN5fTUHH6DjY/ZaQodFCGFqMKkwJKXYIIv6rHHlEIHK6yyM739024HEAtd8xB4X 4 | kAld9fL3QtZHbewPhR5PlWvGFi3t3UBJZH93Nn8lVL9clRHIZw4KZi9l81cS7M1D 5 | UzfR3xP5KlAcleeLffGVCvXsZdCvuuhiEly5VFuwmfk7kSyru26ym/N0wF9xmS6M 6 | DJvad93RV3eJYPtTqbR5KA4Pn78UtawN3vyL3t8K0CbqsX45Zalzf1lqcGX4ky7V 7 | 2Ah3oZ5ZgEPmuwv7UcI4UzIm3CXik1miw30o7LFRqO2BXQ1iD+0lYPOkkyehEMAz 8 | Wa0i0DzbAgMBAAECggEAAlexEMFnAUXYR9TWMXCHJbSWO992Jb/okcq99CXxJgF+ 9 | 88fMFu7paJKhG5d88bDWpO1Lm9bxOsPzIBYSl9JGGiECLNfI9pSRQSq6sjh6kBmP 10 | AJs5H5JVWXDKBexx0U6/lQ+bDalP75N2J52092/RfuyxHPodbda/GT2OvUizpk0n 11 | uSPyB2tGpZhTBOHVWAioxFktO0ry2TQbs4dUC2Nd5Rl7/Njo8+W6HXYTtOIvMeqx 12 | KuV0upd3tG7Y0C1CS/KbWEM03/fSy1ZZfBg8Any5ysCTBm57EMaGT2plJI9YsAOO 13 | scpSuSzcPyDUDMn+nDvhFDcSpyW/ujM3TkkJaTLtoQKBgQDlWRE6T6bD3rICMnU1 14 | bB5x4GW1qV86dQUZGuQZOyo3SDYCJJPQI1o1csCiKV4MZfGQcXbYBTzSYeA/SAwC 15 | aY8xTudbzMqn1LgvJggVugItJ4iGYfBVxOshksYKZwXMRuiMXafsFTBdWSzDv+OU 16 | ktKo5Geo3ens673ECkNoh52AkQKBgQDRv3kXVObp9LIw8GbImir+Yq4Rx5AZ+NT5 17 | qx39in5xb1FfWx6zPUIEw0nqMD1JXkXOCAA7ElJeKOvBFj8vmunOChmrx2qYfRzb 18 | MzC87uZ7svMcJWClhm5vKE6gFiqPtAf0pFukCOYu//tS7GNpspJlwHTKPKo1ZcDP 19 | MhEJT5OcqwKBgADNJ99BSf7jN1IEpR4zq4OQWiqhVeDZadQloOhpqYMZ8H5fbFjM 20 | 1tLa/MtUQ6zdalOr4dNtaUH+746pDMmxXru4X9yVQZwGhUI86shQpxNLURHPI8zY 21 | 7E1ouuJsa7vD/6oF5cFQbaPV3O8uK3hobu4CJk6Tv+6BAF+//W5PEwDRAoGAEWQo 22 | 7DBT/S4W4Evumc9+pR0Vhc/gOOcS8aioke870LgELT3m68G2iaKPrGVXj4/LhevP 23 | 6RX50mjeM2Je1tmnbTgVLNMaGY62J860ydWdMsCBu+G1g8QDwB+9dTShTs0Eo9pE 24 | 5vL98wOymQuUqpzt2pX8mRAypL7NH+Ds3LLGcIUCgYBozXdjgkMGlhTZQXW2wnB/ 25 | bN6pZEyq1inON/mXoP5f8s98UP0bx+AF6gqg984nL0hbzucUoq4CY/FMHG23qo6P 26 | y0kB6wDzE4Hsi854MPaiAtPZyOgvd1TsxTDvGaOrP9uyy7s38L9yE3xwZyRk6j0i 27 | fr2GxjuUZw0NW2LJY6XClw== 28 | -----END PRIVATE KEY----- 29 | -------------------------------------------------------------------------------- /extensions/baseline/config.lua: -------------------------------------------------------------------------------- 1 | local config = {} -- extension configuration 2 | 3 | config.frontend = { 4 | baseline_color1 = "#fff", -- white 5 | baseline_color2 = "#000", -- black 6 | baseline_color3 = "#888", 7 | baseline_color4 = "#000", 8 | baseline_color5 = "144, 144, 144", 9 | baseline_color6 = "#bbb", 10 | baseline_color01 = "#888", 11 | baseline_color02 = "#ccc", 12 | baseline_color04 = "#f6f6f6", 13 | baseline_color05 = "#f2f2f2", 14 | baseline_color06 = "0, 0, 0", 15 | baseline_color08 = "#ebebeb", 16 | baseline_color09 = "#d9d9d9", 17 | 18 | baseline_font1 = "Arial, Helvetica, sans-serif", 19 | baseline_font2 = '"Courier New", monospace', 20 | } 21 | 22 | config.module = { 23 | {name = "BaselineHtmlTemplate", script = "BaselineHtmlTemplate.lua"} 24 | } 25 | 26 | config.javascript = { 27 | {name = "Popup", script = "widget/popup/Popup.js"}, 28 | {name = "InfoPopup", script = "widget/popup/InfoPopup.js"}, 29 | {name = "OneFieldPopup", script = "widget/popup/OneFieldPopup.js"}, 30 | {name = "TwoFieldsPopup", script = "widget/popup/TwoFieldsPopup.js"}, 31 | {name = "ThreeFieldsPopup", script = "widget/popup/ThreeFieldsPopup.js"}, 32 | {name = "QuestionPopup", script = "widget/popup/QuestionPopup.js"} 33 | } 34 | 35 | config.stylesheet = { 36 | {name = "style", script = "widget/style.css"}, 37 | {name = "Popup", script = "widget/popup/Popup.css"} 38 | } 39 | 40 | config.parse = { 41 | {name = "/build/static/nav.css", script = "widget/nav.css"} 42 | } 43 | 44 | config.static = { 45 | "static" 46 | } 47 | 48 | return config -- return extension configuration -------------------------------------------------------------------------------- /extensions/baseline/src/BaselineHtmlTemplate.lua: -------------------------------------------------------------------------------- 1 | return [[ 2 | 3 | 4 | 5 | {{title}} 6 | 7 | 8 | 9 | 10 | 11 | 12 | {{externalCSS}} 13 | 14 | 15 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 27 | 28 | {{externalJS}} 29 | 30 | 33 | 34 | 35 | 36 | 37 |
38 |
39 | 42 | 43 | 44 | ]] -------------------------------------------------------------------------------- /extensions/baseline/src/widget/nav.css: -------------------------------------------------------------------------------- 1 | @charset "UTF-8"; 2 | 3 | /* skel-baseline v2.0.3 | (c) n33 | getskel.com | MIT licensed */ 4 | 5 | /* Basic */ 6 | 7 | body, input, select, textarea { 8 | font-size: 12pt; 9 | } 10 | 11 | /* Header */ 12 | 13 | #skel-layers-wrapper { 14 | padding-top: 0; 15 | } 16 | 17 | #header { 18 | display: none; 19 | } 20 | 21 | /* Banner */ 22 | 23 | #banner { 24 | padding: 6em 2em; 25 | } 26 | 27 | /* Layers */ 28 | 29 | #navButton .toggle { 30 | text-decoration: none; 31 | height: 100%; 32 | left: 0; 33 | position: absolute; 34 | top: 0; 35 | width: 100%; 36 | } 37 | 38 | #navButton .toggle:before { 39 | content: ""; 40 | -moz-osx-font-smoothing: grayscale; 41 | -webkit-font-smoothing: antialiased; 42 | font-family: FontAwesome; 43 | font-style: normal; 44 | font-weight: normal; 45 | text-transform: none !important; 46 | } 47 | 48 | #navButton .toggle:before { 49 | background: rgba({{baseline_color5}}, 0.65); 50 | border-radius: 4px; 51 | color: {{baseline_color1}}; 52 | display: block; 53 | font-size: 16px; 54 | height: 2.25em; 55 | left: 0.5em; 56 | line-height: 2.25em; 57 | position: absolute; 58 | text-align: center; 59 | top: 0.5em; 60 | width: 3.5em; 61 | } 62 | 63 | #navPanel { 64 | background: {{baseline_color1}}; 65 | color: {{baseline_color2}}; 66 | } 67 | 68 | #navPanel nav { 69 | padding: 0.5em 1.25em; 70 | } 71 | 72 | #navPanel nav ul { 73 | list-style: none; 74 | margin: 0; 75 | padding: 0; 76 | } 77 | 78 | #navPanel nav ul li { 79 | padding: 0; 80 | } 81 | 82 | #navPanel nav ul li:first-child a:not(.button), #navPanel nav ul li:first-child span:not(.button) { 83 | border-top: 0; 84 | } 85 | 86 | #navPanel nav .button { 87 | width: 100%; 88 | } -------------------------------------------------------------------------------- /extensions/baseline/src/widget/popup/InfoPopup.js: -------------------------------------------------------------------------------- 1 | Widget.InfoPopup = function (data) { 2 | var info = parse(function(){/*! 3 |

{{info}}

4 | 5 | 9 | */}, data) 10 | 11 | this.popup = new Widget.Popup({info: info}) 12 | vars.infoPopup = this.popup 13 | this.popup.init() 14 | } 15 | 16 | Widget.InfoPopup.prototype = { 17 | constructor: Widget.InfoPopup 18 | } -------------------------------------------------------------------------------- /extensions/baseline/src/widget/popup/OneFieldPopup.js: -------------------------------------------------------------------------------- 1 | Widget.OneFieldPopup = function (data) { 2 | data.guid = Widget.guid() 3 | 4 | var info = parse(function(){/*! 5 | {{?@ !isEmpty(data.info) 6 |

{{info}}

7 | }}? 8 | 9 | 17 | 18 | 22 | 26 | */}, data) 27 | 28 | this.popup = new Widget.Popup({info: info}) 29 | this.popup.proceed = data.proceed 30 | vars.oneFieldPopup = this.popup 31 | this.popup.init() 32 | } 33 | 34 | Widget.OneFieldPopup.prototype = { 35 | constructor: Widget.OneFieldPopup 36 | } -------------------------------------------------------------------------------- /extensions/baseline/src/widget/popup/Popup.css: -------------------------------------------------------------------------------- 1 | .overlay { 2 | position: fixed; 3 | top: 0px; 4 | right: 0px; 5 | bottom: 0px; 6 | left: 0px; 7 | opacity: 0; 8 | background-color: white; 9 | z-index: 100000; 10 | } 11 | 12 | .popup { 13 | position: fixed; 14 | top: 50%; 15 | left: 50%; 16 | -webkit-transform: translate(-50%, -50%); 17 | transform: translate(-50%, -50%); 18 | max-width: 90%; 19 | overflow-x: auto; 20 | max-height: 90%; 21 | overflow-y: auto; 22 | padding: 30px 30px 30px 30px; 23 | border-radius: 4px; 24 | border: 1px solid black; 25 | background-color: white; 26 | z-index: 100001; 27 | } 28 | 29 | .spaced-down { 30 | margin: 0px 0px 9px 0px; 31 | } 32 | 33 | .spaced-up { 34 | margin: 9px 0px 0px 0px; 35 | } -------------------------------------------------------------------------------- /extensions/baseline/src/widget/popup/Popup.js: -------------------------------------------------------------------------------- 1 | Widget.Popup = function (data) { 2 | this.data = data 3 | this.html = parse(function(){/*! 4 |
5 |
6 | 7 |
8 | */}, data) 9 | } 10 | 11 | Widget.Popup.prototype = { 12 | constructor: Widget.Popup, 13 | 14 | init: function () { 15 | $("#popups").html(this.html) 16 | }, 17 | 18 | delete: function () { 19 | $("#popups").empty() 20 | } 21 | } -------------------------------------------------------------------------------- /extensions/baseline/src/widget/popup/QuestionPopup.js: -------------------------------------------------------------------------------- 1 | Widget.QuestionPopup = function (data) { 2 | var info = parse(function(){/*! 3 |

{{question}}

4 | 5 | 9 | 13 | */}, data) 14 | 15 | this.popup = new Widget.Popup({info: info}) 16 | this.popup.proceed = data.proceed 17 | vars.questionPopup = this.popup 18 | this.popup.init() 19 | } 20 | 21 | Widget.QuestionPopup.prototype = { 22 | constructor: Widget.QuestionPopup 23 | } -------------------------------------------------------------------------------- /extensions/baseline/src/widget/popup/ThreeFieldsPopup.js: -------------------------------------------------------------------------------- 1 | Widget.ThreeFieldsPopup = function (data) { 2 | data.guid1 = Widget.guid() 3 | data.guid2 = Widget.guid() 4 | data.guid3 = Widget.guid() 5 | 6 | var info = parse(function(){/*! 7 | {{?@ !isEmpty(data.info) 8 |

{{info}}

9 | }}? 10 | 11 | 19 | 20 | 28 | 29 | 37 | 38 | 42 | 46 | */}, data) 47 | 48 | this.popup = new Widget.Popup({info: info}) 49 | this.popup.proceed = data.proceed 50 | vars.threeFieldsPopup = this.popup 51 | this.popup.init() 52 | } 53 | 54 | Widget.ThreeFieldsPopup.prototype = { 55 | constructor: Widget.ThreeFieldsPopup 56 | } -------------------------------------------------------------------------------- /extensions/baseline/src/widget/popup/TwoFieldsPopup.js: -------------------------------------------------------------------------------- 1 | Widget.TwoFieldsPopup = function (data) { 2 | data.guid1 = Widget.guid() 3 | data.guid2 = Widget.guid() 4 | 5 | var info = parse(function(){/*! 6 | {{?@ !isEmpty(data.info) 7 |

{{info}}

8 | }}? 9 | 10 | 18 | 19 | 27 | 28 | 32 | 36 | */}, data) 37 | 38 | this.popup = new Widget.Popup({info: info}) 39 | this.popup.proceed = data.proceed 40 | vars.twoFieldsPopup = this.popup 41 | this.popup.init() 42 | } 43 | 44 | Widget.TwoFieldsPopup.prototype = { 45 | constructor: Widget.TwoFieldsPopup 46 | } -------------------------------------------------------------------------------- /extensions/baseline/static/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/strumasoft/octopus/4d66e3d6045cbd533353696abd80e48b1d606f18/extensions/baseline/static/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /extensions/baseline/static/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/strumasoft/octopus/4d66e3d6045cbd533353696abd80e48b1d606f18/extensions/baseline/static/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /extensions/baseline/static/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/strumasoft/octopus/4d66e3d6045cbd533353696abd80e48b1d606f18/extensions/baseline/static/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /extensions/baseline/static/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/strumasoft/octopus/4d66e3d6045cbd533353696abd80e48b1d606f18/extensions/baseline/static/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /extensions/baseline/static/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/strumasoft/octopus/4d66e3d6045cbd533353696abd80e48b1d606f18/extensions/baseline/static/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /extensions/baseline/static/js/html5shiv.js: -------------------------------------------------------------------------------- 1 | /* 2 | HTML5 Shiv v3.6.2 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed 3 | */ 4 | (function(l,f){function m(){var a=e.elements;return"string"==typeof a?a.split(" "):a}function i(a){var b=n[a[o]];b||(b={},h++,a[o]=h,n[h]=b);return b}function p(a,b,c){b||(b=f);if(g)return b.createElement(a);c||(c=i(b));b=c.cache[a]?c.cache[a].cloneNode():r.test(a)?(c.cache[a]=c.createElem(a)).cloneNode():c.createElem(a);return b.canHaveChildren&&!s.test(a)?c.frag.appendChild(b):b}function t(a,b){if(!b.cache)b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag(); 5 | a.createElement=function(c){return!e.shivMethods?b.createElem(c):p(c,a,b)};a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+m().join().replace(/\w+/g,function(a){b.createElem(a);b.frag.createElement(a);return'c("'+a+'")'})+");return n}")(e,b.frag)}function q(a){a||(a=f);var b=i(a);if(e.shivCSS&&!j&&!b.hasCSS){var c,d=a;c=d.createElement("p");d=d.getElementsByTagName("head")[0]||d.documentElement;c.innerHTML="x"; 6 | c=d.insertBefore(c.lastChild,d.firstChild);b.hasCSS=!!c}g||t(a,b);return a}var k=l.html5||{},s=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,r=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,j,o="_html5shiv",h=0,n={},g;(function(){try{var a=f.createElement("a");a.innerHTML="";j="hidden"in a;var b;if(!(b=1==a.childNodes.length)){f.createElement("a");var c=f.createDocumentFragment();b="undefined"==typeof c.cloneNode|| 7 | "undefined"==typeof c.createDocumentFragment||"undefined"==typeof c.createElement}g=b}catch(d){g=j=!0}})();var e={elements:k.elements||"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup main mark meter nav output progress section summary time video",version:"3.6.2",shivCSS:!1!==k.shivCSS,supportsUnknownElements:g,shivMethods:!1!==k.shivMethods,type:"default",shivDocument:q,createElement:p,createDocumentFragment:function(a,b){a||(a=f);if(g)return a.createDocumentFragment(); 8 | for(var b=b||i(a),c=b.frag.cloneNode(),d=0,e=m(),h=e.length;d', 53 | orientation: 'vertical', 54 | position: 'top-left', 55 | side: 'left', 56 | width: 250 57 | }, 58 | navButton: { 59 | breakpoints: 'medium', 60 | html: '', 61 | position: 'top-left', 62 | side: 'top' 63 | } 64 | } 65 | } 66 | }); 67 | 68 | $(function() { 69 | 70 | var $window = $(window), 71 | $body = $('body'); 72 | 73 | // Disable animations/transitions until the page has loaded. 74 | $body.addClass('is-loading'); 75 | 76 | $window.on('load', function() { 77 | $body.removeClass('is-loading'); 78 | }); 79 | 80 | }); 81 | 82 | })(jQuery); 83 | -------------------------------------------------------------------------------- /extensions/baseline/static/js/init-shop.js: -------------------------------------------------------------------------------- 1 | /* skel-baseline v2.0.3 | (c) n33 | getskel.com | MIT licensed */ 2 | 3 | (function($) { 4 | 5 | skel.init({ 6 | reset: 'full', 7 | breakpoints: { 8 | global: { 9 | href: '', 10 | containers: '90%', 11 | grid: { gutters: ['2em', 0] } 12 | }, 13 | xlarge: { 14 | media: '(max-width: 1680px)', 15 | href: '', 16 | containers: '90%' 17 | }, 18 | large: { 19 | media: '(max-width: 1280px)', 20 | href: '', 21 | containers: '90%', 22 | grid: { gutters: ['1.5em', 0] }, 23 | viewport: { scalable: false } 24 | }, 25 | medium: { 26 | media: '(max-width: 980px)', 27 | href: '/build/static/nav.css', 28 | containers: '90%' 29 | }, 30 | small: { 31 | media: '(max-width: 736px)', 32 | href: '', 33 | containers: '90%', 34 | grid: { gutters: ['1.25em', 0] } 35 | }, 36 | xsmall: { 37 | media: '(max-width: 480px)', 38 | href: '' 39 | } 40 | }, 41 | plugins: { 42 | layers: { 43 | config: { 44 | mode: 'transform' 45 | }, 46 | navPanel: { 47 | animation: 'pushX', 48 | breakpoints: 'medium', 49 | clickToHide: true, 50 | height: '100%', 51 | hidden: true, 52 | html: '
', 53 | orientation: 'vertical', 54 | position: 'top-left', 55 | side: 'left', 56 | width: 250 57 | }, 58 | navButton: { 59 | breakpoints: 'medium', 60 | html: '', 61 | position: 'top-left', 62 | side: 'top' 63 | } 64 | } 65 | } 66 | }); 67 | 68 | $(function() { 69 | 70 | var $window = $(window), 71 | $body = $('body'); 72 | 73 | // Disable animations/transitions until the page has loaded. 74 | $body.addClass('is-loading'); 75 | 76 | $window.on('load', function() { 77 | $body.removeClass('is-loading'); 78 | }); 79 | 80 | }); 81 | 82 | })(jQuery); -------------------------------------------------------------------------------- /extensions/baseline/static/js/jquery.pretty-text-diff.js: -------------------------------------------------------------------------------- 1 | // patched by laz 2 | 3 | /* 4 | @preserve jQuery.PrettyTextDiff 1.0.4 5 | See https://github.com/arnab/jQuery.PrettyTextDiff/ 6 | */ 7 | 8 | (function() { 9 | var $; 10 | 11 | $ = jQuery; 12 | 13 | $.fn.extend({ 14 | prettyTextDiff: function(options) { 15 | var dmp, settings; 16 | settings = { 17 | originalContainer: ".original", 18 | changedContainer: ".changed", 19 | diffContainer: ".diff", 20 | cleanup: true, 21 | debug: false 22 | }; 23 | settings = $.extend(settings, options); 24 | $.fn.prettyTextDiff.debug("Options: ", settings, settings); 25 | dmp = new diff_match_patch(); 26 | return this.each(function() { 27 | var changed, diff_as_html, diffs, original; 28 | if (settings.originalContent && settings.changedContent) { 29 | original = settings.originalContent // enable markup detection 30 | changed = settings.changedContent // enable markup detection 31 | } else { 32 | original = $(settings.originalContainer, this).text(); 33 | changed = $(settings.changedContainer, this).text(); 34 | } 35 | $.fn.prettyTextDiff.debug("Original text found: ", original, settings); 36 | $.fn.prettyTextDiff.debug("Changed text found: ", changed, settings); 37 | diffs = dmp.diff_main(original, changed); 38 | if (settings.cleanup) { 39 | dmp.diff_cleanupSemantic(diffs); 40 | } 41 | $.fn.prettyTextDiff.debug("Diffs: ", diffs, settings); 42 | diff_as_html = $.map(diffs, function(diff) { 43 | return $.fn.prettyTextDiff.createHTML(diff); 44 | }); 45 | $(settings.diffContainer, this).html(diff_as_html.join('')); 46 | return this; 47 | }); 48 | } 49 | }); 50 | 51 | $.fn.prettyTextDiff.debug = function(message, object, settings) { 52 | if (settings.debug) { 53 | return console.log(message, object); 54 | } 55 | }; 56 | 57 | $.fn.prettyTextDiff.createHTML = function(diff) { 58 | var data, html, operation, pattern_amp, pattern_gt, pattern_lt, pattern_para, text; 59 | html = []; 60 | pattern_amp = /&/g; 61 | pattern_lt = //g; 63 | pattern_para = /\r\n/g; 64 | operation = diff[0], data = diff[1]; 65 | text = data.replace(pattern_amp, '&').replace(pattern_lt, '<').replace(pattern_gt, '>').replace(pattern_para, '\n'); 66 | switch (operation) { 67 | case DIFF_INSERT: 68 | return '' + text + ''; 69 | case DIFF_DELETE: 70 | return '' + text + ''; 71 | case DIFF_EQUAL: 72 | return '' + text + ''; 73 | } 74 | }; 75 | 76 | }).call(this); -------------------------------------------------------------------------------- /extensions/config.lua: -------------------------------------------------------------------------------- 1 | return { 2 | extensions = { 3 | {octopusExtensionsDir, "core"}, 4 | {octopusExtensionsDir, "baseline"}, 5 | --{octopusExtensionsDir, "orm"}, -- @deprecated > use luaorm > https://github.com/strumasoft/luaorm 6 | {octopusExtensionsDir, "security"}, 7 | {octopusExtensionsDir, "editor"}, 8 | {octopusExtensionsDir, "repository"}, 9 | {octopusExtensionsDir, "database"}, 10 | {octopusExtensionsDir, "shop"}, 11 | {octopusExtensionsDir, "demo"}, 12 | }, 13 | 14 | octopusExtensionsDir = octopusExtensionsDir, 15 | octopusHostDir = octopusHostDir, 16 | port = port, 17 | securePort = securePort, 18 | luaCodeCache = luaCodeCache, 19 | serverName = "localhost", 20 | errorLog = "error_log logs/error.log;", 21 | accessLog = "access_log logs/access.log;", 22 | includeDrop = "", 23 | maxBodySize = "50k", 24 | 25 | databaseConnection = { 26 | rdbms = rdbms, 27 | driver = rdbms_driver, 28 | host = rdbms_host, 29 | port = rdbms_port, 30 | user = rdbms_user, 31 | password = rdbms_password, 32 | database = rdbms_db, 33 | compact = false, 34 | usePreparedStatement = false, 35 | debugDB = true, 36 | charset = "utf8", 37 | max_packet_size = 1024 * 1024, 38 | ssl = true 39 | }, 40 | 41 | globalParameters = { 42 | octopusHostDir = octopusHostDir, 43 | sourceCtxPath = "", 44 | requireSecurity = requireSecurity, 45 | sessionTimeout = sessionTimeout, 46 | }, 47 | } -------------------------------------------------------------------------------- /extensions/core/config.lua: -------------------------------------------------------------------------------- 1 | local config = {} -- extension configuration 2 | 3 | config.module = { 4 | {name = "builder", script = "builder.lua"}, 5 | {name = "cookie", script = "cookie.lua"}, 6 | {name = "crypto", script = "rocky/crypto.lua"}, 7 | {name = "database", script = "database.lua"}, 8 | {name = "date", script = "date.lua"}, 9 | {name = "eval", script = "eval.lua"}, 10 | {name = "exception", script = "exception.lua"}, 11 | {name = "exit", script = "exit.lua"}, 12 | {name = "fileutil", script = "fileutil.lua"}, 13 | {name = "http", script = "http.lua"}, 14 | {name = "http_headers", script = "http_headers.lua"}, 15 | {name = "json", script = "json.lua"}, 16 | {name = "param", script = "param.lua"}, 17 | {name = "parse", script = "parse.lua"}, 18 | {name = "persistence", script = "persistence.lua"}, 19 | {name = "stacktrace", script = "stacktrace.lua"}, 20 | {name = "template", script = "template.lua"}, 21 | {name = "upload", script = "upload.lua"}, 22 | {name = "utf8", script = "utf8.lua"}, 23 | {name = "utf8data", script = "utf8data.lua"}, 24 | {name = "util", script = "util.lua"}, 25 | {name = "uuid", script = "uuid.lua"}, 26 | 27 | {name = "resty.md5", script = "resty/md5.lua"}, 28 | {name = "resty.mysql", script = "resty/mysql.lua"}, 29 | {name = "resty.rsa", script = "resty/rsa.lua"}, 30 | {name = "resty.sha", script = "resty/sha.lua"}, 31 | {name = "resty.sha1", script = "resty/sha1.lua"}, 32 | {name = "resty.sha256", script = "resty/sha256.lua"}, 33 | 34 | {name = "rocky.crypto", script = "rocky/crypto.lua"}, 35 | {name = "rocky.luaorm", script = "rocky/luaorm.lua"}, 36 | {name = "rocky.ngxssl", script = "rocky/ngxssl.lua"}, 37 | {name = "rocky.postgresql", script = "rocky/postgresql.lua"}, 38 | {name = "rocky.typedef", script = "rocky/typedef.lua"}, 39 | } 40 | 41 | config.javascript = { 42 | {name = "parse", script = "js/parse.js"}, 43 | {name = "widget", script = "js/widget.js"} 44 | } 45 | 46 | return config -- return extension configuration -------------------------------------------------------------------------------- /extensions/core/src/database.lua: -------------------------------------------------------------------------------- 1 | local property = require "property" 2 | local luaorm = require "rocky.luaorm" 3 | local types = require "type" 4 | 5 | local opts = {types = types} 6 | for k,v in pairs(property.databaseConnection) do opts[k] = v end 7 | 8 | return { 9 | connect = function () 10 | return luaorm.connect(opts) 11 | end 12 | } 13 | -------------------------------------------------------------------------------- /extensions/core/src/eval.lua: -------------------------------------------------------------------------------- 1 | local param = require "param" 2 | 3 | 4 | local function load_code(code, environment) 5 | if setfenv and loadstring then 6 | local f = assert(loadstring(code)) 7 | setfenv(f,environment) 8 | return f 9 | else 10 | return assert(load(code, nil, "t", environment)) 11 | end 12 | end 13 | 14 | 15 | local function load_file(fileName, environment) 16 | if setfenv and loadfile then 17 | local f = assert(loadfile(fileName)) 18 | setfenv(f,environment) 19 | return f 20 | else 21 | return assert(loadfile(fileName, "t", environment)) 22 | end 23 | end 24 | 25 | 26 | local function evalCode(code, environment, addReturn) 27 | if addReturn then 28 | local f = load_code("return " .. code, environment) 29 | local res, res2, res3, res4, res5 = f() 30 | return res, res2, res3, res4, res5 31 | else 32 | local f = load_code(code, environment) 33 | local res, res2, res3, res4, res5 = f() 34 | return res, res2, res3, res4, res5 35 | end 36 | end 37 | 38 | 39 | local function evalFile(fileName, environment) 40 | local f = load_file(fileName, environment) 41 | local res, res2, res3, res4, res5 = f() 42 | return res, res2, res3, res4, res5 43 | end 44 | 45 | 46 | return { 47 | code = evalCode, 48 | file = evalFile 49 | } -------------------------------------------------------------------------------- /extensions/core/src/exception.lua: -------------------------------------------------------------------------------- 1 | return function (err) 2 | if not ngx then 3 | print(err .. "\n" .. debug.traceback()) 4 | error(err) 5 | end 6 | 7 | if err then 8 | if type(err) == "table" then 9 | local json = require "json" 10 | ngx.log(ngx.ERR, json.encode(err) .. "\n" .. debug.traceback()) 11 | else 12 | ngx.log(ngx.ERR, err .. "\n" .. debug.traceback()) 13 | end 14 | else 15 | err = "error" 16 | ngx.log(ngx.ERR, err .. "\n" .. debug.traceback()) 17 | end 18 | 19 | error(err) 20 | end -------------------------------------------------------------------------------- /extensions/core/src/exit.lua: -------------------------------------------------------------------------------- 1 | return function (err, status) 2 | ngx.status = status or ngx.HTTP_INTERNAL_SERVER_ERROR 3 | 4 | if type(err) == "table" then 5 | local json = require "json" 6 | ngx.say(json.encode(err)) 7 | elseif err then 8 | ngx.say(err) 9 | end 10 | 11 | return ngx.exit(ngx.HTTP_OK) 12 | end -------------------------------------------------------------------------------- /extensions/core/src/http_headers.lua: -------------------------------------------------------------------------------- 1 | local rawget, rawset, setmetatable = 2 | rawget, rawset, setmetatable 3 | 4 | local str_gsub = string.gsub 5 | local str_lower = string.lower 6 | 7 | 8 | local _M = { 9 | _VERSION = '0.01', 10 | } 11 | 12 | 13 | -- Returns an empty headers table with internalised case normalisation. 14 | -- Supports the same cases as in ngx_lua: 15 | -- 16 | -- headers.content_length 17 | -- headers["content-length"] 18 | -- headers["Content-Length"] 19 | function _M.new(self) 20 | local mt = { 21 | normalised = {}, 22 | } 23 | 24 | 25 | mt.__index = function(t, k) 26 | local k_hyphened = str_gsub(k, "_", "-") 27 | local matched = rawget(t, k) 28 | if matched then 29 | return matched 30 | else 31 | local k_normalised = str_lower(k_hyphened) 32 | return rawget(t, mt.normalised[k_normalised]) 33 | end 34 | end 35 | 36 | 37 | -- First check the normalised table. If there's no match (first time) add an entry for 38 | -- our current case in the normalised table. This is to preserve the human (prettier) case 39 | -- instead of outputting lowercased header names. 40 | -- 41 | -- If there's a match, we're being updated, just with a different case for the key. We use 42 | -- the normalised table to give us the original key, and perorm a rawset(). 43 | mt.__newindex = function(t, k, v) 44 | -- we support underscore syntax, so always hyphenate. 45 | local k_hyphened = str_gsub(k, "_", "-") 46 | 47 | -- lowercase hyphenated is "normalised" 48 | local k_normalised = str_lower(k_hyphened) 49 | 50 | if not mt.normalised[k_normalised] then 51 | mt.normalised[k_normalised] = k_hyphened 52 | rawset(t, k_hyphened, v) 53 | else 54 | rawset(t, mt.normalised[k_normalised], v) 55 | end 56 | end 57 | 58 | return setmetatable({}, mt) 59 | end 60 | 61 | 62 | return _M 63 | -------------------------------------------------------------------------------- /extensions/core/src/param.lua: -------------------------------------------------------------------------------- 1 | local util = require "util" 2 | 3 | 4 | local m = {} -- module 5 | 6 | setmetatable(m, { 7 | __index = function (table, key) 8 | local x = ngx.var["arg_" .. key] 9 | if x then 10 | return util.unescape(x) 11 | else 12 | return nil 13 | end 14 | end 15 | } 16 | ) 17 | 18 | return m -- return module -------------------------------------------------------------------------------- /extensions/core/src/resty/README.md: -------------------------------------------------------------------------------- 1 | ### OpenResty MySQL driver and related software with very slight modifications 2 | Run resty.sh to download, modify with patch if necessary or remove them 3 | ```sh 4 | bash resty.sh download 5 | bash resty.sh modify 6 | bash resty.sh remove 7 | ``` 8 | 9 | ### md5.lua 10 | https://github.com/openresty/lua-resty-string/blob/master/lib/resty/md5.lua 11 | 12 | ### sha.lua 13 | https://github.com/openresty/lua-resty-string/blob/master/lib/resty/sha.lua 14 | 15 | ### sha1.lua 16 | https://github.com/openresty/lua-resty-string/blob/master/lib/resty/sha1.lua 17 | 18 | ### sha256.lua 19 | https://github.com/openresty/lua-resty-string/blob/master/lib/resty/sha256.lua 20 | 21 | ### rsa.lua 22 | https://github.com/spacewander/lua-resty-rsa/blob/master/lib/resty/rsa.lua 23 | 24 | ### mysql.lua 25 | https://github.com/openresty/lua-resty-mysql/blob/master/lib/resty/mysql.lua -------------------------------------------------------------------------------- /extensions/core/src/resty/md5.lua: -------------------------------------------------------------------------------- 1 | -- Copyright (C) by Yichun Zhang (agentzh) 2 | 3 | 4 | local ffi = require "ffi" 5 | local ffi_new = ffi.new 6 | local ffi_str = ffi.string 7 | local C = ffi.load("ssl.so.3") 8 | local setmetatable = setmetatable 9 | --local error = error 10 | 11 | 12 | local _M = { _VERSION = '0.14' } 13 | 14 | local mt = { __index = _M } 15 | 16 | 17 | ffi.cdef[[ 18 | typedef unsigned long MD5_LONG ; 19 | 20 | enum { 21 | MD5_CBLOCK = 64, 22 | MD5_LBLOCK = MD5_CBLOCK/4 23 | }; 24 | 25 | typedef struct MD5state_st 26 | { 27 | MD5_LONG A,B,C,D; 28 | MD5_LONG Nl,Nh; 29 | MD5_LONG data[MD5_LBLOCK]; 30 | unsigned int num; 31 | } MD5_CTX; 32 | 33 | int MD5_Init(MD5_CTX *c); 34 | int MD5_Update(MD5_CTX *c, const void *data, size_t len); 35 | int MD5_Final(unsigned char *md, MD5_CTX *c); 36 | ]] 37 | 38 | local buf = ffi_new("char[16]") 39 | local ctx_ptr_type = ffi.typeof("MD5_CTX[1]") 40 | 41 | 42 | function _M.new(self) 43 | local ctx = ffi_new(ctx_ptr_type) 44 | if C.MD5_Init(ctx) == 0 then 45 | return nil 46 | end 47 | 48 | return setmetatable({ _ctx = ctx }, mt) 49 | end 50 | 51 | 52 | function _M.update(self, s, len) 53 | return C.MD5_Update(self._ctx, s, len or #s) == 1 54 | end 55 | 56 | 57 | function _M.final(self) 58 | if C.MD5_Final(buf, self._ctx) == 1 then 59 | return ffi_str(buf, 16) 60 | end 61 | 62 | return nil 63 | end 64 | 65 | 66 | function _M.reset(self) 67 | return C.MD5_Init(self._ctx) == 1 68 | end 69 | 70 | 71 | return _M 72 | 73 | -------------------------------------------------------------------------------- /extensions/core/src/resty/resty.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Usage: bash resty.sh download 4 | # Usage: bash resty.sh modify 5 | # Usage: bash resty.sh remove 6 | 7 | 8 | download() { 9 | curl -O https://raw.githubusercontent.com/openresty/lua-resty-string/master/lib/resty/md5.lua 10 | curl -O https://raw.githubusercontent.com/openresty/lua-resty-string/master/lib/resty/sha.lua 11 | curl -O https://raw.githubusercontent.com/openresty/lua-resty-string/master/lib/resty/sha1.lua 12 | curl -O https://raw.githubusercontent.com/openresty/lua-resty-string/master/lib/resty/sha256.lua 13 | curl -O https://raw.githubusercontent.com/spacewander/lua-resty-rsa/master/lib/resty/rsa.lua 14 | curl -O https://raw.githubusercontent.com/openresty/lua-resty-mysql/master/lib/resty/mysql.lua 15 | } 16 | 17 | modify() { 18 | ssl_3_files=("md5" "sha1" "sha256") 19 | for file in "${ssl_3_files[@]}"; do 20 | sed -i 's/ffi\.C/ffi.load("ssl.so.3")/g' "$file.lua" 21 | done 22 | 23 | ssl_1_1_files=("rsa") 24 | for file in "${ssl_1_1_files[@]}"; do 25 | sed -i 's/ffi\.C/ffi.load("ssl.so.1.1")/g' "$file.lua" 26 | done 27 | } 28 | 29 | remove() { 30 | rm *.lua 31 | } 32 | 33 | main() { 34 | case $1 in 35 | download) 36 | download 37 | ;; 38 | modify) 39 | modify 40 | ;; 41 | remove) 42 | remove 43 | ;; 44 | *) 45 | SH=bash 46 | echo "Usage: $SH $0 download" 47 | echo "Usage: $SH $0 modify" 48 | echo "Usage: $SH $0 remove" 49 | exit 0 50 | ;; 51 | esac 52 | } 53 | 54 | main "$@" -------------------------------------------------------------------------------- /extensions/core/src/resty/sha.lua: -------------------------------------------------------------------------------- 1 | -- Copyright (C) by Yichun Zhang (agentzh) 2 | 3 | 4 | local ffi = require "ffi" 5 | 6 | 7 | local _M = { _VERSION = '0.14' } 8 | 9 | 10 | ffi.cdef[[ 11 | typedef unsigned long SHA_LONG; 12 | typedef unsigned long long SHA_LONG64; 13 | 14 | enum { 15 | SHA_LBLOCK = 16 16 | }; 17 | ]]; 18 | 19 | return _M 20 | -------------------------------------------------------------------------------- /extensions/core/src/resty/sha1.lua: -------------------------------------------------------------------------------- 1 | -- Copyright (C) by Yichun Zhang (agentzh) 2 | 3 | 4 | require "resty.sha" 5 | local ffi = require "ffi" 6 | local ffi_new = ffi.new 7 | local ffi_str = ffi.string 8 | local C = ffi.load("ssl.so.3") 9 | local setmetatable = setmetatable 10 | --local error = error 11 | 12 | 13 | local _M = { _VERSION = '0.14' } 14 | 15 | 16 | local mt = { __index = _M } 17 | 18 | 19 | ffi.cdef[[ 20 | typedef struct SHAstate_st 21 | { 22 | SHA_LONG h0,h1,h2,h3,h4; 23 | SHA_LONG Nl,Nh; 24 | SHA_LONG data[SHA_LBLOCK]; 25 | unsigned int num; 26 | } SHA_CTX; 27 | 28 | int SHA1_Init(SHA_CTX *c); 29 | int SHA1_Update(SHA_CTX *c, const void *data, size_t len); 30 | int SHA1_Final(unsigned char *md, SHA_CTX *c); 31 | ]] 32 | 33 | local digest_len = 20 34 | 35 | local buf = ffi_new("char[?]", digest_len) 36 | local ctx_ptr_type = ffi.typeof("SHA_CTX[1]") 37 | 38 | 39 | function _M.new(self) 40 | local ctx = ffi_new(ctx_ptr_type) 41 | if C.SHA1_Init(ctx) == 0 then 42 | return nil 43 | end 44 | 45 | return setmetatable({ _ctx = ctx }, mt) 46 | end 47 | 48 | 49 | function _M.update(self, s) 50 | return C.SHA1_Update(self._ctx, s, #s) == 1 51 | end 52 | 53 | 54 | function _M.final(self) 55 | if C.SHA1_Final(buf, self._ctx) == 1 then 56 | return ffi_str(buf, digest_len) 57 | end 58 | 59 | return nil 60 | end 61 | 62 | 63 | function _M.reset(self) 64 | return C.SHA1_Init(self._ctx) == 1 65 | end 66 | 67 | 68 | return _M 69 | 70 | -------------------------------------------------------------------------------- /extensions/core/src/resty/sha256.lua: -------------------------------------------------------------------------------- 1 | -- Copyright (C) by Yichun Zhang (agentzh) 2 | 3 | 4 | require "resty.sha" 5 | local ffi = require "ffi" 6 | local ffi_new = ffi.new 7 | local ffi_str = ffi.string 8 | local C = ffi.load("ssl.so.3") 9 | local setmetatable = setmetatable 10 | --local error = error 11 | 12 | 13 | local _M = { _VERSION = '0.14' } 14 | 15 | 16 | local mt = { __index = _M } 17 | 18 | 19 | ffi.cdef[[ 20 | typedef struct SHA256state_st 21 | { 22 | SHA_LONG h[8]; 23 | SHA_LONG Nl,Nh; 24 | SHA_LONG data[SHA_LBLOCK]; 25 | unsigned int num,md_len; 26 | } SHA256_CTX; 27 | 28 | int SHA256_Init(SHA256_CTX *c); 29 | int SHA256_Update(SHA256_CTX *c, const void *data, size_t len); 30 | int SHA256_Final(unsigned char *md, SHA256_CTX *c); 31 | ]] 32 | 33 | local digest_len = 32 34 | 35 | local buf = ffi_new("char[?]", digest_len) 36 | local ctx_ptr_type = ffi.typeof("SHA256_CTX[1]") 37 | 38 | 39 | function _M.new(self) 40 | local ctx = ffi_new(ctx_ptr_type) 41 | if C.SHA256_Init(ctx) == 0 then 42 | return nil 43 | end 44 | 45 | return setmetatable({ _ctx = ctx }, mt) 46 | end 47 | 48 | 49 | function _M.update(self, s) 50 | return C.SHA256_Update(self._ctx, s, #s) == 1 51 | end 52 | 53 | 54 | function _M.final(self) 55 | if C.SHA256_Final(buf, self._ctx) == 1 then 56 | return ffi_str(buf, digest_len) 57 | end 58 | 59 | return nil 60 | end 61 | 62 | 63 | function _M.reset(self) 64 | return C.SHA256_Init(self._ctx) == 1 65 | end 66 | 67 | 68 | return _M 69 | 70 | -------------------------------------------------------------------------------- /extensions/core/src/rocky/typedef.lua: -------------------------------------------------------------------------------- 1 | -- Copyright (C) 2024, StrumaSoft 2 | 3 | 4 | local function hasMany (type, property) 5 | if property then 6 | return {type = type .. "." .. property, has = "many"} 7 | else 8 | return {type = type, has = "many"} 9 | end 10 | end 11 | 12 | local function hasOne (type, property) 13 | if property then 14 | return {type = type .. "." .. property, has = "one"} 15 | else 16 | return {type = type, has = "one"} 17 | end 18 | end 19 | 20 | return { hasMany = hasMany, hasOne = hasOne } -------------------------------------------------------------------------------- /extensions/core/src/stacktrace.lua: -------------------------------------------------------------------------------- 1 | return function (err) 2 | if not ngx then 3 | print(err .. "\n" .. debug.traceback()) 4 | return 5 | end 6 | 7 | if err then 8 | if type(err) == "table" then 9 | local json = require "json" 10 | ngx.log(ngx.ERR, json.encode(err) .. "\n" .. debug.traceback()) 11 | else 12 | ngx.log(ngx.ERR, err .. "\n" .. debug.traceback()) 13 | end 14 | else 15 | ngx.log(ngx.ERR, "\n" .. debug.traceback()) 16 | end 17 | end -------------------------------------------------------------------------------- /extensions/core/src/template.lua: -------------------------------------------------------------------------------- 1 | local exception = require "exception" 2 | local eval = require "eval" 3 | local parse = require "parse" 4 | 5 | 6 | package.loaded.TEMPLATES = {} 7 | local function configuration (templateName) 8 | local TEMPLATES = package.loaded.TEMPLATES 9 | local octopusHostDir = ngx.var.octopusHostDir 10 | 11 | if TEMPLATES[octopusHostDir] then 12 | return TEMPLATES[octopusHostDir][templateName] 13 | else 14 | local templatesConfig = dofile(octopusHostDir .. "/build/src/html.lua") 15 | TEMPLATES[octopusHostDir] = templatesConfig 16 | return templatesConfig[templateName] 17 | end 18 | end 19 | 20 | 21 | package.loaded.TEMPLATES_CACHE = {} 22 | local template = {} 23 | setmetatable(template, { 24 | __index = function (t, templateName) 25 | local CACHE = package.loaded.TEMPLATES_CACHE 26 | 27 | local key 28 | if templateName:find("global.", 1, true) then 29 | key = templateName 30 | else 31 | key = ngx.var.octopusHostDir .. ":" .. templateName 32 | end 33 | 34 | local cached = CACHE[key] 35 | if cached then 36 | local view = cached 37 | return function (context, arguments) return parse(view, context, arguments) end 38 | end 39 | 40 | local scripts = configuration(templateName) 41 | if scripts then 42 | local view = eval.file(scripts[#scripts], {}) 43 | CACHE[key] = view 44 | return function (context, arguments) return parse(view, context, arguments) end 45 | end 46 | 47 | exception("html template " .. templateName .. " does not exists") 48 | end 49 | }) 50 | 51 | return template -------------------------------------------------------------------------------- /extensions/database/src/controller/DatabaseAddController.lua: -------------------------------------------------------------------------------- 1 | local json = require "json" 2 | local param = require "param" 3 | local util = require "util" 4 | local types = require "type" 5 | 6 | 7 | local typeName = param.type 8 | 9 | if util.isNotEmpty(typeName) then 10 | if types[typeName] then 11 | local arr = {} 12 | for k,v in pairs(types[typeName]) do 13 | arr[#arr + 1] = {name = k, value = nil, type = v} 14 | end 15 | arr[#arr + 1] = typeName -- last element is type name 16 | 17 | ngx.say(json.encode(arr)) 18 | else 19 | ngx.say(typeName .. " does not exist!") 20 | end 21 | else 22 | ngx.say("Select type!") 23 | end -------------------------------------------------------------------------------- /extensions/database/src/controller/DatabaseAddReferenceController.lua: -------------------------------------------------------------------------------- 1 | local json = require "json" 2 | local param = require "param" 3 | local exception = require "exception" 4 | local exit = require "exit" 5 | local util = require "util" 6 | local database = require "database" 7 | 8 | 9 | local from = param.from 10 | local to = param.to 11 | local parentId = param.parentId 12 | local id = param.id 13 | 14 | 15 | local db = database.connect() 16 | local op = db:operators() 17 | 18 | 19 | local function add (typeTo, typeFrom) 20 | if util.isNotEmpty(id) and util.isNotEmpty(parentId) then 21 | if typeTo == typeFrom then -- self referencing 22 | if from < to then 23 | db:add({[from .. "-" .. to] = {key = id, value = parentId}}) 24 | else 25 | db:add({[to .. "-" .. from] = {key = parentId, value = id}}) 26 | end 27 | else 28 | if from < to then 29 | db:add({[from .. "-" .. to] = {key = parentId, value = id}}) 30 | else 31 | db:add({[to .. "-" .. from] = {key = id, value = parentId}}) 32 | end 33 | end 34 | else 35 | exception("id or parantId is empty") 36 | end 37 | end 38 | 39 | 40 | local function f () 41 | -- find if reference(to) object exist 42 | local typeAndPropertyTo = util.split(to, ".") 43 | local typeTo = typeAndPropertyTo[1] 44 | local propertyTo = typeAndPropertyTo[2] 45 | 46 | local toObject = db:findOne({[typeTo] = {id = op.equal(id)}}) 47 | 48 | -- add reference 49 | local typeAndPropertyFrom = util.split(from, ".") 50 | local typeFrom = typeAndPropertyFrom[1] 51 | local propertyFrom = typeAndPropertyFrom[2] 52 | 53 | local t = db.types[typeFrom] 54 | local property = t[propertyFrom] 55 | if property then 56 | if property.has then 57 | if property.has == "one" then 58 | local res 59 | if from < to then 60 | res = db:find({[from .. "-" .. to] = {key = op.equal(parentId)}}) 61 | else 62 | res = db:find({[to .. "-" .. from] = {value = op.equal(parentId)}}) 63 | end 64 | if #res >= 1 then 65 | exception(from .. " must be one not many") 66 | else 67 | add(typeTo, typeFrom) 68 | end 69 | else 70 | add(typeTo, typeFrom) 71 | end 72 | else 73 | exception(from .. " is not reference") 74 | end 75 | else 76 | exception(from .. " does not exists") 77 | end 78 | end 79 | 80 | 81 | local ok, res = pcall(db.transaction, db, f) 82 | db:close() 83 | 84 | 85 | if ok then 86 | ngx.say("Add done!") 87 | else 88 | exit(res) 89 | end -------------------------------------------------------------------------------- /extensions/database/src/controller/DatabaseController.lua: -------------------------------------------------------------------------------- 1 | local json = require "json" 2 | local parse = require "parse" 3 | local param = require "param" 4 | local property = require "property" 5 | local database = require "database" 6 | 7 | 8 | 9 | local externalJS = [[ 10 | 11 | 12 | ]] 13 | 14 | 15 | local externalCSS = [[ 16 | 17 | ]] 18 | 19 | 20 | local initJSTemplate = [[ 21 | var vars = {} 22 | 23 | 24 | var editor = new Widget.DatabaseEditor({id: "editor"}) 25 | 26 | vars.scriptTab = { 27 | guid: Widget.guid(), 28 | id: Widget.guid(), 29 | name: "Script", 30 | html: editor.html 31 | } 32 | 33 | vars.resultTab = { 34 | guid: Widget.guid(), 35 | id: Widget.guid(), 36 | name: "Result", 37 | html: '
' 38 | } 39 | 40 | vars.editTab = { 41 | guid: Widget.guid(), 42 | id: Widget.guid(), 43 | name: "Edit", 44 | html: '
' 45 | } 46 | 47 | var tabs = [vars.scriptTab, vars.resultTab, vars.editTab] 48 | 49 | var databaseTabs = new Widget.DatabaseTabs({tabs: tabs}) 50 | 51 | var databaseNavigation = new Widget.DatabaseNavigation({{types}}) 52 | var databaseHeader = new Widget.DatabaseHeader({tabs: tabs}) 53 | 54 | var databaseTemplate = new Widget.DatabaseTemplate({ 55 | tabs: databaseTabs.html, 56 | navigation: databaseNavigation.html, 57 | header: databaseHeader.html 58 | }) 59 | 60 | Widget.setHtmlToPage(databaseTemplate.html); 61 | 62 | editor.init() 63 | databaseNavigation.init() 64 | ]] 65 | 66 | 67 | 68 | local db = database.connect() 69 | db:close() 70 | 71 | 72 | -- sort types -- 73 | local typeNames = {} 74 | for k,v in pairs(db.types) do typeNames[#typeNames + 1] = k end 75 | table.sort(typeNames) 76 | 77 | -- wrap everything up -- 78 | local types = {} 79 | for i=1,#typeNames do 80 | local k = typeNames[i] 81 | types[#types + 1] = {name = k} 82 | end 83 | 84 | 85 | 86 | local page = parse(require("BaselineHtmlTemplate"), { 87 | title = "Database", 88 | externalJS = externalJS, 89 | externalCSS = externalCSS, 90 | initJS = parse(initJSTemplate, { 91 | types = json.encode(types) 92 | }) 93 | }) 94 | 95 | ngx.say(page) -------------------------------------------------------------------------------- /extensions/database/src/controller/DatabaseDeleteAllReferencesController.lua: -------------------------------------------------------------------------------- 1 | local json = require "json" 2 | local exception = require "exception" 3 | local exit = require "exit" 4 | local util = require "util" 5 | local database = require "database" 6 | 7 | 8 | local data = util.parseForm(ngx.req.get_body_data()) 9 | local from = data.from 10 | local to = data.to 11 | local parentId = data.parentId 12 | 13 | 14 | local db = database.connect() 15 | local op = db:operators() 16 | 17 | 18 | local function f () 19 | local typeTo = util.split(to, ".")[1] 20 | local typeFrom = util.split(from, ".")[1] 21 | 22 | if util.isNotEmpty(from) and util.isNotEmpty(to) and util.isNotEmpty(parentId) then 23 | if typeTo == typeFrom then -- self referencing 24 | if from < to then 25 | db:delete({[from .. "-" .. to] = {value = parentId}}) 26 | else 27 | db:delete({[to .. "-" .. from] = {key = parentId}}) 28 | end 29 | else 30 | if from < to then 31 | db:delete({[from .. "-" .. to] = {key = parentId}}) 32 | else 33 | db:delete({[to .. "-" .. from] = {value = parentId}}) 34 | end 35 | end 36 | else 37 | exception("from, to or parentId is empty") 38 | end 39 | end 40 | 41 | 42 | local ok, res = pcall(db.transaction, db, f) 43 | db:close() 44 | 45 | 46 | if ok then 47 | ngx.say("Delete done!") 48 | else 49 | exit(res) 50 | end -------------------------------------------------------------------------------- /extensions/database/src/controller/DatabaseDeleteController.lua: -------------------------------------------------------------------------------- 1 | local json = require "json" 2 | local param = require "param" 3 | local exit = require "exit" 4 | local database = require "database" 5 | 6 | 7 | local instancesToDelete = json.decode(ngx.req.get_body_data()) 8 | 9 | 10 | local db = database.connect() 11 | local op = db:operators() 12 | 13 | local function f () 14 | for i=1,#instancesToDelete do 15 | db:delete({[instancesToDelete[i].type] = {id = instancesToDelete[i].id}}) 16 | end 17 | end 18 | 19 | local ok, res = pcall(db.transaction, db, f) 20 | db:close() 21 | 22 | 23 | if ok then 24 | ngx.say("Delete done!") 25 | else 26 | exit(res) 27 | end -------------------------------------------------------------------------------- /extensions/database/src/controller/DatabaseDeleteReferenceController.lua: -------------------------------------------------------------------------------- 1 | local json = require "json" 2 | local exit = require "exit" 3 | local util = require "util" 4 | local database = require "database" 5 | 6 | 7 | local instancesToDelete = json.decode(ngx.req.get_body_data()) 8 | 9 | 10 | local db = database.connect() 11 | local op = db:operators() 12 | 13 | local function f () 14 | for i=1,#instancesToDelete do 15 | local typeTo = util.split(instancesToDelete[i].to, ".")[1] 16 | local typeFrom = util.split(instancesToDelete[i].from, ".")[1] 17 | 18 | if typeTo == typeFrom then -- self referencing 19 | if instancesToDelete[i].from < instancesToDelete[i].to then 20 | db:delete({[instancesToDelete[i].from .. "-" .. instancesToDelete[i].to] = 21 | {key = instancesToDelete[i].id, value = instancesToDelete[i].parentId}}) 22 | else 23 | db:delete({[instancesToDelete[i].to .. "-" .. instancesToDelete[i].from] = 24 | {key = instancesToDelete[i].parentId, value = instancesToDelete[i].id}}) 25 | end 26 | else 27 | if instancesToDelete[i].from < instancesToDelete[i].to then 28 | db:delete({[instancesToDelete[i].from .. "-" .. instancesToDelete[i].to] = 29 | {key = instancesToDelete[i].parentId, value = instancesToDelete[i].id}}) 30 | else 31 | db:delete({[instancesToDelete[i].to .. "-" .. instancesToDelete[i].from] = 32 | {key = instancesToDelete[i].id, value = instancesToDelete[i].parentId}}) 33 | end 34 | end 35 | end 36 | end 37 | 38 | local ok, res = pcall(db.transaction, db, f) 39 | db:close() 40 | 41 | 42 | if ok then 43 | ngx.say("Delete done!") 44 | else 45 | exit(res) 46 | end -------------------------------------------------------------------------------- /extensions/database/src/controller/DatabaseEditController.lua: -------------------------------------------------------------------------------- 1 | local json = require "json" 2 | local param = require "param" 3 | local util = require "util" 4 | local database = require "database" 5 | local types = require "type" 6 | 7 | 8 | local id = param.id 9 | local typeName = param.type 10 | 11 | if util.isNotEmpty(typeName) then 12 | if types[typeName] then 13 | local db = database.connect() 14 | local op = db:operators() 15 | 16 | local ok, res = pcall(db.find, db, {[typeName] = {id = op.equal(id)}}) 17 | 18 | if ok then 19 | if #res == 1 then 20 | local type = types[typeName] 21 | 22 | -- sort property names -- 23 | local propertyNames = {} 24 | for k,v in pairs(type) do propertyNames[#propertyNames + 1] = k end 25 | table.sort(propertyNames) 26 | 27 | -- wrap everything up -- 28 | local arr = {} 29 | for i=1,#propertyNames do 30 | local k = propertyNames[i] 31 | local v = type[k] 32 | arr[#arr + 1] = {name = k, value = res[1][k], type = v} 33 | end 34 | arr[#arr + 1] = typeName -- last element is type name 35 | 36 | ngx.say(json.encode(arr)) 37 | else 38 | ngx.say("Can't edit 0 or more then 1 results!") 39 | end 40 | else 41 | ngx.say(json.encode(res)) 42 | end 43 | 44 | db:close() 45 | else 46 | ngx.say(typeName .. " does not exist!") 47 | end 48 | else 49 | ngx.say("Select type!") 50 | end -------------------------------------------------------------------------------- /extensions/database/src/controller/DatabaseExecuteController.lua: -------------------------------------------------------------------------------- 1 | local eval = require "eval" 2 | local parse = require "parse" 3 | local json = require "json" 4 | local param = require "param" 5 | local database = require "database" 6 | local property = require "property" 7 | 8 | 9 | -- prepare cript 10 | 11 | local script = ngx.req.get_body_data() 12 | 13 | local function f (env) 14 | local res, typeName = eval.code(script, env) 15 | return res, typeName 16 | end 17 | 18 | 19 | -- execute 20 | 21 | local db = database.connect() 22 | local op = db:operators() 23 | 24 | if property.forbidDirectSqlQuery then 25 | db.query = nil 26 | end 27 | 28 | local ok, res, typeName = pcall(f, {db = db, op = op}) 29 | db:close() 30 | 31 | 32 | if ok then 33 | if type(res) == "table" then 34 | if #res > 0 then 35 | local results = {} 36 | for i=1,#res do 37 | results[#results + 1] = res[i] 38 | end 39 | 40 | results[#results + 1] = typeName -- last element is type name 41 | 42 | ngx.say(json.encode(results)) 43 | else 44 | if typeName then 45 | ngx.say(json.encode({res, typeName})) 46 | else 47 | ngx.say(json.encode(res)) 48 | end 49 | end 50 | else 51 | ngx.say(res) 52 | end 53 | else 54 | ngx.say(res) 55 | end -------------------------------------------------------------------------------- /extensions/database/src/controller/DatabaseSaveController.lua: -------------------------------------------------------------------------------- 1 | local json = require "json" 2 | local param = require "param" 3 | local exit = require "exit" 4 | local database = require "database" 5 | 6 | 7 | local description = json.decode(ngx.req.get_body_data()) 8 | 9 | 10 | local db = database.connect() 11 | local op = db:operators() 12 | 13 | local function f () 14 | if description.spec.id then 15 | description.properties.id = description.spec.id 16 | return db:update({[description.spec.type] = description.properties}) 17 | else 18 | return db:add({[description.spec.type] = description.properties}) 19 | end 20 | end 21 | 22 | local ok, res = pcall(db.transaction, db, f) 23 | db:close() 24 | 25 | 26 | if ok then 27 | ngx.say(json.encode({info = "Save done!", id = res})) 28 | else 29 | exit(res) 30 | end -------------------------------------------------------------------------------- /extensions/database/src/controller/DatabaseTemplate.css: -------------------------------------------------------------------------------- 1 | #main { 2 | padding: 1em 0; 3 | } 4 | 5 | #databaseNavigation { 6 | overflow-x: scroll; 7 | } 8 | 9 | #editorDatabaseArea { 10 | padding: 0; 11 | } 12 | 13 | .resultbox { 14 | padding: 15px; 15 | margin: 15px; 16 | 17 | color: #333; 18 | font-size: 1em; 19 | font-weight: normal; 20 | 21 | background: #fff; 22 | border-radius: 6px; 23 | border: solid 1px #ddd; 24 | 25 | /* white-space: pre; */ 26 | } -------------------------------------------------------------------------------- /extensions/database/src/controller/DatabaseTemplate.js: -------------------------------------------------------------------------------- 1 | Widget.DatabaseTemplate = function (data) { 2 | this.data = data 3 | this.html = parse(function(){/*! 4 |
5 | 6 | {{header}} 7 | 8 |
9 |
10 |
11 | {{navigation}} 12 |
13 |
14 |
15 | {{tabs}} 16 |
17 |
18 |
19 | */}, data) 20 | } 21 | 22 | Widget.DatabaseTemplate.prototype = { 23 | constructor: Widget.DatabaseTemplate 24 | } 25 | 26 | Widget.DatabaseTemplate.maxHeight = function () { 27 | return window.innerHeight - Widget.DatabaseHeader.height() - 30 + "px" 28 | } -------------------------------------------------------------------------------- /extensions/database/src/filter/DatabaseRedirectOnSessionTimeoutFilter.lua: -------------------------------------------------------------------------------- 1 | local property = require "property" 2 | local util = require "util" 3 | local database = require "database" 4 | local userService = require "userService" 5 | 6 | 7 | 8 | -- security -- 9 | if property.requireSecurity then 10 | local db = database.connect() 11 | local ok, res = pcall(userService.loggedIn, db, {}, {"dbAdmin"}) 12 | db:close() 13 | 14 | -- remove cache -- 15 | ngx.ctx = {} 16 | 17 | if not ok or not res then 18 | if util.isNotEmpty(ngx.var.args) then 19 | ngx.redirect(property.securityLoginUrl .. ngx.var.uri .. "?" .. ngx.var.args) 20 | ngx.exit(ngx.HTTP_OK) 21 | else 22 | ngx.redirect(property.securityLoginUrl .. ngx.var.uri) 23 | ngx.exit(ngx.HTTP_OK) 24 | end 25 | end 26 | end -------------------------------------------------------------------------------- /extensions/database/src/filter/DatabaseThrowErrorOnSessionTimeoutFilter.lua: -------------------------------------------------------------------------------- 1 | local param = require "param" 2 | local property = require "property" 3 | local database = require "database" 4 | local userService = require "userService" 5 | 6 | 7 | 8 | -- security -- 9 | if property.requireSecurity then 10 | local db = database.connect() 11 | local ok, res = pcall(userService.loggedIn, db, {}, {"dbAdmin"}) 12 | db:close() 13 | 14 | -- remove cache -- 15 | ngx.ctx = {} 16 | 17 | if not ok or not res then 18 | ngx.status = ngx.HTTP_FORBIDDEN 19 | ngx.say("ERROR: user not logged in") 20 | ngx.exit(ngx.HTTP_OK) 21 | end 22 | end -------------------------------------------------------------------------------- /extensions/database/src/widget/DatabaseEditor.js: -------------------------------------------------------------------------------- 1 | Widget.DatabaseEditor = function (data) { 2 | this.data = data 3 | this.html = parse(function(){/*! 4 |
5 | */}, data) 6 | } 7 | 8 | Widget.DatabaseEditor.prototype = { 9 | constructor: Widget.DatabaseEditor, 10 | 11 | init: function () { 12 | var aceEditor = ace.edit(this.data.id) 13 | aceEditor.setTheme("ace/theme/chrome") 14 | aceEditor.getSession().setMode("ace/mode/lua") 15 | 16 | aceEditor.setShowPrintMargin(false) 17 | 18 | aceEditor.getSession().setOptions({ tabSize: 2, useSoftTabs: true }); 19 | //aceEditor.getSession().setTabSize(4) 20 | //aceEditor.getSession().setUseSoftTabs(true) 21 | 22 | //aceEditor.getSession().setUseWorker(false) // disable syntax checker and information 23 | 24 | document.getElementById(this.data.id).style.fontSize = "14px" 25 | document.getElementById(this.data.id).style.height = Widget.DatabaseTemplate.maxHeight() 26 | 27 | this.aceEditor = aceEditor 28 | }, 29 | 30 | setValue: function (content) { 31 | // delete previous and set new content 32 | this.aceEditor.removeLines() 33 | this.aceEditor.setValue(content, -1) 34 | this.aceEditor.navigateFileStart() 35 | }, 36 | 37 | getValue: function () { 38 | return this.aceEditor.getValue() 39 | } 40 | } -------------------------------------------------------------------------------- /extensions/database/src/widget/DatabaseHeader.css: -------------------------------------------------------------------------------- 1 | #dbmenu { 2 | color: {{baseline_color2}}; 3 | } 4 | 5 | .hand { 6 | cursor: pointer; 7 | } -------------------------------------------------------------------------------- /extensions/database/src/widget/DatabaseNavigation.css: -------------------------------------------------------------------------------- 1 | .database { 2 | color: {{baseline_color2}}; 3 | cursor: pointer; 4 | } 5 | 6 | ul.no-bullets 7 | { 8 | list-style-type: none; 9 | padding-left: 0em; 10 | margin: 0em; 11 | } 12 | 13 | .nowrap { 14 | white-space: nowrap; 15 | } -------------------------------------------------------------------------------- /extensions/database/src/widget/DatabaseNavigation.js: -------------------------------------------------------------------------------- 1 | Widget.DatabaseNavigation = function (types) { 2 | types = types || [] 3 | 4 | for (var i = 0; i < types.length; i++) {types[i].guid = Widget.guid()} 5 | 6 | var filteredTypes = [] 7 | for (var i = 0; i < types.length; i++) { 8 | if (types[i].name.indexOf("-") < 0) {filteredTypes.push(types[i])} 9 | } 10 | 11 | var data = {types: filteredTypes} 12 | 13 | this.data = data 14 | this.html = parse(function(){/*! 15 | {{? types.length > 0 16 | 27 | }}? 28 | */}, data) 29 | } 30 | 31 | Widget.DatabaseNavigation.prototype = { 32 | constructor: Widget.DatabaseNavigation, 33 | 34 | init: function () { 35 | $("#databaseNavigation").css("max-height", Widget.DatabaseTemplate.maxHeight()) 36 | } 37 | } 38 | 39 | Widget.DatabaseNavigation.selectType = function (type, guid) { 40 | Widget.DatabaseNavigation.selectDatabaseGuid(guid) 41 | Widget.DatabaseNavigation.type = type 42 | } 43 | 44 | Widget.DatabaseNavigation.selectDatabaseGuid = function (guid) { 45 | if (!isEmpty(vars.databaseGuid)) { 46 | $("#" + vars.databaseGuid).css("font-weight", "normal") 47 | $("#" + vars.databaseGuid + " span.navigationName").css('text-decoration', 'none') 48 | } 49 | 50 | vars.databaseGuid = guid 51 | $("#" + vars.databaseGuid).css("font-weight", "900") 52 | $("#" + vars.databaseGuid + " span.navigationName").css('text-decoration', 'underline') 53 | } -------------------------------------------------------------------------------- /extensions/database/src/widget/DatabaseResult.js: -------------------------------------------------------------------------------- 1 | Widget.DatabaseResult = function (results) { 2 | var type 3 | if (results.length > 0 && typeof(results[results.length - 1]) == "string") { 4 | type = results.splice(results.length - 1, 1)[0] 5 | } else { 6 | type = "" 7 | } 8 | 9 | var guid = [] 10 | for (var i = 0; i < results.length; i++) {guid.push(Widget.guid())} 11 | 12 | var data = {type: type, results: results, guid: guid} 13 | 14 | this.data = data 15 | this.html = parse(function(){/*! 16 | {{? results.length > 0 17 |

{{type}}

18 | 19 |
20 | 21 | 22 | {{# results[i] 23 | 24 | 33 | 34 | }}# 35 | 36 |
25 | 31 | 32 |
37 |
38 | }}? 39 | */}, data) 40 | } 41 | 42 | Widget.DatabaseResult.prototype = { 43 | constructor: Widget.DatabaseResult 44 | } -------------------------------------------------------------------------------- /extensions/database/src/widget/DatabaseTabs.js: -------------------------------------------------------------------------------- 1 | Widget.DatabaseTabs = function (data) { 2 | this.data = data 3 | this.html = parse(function(){/*! 4 |
5 | {{# tabs[i] 6 | 10 | }}# 11 |
12 | */}, data) 13 | } 14 | 15 | Widget.DatabaseTabs.prototype = { 16 | constructor: Widget.DatabaseTabs 17 | } -------------------------------------------------------------------------------- /extensions/database/static/database-favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/strumasoft/octopus/4d66e3d6045cbd533353696abd80e48b1d606f18/extensions/database/static/database-favicon.ico -------------------------------------------------------------------------------- /extensions/demo/config.lua: -------------------------------------------------------------------------------- 1 | local config = {} -- extension configuration 2 | 3 | config.localization = { 4 | helloMessage = {en = "Hello World", bg = "Здравейте!!!!"}, 5 | copyright = { 6 | en = "© cyberz.eu. All rights reserved.", 7 | bg = "© cyberz.eu. Всички права запазени."}, 8 | reload = {en = "Reload", bg = "Презареди"}, 9 | showError = {en = "Show Error", bg = "Покажи Грешката"}, 10 | addToCart = {en = "Buy", bg = "Купи"}, 11 | clickToClose = {en = "click to close", bg = "натисни за да го скриеш"}, 12 | noErrors = {en = "no errors", bg = "няма грешки"}, 13 | index = {en = "Index", bg = "начало"}, 14 | } 15 | 16 | config.location = { 17 | {name = "/", script = "controller/IndexController.lua"}, 18 | {name = "/hello", script = "controller/HelloWorldController.lua"}, 19 | {name = "/product", script = "controller/ProductDetailController.lua"}, 20 | } 21 | 22 | config.module = { 23 | {name = "DemoProductService", script = "module/DemoProductService.lua"}, 24 | } 25 | 26 | config.html = { 27 | {name = "t1", script = "widget/DemoTemplate1.lua"}, 28 | {name = "t2", script = "widget/DemoTemplate2.lua"}, 29 | } 30 | 31 | config.javascript = { 32 | {name = "DemoProductDetail", script = "widget/DemoProductDetail.js"}, 33 | {name = "DemoError", script = "widget/DemoError.js"}, 34 | {name = "DemoHeader", script = "widget/DemoHeader.js"}, 35 | {name = "DemoFooter", script = "widget/DemoFooter.js"}, 36 | } 37 | 38 | config.stylesheet = { 39 | 40 | } 41 | 42 | config.static = { 43 | "static" 44 | } 45 | 46 | config.type = { 47 | 48 | } 49 | 50 | return config -- return extension configuration -------------------------------------------------------------------------------- /extensions/demo/src/controller/HelloWorldController.lua: -------------------------------------------------------------------------------- 1 | local _ = require "template" 2 | 3 | ngx.header.content_type = 'text/plain' 4 | 5 | ngx.say(_.t1{ 6 | _ = _, -- import template 7 | message1 = "Hello", 8 | message2 = "Worrld", 9 | message3 = "!!!", 10 | }) 11 | 12 | ngx.say(_.t2{ 13 | message = "gogo", 14 | logo = "$", 15 | array = {{1,2}, {3,4}, {5,6}}, 16 | array2 = {7,8}, 17 | array3 = { 18 | x = "X", 19 | y = "Y" 20 | }, 21 | array4 = {}, 22 | }) -------------------------------------------------------------------------------- /extensions/demo/src/controller/IndexController.lua: -------------------------------------------------------------------------------- 1 | ngx.say([[ 2 |

Demo

3 | Hello World 4 |
5 | Product with code 1 6 | 7 |

Editor & Repository

8 | Editor 9 | 10 |

Database

11 | Database, requires proper database credentials, see config.lua 12 | 13 |

Shop

14 | Shop, requires import from Database, execute: 15 |
16 | db:dropAllTables()
17 | db:createAllTables()
18 | db:import("shopImport")
19 | 
20 | use the following credentials - username 'test@test.com' and password 'test' 21 | 22 | ]]) -------------------------------------------------------------------------------- /extensions/demo/src/controller/ProductDetailController.lua: -------------------------------------------------------------------------------- 1 | local json = require "json" 2 | local parse = require "parse" 3 | local property = require "property" 4 | local localization = require "localization" 5 | local exception = require "exception" 6 | local param = require "param" 7 | local productService = require "DemoProductService" 8 | 9 | 10 | 11 | local function process (data) 12 | data.locale = "en" 13 | 14 | local productCode = param.code 15 | if productCode then 16 | local product = productService.getProduct(productCode) 17 | data.product = product 18 | else 19 | exception("product code required") 20 | end 21 | end 22 | 23 | 24 | local data = {} 25 | local ok, err = pcall(process, data) 26 | if not ok then 27 | data.error = {err} 28 | end 29 | 30 | 31 | ngx.say(parse(require("BaselineHtmlTemplate"), { 32 | title = "Product Detail", 33 | externalJS = [[ 34 | 35 | ]], 36 | externalCSS = [[ 37 | 38 | ]], 39 | initJS = parse([[ 40 | var vars = {} 41 | 42 | vars.locale = {{locale}} 43 | 44 | Widget.setHeader(new Widget.DemoHeader()) 45 | Widget.setContainerToPage([ 46 | [ 47 | {size: "12u", widget: new Widget.DemoError({{error}})} 48 | ], 49 | [ 50 | {size: "9u -3u", medium: "8u -4u", small: "12u", widget: new Widget.DemoProductDetail({{product}})} 51 | ] 52 | ]) 53 | Widget.setFooter(new Widget.DemoFooter()) 54 | ]], json.encodeProperties(data)) 55 | })) -------------------------------------------------------------------------------- /extensions/demo/src/module/DemoProductService.lua: -------------------------------------------------------------------------------- 1 | local exception = require "exception" 2 | 3 | 4 | local function getProduct (productCode) 5 | if productCode == "1" then 6 | return { 7 | code = "1", 8 | name = "Box", 9 | description = "Very good box", 10 | price = "$20", 11 | picture = "/demo/static/box.jpg", 12 | width = "300px", 13 | height = "300px", 14 | } 15 | else 16 | exception("product '" .. productCode .. "' not found") 17 | end 18 | end 19 | 20 | 21 | return { 22 | getProduct = getProduct, 23 | } -------------------------------------------------------------------------------- /extensions/demo/src/widget/DemoError.js: -------------------------------------------------------------------------------- 1 | Widget.DemoError = function (errors) { 2 | var data = {errors: errors} 3 | 4 | this.data = data 5 | this.html = parse(function(){/*! 6 | {{?@ data.errors instanceof Array 7 |
8 |
9 |
10 | {{# errors[i] 11 |

{{errors[i]}}

12 | }}# 13 |
14 | }}? 15 | */}, data) 16 | } 17 | 18 | Widget.DemoError.prototype = { 19 | constructor: Widget.DemoError 20 | } 21 | 22 | Widget.DemoError.hide = function (guid) { 23 | $("#errors").hide() 24 | } -------------------------------------------------------------------------------- /extensions/demo/src/widget/DemoFooter.js: -------------------------------------------------------------------------------- 1 | Widget.DemoFooter = function (data) { 2 | data = data || {} 3 | 4 | this.data = data 5 | this.html = parse(function(){/*! 6 | 11 | */}, data) 12 | } 13 | 14 | Widget.DemoFooter.prototype = { 15 | constructor: Widget.DemoFooter 16 | } -------------------------------------------------------------------------------- /extensions/demo/src/widget/DemoHeader.js: -------------------------------------------------------------------------------- 1 | Widget.DemoHeader = function (data) { 2 | data = data || {} 3 | 4 | this.data = data 5 | this.html = parse(function(){/*! 6 | 21 | */}, data) 22 | } 23 | 24 | Widget.DemoHeader.prototype = { 25 | constructor: Widget.DemoHeader 26 | } 27 | 28 | Widget.DemoHeader.showError = function () { 29 | if($("#errors").length == 0) { 30 | var infoPopup = new Widget.InfoPopup({info: localize("noErrors")}) 31 | } else { 32 | $("#errors").show() 33 | } 34 | } -------------------------------------------------------------------------------- /extensions/demo/src/widget/DemoProductDetail.js: -------------------------------------------------------------------------------- 1 | Widget.DemoProductDetail = function (product) { 2 | var data = {product: product, pictureWidth: property.pictureWidth, pictureHeight: property.pictureHeight} 3 | 4 | this.data = data 5 | this.html = parse(function(){/*! 6 | 7 | {{?@ data.product != null 8 | 9 |
10 |
11 | 12 | {{product.name}} 13 | 14 |
15 | 16 |
17 |

{{product.name}}

18 | 19 |

20 | 21 | 1 Reviews | 22 | Write a review 23 |

24 | 25 |
26 | Product Code: 27 | {{product.code}} 28 |
29 | 30 |

31 | {{product.price}} 32 |

33 | 34 |
35 | 36 | 37 | 38 | 40 | 41 | 42 | 43 | 44 |
45 |
46 |
47 | 48 | 49 |
50 |
51 |

Description

52 |

Lorem ipsum dolor sit amet, consectetur adipisicing elit

53 |
54 |
55 | 56 | 57 |
58 |
59 |

Reviews (1)

60 |
61 | 62 |
63 |
Aliquam a malesuada lorem. Nunc in porta.
64 |
65 |
66 | 67 | 68 | }}? 69 | 70 | */}, data) 71 | } 72 | 73 | Widget.DemoProductDetail.prototype = { 74 | constructor: Widget.DemoProductDetail 75 | } 76 | 77 | Widget.DemoProductDetail.addToCart = function (productCode, price) { 78 | var infoPopup = new Widget.InfoPopup({info: "Buy product '" + productCode + "' for " + price}) 79 | } -------------------------------------------------------------------------------- /extensions/demo/src/widget/DemoTemplate1.lua: -------------------------------------------------------------------------------- 1 | return [[ 2 | 3 | 4 | 5 | {{message1}} 6 |
7 | {{message2}} 8 |
9 | {{message3}} 10 |
11 | {{ 12 | _.t2({message = message1 .. message2 .. message3}) 13 | }} 14 | 15 | {{= ddd = message1 .. message2 .. message3 }}= 16 | ddd={{ddd}} 17 | 18 | {{@ json }}@ 19 | {{ json.encode({a = 3, b = 2}) }} 20 | 21 | 22 | 23 | ---------------------------------------- 24 | 25 | 26 | ]] -------------------------------------------------------------------------------- /extensions/demo/src/widget/DemoTemplate2.lua: -------------------------------------------------------------------------------- 1 | return [[ 2 | ^hi-{{message}}$boy| 3 | {{# array2 4 | this row will SHOW 5 | }}# 6 | {{# unknownArray 7 | this row will NOT SHOW 8 | }}# 9 | {{# array5 10 | this row will NOT SHOW TOO 11 | }}# 12 | 13 | {{# array 14 | {{## array[i] 15 | +{{array[i][ii]}}| 16 | }}## 17 | 18 | {{? logo == "$$" 19 | {{## array2 20 | _{{array2[ii]}}| 21 | }}## 22 | }}? 23 | }}# 24 | 25 | {{message}} 26 | 27 | {{# array2 28 | -{{array2[i]}}| 29 | }}# 30 | 31 | usb<>{{logo}} 32 | 33 | {{? logo == "$" 34 | www! 35 | 36 | {{?? logo == "$" 37 | x{{array2[2]}} 38 | 39 | {{# array2 40 | ={{array2[i]}}| 41 | }}# 42 | }}?? 43 | }}? 44 | 45 | {{# array3 46 | {{i}} = {{array3[i]}} 47 | }}# 48 | 49 | 50 | ]] -------------------------------------------------------------------------------- /extensions/demo/static/box.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/strumasoft/octopus/4d66e3d6045cbd533353696abd80e48b1d606f18/extensions/demo/static/box.jpg -------------------------------------------------------------------------------- /extensions/demo/static/stars-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/strumasoft/octopus/4d66e3d6045cbd533353696abd80e48b1d606f18/extensions/demo/static/stars-5.png -------------------------------------------------------------------------------- /extensions/editor/src/controller/CompareController.lua: -------------------------------------------------------------------------------- 1 | local parse = require "parse" 2 | 3 | 4 | ngx.say(parse(require("BaselineHtmlTemplate"), { 5 | title = "Compare", 6 | externalJS = [[ 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | ]], 18 | externalCSS = [[ 19 | 20 | ]], 21 | customJS = [[ 22 | function diffUsingJS(viewType, originalContent, changedContent) { 23 | "use strict"; 24 | var byId = function (id) { return document.getElementById(id); }, 25 | base = difflib.stringAsLines(originalContent), 26 | newtxt = difflib.stringAsLines(changedContent), 27 | sm = new difflib.SequenceMatcher(base, newtxt), 28 | opcodes = sm.get_opcodes(), 29 | diffoutputdiv = byId("diffoutput"); 30 | 31 | diffoutputdiv.innerHTML = ""; 32 | var contextSize = null; 33 | 34 | diffoutputdiv.appendChild(diffview.buildView({ 35 | baseTextLines: base, 36 | newTextLines: newtxt, 37 | opcodes: opcodes, 38 | baseTextName: "OLD", 39 | newTextName: "NEW", 40 | contextSize: contextSize, 41 | viewType: viewType 42 | })); 43 | } 44 | ]], 45 | initJS = [[ 46 | var vars = {} 47 | 48 | vars.originalEditor = new Widget.CompareEditor({id: "originalEditor", name: "Old"}) 49 | vars.changedEditor = new Widget.CompareEditor({id: "changedEditor", name: "New"}) 50 | 51 | Widget.setContainerToPage([ 52 | [ 53 | {size: "12u", widget: new Widget.CompareHeader()} 54 | ], 55 | [ 56 | {size: "6u", small: "12u", widget: vars.originalEditor}, 57 | {size: "6u", small: "12u", widget: vars.changedEditor} 58 | ], 59 | [ 60 | {size: "12u", widget: new Widget.CompareTabs()} 61 | ] 62 | ]) 63 | 64 | vars.originalEditor.init() 65 | vars.originalEditor.setHeight("20em") 66 | vars.changedEditor.init() 67 | vars.changedEditor.setHeight("20em") 68 | ]] 69 | })) -------------------------------------------------------------------------------- /extensions/editor/src/controller/EditorController.lua: -------------------------------------------------------------------------------- 1 | local json = require "json" 2 | local parse = require "parse" 3 | local param = require "param" 4 | local property = require "property" 5 | local directory = require "Directory" 6 | local util = require "util" 7 | local fileutil = require "fileutil" 8 | 9 | 10 | 11 | local directoryName = param.directoryName 12 | local dirs, parent, title, isGIT 13 | 14 | if directoryName then 15 | dirs = directory.sortedEntries(directoryName) 16 | 17 | for _,v in pairs(dirs) do 18 | if v.name == ".git" and v.mode == "directory" then isGIT = true end 19 | end 20 | 21 | local paths = util.split(directoryName, "/") 22 | parent = {path = directoryName, name = paths[#paths], mode = "directory"} 23 | 24 | title = paths[#paths] 25 | else 26 | local system = io.popen("uname -s"):read("*l") 27 | 28 | local drives 29 | if system == nil then 30 | drives = {"c:/", "d:/"} 31 | else 32 | drives = {"/"} 33 | end 34 | 35 | dirs = {} 36 | for i = 1, #drives do 37 | dirs[#dirs + 1] = {path = drives[i], name = drives[i], mode = "directory"} 38 | end 39 | 40 | parent = nil 41 | 42 | title = "/" 43 | end 44 | 45 | 46 | ngx.say(parse(require("BaselineHtmlTemplate"), { 47 | title = title, 48 | externalJS = [[ 49 | 50 | 51 | ]], 52 | externalCSS = [[ 53 | 54 | ]], 55 | initJS = parse([[ 56 | var vars = {} 57 | 58 | {{? isGIT 59 | vars.repository = {repository: "GIT"} 60 | }}? 61 | 62 | var editor = new Widget.Editor({id: "editor"}) 63 | var editorNavigation = new Widget.EditorNavigation({{dirs}}, {{parent}}) 64 | var editorHeader = new Widget.EditorHeader("{{title}}") 65 | 66 | var editorTemplate = new Widget.EditorTemplate({ 67 | editor: editor.html, 68 | navigation: editorNavigation.html, 69 | header: editorHeader.html 70 | }) 71 | 72 | Widget.setHtmlToPage(editorTemplate.html); 73 | 74 | editor.init() 75 | editorNavigation.init() 76 | ]], { 77 | isGIT = isGIT, 78 | title = fileutil.escapeCommandlineSpecialCharacters(title), 79 | dirs = json.encode(dirs), 80 | parent = json.encode(parent) 81 | }) 82 | })) -------------------------------------------------------------------------------- /extensions/editor/src/controller/EditorDownloadFileController.lua: -------------------------------------------------------------------------------- 1 | local param = require "param" 2 | local exit = require "exit" 3 | local util = require "util" 4 | local editor = require "Editor" 5 | 6 | 7 | 8 | ngx.header.content_type = 'application/octet-stream' 9 | 10 | 11 | local function process () 12 | local fileName = param.f 13 | 14 | local paths = util.split(fileName, "/") 15 | local name = paths[#paths] 16 | ngx.header["Content-Disposition"] = 'attachment; filename="' .. name .. '"' 17 | 18 | return editor.fileContent(fileName) 19 | end 20 | 21 | 22 | local ok, res = pcall(process) 23 | if ok then 24 | if res then ngx.say(res) end 25 | else 26 | exit(res) 27 | end -------------------------------------------------------------------------------- /extensions/editor/src/controller/EditorEditFileController.lua: -------------------------------------------------------------------------------- 1 | local json = require "json" 2 | local param = require "param" 3 | local property = require "property" 4 | local exit = require "exit" 5 | local editor = require "Editor" 6 | local parse = require "parse" 7 | local directory = require "Directory" 8 | local util = require "util" 9 | local fileutil = require "fileutil" 10 | 11 | 12 | 13 | local externalJS = [[ 14 | 15 | 16 | ]] 17 | 18 | 19 | local externalCSS = [[ 20 | 21 | ]] 22 | 23 | 24 | local initJSTemplate = [[ 25 | var vars = {} 26 | 27 | var editor = new Widget.Editor({id: "editor"}) 28 | var editorSearchHeader = new Widget.EditorSearchHeader("{{title}}") 29 | 30 | var editorSearchTemplate = new Widget.EditorSearchTemplate({ 31 | editor: editor.html, 32 | header: editorSearchHeader.html 33 | }) 34 | 35 | Widget.setHtmlToPage(editorSearchTemplate.html); 36 | 37 | editor.init((window.innerHeight - Widget.EditorHeader.height()) + "px") 38 | vars.searchEditor = editor 39 | 40 | Widget.EditorSearchHeader.toggle(); 41 | Widget.EditorNavigation.openFile("{{fileName}}", Widget.guid()) 42 | ]] 43 | 44 | 45 | local function process () 46 | local directoryName = param.directoryName 47 | local fileName = param.fileName 48 | 49 | local paths = util.split(fileName, "/") 50 | local title = paths[#paths] 51 | 52 | return parse(require("BaselineHtmlTemplate"), { 53 | title = title, 54 | externalJS = externalJS, 55 | externalCSS = externalCSS, 56 | initJS = parse(initJSTemplate, { 57 | title = fileutil.escapeCommandlineSpecialCharacters(title), 58 | fileName = fileName 59 | }) 60 | }) 61 | end 62 | 63 | 64 | local ok, res = pcall(process) 65 | if ok then 66 | if res then ngx.say(res) end 67 | else 68 | exit(res) 69 | end -------------------------------------------------------------------------------- /extensions/editor/src/controller/EditorSearchTemplate.js: -------------------------------------------------------------------------------- 1 | Widget.EditorSearchTemplate = function (data) { 2 | this.data = data 3 | this.html = parse(function(){/*! 4 |
5 | 6 | {{header}} 7 | 8 |
9 | {{? searchResult 10 |
11 |
12 | {{searchResult}} 13 |
14 |
15 | }}? 16 |
17 | {{editor}} 18 |
19 |
20 |
21 | */}, data) 22 | } 23 | 24 | Widget.EditorSearchTemplate.prototype = { 25 | constructor: Widget.EditorSearchTemplate 26 | } -------------------------------------------------------------------------------- /extensions/editor/src/controller/EditorTemplate.css: -------------------------------------------------------------------------------- 1 | #main { 2 | padding: 1em 0; 3 | } 4 | 5 | #directoryNavigation { 6 | overflow-x: scroll; 7 | margin-right: 8px; 8 | } 9 | 10 | #editorArea { 11 | padding: 0; 12 | } 13 | 14 | #editorSearchArea.editorSearchWrapper { 15 | padding: 0; 16 | } -------------------------------------------------------------------------------- /extensions/editor/src/controller/EditorTemplate.js: -------------------------------------------------------------------------------- 1 | Widget.EditorTemplate = function (data) { 2 | this.data = data 3 | this.html = parse(function(){/*! 4 |
5 | 6 | {{header}} 7 | 8 |
9 |
10 |
11 | {{navigation}} 12 |
13 |
14 |
15 | {{editor}} 16 |
17 |
18 |
19 | */}, data) 20 | } 21 | 22 | Widget.EditorTemplate.prototype = { 23 | constructor: Widget.EditorTemplate, 24 | 25 | setDirectoryNavigation: function (html) { 26 | $("#directoryNavigation").html(html) 27 | } 28 | } 29 | 30 | Widget.EditorTemplate.maxHeight = function () { 31 | return (window.innerHeight - Widget.EditorHeader.height() - 25) + "px" 32 | } 33 | -------------------------------------------------------------------------------- /extensions/editor/src/controller/operation/CreateDirectoryController.lua: -------------------------------------------------------------------------------- 1 | local param = require "param" 2 | local exit = require "exit" 3 | local util = require "util" 4 | local editor = require "Editor" 5 | 6 | 7 | 8 | local function process () 9 | local directoryName = param.directoryName 10 | 11 | editor.createDirectory(directoryName) 12 | 13 | if util.isNotEmpty(param.repository) then 14 | local repository = require(param.repository) 15 | 16 | local username = param.username 17 | local password = param.password 18 | 19 | if param.repository == "SVN" then 20 | return repository.add(username, password, directoryName) 21 | end 22 | end 23 | end 24 | 25 | 26 | local ok, res = pcall(process) 27 | if ok then 28 | if res then ngx.say(res) end 29 | else 30 | exit(res) 31 | end -------------------------------------------------------------------------------- /extensions/editor/src/controller/operation/CreateFileController.lua: -------------------------------------------------------------------------------- 1 | local param = require "param" 2 | local exit = require "exit" 3 | local util = require "util" 4 | local editor = require "Editor" 5 | 6 | 7 | 8 | local function process () 9 | local fileName = param.fileName 10 | 11 | editor.createFile(fileName) 12 | 13 | if util.isNotEmpty(param.repository) then 14 | local repository = require(param.repository) 15 | 16 | local username = param.username 17 | local password = param.password 18 | 19 | return repository.add(username, password, fileName) 20 | end 21 | end 22 | 23 | 24 | local ok, res = pcall(process) 25 | if ok then 26 | if res then ngx.say(res) end 27 | else 28 | exit(res) 29 | end -------------------------------------------------------------------------------- /extensions/editor/src/controller/operation/DirectoryController.lua: -------------------------------------------------------------------------------- 1 | local json = require "json" 2 | local param = require "param" 3 | local exit = require "exit" 4 | local directory = require "Directory" 5 | 6 | 7 | 8 | local function process () 9 | local dir = param.d 10 | if dir == nil then dir = "/" end 11 | 12 | return json.encode(directory.sortedEntries(dir)) 13 | end 14 | 15 | 16 | local ok, res = pcall(process) 17 | if ok then 18 | if res then ngx.say(res) end 19 | else 20 | exit(res) 21 | end -------------------------------------------------------------------------------- /extensions/editor/src/controller/operation/FileContentController.lua: -------------------------------------------------------------------------------- 1 | local param = require "param" 2 | local exit = require "exit" 3 | local util = require "util" 4 | local editor = require "Editor" 5 | 6 | 7 | 8 | local notPlainTextExtensions = [[ 9 | flac mp3 ogg oga mogg raw voc vox wav wma wv webm 10 | 3gp 3g2 flv f4v f4p f4a f4b ogv gif gifv avi mp4 m4p m4v mpg mp2 mpeg mpe mpv mts m2ts mov qt wmv yuv 11 | jpg jpeg jpe jif jfif jfi png webp tiff tif psd raw arw cr2 nrw k25 bmp dib heif heic ind indd indt jp2 j2k jpf jpx jpm mj2 ico svgz ai eps 12 | pdf doc docx dot odt ott xls xlsx ppt pptx 13 | exe dll so o a ar cpio shar lbr iso mar sbx f xf lz lzma lzmo rz sfark sz q z xz 14 | 7z s7z ace afa alz apk arc ark cdx b1 cab dmg jar rar gz tgz tbz2 tar bz2 txz war zip zipx zz 15 | ]] 16 | 17 | ngx.header.content_type = 'text/plain' 18 | 19 | 20 | local function process () 21 | local fileName = param.f 22 | 23 | local paths = util.split(fileName, "/") 24 | local name = paths[#paths] 25 | 26 | local extensions, hasExtension = util.split(name, ".") 27 | local extension = extensions[#extensions] 28 | 29 | if hasExtension and notPlainTextExtensions:findQuery(" " .. extension .. " ", 1, true, true) then 30 | return "File is not plain text!" 31 | else 32 | return editor.fileContent(fileName) 33 | end 34 | end 35 | 36 | 37 | local ok, res = pcall(process) 38 | if ok then 39 | if res then ngx.say(res) end 40 | else 41 | exit(res) 42 | end 43 | -------------------------------------------------------------------------------- /extensions/editor/src/controller/operation/RemoveController.lua: -------------------------------------------------------------------------------- 1 | local param = require "param" 2 | local exit = require "exit" 3 | local util = require "util" 4 | local editor = require "Editor" 5 | 6 | 7 | 8 | local function process () 9 | local path = param.path 10 | 11 | if util.isNotEmpty(param.repository) then 12 | local repository = require(param.repository) 13 | 14 | local username = param.username 15 | local password = param.password 16 | 17 | if param.repository == "GIT" and param.isFile == "false" then 18 | editor.remove(path) 19 | else 20 | return repository.delete(username, password, path) 21 | end 22 | else 23 | editor.remove(path) 24 | end 25 | end 26 | 27 | 28 | local ok, res = pcall(process) 29 | if ok then 30 | if res then ngx.say(res) end 31 | else 32 | exit(res) 33 | end -------------------------------------------------------------------------------- /extensions/editor/src/controller/operation/RenameController.lua: -------------------------------------------------------------------------------- 1 | local param = require "param" 2 | local exit = require "exit" 3 | local util = require "util" 4 | local editor = require "Editor" 5 | 6 | 7 | 8 | local function process () 9 | local oldName = param.oldName 10 | local newName = param.newName 11 | 12 | if util.isNotEmpty(param.repository) then 13 | local repository = require(param.repository) 14 | 15 | local username = param.username 16 | local password = param.password 17 | local directoryName = param.directoryName 18 | 19 | return repository.move(username, password, oldName, newName, directoryName) 20 | else 21 | editor.rename(oldName, newName) 22 | end 23 | end 24 | 25 | 26 | local ok, res = pcall(process) 27 | if ok then 28 | if res then ngx.say(res) end 29 | else 30 | exit(res) 31 | end -------------------------------------------------------------------------------- /extensions/editor/src/controller/operation/SaveController.lua: -------------------------------------------------------------------------------- 1 | local param = require "param" 2 | local exit = require "exit" 3 | local editor = require "Editor" 4 | 5 | 6 | 7 | local function process () 8 | local fileName = param.f 9 | 10 | editor.save(fileName, ngx.req.get_body_data()) 11 | end 12 | 13 | 14 | local ok, res = pcall(process) 15 | if ok then 16 | if res then ngx.say(res) end 17 | else 18 | exit(res) 19 | end -------------------------------------------------------------------------------- /extensions/editor/src/filter/EditorRedirectOnSessionTimeoutFilter.lua: -------------------------------------------------------------------------------- 1 | local property = require "property" 2 | local database = require "database" 3 | local util = require "util" 4 | local userService = require "userService" 5 | 6 | 7 | 8 | -- security -- 9 | if property.requireSecurity then 10 | local db = database.connect() 11 | local ok, res = pcall(userService.loggedIn, db, {}, {"codeEditor"}) 12 | db:close() 13 | 14 | -- remove cache -- 15 | ngx.ctx = {} 16 | 17 | if not ok or not res then 18 | if util.isNotEmpty(ngx.var.args) then 19 | ngx.redirect(property.securityLoginUrl .. ngx.var.uri .. "?" .. ngx.var.args) 20 | ngx.exit(ngx.HTTP_OK) 21 | else 22 | ngx.redirect(property.securityLoginUrl .. ngx.var.uri) 23 | ngx.exit(ngx.HTTP_OK) 24 | end 25 | end 26 | end -------------------------------------------------------------------------------- /extensions/editor/src/filter/EditorThrowErrorOnSessionTimeoutFilter.lua: -------------------------------------------------------------------------------- 1 | local param = require "param" 2 | local property = require "property" 3 | local database = require "database" 4 | local userService = require "userService" 5 | 6 | 7 | 8 | -- security -- 9 | if property.requireSecurity then 10 | local db = database.connect() 11 | local ok, res = pcall(userService.loggedIn, db, {}, {"codeEditor"}) 12 | db:close() 13 | 14 | -- remove cache -- 15 | ngx.ctx = {} 16 | 17 | if not ok or not res then 18 | ngx.status = ngx.HTTP_FORBIDDEN 19 | ngx.say("ERROR: user not logged in") 20 | ngx.exit(ngx.HTTP_OK) 21 | end 22 | end -------------------------------------------------------------------------------- /extensions/editor/src/module/Directory.lua: -------------------------------------------------------------------------------- 1 | local m = {} -- module 2 | 3 | 4 | local lfs = require "lfs" 5 | local fileutil = require "fileutil" 6 | 7 | 8 | -- 9 | -- sourceCtxPath 10 | -- 11 | 12 | local function sourceCtxPath () 13 | local property = require "property" 14 | return property.sourceCtxPath or "" 15 | end 16 | 17 | 18 | function m.entries(dir) 19 | assert(dir and dir ~= "", "directory parameter is missing or empty") 20 | 21 | -- remove slash at the end of directory unless root is specified 22 | if dir ~= "/" then 23 | if string.sub(dir, -1) == "/" then 24 | dir = string.sub(dir, 1, -2) 25 | end 26 | end 27 | 28 | fileutil.noBackDirectory(dir) 29 | 30 | -- collect all entries in map with attributes 31 | local map = {} 32 | for entry in lfs.dir(sourceCtxPath() .. dir) do 33 | if entry ~= "." and entry ~= ".." then 34 | local path 35 | if dir ~= "/" then 36 | path = dir .. "/" .. entry 37 | else 38 | path = "/" .. entry 39 | end 40 | 41 | local attr = lfs.attributes(sourceCtxPath() .. path) 42 | if attr then 43 | attr.path = path 44 | map[entry] = attr 45 | else 46 | map[entry] = {path = path, mode = "unknown"} 47 | end 48 | end 49 | end 50 | 51 | return map 52 | end 53 | 54 | 55 | function m.sortedEntries(dir) 56 | -- get map of dir entries and their attributes -- 57 | local map = m.entries(dir) 58 | 59 | -- sort dir and file entries -- 60 | local sortedEntries, dirEntries, fileEntries = {}, {}, {} 61 | for entry, attr in pairs(map) do 62 | if attr.mode == "directory" then 63 | dirEntries[#dirEntries + 1] = entry 64 | else 65 | fileEntries[#fileEntries + 1] = entry 66 | end 67 | end 68 | table.sort(dirEntries) 69 | for i=1,#dirEntries do sortedEntries[#sortedEntries + 1] = dirEntries[i] end 70 | table.sort(fileEntries) 71 | for i=1,#fileEntries do sortedEntries[#sortedEntries + 1] = fileEntries[i] end 72 | 73 | -- wrap evrything up -- 74 | local dirs = {} 75 | for i=1,#sortedEntries do 76 | local entry = sortedEntries[i] 77 | local attr = map[entry] 78 | dirs[#dirs + 1] = {path = attr.path, name = entry, mode = attr.mode} 79 | end 80 | 81 | return dirs 82 | end 83 | 84 | 85 | return m -- return module -------------------------------------------------------------------------------- /extensions/editor/src/widget/CompareEditor.js: -------------------------------------------------------------------------------- 1 | Widget.CompareEditor = function (data) { 2 | var editor = new Widget.Editor(data) 3 | 4 | editor.html = parse(function(){/*! 5 |

{{name}}

6 |
7 | */}, data) 8 | 9 | return editor 10 | } 11 | 12 | Widget.CompareEditor.prototype = { 13 | constructor: Widget.CompareEditor 14 | } -------------------------------------------------------------------------------- /extensions/editor/src/widget/CompareHeader.js: -------------------------------------------------------------------------------- 1 | Widget.CompareHeader = function () { 2 | var data = {} 3 | if (localStorage.getItem("isDark") === "true") { 4 | data.theme = "fa-moon-o"; 5 | setTimeout(() => Widget.EditorHeader.theme(true), 50); 6 | } else { 7 | data.theme = "fa-sun-o"; 8 | } 9 | 10 | this.data = data 11 | this.html = parse(function(){/*! 12 | 29 | */}, data) 30 | } 31 | 32 | Widget.CompareHeader.prototype = { 33 | constructor: Widget.CompareHeader 34 | } 35 | 36 | Widget.CompareHeader.compare = function () { 37 | var originalContent = vars.originalEditor.getValue() 38 | var changedContent = vars.changedEditor.getValue() 39 | 40 | $("#oldfilecontent .diffbox").html(Widget.createHTML(originalContent)) 41 | $("#newfilecontent .diffbox").html(Widget.createHTML(changedContent)) 42 | 43 | diffUsingJS(0, originalContent, changedContent) 44 | 45 | $("#comparator").prettyTextDiff({ 46 | cleanup: $("#cleanup").is(":checked"), 47 | originalContent: originalContent, 48 | changedContent: changedContent, 49 | diffContainer: ".diffbox" 50 | }) 51 | 52 | Widget.CompareTabs.show("comparator", $("button.diffComparatorButton:last-child").attr('id')) 53 | } -------------------------------------------------------------------------------- /extensions/editor/src/widget/CompareTabs.js: -------------------------------------------------------------------------------- 1 | Widget.CompareTabs = function () { 2 | var tabs = [ 3 | { 4 | guid: Widget.guid(), 5 | id: "oldfilecontent", 6 | name: "old", 7 | html: '
'
 8 |     }, 
 9 |     {   
10 |       guid: Widget.guid(),
11 |       id: "newfilecontent",
12 |       name: "new",
13 |       html: '
'
14 |     }, 
15 |     {   
16 |       guid: Widget.guid(),
17 |       id: "diffoutput",
18 |       name: "diff",
19 |       html: ''
20 |     }, 
21 |     {
22 |       guid: Widget.guid(),
23 |       id: "comparator",
24 |       name: "match",
25 |       html: '
'
26 |     }
27 |   ]
28 |   var data = {tabs: tabs}
29 | 
30 |   this.data = data
31 |   this.html = parse(function(){/*!
32 |     
33 | {{# tabs[i] 34 | 39 | }}# 40 |
41 | 42 |
43 | {{# tabs[i] 44 | 48 | }}# 49 |
50 | */}, data) 51 | } 52 | 53 | Widget.CompareTabs.prototype = { 54 | constructor: Widget.CompareTabs 55 | } 56 | 57 | Widget.CompareTabs.show = function (id, guid) { 58 | $(".diffComparator").hide() 59 | $(".diffComparatorButton").css('text-decoration', 'none') 60 | 61 | $("#" + id).show() 62 | $("#" + guid).css('text-decoration', 'underline') 63 | } -------------------------------------------------------------------------------- /extensions/editor/src/widget/EditorHeader.css: -------------------------------------------------------------------------------- 1 | #menu { 2 | color: {{baseline_color2}}; 3 | } 4 | 5 | #menu.dark { 6 | color: {{baseline_color1}}; 7 | } 8 | 9 | .hand { 10 | cursor: pointer; 11 | } -------------------------------------------------------------------------------- /extensions/editor/src/widget/EditorNavigation.css: -------------------------------------------------------------------------------- 1 | .directory { 2 | color: {{baseline_color2}}; 3 | cursor: pointer; 4 | } 5 | 6 | #directoryNavigation.dark .directory { 7 | color: {{baseline_color1}}; 8 | } 9 | 10 | #listbox.dark .directory { 11 | color: {{baseline_color1}}; 12 | } 13 | 14 | .file { 15 | color: {{baseline_color2}}; 16 | cursor: pointer; 17 | } 18 | 19 | #directoryNavigation.dark .file { 20 | color: {{baseline_color1}}; 21 | } 22 | 23 | #listbox.dark .file { 24 | color: {{baseline_color1}}; 25 | } 26 | 27 | .unknown { 28 | color: red; 29 | cursor: pointer; 30 | } 31 | 32 | ul.no-bullets 33 | { 34 | list-style-type: none; 35 | padding-left: 0em; 36 | margin: 0em; 37 | } 38 | 39 | .nowrap { 40 | white-space: nowrap; 41 | } -------------------------------------------------------------------------------- /extensions/editor/src/widget/EditorSearchPopup.js: -------------------------------------------------------------------------------- 1 | Widget.EditorSearchPopup = function (data) { 2 | data.proceedButtonGuid = Widget.guid() 3 | data.queryGuid = Widget.guid() 4 | data.replaceGuid = Widget.guid() 5 | data.filterGuid = Widget.guid() 6 | data.isRegexGuid = Widget.guid() 7 | data.isFileNameGuid = Widget.guid() 8 | data.isIgnoreCaseGuid = Widget.guid() 9 | 10 | var info = parse(function(){/*! 11 | {{?@ !isEmpty(data.info) 12 |

{{info}}

13 | }}? 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 |
33 | 34 | 36 | Close 37 | 38 | 42 | Search / Replace 43 | 44 | */}, data) 45 | 46 | this.popup = new Widget.Popup({info: info}) 47 | this.popup.proceed = data.proceed 48 | vars.editorSearchPopup = this.popup 49 | this.popup.init() 50 | } 51 | 52 | Widget.EditorSearchPopup.prototype = { 53 | constructor: Widget.EditorSearchPopup 54 | } -------------------------------------------------------------------------------- /extensions/editor/src/widget/EditorSearchResult.js: -------------------------------------------------------------------------------- 1 | Widget.EditorSearchResult = function (filePaths) { 2 | var files = [] 3 | 4 | if (filePaths != null) { 5 | for (var i = 0; i < filePaths.length; i++) { 6 | files[i] = {} 7 | files[i].guid = Widget.guid() 8 | files[i].path = filePaths[i] 9 | } 10 | } 11 | 12 | var data = {files: files} 13 | 14 | this.data = data 15 | this.html = parse(function(){/*! 16 | {{? files.length > 0 17 | 28 | }}? 29 | */}, data) 30 | } 31 | 32 | Widget.EditorSearchResult.prototype = { 33 | constructor: Widget.EditorSearchResult 34 | } -------------------------------------------------------------------------------- /extensions/editor/src/widget/UploadResult.js: -------------------------------------------------------------------------------- 1 | Widget.UploadResult = function (files) { 2 | var data = {files: files} 3 | 4 | this.data = data 5 | this.html = parse(function(){/*! 6 | {{? files.length > 0 7 | 17 | }}? 18 | */}, data) 19 | } 20 | 21 | Widget.UploadResult.prototype = { 22 | constructor: Widget.UploadResult 23 | } -------------------------------------------------------------------------------- /extensions/editor/static/editor-favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/strumasoft/octopus/4d66e3d6045cbd533353696abd80e48b1d606f18/extensions/editor/static/editor-favicon.ico -------------------------------------------------------------------------------- /extensions/editor/static/search-favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/strumasoft/octopus/4d66e3d6045cbd533353696abd80e48b1d606f18/extensions/editor/static/search-favicon.ico -------------------------------------------------------------------------------- /extensions/orm/config.lua: -------------------------------------------------------------------------------- 1 | local config = {} -- extension configuration 2 | 3 | config.property = { 4 | usePreparedStatement = true, 5 | debugDB = false, 6 | } 7 | 8 | config.module = { 9 | {name = "database", script = "database.lua"}, -- @deprecated > use luaorm > https://github.com/strumasoft/luaorm 10 | {name = "db.api.common", script = "db/api/common.lua"}, 11 | {name = "db.api.mysql", script = "db/api/mysql.lua"}, 12 | {name = "db.api.postgres", script = "db/api/postgres.lua"}, 13 | {name = "db.driver.mysql", script = "db/driver/mysql.lua"}, 14 | {name = "db.driver.postgres", script = "db/driver/postgres.lua"}, 15 | } 16 | 17 | 18 | return config -- return extension configuration -------------------------------------------------------------------------------- /extensions/repository/src/controller/RepositoryLogHistoryController.lua: -------------------------------------------------------------------------------- 1 | local json = require "json" 2 | local parse = require "parse" 3 | local param = require "param" 4 | local exit = require "exit" 5 | local exception = require "exception" 6 | local util = require "util" 7 | 8 | 9 | 10 | local externalJS = [[ 11 | 12 | 13 | 14 | ]] 15 | 16 | 17 | local externalCSS = [[ 18 | 19 | ]] 20 | 21 | 22 | local initJSTemplate = [[ 23 | var vars = {} 24 | 25 | var repositoryLog = new Widget.RepositoryLog() 26 | 27 | var repositoryTemplate = new Widget.RepositoryTemplate({ 28 | diff: repositoryLog.html 29 | }) 30 | 31 | $.ajax({ 32 | async: false, 33 | url: window.location.href + "&log=true", 34 | success: function (content) { 35 | Widget.setHtmlToPage(repositoryTemplate.html) 36 | Widget.RepositoryLog.setContent(content) 37 | }, 38 | error: Widget.errorHandler 39 | }) 40 | ]] 41 | 42 | 43 | local function process () 44 | if util.isEmpty(param.repository) then exception("repository name like GIT/SVN is required") end 45 | local repository = require(param.repository) 46 | 47 | local username = param.username 48 | local password = param.password 49 | local directoryName = param.directoryName 50 | 51 | if param.log then 52 | local limit 53 | if util.isNotEmpty(param.limit) then limit = param.limit end 54 | 55 | return repository.logHistory(username, password, directoryName, limit) 56 | else 57 | local paths = util.split(directoryName, "/") 58 | 59 | return parse(require("BaselineHtmlTemplate"), { 60 | title = paths[#paths], 61 | customCSS = [[ 62 | #skel-layers-wrapper {padding-top: 0;} 63 | ]], 64 | externalJS = externalJS, 65 | externalCSS = externalCSS, 66 | initJS = parse(initJSTemplate, json.encodeProperties({})) 67 | }) 68 | end 69 | end 70 | 71 | 72 | local ok, res = pcall(process) 73 | if ok then 74 | if res then ngx.say(res) end 75 | else 76 | exit(res) 77 | end -------------------------------------------------------------------------------- /extensions/repository/src/controller/RepositoryTemplate.css: -------------------------------------------------------------------------------- 1 | ins { 2 | background-color: #c6ffc6; 3 | text-decoration: none; 4 | } 5 | 6 | .diffbox.dark ins { 7 | color: {{baseline_color2}}; 8 | } 9 | 10 | del { 11 | background-color: #ffc6c6; 12 | text-decoration: none; 13 | } 14 | 15 | .diffbox.dark del { 16 | color: {{baseline_color2}}; 17 | } 18 | 19 | #diffoutput { 20 | margin: 15px; 21 | } 22 | 23 | #diffComparatorTabs { 24 | margin: 15px; 25 | } 26 | 27 | .diffbox { 28 | padding: 15px; 29 | margin: 0px 5px 15px 5px; 30 | 31 | color: {{baseline_color2}}; 32 | font-size: 14px; 33 | font-weight: normal; 34 | line-height: 16px; 35 | 36 | background: {{baseline_color1}}; 37 | border-radius: 6px; 38 | border: solid 1px {{baseline_color2}}; 39 | 40 | overflow-x: scroll; 41 | } 42 | 43 | .diffbox.dark { 44 | color: {{baseline_color1}}; 45 | background: {{baseline_color2}}; 46 | } 47 | 48 | #listbox { 49 | padding-top: 10px; 50 | margin: 5px; 51 | 52 | background: {{baseline_color1}}; 53 | border-radius: 6px; 54 | border: solid 1px {{baseline_color2}}; 55 | 56 | overflow-x: scroll; 57 | } 58 | 59 | #listbox.dark { 60 | background: {{baseline_color2}}; 61 | border: solid 1px {{baseline_color1}}; 62 | } 63 | 64 | .repolog { 65 | margin: 0 0 0 0; 66 | color: {{baseline_color2}}; 67 | } 68 | 69 | #listbox.dark .repolog { 70 | color: {{baseline_color1}}; 71 | } 72 | 73 | table.diff tbody td { 74 | color: {{baseline_color2}}; 75 | font-size: 14px; 76 | } 77 | 78 | #diffoutput.dark table.diff tbody td { 79 | color: {{baseline_color1}}; 80 | } 81 | 82 | #diffoutput.dark table.diff tbody td.insert { 83 | color: {{baseline_color2}}; 84 | } 85 | 86 | #diffoutput.dark table.diff tbody td.delete { 87 | color: {{baseline_color2}}; 88 | } 89 | 90 | #diffoutput.dark table.diff tbody td.replace { 91 | color: {{baseline_color2}}; 92 | } 93 | 94 | table.diff { 95 | white-space: pre-wrap; 96 | } -------------------------------------------------------------------------------- /extensions/repository/src/controller/RepositoryTemplate.js: -------------------------------------------------------------------------------- 1 | Widget.RepositoryTemplate = function (data) { 2 | this.data = data 3 | this.html = parse(function(){/*! 4 |
5 | 6 | {{header}} 7 | 8 |
9 |
10 | {{navigation}} 11 |
12 |
13 |
14 |
15 | {{diff}} 16 |
17 |
18 |
19 | */}, data) 20 | } 21 | 22 | Widget.RepositoryTemplate.prototype = { 23 | constructor: Widget.RepositoryTemplate 24 | } -------------------------------------------------------------------------------- /extensions/repository/src/controller/operation/AddController.lua: -------------------------------------------------------------------------------- 1 | local param = require "param" 2 | local exit = require "exit" 3 | local exception = require "exception" 4 | local util = require "util" 5 | 6 | 7 | 8 | local function process () 9 | if util.isEmpty(param.repository) then exception("repository name like GIT/SVN is required") end 10 | local repository = require(param.repository) 11 | 12 | local username = param.username 13 | local password = param.password 14 | local path = param.path 15 | local directoryName = param.directoryName 16 | 17 | return repository.add(username, password, path, directoryName) 18 | end 19 | 20 | 21 | local ok, res = pcall(process) 22 | if ok then 23 | if res then ngx.say(res) end 24 | else 25 | exit(res) 26 | end -------------------------------------------------------------------------------- /extensions/repository/src/controller/operation/CommitController.lua: -------------------------------------------------------------------------------- 1 | local param = require "param" 2 | local exit = require "exit" 3 | local exception = require "exception" 4 | local util = require "util" 5 | 6 | 7 | 8 | local function process () 9 | if util.isEmpty(param.repository) then exception("repository name like GIT/SVN is required") end 10 | local repository = require(param.repository) 11 | 12 | local username = param.username 13 | local password = param.password 14 | local message = param.message 15 | local directoryName = param.directoryName 16 | 17 | local list = {} 18 | 19 | local file = param["f" .. #list] -- from 0 to N-1 20 | while file do 21 | list[#list + 1] = file 22 | file = param["f" .. #list] 23 | end 24 | 25 | return repository.commit(username, password, message, list, directoryName) 26 | end 27 | 28 | 29 | local ok, res = pcall(process) 30 | if ok then 31 | if res then ngx.say(res) end 32 | else 33 | exit(res) 34 | end -------------------------------------------------------------------------------- /extensions/repository/src/controller/operation/DeleteController.lua: -------------------------------------------------------------------------------- 1 | local param = require "param" 2 | local exit = require "exit" 3 | local exception = require "exception" 4 | local util = require "util" 5 | 6 | 7 | 8 | local function process () 9 | if util.isEmpty(param.repository) then exception("repository name like GIT/SVN is required") end 10 | local repository = require(param.repository) 11 | 12 | local username = param.username 13 | local password = param.password 14 | local path = param.path 15 | local directoryName = param.directoryName 16 | 17 | return repository.delete(username, password, path, directoryName) 18 | end 19 | 20 | 21 | local ok, res = pcall(process) 22 | if ok then 23 | if res then ngx.say(res) end 24 | else 25 | exit(res) 26 | end -------------------------------------------------------------------------------- /extensions/repository/src/controller/operation/FileDiffController.lua: -------------------------------------------------------------------------------- 1 | local param = require "param" 2 | local exit = require "exit" 3 | local exception = require "exception" 4 | local util = require "util" 5 | 6 | 7 | 8 | local function process () 9 | if util.isEmpty(param.repository) then exception("repository name like GIT/SVN is required") end 10 | local repository = require(param.repository) 11 | 12 | local username = param.username 13 | local password = param.password 14 | local oldRevision = param.oldRevision 15 | local newRevision = param.newRevision 16 | local fileName = param.fileName 17 | local newFileName = param.newFileName 18 | local directoryName = param.directoryName 19 | 20 | return repository.fileDiff(username, password, oldRevision, newRevision, fileName, newFileName, directoryName) 21 | end 22 | 23 | 24 | local ok, res = pcall(process) 25 | if ok then 26 | if res then ngx.say(res) end 27 | else 28 | exit(res) 29 | end -------------------------------------------------------------------------------- /extensions/repository/src/controller/operation/FileRevisionContentController.lua: -------------------------------------------------------------------------------- 1 | local param = require "param" 2 | local exit = require "exit" 3 | local exception = require "exception" 4 | local util = require "util" 5 | 6 | 7 | 8 | ngx.header.content_type = 'text/plain' 9 | 10 | 11 | local function process () 12 | if util.isEmpty(param.repository) then exception("repository name like GIT/SVN is required") end 13 | local repository = require(param.repository) 14 | 15 | local username = param.username 16 | local password = param.password 17 | local revision = param.revision 18 | local fileName = param.fileName 19 | local directoryName = param.directoryName 20 | 21 | return repository.fileRevisionContent(username, password, revision, fileName, directoryName) 22 | end 23 | 24 | 25 | local ok, res = pcall(process) 26 | if ok then 27 | if res then ngx.say(res) end 28 | else 29 | exit(res) 30 | end -------------------------------------------------------------------------------- /extensions/repository/src/controller/operation/MergeController.lua: -------------------------------------------------------------------------------- 1 | local param = require "param" 2 | local exit = require "exit" 3 | local exception = require "exception" 4 | local util = require "util" 5 | 6 | 7 | 8 | local function process () 9 | if util.isEmpty(param.repository) then exception("repository name like GIT/SVN is required") end 10 | local repository = require(param.repository) 11 | 12 | local username = param.username 13 | local password = param.password 14 | local fromRevision = param.fromRevision 15 | local toRevision = param.toRevision 16 | local path = param.path 17 | 18 | return repository.merge(username, password, fromRevision, toRevision, path) 19 | end 20 | 21 | 22 | local ok, res = pcall(process) 23 | if ok then 24 | if res then ngx.say(res) end 25 | else 26 | exit(res) 27 | end -------------------------------------------------------------------------------- /extensions/repository/src/controller/operation/RefreshController.lua: -------------------------------------------------------------------------------- 1 | local param = require "param" 2 | local exit = require "exit" 3 | local exception = require "exception" 4 | local util = require "util" 5 | 6 | 7 | 8 | local function process () 9 | if util.isEmpty(param.repository) then exception("repository name like GIT/SVN is required") end 10 | local repository = require(param.repository) 11 | 12 | local username = param.username 13 | local password = param.password 14 | local path = param.path 15 | local directoryName = param.directoryName 16 | 17 | return repository.refresh(username, password, path, directoryName) 18 | end 19 | 20 | 21 | local ok, res = pcall(process) 22 | if ok then 23 | if res then ngx.say(res) end 24 | else 25 | exit(res) 26 | end -------------------------------------------------------------------------------- /extensions/repository/src/controller/operation/RevertController.lua: -------------------------------------------------------------------------------- 1 | local param = require "param" 2 | local exit = require "exit" 3 | local exception = require "exception" 4 | local util = require "util" 5 | 6 | 7 | 8 | local function process () 9 | if util.isEmpty(param.repository) then exception("repository name like GIT/SVN is required") end 10 | local repository = require(param.repository) 11 | 12 | local username = param.username 13 | local password = param.password 14 | local path = param.path 15 | local recursively = param.recursively 16 | local directoryName = param.directoryName 17 | 18 | return repository.revert(username, password, path, recursively, directoryName) 19 | end 20 | 21 | 22 | local ok, res = pcall(process) 23 | if ok then 24 | if res then ngx.say(res) end 25 | else 26 | exit(res) 27 | end -------------------------------------------------------------------------------- /extensions/repository/src/controller/operation/UpdateController.lua: -------------------------------------------------------------------------------- 1 | local param = require "param" 2 | local exit = require "exit" 3 | local exception = require "exception" 4 | local util = require "util" 5 | 6 | 7 | 8 | local function process () 9 | if util.isEmpty(param.repository) then exception("repository name like GIT/SVN is required") end 10 | local repository = require(param.repository) 11 | 12 | local username = param.username 13 | local password = param.password 14 | local revision = param.revision 15 | local path = param.path 16 | 17 | return repository.update(username, password, revision, path) 18 | end 19 | 20 | 21 | local ok, res = pcall(process) 22 | if ok then 23 | if res then ngx.say(res) end 24 | else 25 | exit(res) 26 | end -------------------------------------------------------------------------------- /extensions/repository/src/widget/RepositoryDiff.js: -------------------------------------------------------------------------------- 1 | Widget.RepositoryDiff = function (data) { 2 | var tabs = [ 3 | { 4 | guid: Widget.guid(), 5 | id: "oldfilecontent", 6 | name: "old", 7 | html: '
'
 8 |     }, 
 9 |     {   
10 |       guid: Widget.guid(),
11 |       id: "newfilecontent",
12 |       name: "new",
13 |       html: '
'
14 |     }, 
15 |     {   
16 |       guid: Widget.guid(),
17 |       id: "diffoutput",
18 |       name: "diff",
19 |       html: ''
20 |     }, 
21 |     {
22 |       guid: Widget.guid(),
23 |       id: "comparator",
24 |       name: "match",
25 |       html: '
'
26 |     },
27 |     {
28 |       guid: Widget.guid(),
29 |       id: "patch",
30 |       name: "patch",
31 |       html: '
'
32 |     }
33 |   ]
34 |   data.tabs = tabs
35 | 
36 |   this.data = data
37 |   this.html = parse(function(){/*!
38 |     
39 | {{# tabs[i] 40 | 45 | }}# 46 |
47 | 48 |
49 | {{# tabs[i] 50 | 54 | }}# 55 |
56 | */}, data) 57 | } 58 | 59 | Widget.RepositoryDiff.prototype = { 60 | constructor: Widget.RepositoryDiff 61 | } 62 | 63 | Widget.RepositoryDiff.show = function (id, guid) { 64 | $(".diffComparator").hide() 65 | $(".diffComparatorButton").css('text-decoration', 'none') 66 | 67 | $("#" + id).show() 68 | $("#" + guid).css('text-decoration', 'underline') 69 | } -------------------------------------------------------------------------------- /extensions/repository/src/widget/RepositoryFileHistoryNavigation.js: -------------------------------------------------------------------------------- 1 | Widget.RepositoryFileHistoryNavigation = function (revisions) { 2 | revisions = revisions || [] 3 | 4 | for (var i = 0; i < revisions.length; i++) {revisions[i].guid = Widget.guid()} 5 | 6 | var data = {revisions: revisions} 7 | 8 | this.data = data 9 | 10 | if (getURLParameter("repository") == "SVN") { 11 | this.html = parse(function(){/*! 12 | {{? revisions.length > 0 13 | 25 | }}? 26 | */}, data) 27 | } else if (getURLParameter("repository") == "GIT") { 28 | this.html = parse(function(){/*! 29 | {{? revisions.length > 0 30 | 45 | }}? 46 | */}, data) 47 | } 48 | } 49 | 50 | Widget.RepositoryFileHistoryNavigation.prototype = { 51 | constructor: Widget.RepositoryFileHistoryNavigation 52 | } -------------------------------------------------------------------------------- /extensions/repository/src/widget/RepositoryLog.js: -------------------------------------------------------------------------------- 1 | Widget.RepositoryLog = function () { 2 | var data = {} 3 | if (localStorage.getItem("isDark") === "true") { 4 | data.clazz = "dark"; 5 | } 6 | 7 | this.data = data 8 | this.html = parse(function(){/*! 9 |
10 |
11 |

12 |       
13 |
14 | */}, data) 15 | } 16 | 17 | Widget.RepositoryLog.prototype = { 18 | constructor: Widget.RepositoryLog 19 | } 20 | 21 | Widget.RepositoryLog.setContent = function (content) { 22 | $('#repositoryLogContent').html(Widget.createHTML(content)) 23 | } -------------------------------------------------------------------------------- /extensions/repository/src/widget/RepositoryPatch.js: -------------------------------------------------------------------------------- 1 | Widget.RepositoryPatch = function () { 2 | var data = {} 3 | 4 | this.data = data 5 | this.html = parse(function(){/*! 6 |
7 | */}, data) 8 | } 9 | 10 | Widget.RepositoryPatch.prototype = { 11 | constructor: Widget.RepositoryPatch 12 | } 13 | 14 | Widget.RepositoryPatch.setContent = function (contents) { 15 | let clazz = ""; 16 | if (localStorage.getItem("isDark") === "true") { 17 | clazz = "dark"; 18 | } 19 | 20 | var html = "" 21 | for (var i = 0; i < contents.length; i++) { 22 | html = html 23 | + '
' 
24 |       + Widget.decoratePatch(Widget.createHTML(contents[i])) 
25 |       + "
" 26 | } 27 | 28 | $('#patch').html(html) 29 | } -------------------------------------------------------------------------------- /extensions/repository/src/widget/RepositoryStatusNavigation.js: -------------------------------------------------------------------------------- 1 | Widget.RepositoryStatusNavigation = function (statuses) { 2 | statuses = statuses || [] 3 | 4 | for (var i = 0; i < statuses.length; i++) {statuses[i].guid = Widget.guid()} 5 | 6 | var data = {statuses: statuses} 7 | 8 | this.data = data 9 | if (getURLParameter("repository") == "SVN") { 10 | this.html = parse(function(){/*! 11 | {{? statuses.length > 0 12 | 27 | }}? 28 | */}, data) 29 | } else if (getURLParameter("repository") == "GIT") { 30 | this.html = parse(function(){/*! 31 | {{? statuses.length > 0 32 | 47 | }}? 48 | */}, data) 49 | } 50 | } 51 | 52 | Widget.RepositoryStatusNavigation.prototype = { 53 | constructor: Widget.RepositoryStatusNavigation 54 | } -------------------------------------------------------------------------------- /extensions/repository/static/repository-favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/strumasoft/octopus/4d66e3d6045cbd533353696abd80e48b1d606f18/extensions/repository/static/repository-favicon.ico -------------------------------------------------------------------------------- /extensions/security/config.lua: -------------------------------------------------------------------------------- 1 | local config = {} -- extension configuration 2 | 3 | config.frontend = { 4 | securityLoginUrl = "/security/login", 5 | securityRegisterUrl = "/security/register", 6 | securityLoginUserUrl = "/security/loginUser", 7 | securityRegisterUserUrl = "/security/registerUser", 8 | } 9 | 10 | config.property = { 11 | failedLoginAttempts = 7, 12 | failedLoginAttemptsTimeout = 10800, -- 3h 13 | } 14 | 15 | config.localization = { 16 | 17 | } 18 | 19 | config.location = { 20 | {name = property.securityLoginUrl, script = "controller/SecurityLoginPageController.lua"}, 21 | {name = property.securityRegisterUrl, script = "controller/SecurityRegisterPageController.lua"}, 22 | {name = property.securityLoginUserUrl, script = "controller/SecurityLoginUserController.lua", requestBody = true}, 23 | {name = property.securityRegisterUserUrl, script = "controller/SecurityRegisterUserController.lua", requestBody = true}, 24 | } 25 | 26 | config.javascript = { 27 | {name = "SecurityLoginForm", script = "widget/LoginForm.js"}, 28 | {name = "SecurityRegisterForm", script = "widget/RegisterForm.js"}, 29 | } 30 | 31 | config.stylesheet = { 32 | 33 | } 34 | 35 | config.module = { 36 | {name = "userService", script = "module/UserService.lua"}, 37 | {name = "securityImport", script = "import.lua"}, 38 | } 39 | 40 | config.static = { 41 | 42 | } 43 | 44 | config.type = { 45 | "types.lua" 46 | } 47 | 48 | return config -- return extension configuration -------------------------------------------------------------------------------- /extensions/security/src/controller/SecurityLoginPageController.lua: -------------------------------------------------------------------------------- 1 | local json = require "json" 2 | local parse = require "parse" 3 | local param = require "param" 4 | local property = require "property" 5 | local userService = require "userService" 6 | 7 | 8 | 9 | local to = userService.redirectTo(property.securityLoginUrl) 10 | 11 | 12 | local data = {to = to} 13 | 14 | 15 | ngx.say(parse(require("BaselineHtmlTemplate"), { 16 | title = "Login", 17 | externalJS = [[ 18 | 19 | ]], 20 | initJS = parse([[ 21 | var vars = {} 22 | 23 | Widget.setContainerToPage([ 24 | [ 25 | {size: "6u", medium: "8u", small: "12u", widget: new Widget.LoginForm({to: {{to}}})} 26 | ] 27 | ]); 28 | ]], json.encodeProperties(data)) 29 | })) -------------------------------------------------------------------------------- /extensions/security/src/controller/SecurityLoginUserController.lua: -------------------------------------------------------------------------------- 1 | local json = require "json" 2 | local property = require "property" 3 | local database = require "database" 4 | local util = require "util" 5 | local userService = require "userService" 6 | 7 | 8 | 9 | local parameters = util.parseForm(util.urldecode(ngx.req.get_body_data())) 10 | 11 | local db = database.connect() 12 | local ok, res = pcall(userService.loginAndSetToken, db, parameters.email, parameters.password) 13 | db:close() 14 | 15 | if ok and res then 16 | local to = userService.redirectTo(property.securityLoginUserUrl) 17 | 18 | if util.isNotEmpty(to) then 19 | return ngx.redirect(to) 20 | else 21 | ngx.say("successful login") 22 | end 23 | else 24 | ngx.say("wrong credentials") 25 | end -------------------------------------------------------------------------------- /extensions/security/src/controller/SecurityRegisterPageController.lua: -------------------------------------------------------------------------------- 1 | local json = require "json" 2 | local parse = require "parse" 3 | local param = require "param" 4 | local property = require "property" 5 | local userService = require "userService" 6 | 7 | 8 | 9 | local data = {} 10 | 11 | 12 | ngx.say(parse(require("BaselineHtmlTemplate"), { 13 | title = "Register", 14 | externalJS = [[ 15 | 16 | ]], 17 | initJS = parse([[ 18 | var vars = {} 19 | 20 | Widget.setContainerToPage([ 21 | [ 22 | {size: "6u", medium: "8u", small: "12u", widget: new Widget.RegisterForm({})} 23 | ] 24 | ]); 25 | ]], json.encodeProperties(data)) 26 | })) -------------------------------------------------------------------------------- /extensions/security/src/controller/SecurityRegisterUserController.lua: -------------------------------------------------------------------------------- 1 | local json = require "json" 2 | local property = require "property" 3 | local database = require "database" 4 | local util = require "util" 5 | local userService = require "userService" 6 | 7 | 8 | 9 | local parameters = util.parseForm(util.urldecode(ngx.req.get_body_data())) 10 | 11 | if util.isNotEmpty(parameters.email) 12 | and util.isNotEmpty(parameters.password) 13 | and util.isNotEmpty(parameters.repeatPassword) 14 | and (parameters.password == parameters.repeatPassword) 15 | then 16 | local db = database.connect() 17 | local ok, res = pcall(userService.registerAndSetToken, db, parameters.email, parameters.password) 18 | db:close() 19 | 20 | if ok then 21 | ngx.say("successful register") 22 | else 23 | ngx.say("unsuccessful register") 24 | end 25 | else 26 | ngx.say("wrong data") 27 | end -------------------------------------------------------------------------------- /extensions/security/src/import.lua: -------------------------------------------------------------------------------- 1 | return { 2 | objects = { 3 | userPermission = { 4 | open = {code = "open"}, 5 | 6 | read = {code = "read"}, 7 | write = {code = "write"}, 8 | 9 | execute = {code = "execute"}, 10 | add = {code = "add"}, 11 | remove = {code = "remove"}, 12 | edit = {code = "edit"}, 13 | save = {code = "save"}, 14 | refresh = {code = "refresh"}, 15 | }, 16 | 17 | userGroup = { 18 | dbAdmin = {code = "dbAdmin"}, 19 | codeEditor = {code = "codeEditor"}, 20 | } 21 | }, 22 | 23 | relations = { 24 | ["userGroup.permissions-userPermission.groups"] = { 25 | codeEditor_read = {key = "codeEditor", value = "read"}, 26 | codeEditor_write = {key = "codeEditor", value = "write"}, 27 | 28 | dbAdmin_execute = {key = "dbAdmin", value = "execute"}, 29 | dbAdmin_add = {key = "dbAdmin", value = "add"}, 30 | dbAdmin_remove = {key = "dbAdmin", value = "remove"}, 31 | dbAdmin_edit = {key = "dbAdmin", value = "edit"}, 32 | dbAdmin_save = {key = "dbAdmin", value = "save"}, 33 | dbAdmin_refresh = {key = "dbAdmin", value = "refresh"}, 34 | }, 35 | } 36 | } -------------------------------------------------------------------------------- /extensions/security/src/types.lua: -------------------------------------------------------------------------------- 1 | return { 2 | 3 | user = { 4 | email = {type = "string", unique = true}, 5 | passwordSalt = "string", 6 | passwordHash = "string", 7 | token = "string", 8 | lastLoginTime = "integer", 9 | lastFailedLoginTime = "integer", 10 | failedLoginAttempts = "integer", 11 | groups = hasMany("userGroup", "users"), 12 | permissions = hasMany("userPermission", "users") 13 | }, 14 | 15 | userGroup = { 16 | code = {type = "string", unique = true}, 17 | users = hasMany("user", "groups"), 18 | permissions = hasMany("userPermission", "groups") 19 | }, 20 | 21 | userPermission = { 22 | code = {type = "string", unique = true}, 23 | users = hasMany("user", "permissions"), 24 | groups = hasMany("userGroup", "permissions") 25 | }, 26 | } -------------------------------------------------------------------------------- /extensions/security/src/widget/LoginForm.js: -------------------------------------------------------------------------------- 1 | Widget.LoginForm = function (data) { 2 | this.data = data 3 | this.html = parse(function(){/*! 4 |

Login

5 | 6 |
7 |
8 |
9 | 10 |
11 |
12 | 13 |
14 | 15 |
16 |
    17 |
  • 18 |
19 |
20 |
21 |
22 | */}, data) 23 | } 24 | 25 | Widget.LoginForm.prototype = { 26 | constructor: Widget.LoginForm 27 | } -------------------------------------------------------------------------------- /extensions/security/src/widget/RegisterForm.js: -------------------------------------------------------------------------------- 1 | Widget.RegisterForm = function (data) { 2 | this.data = data 3 | this.html = parse(function(){/*! 4 |

Register

5 | 6 |
7 |
8 |
9 | 10 |
11 |
12 | 13 |
14 |
15 | 16 |
17 | 18 |
19 |
    20 |
  • 21 |
22 |
23 |
24 |
25 | */}, data) 26 | } 27 | 28 | Widget.RegisterForm.prototype = { 29 | constructor: Widget.RegisterForm 30 | } -------------------------------------------------------------------------------- /extensions/shop/src/controller/ChangeCountryController.lua: -------------------------------------------------------------------------------- 1 | local param = require "param" 2 | local countryService = require "countryService" 3 | 4 | 5 | countryService.setCountry(param.country) -------------------------------------------------------------------------------- /extensions/shop/src/controller/ChangeLanguageController.lua: -------------------------------------------------------------------------------- 1 | local param = require "param" 2 | local localeService = require "localeService" 3 | 4 | 5 | localeService.setLocale(param.locale) -------------------------------------------------------------------------------- /extensions/shop/src/controller/account/AccountAddUpdateAddressController.lua: -------------------------------------------------------------------------------- 1 | local json = require "json" 2 | local parse = require "parse" 3 | local property = require "property" 4 | local localization = require "localization" 5 | local database = require "database" 6 | local exit = require "exit" 7 | local exception = require "exception" 8 | local exceptionHandler = require "exceptionHandler" 9 | local util = require "util" 10 | local userService = require "userService" 11 | local localeService = require "localeService" 12 | local priceService = require "priceService" 13 | local cartService = require "cartService" 14 | 15 | 16 | 17 | local function process (db, data) 18 | local op = db:operators() 19 | 20 | 21 | local locale = localeService.getLocale(db) 22 | data.locale = locale 23 | 24 | 25 | local address = util.parseForm(util.urldecode(ngx.req.get_body_data())) 26 | data.address = address 27 | 28 | if util.isNotEmpty(address.id) then 29 | db:update({address = address}) 30 | else 31 | local user = userService.authenticatedUser(db) 32 | if user then 33 | address.user = user 34 | db:add({address = address}) 35 | 36 | user.addresses = nil -- refresh 37 | end 38 | end 39 | end 40 | 41 | 42 | local data = {} 43 | local db = database.connect() 44 | local ok, err = pcall(process, db, data) 45 | db:close() 46 | 47 | 48 | if ok then 49 | return ngx.redirect(property.shopUrl .. property.accountAddressesUrl) 50 | else 51 | exceptionHandler.toCookie(err) 52 | 53 | if data.address and data.address.id then 54 | return ngx.redirect(property.shopUrl .. property.accountAddressUrl .. "?address=" .. data.address.id) 55 | else 56 | return ngx.redirect(property.shopUrl .. property.accountAddressesUrl) 57 | end 58 | end -------------------------------------------------------------------------------- /extensions/shop/src/controller/account/AccountOrderPageController.lua: -------------------------------------------------------------------------------- 1 | local json = require "json" 2 | local parse = require "parse" 3 | local param = require "param" 4 | local property = require "property" 5 | local localization = require "localization" 6 | local database = require "database" 7 | local exception = require "exception" 8 | local exceptionHandler = require "exceptionHandler" 9 | local util = require "util" 10 | local localeService = require "localeService" 11 | local priceService = require "priceService" 12 | local cartService = require "cartService" 13 | 14 | 15 | 16 | local function process (db, data) 17 | local op = db:operators() 18 | 19 | 20 | local locale = localeService.getLocale(db) 21 | data.locale = locale 22 | 23 | 24 | if util.isNotEmpty(param.order) then 25 | local order = db:findOne({order = {id = op.equal(param.order)}}) 26 | data.order = cartService.convertCart(db, order) 27 | else 28 | exception("order is required") 29 | end 30 | end 31 | 32 | 33 | local data = {} 34 | local db = database.connect() 35 | local ok, err = pcall(process, db, data) 36 | db:close() 37 | if not ok then 38 | exceptionHandler.toData(data, err) 39 | end 40 | 41 | 42 | ngx.say(parse(require("BaselineHtmlTemplate"), { 43 | title = "Account Order", 44 | externalJS = [[ 45 | 46 | ]], 47 | externalCSS = [[ 48 | 49 | 50 | 51 | ]], 52 | initJS = parse([[ 53 | var vars = {} 54 | 55 | vars.locale = {{locale}} 56 | 57 | Widget.setContainerToPage([ 58 | [ 59 | {size: "12u", widget: new Widget.ShopHeader()} 60 | ], 61 | [ 62 | {size: "3u", medium: "6u", small: "12u", widget: new Widget.Logo()}, 63 | {size: "3u", medium: "6u", small: "12u", widget: new Widget.CallUs()}, 64 | {size: "3u", medium: "6u", small: "12u", widget: new Widget.Search()}, 65 | {size: "3u", medium: "6u", small: "12u", widget: new Widget.MiniCart()} 66 | ], 67 | [ 68 | {size: "12u", widget: new Widget.Error({{error}})} 69 | ], 70 | [ 71 | {size: "6u", medium: "8u", small: "12u", widget: "

My Account

"} 72 | ], 73 | [ 74 | {size: "3u", medium: "6u", small: "12u", widget: new Widget.AccountOptions()}, 75 | {size: "9u", medium: "6u", small: "12u", widget: new Widget.Order({{order}})} 76 | ] 77 | ]); 78 | ]], json.encodeProperties(data)) 79 | })) -------------------------------------------------------------------------------- /extensions/shop/src/controller/account/AccountPageController.lua: -------------------------------------------------------------------------------- 1 | local json = require "json" 2 | local parse = require "parse" 3 | local param = require "param" 4 | local property = require "property" 5 | local localization = require "localization" 6 | local database = require "database" 7 | local exception = require "exception" 8 | local exceptionHandler = require "exceptionHandler" 9 | local localeService = require "localeService" 10 | local priceService = require "priceService" 11 | local cartService = require "cartService" 12 | 13 | 14 | 15 | local function process (db, data) 16 | local locale = localeService.getLocale(db) 17 | data.locale = locale 18 | end 19 | 20 | 21 | local data = {} 22 | local db = database.connect() 23 | local ok, err = pcall(process, db, data) 24 | db:close() 25 | if not ok then 26 | exceptionHandler.toData(data, err) 27 | end 28 | 29 | 30 | ngx.say(parse(require("BaselineHtmlTemplate"), { 31 | title = "Account", 32 | externalJS = [[ 33 | 34 | ]], 35 | externalCSS = [[ 36 | 37 | 38 | 39 | ]], 40 | initJS = parse([[ 41 | var vars = {} 42 | 43 | vars.locale = {{locale}} 44 | 45 | Widget.setContainerToPage([ 46 | [ 47 | {size: "12u", widget: new Widget.ShopHeader()} 48 | ], 49 | [ 50 | {size: "3u", medium: "6u", small: "12u", widget: new Widget.Logo()}, 51 | {size: "3u", medium: "6u", small: "12u", widget: new Widget.CallUs()}, 52 | {size: "3u", medium: "6u", small: "12u", widget: new Widget.Search()}, 53 | {size: "3u", medium: "6u", small: "12u", widget: new Widget.MiniCart()} 54 | ], 55 | [ 56 | {size: "12u", widget: new Widget.Error({{error}})} 57 | ], 58 | [ 59 | {size: "6u", medium: "8u", small: "12u", widget: "

My Account

"} 60 | ], 61 | [ 62 | {size: "3u", medium: "6u", small: "12u", widget: new Widget.AccountOptions()} 63 | ] 64 | ]); 65 | ]], json.encodeProperties(data)) 66 | })) -------------------------------------------------------------------------------- /extensions/shop/src/controller/account/AccountRemoveAddressController.lua: -------------------------------------------------------------------------------- 1 | local json = require "json" 2 | local parse = require "parse" 3 | local param = require "param" 4 | local property = require "property" 5 | local localization = require "localization" 6 | local database = require "database" 7 | local exit = require "exit" 8 | local exception = require "exception" 9 | local exceptionHandler = require "exceptionHandler" 10 | local util = require "util" 11 | local userService = require "userService" 12 | local localeService = require "localeService" 13 | local priceService = require "priceService" 14 | local cartService = require "cartService" 15 | 16 | 17 | 18 | local function process (db, data) 19 | local op = db:operators() 20 | 21 | 22 | local locale = localeService.getLocale(db) 23 | data.locale = locale 24 | 25 | 26 | if util.isNotEmpty(param.address) then 27 | db:delete({address = {id = param.address}}) 28 | else 29 | exception("address is required") 30 | end 31 | end 32 | 33 | 34 | local data = {} 35 | local db = database.connect() 36 | local ok, err = pcall(process, db, data) 37 | db:close() 38 | 39 | 40 | if ok then 41 | return ngx.redirect(property.shopUrl .. property.accountAddressesUrl) 42 | else 43 | exceptionHandler.toCookie(err) 44 | return ngx.redirect(property.shopUrl .. property.accountAddressesUrl) 45 | end -------------------------------------------------------------------------------- /extensions/shop/src/controller/account/LoginPageController.lua: -------------------------------------------------------------------------------- 1 | local json = require "json" 2 | local parse = require "parse" 3 | local property = require "property" 4 | local localization = require "localization" 5 | local database = require "database" 6 | local exception = require "exception" 7 | local exceptionHandler = require "exceptionHandler" 8 | local util = require "util" 9 | local userService = require "userService" 10 | local localeService = require "localeService" 11 | local priceService = require "priceService" 12 | local cartService = require "cartService" 13 | 14 | 15 | 16 | local function process (db, data) 17 | local locale = localeService.getLocale(db) 18 | data.locale = locale 19 | 20 | 21 | local to = userService.redirectTo(property.shopUrl .. property.loginUrl) 22 | if util.isNotEmpty(to) then 23 | data.to = to 24 | else 25 | data.to = property.shopUrl .. property.accountUrl 26 | end 27 | 28 | 29 | data.registerUrl = property.shopUrl .. property.registerUrl 30 | end 31 | 32 | 33 | local data = {} 34 | local db = database.connect() 35 | local ok, err = pcall(process, db, data) 36 | db:close() 37 | if not ok then 38 | exceptionHandler.toData(data, err) 39 | end 40 | 41 | 42 | ngx.say(parse(require("BaselineHtmlTemplate"), { 43 | title = "Login", 44 | externalJS = [[ 45 | 46 | ]], 47 | externalCSS = [[ 48 | 49 | 50 | 51 | ]], 52 | initJS = parse([[ 53 | var vars = {} 54 | 55 | vars.locale = {{locale}} 56 | 57 | Widget.setContainerToPage([ 58 | [ 59 | {size: "12u", widget: new Widget.ShopHeader()} 60 | ], 61 | [ 62 | {size: "3u", medium: "6u", small: "12u", widget: new Widget.Logo()}, 63 | {size: "3u", medium: "6u", small: "12u", widget: new Widget.CallUs()}, 64 | {size: "3u", medium: "6u", small: "12u", widget: new Widget.Search()}, 65 | {size: "3u", medium: "6u", small: "12u", widget: new Widget.MiniCart()} 66 | ], 67 | [ 68 | {size: "12u", widget: new Widget.Error({{error}})} 69 | ], 70 | [ 71 | {size: "6u", medium: "8u", small: "12u", widget: new Widget.LoginForm({to: {{to}}})} 72 | ], 73 | [ 74 | {size: "6u", medium: "8u", small: "12u", widget: '

Register

'} 75 | ] 76 | ]); 77 | ]], json.encodeProperties(data)) 78 | })) -------------------------------------------------------------------------------- /extensions/shop/src/controller/account/RegisterPageController.lua: -------------------------------------------------------------------------------- 1 | local json = require "json" 2 | local parse = require "parse" 3 | local property = require "property" 4 | local localization = require "localization" 5 | local database = require "database" 6 | local exception = require "exception" 7 | local exceptionHandler = require "exceptionHandler" 8 | local util = require "util" 9 | local userService = require "userService" 10 | local localeService = require "localeService" 11 | local priceService = require "priceService" 12 | local cartService = require "cartService" 13 | 14 | 15 | 16 | local function process (db, data) 17 | local locale = localeService.getLocale(db) 18 | data.locale = locale 19 | 20 | 21 | local to = userService.redirectTo(property.shopUrl .. property.registerUrl) 22 | if util.isNotEmpty(to) then 23 | data.to = to 24 | else 25 | data.to = property.shopUrl .. property.accountUrl 26 | end 27 | end 28 | 29 | 30 | local data = {} 31 | local db = database.connect() 32 | local ok, err = pcall(process, db, data) 33 | db:close() 34 | if not ok then 35 | exceptionHandler.toData(data, err) 36 | end 37 | 38 | 39 | ngx.say(parse(require("BaselineHtmlTemplate"), { 40 | title = "Register", 41 | externalJS = [[ 42 | 43 | ]], 44 | externalCSS = [[ 45 | 46 | 47 | 48 | ]], 49 | initJS = parse([[ 50 | var vars = {} 51 | 52 | vars.locale = {{locale}} 53 | 54 | Widget.setContainerToPage([ 55 | [ 56 | {size: "12u", widget: new Widget.ShopHeader()} 57 | ], 58 | [ 59 | {size: "3u", medium: "6u", small: "12u", widget: new Widget.Logo()}, 60 | {size: "3u", medium: "6u", small: "12u", widget: new Widget.CallUs()}, 61 | {size: "3u", medium: "6u", small: "12u", widget: new Widget.Search()}, 62 | {size: "3u", medium: "6u", small: "12u", widget: new Widget.MiniCart()} 63 | ], 64 | [ 65 | {size: "12u", widget: new Widget.Error({{error}})} 66 | ], 67 | [ 68 | {size: "6u", medium: "8u", small: "12u", widget: new Widget.RegisterForm({to: {{to}}})} 69 | ] 70 | ]); 71 | ]], json.encodeProperties(data)) 72 | })) -------------------------------------------------------------------------------- /extensions/shop/src/controller/catalog/ProductPageController.lua: -------------------------------------------------------------------------------- 1 | local json = require "json" 2 | local parse = require "parse" 3 | local property = require "property" 4 | local localization = require "localization" 5 | local database = require "database" 6 | local exception = require "exception" 7 | local exceptionHandler = require "exceptionHandler" 8 | local util = require "util" 9 | local localeService = require "localeService" 10 | local priceService = require "priceService" 11 | 12 | 13 | 14 | local function process (db, data) 15 | local op = db:operators() 16 | 17 | 18 | local locale = localeService.getLocale(db) 19 | data.locale = locale 20 | 21 | 22 | local productCode 23 | local uries = util.split(ngx.var.uri, "/") 24 | if property.productUrl == "/" .. uries[#uries - 1] then 25 | productCode = uries[#uries] 26 | end 27 | 28 | if productCode then 29 | local product = db:findOne({product = {code = op.equal(productCode)}}, { 30 | "pictures", 31 | "prices", 32 | {name = {locale = locale}} 33 | }) 34 | priceService.convertProductsPrices(db, product) 35 | data.product = product 36 | end 37 | end 38 | 39 | 40 | local data = {} 41 | local db = database.connect() 42 | local ok, err = pcall(process, db, data) 43 | db:close() 44 | if not ok then 45 | exceptionHandler.toData(data, err) 46 | end 47 | 48 | 49 | ngx.say(parse(require("BaselineHtmlTemplate"), { 50 | title = "Product Detail", 51 | externalJS = [[ 52 | 53 | 54 | ]], 55 | externalCSS = [[ 56 | 57 | 58 | 59 | ]], 60 | initJS = parse([[ 61 | var vars = {} 62 | 63 | vars.locale = {{locale}} 64 | 65 | Widget.setContainerToPage([ 66 | [ 67 | {size: "12u", widget: new Widget.ShopHeader()} 68 | ], 69 | [ 70 | {size: "3u", medium: "6u", small: "12u", widget: new Widget.Logo()}, 71 | {size: "3u", medium: "6u", small: "12u", widget: new Widget.CallUs()}, 72 | {size: "3u", medium: "6u", small: "12u", widget: new Widget.Search()}, 73 | {size: "3u", medium: "6u", small: "12u", widget: new Widget.MiniCart()} 74 | ], 75 | [ 76 | {size: "12u", widget: new Widget.Error({{error}})} 77 | ], 78 | [ 79 | {size: "9u -3u", medium: "8u -4u", small: "12u", widget: new Widget.ProductDetail({{product}})} 80 | ] 81 | ]) 82 | ]], json.encodeProperties(data)) 83 | })) -------------------------------------------------------------------------------- /extensions/shop/src/controller/checkout/AddToCartController.lua: -------------------------------------------------------------------------------- 1 | local json = require "json" 2 | local parse = require "parse" 3 | local param = require "param" 4 | local property = require "property" 5 | local localization = require "localization" 6 | local database = require "database" 7 | local exit = require "exit" 8 | local localeService = require "localeService" 9 | local priceService = require "priceService" 10 | local cartService = require "cartService" 11 | 12 | 13 | 14 | local function process (db, data) 15 | local locale = localeService.getLocale(db) 16 | data.locale = locale 17 | 18 | 19 | local cart = cartService.addToCart(db, param.productCode, param.quantity) 20 | data.cart = cartService.convertCart(db, cart) 21 | end 22 | 23 | 24 | local data = {} 25 | local db = database.connect() 26 | local ok, err = pcall(process, db, data) 27 | db:close() 28 | 29 | 30 | if ok then 31 | ngx.say(json.encode(data)) 32 | else 33 | exit(err) 34 | end -------------------------------------------------------------------------------- /extensions/shop/src/controller/checkout/CheckoutAddAddressController.lua: -------------------------------------------------------------------------------- 1 | local json = require "json" 2 | local parse = require "parse" 3 | local property = require "property" 4 | local localization = require "localization" 5 | local database = require "database" 6 | local exit = require "exit" 7 | local exception = require "exception" 8 | local exceptionHandler = require "exceptionHandler" 9 | local util = require "util" 10 | local userService = require "userService" 11 | local localeService = require "localeService" 12 | local priceService = require "priceService" 13 | local cartService = require "cartService" 14 | 15 | 16 | 17 | local function process (db, data) 18 | local op = db:operators() 19 | 20 | 21 | local locale = localeService.getLocale(db) 22 | data.locale = locale 23 | 24 | 25 | local cart = cartService.getCart(db) 26 | local user = userService.authenticatedUser(db) 27 | if user then 28 | local function addAddressTransaction () 29 | local address = util.parseForm(util.urldecode(ngx.req.get_body_data())) 30 | address.user = user 31 | address.carts = {cart} 32 | db:add({address = address}) 33 | 34 | user.addresses = nil -- refresh 35 | end 36 | 37 | local ok, res = pcall(db.transaction, db, addAddressTransaction) 38 | if not ok then exception("user=" .. user.id .. " => " .. res) end 39 | end 40 | end 41 | 42 | 43 | local data = {} 44 | local db = database.connect() 45 | local ok, err = pcall(process, db, data) 46 | db:close() 47 | 48 | 49 | if ok then 50 | return ngx.redirect(property.shopUrl .. property.checkoutDeliveryMethodUrl) 51 | else 52 | exceptionHandler.toCookie(err) 53 | return ngx.redirect(property.shopUrl .. property.checkoutAddressUrl) 54 | end -------------------------------------------------------------------------------- /extensions/shop/src/controller/checkout/CheckoutConfirmationPageController.lua: -------------------------------------------------------------------------------- 1 | local json = require "json" 2 | local parse = require "parse" 3 | local param = require "param" 4 | local property = require "property" 5 | local localization = require "localization" 6 | local database = require "database" 7 | local exception = require "exception" 8 | local exceptionHandler = require "exceptionHandler" 9 | local localeService = require "localeService" 10 | local priceService = require "priceService" 11 | local cartService = require "cartService" 12 | 13 | 14 | 15 | local function process (db, data) 16 | local locale = localeService.getLocale(db) 17 | data.locale = locale 18 | end 19 | 20 | 21 | local data = {} 22 | local db = database.connect() 23 | local ok, err = pcall(process, db, data) 24 | db:close() 25 | if not ok then 26 | exceptionHandler.toData(data, err) 27 | end 28 | 29 | 30 | ngx.say(parse(require("BaselineHtmlTemplate"), { 31 | title = "Thank You", 32 | externalJS = [[ 33 | 34 | ]], 35 | externalCSS = [[ 36 | 37 | 38 | 39 | ]], 40 | initJS = parse([[ 41 | var vars = {} 42 | 43 | vars.locale = {{locale}} 44 | 45 | Widget.setContainerToPage([ 46 | [ 47 | {size: "12u", widget: new Widget.ShopHeader()} 48 | ], 49 | [ 50 | {size: "3u", medium: "6u", small: "12u", widget: new Widget.Logo()}, 51 | {size: "3u", medium: "6u", small: "12u", widget: new Widget.CallUs()}, 52 | {size: "3u", medium: "6u", small: "12u", widget: new Widget.Search()}, 53 | {size: "3u", medium: "6u", small: "12u", widget: new Widget.MiniCart()} 54 | ], 55 | [ 56 | {size: "12u", widget: new Widget.Error({{error}})} 57 | ], 58 | [ 59 | {size: "6u", medium: "8u", small: "12u", widget: "

Thank You For Your Order

"} 60 | ] 61 | ]); 62 | ]], json.encodeProperties(data)) 63 | })) -------------------------------------------------------------------------------- /extensions/shop/src/controller/checkout/CheckoutPageController.lua: -------------------------------------------------------------------------------- 1 | local json = require "json" 2 | local parse = require "parse" 3 | local param = require "param" 4 | local property = require "property" 5 | local localization = require "localization" 6 | local database = require "database" 7 | local exit = require "exit" 8 | local exception = require "exception" 9 | local exceptionHandler = require "exceptionHandler" 10 | local localeService = require "localeService" 11 | local priceService = require "priceService" 12 | local cartService = require "cartService" 13 | 14 | 15 | 16 | local function process (db, data) 17 | local locale = localeService.getLocale(db) 18 | data.locale = locale 19 | 20 | 21 | local cart = cartService.getCart(db) 22 | if cart.productEntries then 23 | data.redirectUrl = property.shopUrl .. property.checkoutAddressesUrl 24 | return 25 | else 26 | exceptionHandler.toCookie("cart does not have products") 27 | data.redirectUrl = property.shopUrl .. property.cartUrl 28 | return 29 | end 30 | end 31 | 32 | 33 | local data = {} 34 | local db = database.connect() 35 | local ok, err = pcall(process, db, data) 36 | db:close() 37 | 38 | 39 | if ok and data.redirectUrl then 40 | return ngx.redirect(data.redirectUrl) 41 | else 42 | exceptionHandler.toCookie(err) 43 | return ngx.redirect(property.shopUrl .. property.cartUrl) 44 | end -------------------------------------------------------------------------------- /extensions/shop/src/controller/checkout/CheckoutPlaceOrderController.lua: -------------------------------------------------------------------------------- 1 | local json = require "json" 2 | local parse = require "parse" 3 | local param = require "param" 4 | local property = require "property" 5 | local localization = require "localization" 6 | local database = require "database" 7 | local exception = require "exception" 8 | local exceptionHandler = require "exceptionHandler" 9 | local exit = require "exit" 10 | local uuid = require "uuid" 11 | local localeService = require "localeService" 12 | local priceService = require "priceService" 13 | local cartService = require "cartService" 14 | 15 | 16 | 17 | local function process (db, data) 18 | local op = db:operators() 19 | 20 | 21 | local locale = localeService.getLocale(db) 22 | data.locale = locale 23 | 24 | 25 | local cart = cartService.getCart(db) 26 | if not cart.productEntries or not cart.address or not cart.deliveryMethod or not cart.paymentMethod then 27 | exceptionHandler.toCookie("cart does not have products/address/deliveryMethod/paymentMethod") 28 | data.redirectUrl = property.shopUrl .. property.cartUrl 29 | return 30 | end 31 | 32 | 33 | local order = db:findOne({cart = {id = op.equal(cart.id)}}, { 34 | "totalGrossPrice", 35 | "totalNetPrice", 36 | "totalVAT", 37 | {productEntries = {"unitPrice", "totalPrice", "product"}}, 38 | "deliveryMethod", 39 | "paymentMethod", 40 | "address", 41 | "user", 42 | }) 43 | 44 | uuid.seed(db:timestamp()) 45 | order.code = uuid() 46 | order.creationTime = os.date("%Y-%m-%d %H:%M:%S") 47 | 48 | db:addAll({order = order}, { 49 | {productEntries = {"product"}}, 50 | "deliveryMethod", 51 | "paymentMethod", 52 | "user", 53 | }) 54 | end 55 | 56 | 57 | local data = {} 58 | local db = database.connect() 59 | local ok, err = pcall(process, db, data) 60 | db:close() 61 | 62 | 63 | if ok then 64 | if data.redirectUrl then 65 | return ngx.redirect(data.redirectUrl) 66 | else 67 | return ngx.redirect(property.shopUrl .. property.checkoutConfirmationUrl) 68 | end 69 | else 70 | exceptionHandler.toCookie(err) 71 | return ngx.redirect(property.shopUrl .. property.checkoutReviewOrderUrl) 72 | end -------------------------------------------------------------------------------- /extensions/shop/src/controller/checkout/CheckoutSetAddressController.lua: -------------------------------------------------------------------------------- 1 | local json = require "json" 2 | local parse = require "parse" 3 | local param = require "param" 4 | local property = require "property" 5 | local localization = require "localization" 6 | local database = require "database" 7 | local exit = require "exit" 8 | local exception = require "exception" 9 | local exceptionHandler = require "exceptionHandler" 10 | local util = require "util" 11 | local localeService = require "localeService" 12 | local priceService = require "priceService" 13 | local cartService = require "cartService" 14 | 15 | 16 | 17 | local function process (db, data) 18 | local op = db:operators() 19 | 20 | 21 | local locale = localeService.getLocale(db) 22 | data.locale = locale 23 | 24 | 25 | if util.isNotEmpty(param.address) then 26 | local address = db:findOne({address = {id = op.equal(param.address)}}) 27 | 28 | local cart = cartService.getCart(db) 29 | cart.address = address 30 | db:update({cart = cart}) 31 | else 32 | exception("address is empty") 33 | end 34 | end 35 | 36 | 37 | local data = {} 38 | local db = database.connect() 39 | local ok, err = pcall(process, db, data) 40 | db:close() 41 | 42 | 43 | if ok then 44 | return ngx.redirect(property.shopUrl .. property.checkoutDeliveryMethodUrl) 45 | else 46 | exceptionHandler.toCookie(err) 47 | return ngx.redirect(property.shopUrl .. property.checkoutAddressesUrl) 48 | end -------------------------------------------------------------------------------- /extensions/shop/src/controller/checkout/CheckoutSetDeliveryMethodController.lua: -------------------------------------------------------------------------------- 1 | local json = require "json" 2 | local parse = require "parse" 3 | local param = require "param" 4 | local property = require "property" 5 | local localization = require "localization" 6 | local database = require "database" 7 | local exit = require "exit" 8 | local exception = require "exception" 9 | local exceptionHandler = require "exceptionHandler" 10 | local util = require "util" 11 | local localeService = require "localeService" 12 | local priceService = require "priceService" 13 | local cartService = require "cartService" 14 | 15 | 16 | 17 | local function process (db, data) 18 | local op = db:operators() 19 | 20 | 21 | local locale = localeService.getLocale(db) 22 | data.locale = locale 23 | 24 | 25 | if util.isNotEmpty(param.deliveryMethod) then 26 | local deliveryMethod = db:findOne({deliveryMethod = {id = op.equal(param.deliveryMethod)}}) 27 | 28 | local cart = cartService.getCart(db) 29 | cart.deliveryMethod = deliveryMethod 30 | db:update({cart = cart}) 31 | else 32 | exception("deliveryMethod is empty") 33 | end 34 | end 35 | 36 | 37 | local data = {} 38 | local db = database.connect() 39 | local ok, err = pcall(process, db, data) 40 | db:close() 41 | 42 | 43 | if ok then 44 | return ngx.redirect(property.shopUrl .. property.checkoutPaymentMethodUrl) 45 | else 46 | exceptionHandler.toCookie(err) 47 | return ngx.redirect(property.shopUrl .. property.checkoutDeliveryMethodUrl) 48 | end -------------------------------------------------------------------------------- /extensions/shop/src/controller/checkout/CheckoutSetPaymentMethodController.lua: -------------------------------------------------------------------------------- 1 | local json = require "json" 2 | local parse = require "parse" 3 | local param = require "param" 4 | local property = require "property" 5 | local localization = require "localization" 6 | local database = require "database" 7 | local exit = require "exit" 8 | local exception = require "exception" 9 | local exceptionHandler = require "exceptionHandler" 10 | local util = require "util" 11 | local localeService = require "localeService" 12 | local priceService = require "priceService" 13 | local cartService = require "cartService" 14 | 15 | 16 | 17 | local function process (db, data) 18 | local op = db:operators() 19 | 20 | 21 | local locale = localeService.getLocale(db) 22 | data.locale = locale 23 | 24 | 25 | if util.isNotEmpty(param.paymentMethod) then 26 | local paymentMethod = db:findOne({paymentMethod = {id = op.equal(param.paymentMethod)}}) 27 | 28 | local cart = cartService.getCart(db) 29 | cart.paymentMethod = paymentMethod 30 | db:update({cart = cart}) 31 | else 32 | exception("paymentMethod is empty") 33 | end 34 | end 35 | 36 | 37 | local data = {} 38 | local db = database.connect() 39 | local ok, err = pcall(process, db, data) 40 | db:close() 41 | 42 | 43 | if ok then 44 | return ngx.redirect(property.shopUrl .. property.checkoutReviewOrderUrl) 45 | else 46 | exceptionHandler.toCookie(err) 47 | return ngx.redirect(property.shopUrl .. property.checkoutPaymentMethodUrl) 48 | end -------------------------------------------------------------------------------- /extensions/shop/src/controller/checkout/UpdateProductEntryController.lua: -------------------------------------------------------------------------------- 1 | local json = require "json" 2 | local parse = require "parse" 3 | local param = require "param" 4 | local property = require "property" 5 | local localization = require "localization" 6 | local database = require "database" 7 | local exit = require "exit" 8 | local localeService = require "localeService" 9 | local priceService = require "priceService" 10 | local cartService = require "cartService" 11 | 12 | 13 | 14 | local function process (db, data) 15 | local locale = localeService.getLocale(db) 16 | data.locale = locale 17 | 18 | 19 | local cart = cartService.updateProductEntry(db, param.productEntryId, param.quantity) 20 | data.cart = cartService.convertCart(db, cart) 21 | end 22 | 23 | 24 | local data = {} 25 | local db = database.connect() 26 | local ok, err = pcall(process, db, data) 27 | db:close() 28 | 29 | 30 | if ok then 31 | ngx.say(json.encode(data)) 32 | else 33 | exit(err) 34 | end -------------------------------------------------------------------------------- /extensions/shop/src/filter/ShopRedirectOnSessionTimeoutFilter.lua: -------------------------------------------------------------------------------- 1 | local property = require "property" 2 | local database = require "database" 3 | local util = require "util" 4 | local userService = require "userService" 5 | 6 | 7 | 8 | -- security -- 9 | if property.shopRequireSecurity then 10 | local db = database.connect() 11 | local ok, res = pcall(userService.loggedIn, db) 12 | db:close() 13 | 14 | -- remove cache -- 15 | ngx.ctx = {} 16 | 17 | if not ok or not res then 18 | if util.isNotEmpty(ngx.var.args) then 19 | ngx.redirect(property.shopUrl .. property.loginUrl .. ngx.var.uri .. "?" .. ngx.var.args) 20 | ngx.exit(ngx.HTTP_OK) 21 | else 22 | ngx.redirect(property.shopUrl .. property.loginUrl .. ngx.var.uri) 23 | ngx.exit(ngx.HTTP_OK) 24 | end 25 | end 26 | end -------------------------------------------------------------------------------- /extensions/shop/src/filter/ShopThrowErrorOnSessionTimeoutFilter.lua: -------------------------------------------------------------------------------- 1 | local param = require "param" 2 | local property = require "property" 3 | local database = require "database" 4 | local userService = require "userService" 5 | 6 | 7 | 8 | -- security -- 9 | if property.shopRequireSecurity then 10 | local db = database.connect() 11 | local ok, res = pcall(userService.loggedIn, db) 12 | db:close() 13 | 14 | -- remove cache -- 15 | ngx.ctx = {} 16 | 17 | if not ok or not res then 18 | ngx.status = ngx.HTTP_FORBIDDEN 19 | ngx.say("ERROR: user not logged in") 20 | ngx.exit(ngx.HTTP_OK) 21 | end 22 | end -------------------------------------------------------------------------------- /extensions/shop/src/module/CountryService.lua: -------------------------------------------------------------------------------- 1 | local uuid = require "uuid" 2 | local cookie = require "cookie" 3 | local exception = require "exception" 4 | local util = require "util" 5 | 6 | 7 | 8 | local countryCookieName = "country" 9 | 10 | 11 | -- 12 | -- NOTE: ngx.ctx.country holds country, currency and locale for the whole request 13 | -- 14 | local function getCountry (db) 15 | local property = require "property" 16 | 17 | local op = db:operators() 18 | 19 | if ngx.ctx.country then 20 | return ngx.ctx.country 21 | end 22 | 23 | local countryIsocode, err = cookie:get(countryCookieName) 24 | if util.isEmpty(countryIsocode) or err then 25 | local country = db:findOne({country = {isocode = op.equal(property.defaultCountryIsocode)}}) 26 | ngx.ctx.country = country 27 | return country 28 | else 29 | local country = db:findOne({country = {isocode = op.equal(countryIsocode)}}) 30 | ngx.ctx.country = country 31 | return country 32 | end 33 | end 34 | 35 | 36 | local function setCountry (countryIsocode) 37 | --local property = require "property" 38 | 39 | -- set countryIsocode in cookie 40 | local ok, err = cookie:set({ 41 | key = countryCookieName, 42 | value = countryIsocode, 43 | path = "/", 44 | domain = ngx.var.host, 45 | --max_age = property.sessionTimeout, 46 | --secure = true, 47 | httponly = true 48 | }) 49 | 50 | if not ok then 51 | exception(err) 52 | end 53 | end 54 | 55 | 56 | return { 57 | getCountry = getCountry, 58 | setCountry = setCountry, 59 | } -------------------------------------------------------------------------------- /extensions/shop/src/module/LocaleService.lua: -------------------------------------------------------------------------------- 1 | local uuid = require "uuid" 2 | local cookie = require "cookie" 3 | local exception = require "exception" 4 | local util = require "util" 5 | local countryService = require "countryService" 6 | 7 | 8 | 9 | local localeCookieName = "locale" 10 | 11 | 12 | local function getLocale (db) 13 | local locale, err = cookie:get(localeCookieName) 14 | if util.isEmpty(locale) or err then 15 | local country = countryService.getCountry(db) 16 | return country.locale 17 | --local property = require "property" 18 | --return property.defaultLocale 19 | else 20 | return locale 21 | end 22 | end 23 | 24 | 25 | local function setLocale (locale) 26 | --local property = require "property" 27 | 28 | -- set locale in cookie 29 | local ok, err = cookie:set({ 30 | key = localeCookieName, 31 | value = locale, 32 | path = "/", 33 | domain = ngx.var.host, 34 | --max_age = property.sessionTimeout, 35 | --secure = true, 36 | httponly = true 37 | }) 38 | 39 | if not ok then 40 | exception(err) 41 | end 42 | end 43 | 44 | 45 | return { 46 | getLocale = getLocale, 47 | setLocale = setLocale 48 | } -------------------------------------------------------------------------------- /extensions/shop/src/widget/account/AccountOptions.js: -------------------------------------------------------------------------------- 1 | Widget.AccountOptions = function (data) { 2 | this.data = data 3 | this.html = parse(function(){/*! 4 | 9 | */}, data) 10 | } 11 | 12 | Widget.AccountOptions.prototype = { 13 | constructor: Widget.AccountOptions 14 | } -------------------------------------------------------------------------------- /extensions/shop/src/widget/account/AddressForm.js: -------------------------------------------------------------------------------- 1 | Widget.AddressForm = function (data) { 2 | this.data = data 3 | this.html = parse(function(){/*! 4 |
5 |
6 | 7 | 8 |
9 | 10 |
11 |
12 | 13 |
14 |
15 | 16 |
17 |
18 | 19 |
20 |
21 | 22 |
23 |
24 | 25 |
26 |
27 | 28 |
29 |
30 | 31 |
32 |
33 | 34 |
35 |
36 | 37 |
38 | 39 |
40 |
    41 |
  • 42 |
43 |
44 |
45 |
46 | */}, data) 47 | } 48 | 49 | Widget.AddressForm.prototype = { 50 | constructor: Widget.AddressForm 51 | } -------------------------------------------------------------------------------- /extensions/shop/src/widget/account/Addresses.js: -------------------------------------------------------------------------------- 1 | Widget.Addresses = function (data) { 2 | data.formId = Widget.guid() 3 | 4 | this.data = data 5 | this.html = parse(function(){/*! 6 |
7 |
8 | {{# addresses[i] 9 |
10 | 11 | 12 |
13 | }}# 14 | 15 |
16 |
    17 | {{?@ !isEmpty(data.editAddressUrl) 18 |
  • 20 | }}? 21 | {{?@ !isEmpty(data.removeAddressUrl) 22 |
  • 24 | }}? 25 | {{?@ !isEmpty(data.setAddressUrl) 26 |
  • 28 | }}? 29 |
  • {{addAddressName}}
  • 30 |
31 |
32 |
33 |
34 | */}, data) 35 | } 36 | 37 | Widget.Addresses.prototype = { 38 | constructor: Widget.Addresses 39 | } 40 | 41 | Widget.Addresses.setActionUrl = function (formId, actionUrl) { 42 | $("#" + formId).attr("action", actionUrl) 43 | } -------------------------------------------------------------------------------- /extensions/shop/src/widget/account/Order.js: -------------------------------------------------------------------------------- 1 | Widget.Order = function (cart) { 2 | if (cart && cart.productEntries) { 3 | for (var i = 0; i < cart.productEntries.length; i++) { 4 | var product = cart.productEntries[i].product 5 | 6 | product.url = property.shopUrl + property.productUrl + "/" + product.code 7 | } 8 | } 9 | 10 | var data = {cart: cart, pictureWidth: property.thumbnailPictureWidth, pictureHeight: property.thumbnailPictureHeight} 11 | 12 | this.data = data 13 | this.html = parse(function(){/*! 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | {{# cart.productEntries[i] 27 | 28 | 33 | 34 | 37 | 40 | 43 | 44 | }}# 45 | 46 | 47 | 48 | 49 | 52 | 53 | 54 | 55 | 58 | 59 | 60 | 61 | 64 | 65 | 66 |
PictureNameUnit PriceQuantityTotal Price
29 | 30 | 31 | 32 | {{cart.productEntries[i].product.name[0].content}} 35 | {{cart.productEntries[i].unitPrice}} 36 | 38 | {{cart.productEntries[i].quantity}} 39 | 41 | {{cart.productEntries[i].totalPrice}} 42 |
50 | Net Price: {{cart.totalNetPrice}} 51 |
56 | VAT: {{cart.totalVAT}} 57 |
62 | Gross Price: {{cart.totalGrossPrice}} 63 |
67 |
68 | */}, data) 69 | } 70 | 71 | Widget.Order.prototype = { 72 | constructor: Widget.Order 73 | } -------------------------------------------------------------------------------- /extensions/shop/src/widget/account/Orders.js: -------------------------------------------------------------------------------- 1 | Widget.Orders = function (data) { 2 | this.data = data 3 | this.html = parse(function(){/*! 4 |
5 |
6 | {{# orders[i] 7 |
8 | 9 | 10 |
11 | }}# 12 | 13 |
14 |
    15 |
  • 16 |
17 |
18 |
19 |
20 | */}, data) 21 | } 22 | 23 | Widget.Orders.prototype = { 24 | constructor: Widget.Orders 25 | } -------------------------------------------------------------------------------- /extensions/shop/src/widget/account/RegisterForm.js: -------------------------------------------------------------------------------- 1 | Widget.RegisterForm = function (data) { 2 | this.data = data 3 | this.html = parse(function(){/*! 4 |

Register

5 | 6 |
7 |
8 |
9 | 10 |
11 |
12 | 13 |
14 |
15 | 16 |
17 |
18 | 19 |
20 |
21 |
    22 |
  • 23 |
24 |
25 |
26 |
27 | */}, data) 28 | } 29 | 30 | Widget.RegisterForm.prototype = { 31 | constructor: Widget.RegisterForm 32 | } -------------------------------------------------------------------------------- /extensions/shop/src/widget/catalog/HorizontalNavigation.css: -------------------------------------------------------------------------------- 1 | /* menu */ ul.menu2 { list-style-type: none; margin: 0px 0px 19px 0px; padding: 0; } li.menu2 { display: inline; background: #36c2b9; padding: 13px 13px 13px 13px; margin: 0px -3px 0px 0px; } a.menu2 { text-decoration: none !important; color: white; /* border: 4px solid red; */ } -------------------------------------------------------------------------------- /extensions/shop/src/widget/catalog/HorizontalNavigation.js: -------------------------------------------------------------------------------- 1 | Widget.HorizontalNavigation = function (categories) { 2 | if (categories) { 3 | for (var i = 0; i < categories.length; i++) { 4 | categories[i].url = property.shopUrl + property.categoryUrl + "/" + categories[i].code 5 | } 6 | } 7 | 8 | var data = {categories: categories} 9 | 10 | this.data = data 11 | this.html = parse(function(){/*! 12 | {{? categories.length > 0 13 | 18 | }}? 19 | */}, data) 20 | } 21 | 22 | Widget.HorizontalNavigation.prototype = { 23 | constructor: Widget.HorizontalNavigation 24 | } -------------------------------------------------------------------------------- /extensions/shop/src/widget/catalog/ProductAttributeFilter.js: -------------------------------------------------------------------------------- 1 | Widget.ProductAttributeFilter = function (productAttributes) { 2 | if (productAttributes && productAttributes instanceof Array) { 3 | for (var j = 0; j < productAttributes.length; j++) { 4 | for (var i = 0; i < productAttributes[j].values.length; i++) {productAttributes[j].values[i].guid = Widget.guid()} 5 | } 6 | } 7 | 8 | var data = {productAttributes: productAttributes} 9 | 10 | this.data = data 11 | this.html = parse(function(){/*! 12 | {{# productAttributes[j] 13 | {{? productAttributes[j].values.length > 0 14 |

{{productAttributes[j].name[0].content}}

15 | 27 | }}? 28 | }}# 29 | */}, data) 30 | } 31 | 32 | Widget.ProductAttributeFilter.prototype = { 33 | constructor: Widget.ProductAttributeFilter 34 | } -------------------------------------------------------------------------------- /extensions/shop/src/widget/catalog/ProductDetail.js: -------------------------------------------------------------------------------- 1 | Widget.ProductDetail = function (product) { 2 | var data = {product: product, pictureWidth: property.pictureWidth, pictureHeight: property.pictureHeight} 3 | 4 | this.data = data 5 | this.html = parse(function(){/*! 6 |
7 |
8 | 9 | {{product.name[0].content}} 10 | 11 |
12 | 13 |
14 |

{{product.name[0].content}}

15 | 16 |

17 | 18 | 1 Reviews | 19 | Write a review 20 |

21 | 22 |
23 | Product Code: 24 | {{product.code}} 25 |
26 | 27 |

28 | {{product.prices[0]}} 29 |

30 | 31 |
32 | 33 | 34 | 35 | 37 | 38 | 39 | 40 | 41 |
42 |
43 |
44 | 45 | 46 |
47 |
48 |

Description

49 |

Lorem ipsum dolor sit amet, consectetur adipisicing elit

50 |
51 |
52 | 53 | 54 |
55 |
56 |

Reviews (1)

57 |
58 | 59 |
60 |
Aliquam a malesuada lorem. Nunc in porta.
61 |
62 |
63 | 64 | */}, data) 65 | } 66 | 67 | Widget.ProductDetail.prototype = { 68 | constructor: Widget.ProductDetail 69 | } -------------------------------------------------------------------------------- /extensions/shop/src/widget/catalog/ProductsGrid.js: -------------------------------------------------------------------------------- 1 | Widget.ProductsGrid = function (products) { 2 | if (products) { 3 | for (var i = 0; i < products.length; i++) { 4 | products[i].url = property.shopUrl + property.productUrl + "/" + products[i].code 5 | } 6 | } 7 | 8 | var data = {products: products, pictureWidth: property.pictureWidth, pictureHeight: property.pictureHeight} 9 | 10 | this.data = data 11 | this.html = parse(function(){/*! 12 | {{? products.length > 0 13 |
14 | {{# products[i] 15 |
16 | 17 | 18 | 19 |
20 |
21 | {{products[i].name[0].content}} 22 |
23 |
24 | {{products[i].prices[0]}} 25 |
26 |
27 |
28 |
29 | 31 |
32 |
33 |
34 | }}# 35 |
36 | }}? 37 | */}, data) 38 | } 39 | 40 | Widget.ProductsGrid.prototype = { 41 | constructor: Widget.ProductsGrid 42 | } -------------------------------------------------------------------------------- /extensions/shop/src/widget/checkout/Cart.css: -------------------------------------------------------------------------------- 1 | input.quantity { display: inline; width: 60px !important; text-align: center; } .inline { display: inline; } -------------------------------------------------------------------------------- /extensions/shop/src/widget/checkout/DeliveryMethodForm.js: -------------------------------------------------------------------------------- 1 | Widget.DeliveryMethodForm = function (deliveryMethods) { 2 | var data = {deliveryMethods: deliveryMethods, action: property.shopUrl + property.checkoutSetDeliveryMethodUrl} 3 | 4 | this.data = data 5 | this.html = parse(function(){/*! 6 |
7 |
8 | {{# deliveryMethods[i] 9 |
10 | 11 | 12 |
13 | }}# 14 | 15 |
16 |
    17 |
  • 18 |
19 |
20 |
21 |
22 | */}, data) 23 | } 24 | 25 | Widget.DeliveryMethodForm.prototype = { 26 | constructor: Widget.DeliveryMethodForm 27 | } -------------------------------------------------------------------------------- /extensions/shop/src/widget/checkout/PaymentMethodForm.js: -------------------------------------------------------------------------------- 1 | Widget.PaymentMethodForm = function (paymentMethods) { 2 | var data = {paymentMethods: paymentMethods, action: property.shopUrl + property.checkoutSetPaymentMethodUrl} 3 | 4 | this.data = data 5 | this.html = parse(function(){/*! 6 |
7 |
8 | {{# paymentMethods[i] 9 |
10 | 11 | 12 |
13 | }}# 14 | 15 |
16 |
    17 |
  • 18 |
19 |
20 |
21 |
22 | */}, data) 23 | } 24 | 25 | Widget.PaymentMethodForm.prototype = { 26 | constructor: Widget.PaymentMethodForm 27 | } -------------------------------------------------------------------------------- /extensions/shop/src/widget/header/Background.js: -------------------------------------------------------------------------------- 1 | Widget.Background = function () { 2 | $("body").css('height', $(window).height()) 3 | 4 | var setBackgroundImage = function (imageUrl) { 5 | $("body").css('background', '#FFFFF1 url(' + imageUrl + ') center 0px no-repeat') 6 | } 7 | 8 | 9 | var imageUrl1 = "http://s1emagst.akamaized.net/layout/bg/images/db/5/7385.jpg" 10 | var imageUrl2 = "http://s1emagst.akamaized.net/layout/bg/images/db/5/7391.jpg" 11 | 12 | skel.on('change', function() { 13 | if (skel.isActive('small')) { 14 | setBackgroundImage(imageUrl1) 15 | } else { 16 | setBackgroundImage(imageUrl2) 17 | } 18 | }); 19 | } 20 | 21 | Widget.Background.prototype = { 22 | constructor: Widget.Background 23 | } -------------------------------------------------------------------------------- /extensions/shop/src/widget/header/CallUs.js: -------------------------------------------------------------------------------- 1 | Widget.CallUs = function () { 2 | var data = {} 3 | 4 | this.data = data 5 | this.html = parse(function(){/*! 6 |
7 |
8 | 9 |
10 |
11 |

0123-456-789

12 |

free call orders 24/24h

13 |
14 |
15 | */}, data) 16 | } 17 | 18 | Widget.CallUs.prototype = { 19 | constructor: Widget.CallUs 20 | } -------------------------------------------------------------------------------- /extensions/shop/src/widget/header/Error.js: -------------------------------------------------------------------------------- 1 | Widget.Error = function (errors) { 2 | var data = {errors: errors, guid: Widget.guid()} 3 | 4 | this.data = data 5 | this.html = parse(function(){/*! 6 | {{?@ data.errors instanceof Array 7 |
8 |
9 |
10 | {{# errors[i] 11 |

{{errors[i]}}

12 | }}# 13 |
14 | }}? 15 | */}, data) 16 | } 17 | 18 | Widget.Error.prototype = { 19 | constructor: Widget.Error 20 | } 21 | 22 | Widget.Error.hide = function (guid) { 23 | $("#" + guid).hide() 24 | } -------------------------------------------------------------------------------- /extensions/shop/src/widget/header/Logo.js: -------------------------------------------------------------------------------- 1 | Widget.Logo = function () { 2 | var data = {logoUrl: property.shopUrl + property.shopHomeUrl} 3 | 4 | this.data = data 5 | this.html = parse(function(){/*! 6 |
7 | 8 | 9 | 10 |
11 | */}, data) 12 | } 13 | 14 | Widget.Logo.prototype = { 15 | constructor: Widget.Logo 16 | } -------------------------------------------------------------------------------- /extensions/shop/src/widget/header/MiniCart.js: -------------------------------------------------------------------------------- 1 | Widget.MiniCart = function () { 2 | var data = {} 3 | 4 | this.data = data 5 | this.html = parse(function(){/*! 6 |
7 | 14 |
15 |
16 | Your shopping cart is empty! 17 |
18 |
19 |
20 | */}, data) 21 | } 22 | 23 | Widget.MiniCart.prototype = { 24 | constructor: Widget.MiniCart 25 | } 26 | 27 | Widget.MiniCart.updateNumberOfProducts = function () { 28 | var numberOfProducts = $("#eshop-cart-total") 29 | var oldNumber = parseInt(numberOfProducts.attr("oldNumberOfProducts")) 30 | numberOfProducts.attr("oldNumberOfProducts", oldNumber + 1) 31 | numberOfProducts.html(oldNumber + 1) 32 | } -------------------------------------------------------------------------------- /extensions/shop/src/widget/header/RegBackgroundWithPicture.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: #d50911; 3 | background-image: none; 4 | background-position: center 0px; 5 | padding-top: 0px; 6 | } 7 | body { 8 | background: #d50911 url(http://s1emagst.akamaized.net/layout/bg/images/db/5/7619.jpg) center 0px no-repeat; 9 | } -------------------------------------------------------------------------------- /extensions/shop/src/widget/header/Search.js: -------------------------------------------------------------------------------- 1 | Widget.Search = function () { 2 | var data = {} 3 | 4 | this.data = data 5 | this.html = parse(function(){/*! 6 | 14 | */}, data) 15 | } 16 | 17 | Widget.Search.prototype = { 18 | constructor: Widget.Search 19 | } -------------------------------------------------------------------------------- /extensions/shop/src/widget/header/ShopHeader.js: -------------------------------------------------------------------------------- 1 | Widget.ShopHeader = function (data) { 2 | data = data || {} 3 | 4 | data.homeUrl = property.shopUrl + property.shopHomeUrl 5 | data.accountUrl = property.shopUrl + property.accountUrl 6 | data.cartUrl = property.shopUrl + property.cartUrl 7 | data.checkoutUrl = property.shopUrl + property.checkoutUrl 8 | 9 | this.data = data 10 | this.html = parse(function(){/*! 11 | 38 | */}, data) 39 | } 40 | 41 | Widget.ShopHeader.prototype = { 42 | constructor: Widget.ShopHeader 43 | } 44 | 45 | Widget.ShopHeader.setCountry = function (country) { 46 | $.get(property.shopUrl + property.changeCountryUrl, {country: country}, function(data) { 47 | location.reload() 48 | }) 49 | } -------------------------------------------------------------------------------- /extensions/shop/static/bg_flag.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/strumasoft/octopus/4d66e3d6045cbd533353696abd80e48b1d606f18/extensions/shop/static/bg_flag.gif -------------------------------------------------------------------------------- /extensions/shop/static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/strumasoft/octopus/4d66e3d6045cbd533353696abd80e48b1d606f18/extensions/shop/static/favicon.ico -------------------------------------------------------------------------------- /extensions/shop/static/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/strumasoft/octopus/4d66e3d6045cbd533353696abd80e48b1d606f18/extensions/shop/static/logo.png -------------------------------------------------------------------------------- /extensions/shop/static/p1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/strumasoft/octopus/4d66e3d6045cbd533353696abd80e48b1d606f18/extensions/shop/static/p1.jpg -------------------------------------------------------------------------------- /extensions/shop/static/p2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/strumasoft/octopus/4d66e3d6045cbd533353696abd80e48b1d606f18/extensions/shop/static/p2.jpg -------------------------------------------------------------------------------- /extensions/shop/static/p3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/strumasoft/octopus/4d66e3d6045cbd533353696abd80e48b1d606f18/extensions/shop/static/p3.jpg -------------------------------------------------------------------------------- /extensions/shop/static/p4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/strumasoft/octopus/4d66e3d6045cbd533353696abd80e48b1d606f18/extensions/shop/static/p4.jpg -------------------------------------------------------------------------------- /extensions/shop/static/p5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/strumasoft/octopus/4d66e3d6045cbd533353696abd80e48b1d606f18/extensions/shop/static/p5.jpg -------------------------------------------------------------------------------- /extensions/shop/static/p6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/strumasoft/octopus/4d66e3d6045cbd533353696abd80e48b1d606f18/extensions/shop/static/p6.jpg -------------------------------------------------------------------------------- /extensions/shop/static/stars-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/strumasoft/octopus/4d66e3d6045cbd533353696abd80e48b1d606f18/extensions/shop/static/stars-5.png -------------------------------------------------------------------------------- /extensions/shop/static/style.css: -------------------------------------------------------------------------------- 1 | /* call us */ 2 | 3 | .eshop-phone { 4 | font-size: 40px; 5 | color: #36c2b9; 6 | } 7 | 8 | .eshop-call-us h2 { 9 | color: #36c2b9; 10 | margin: 0 0 -0.1em 0; 11 | } 12 | 13 | .eshop-call-us p { 14 | font-family: "Lato", Arial, sans-serif; 15 | font-size: 14px; 16 | color: #bbb; 17 | } 18 | 19 | /* search */ 20 | .add-on { 21 | border-radius: 0px 4px 4px 0px; 22 | background: #36c2b9; 23 | border: none; 24 | padding: 0.17em 1.3em 5px 20px; 25 | font-size: 30px; 26 | height: auto; 27 | width: 50px; 28 | color: white; 29 | } 30 | 31 | input.search-field { 32 | border-radius: 0px 4px 4px 0px; 33 | border-radius: 4px 0px 0px 4px; 34 | } 35 | 36 | /* basket */ 37 | .eshop-items { 38 | background: #36c2b9; 39 | width: 190px; 40 | } 41 | 42 | .eshop-items a { 43 | color: white; 44 | font-size: 15px; 45 | font-weight: bold; 46 | line-height: 25px; 47 | text-decoration: none; 48 | display: inline-block; 49 | font-weight: bold; 50 | padding: 10px 8px 10px 12px; 51 | text-transform: uppercase; 52 | } 53 | 54 | /* addToCart */ 55 | .addToCart { 56 | margin-bottom: 50px; 57 | } -------------------------------------------------------------------------------- /extensions/shop/static/uk_flag.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/strumasoft/octopus/4d66e3d6045cbd533353696abd80e48b1d606f18/extensions/shop/static/uk_flag.gif --------------------------------------------------------------------------------