waxx 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- checksums.yaml.gz.sig +0 -0
- data/LICENSE +201 -0
- data/README.md +879 -0
- data/bin/waxx +120 -0
- data/lib/waxx/app.rb +173 -0
- data/lib/waxx/conf.rb +54 -0
- data/lib/waxx/console.rb +204 -0
- data/lib/waxx/csrf.rb +14 -0
- data/lib/waxx/database.rb +80 -0
- data/lib/waxx/encrypt.rb +38 -0
- data/lib/waxx/error.rb +60 -0
- data/lib/waxx/html.rb +33 -0
- data/lib/waxx/http.rb +268 -0
- data/lib/waxx/init.rb +273 -0
- data/lib/waxx/irb.rb +44 -0
- data/lib/waxx/irb_env.rb +18 -0
- data/lib/waxx/json.rb +23 -0
- data/lib/waxx/mongodb.rb +221 -0
- data/lib/waxx/mysql2.rb +234 -0
- data/lib/waxx/object.rb +115 -0
- data/lib/waxx/patch.rb +138 -0
- data/lib/waxx/pdf.rb +69 -0
- data/lib/waxx/pg.rb +246 -0
- data/lib/waxx/process.rb +270 -0
- data/lib/waxx/req.rb +116 -0
- data/lib/waxx/res.rb +98 -0
- data/lib/waxx/server.rb +304 -0
- data/lib/waxx/sqlite3.rb +237 -0
- data/lib/waxx/supervisor.rb +47 -0
- data/lib/waxx/test.rb +162 -0
- data/lib/waxx/util.rb +57 -0
- data/lib/waxx/version.rb +3 -0
- data/lib/waxx/view.rb +389 -0
- data/lib/waxx/waxx.rb +73 -0
- data/lib/waxx/x.rb +103 -0
- data/lib/waxx.rb +50 -0
- data/skel/README.md +11 -0
- data/skel/app/app/app.rb +39 -0
- data/skel/app/app/error/app_error.rb +16 -0
- data/skel/app/app/error/dhtml.rb +9 -0
- data/skel/app/app/error/html.rb +8 -0
- data/skel/app/app/error/json.rb +8 -0
- data/skel/app/app/error/pdf.rb +13 -0
- data/skel/app/app/log/app_log.rb +13 -0
- data/skel/app/app.rb +20 -0
- data/skel/app/home/home.rb +16 -0
- data/skel/app/home/html.rb +145 -0
- data/skel/app/html.rb +192 -0
- data/skel/app/usr/email.rb +66 -0
- data/skel/app/usr/html.rb +115 -0
- data/skel/app/usr/list.rb +51 -0
- data/skel/app/usr/password.rb +54 -0
- data/skel/app/usr/record.rb +98 -0
- data/skel/app/usr/usr.js +67 -0
- data/skel/app/usr/usr.rb +277 -0
- data/skel/app/waxx/waxx.rb +109 -0
- data/skel/bin/README.md +1 -0
- data/skel/db/README.md +11 -0
- data/skel/db/app/0-init.sql +88 -0
- data/skel/lib/README.md +1 -0
- data/skel/log/README.md +1 -0
- data/skel/opt/dev/config.yaml +1 -0
- data/skel/opt/prod/config.yaml +1 -0
- data/skel/opt/stage/config.yaml +1 -0
- data/skel/opt/test/config.yaml +1 -0
- data/skel/private/README.md +1 -0
- data/skel/public/lib/site.css +202 -0
- data/skel/public/lib/waxx/w.ico +0 -0
- data/skel/public/lib/waxx/w.png +0 -0
- data/skel/public/lib/waxx/waxx.js +111 -0
- data/skel/tmp/pids/README.md +1 -0
- data.tar.gz.sig +0 -0
- metadata +140 -0
- metadata.gz.sig +3 -0
data/bin/waxx
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
#! /usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
require 'optparse'
|
|
4
|
+
|
|
5
|
+
command = ARGV[0]
|
|
6
|
+
commands = %w(on off buff start stop restart console get put post delete patch config migrate migration deploy test init help)
|
|
7
|
+
if not commands.include? command
|
|
8
|
+
puts "Enter a command: #{commands.join(", ")}"
|
|
9
|
+
puts "waxx --help for all options"
|
|
10
|
+
exit 1
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def parse_options(commands)
|
|
14
|
+
options = {
|
|
15
|
+
sub_command: ARGV[1],
|
|
16
|
+
port: 7700,
|
|
17
|
+
base: Dir.pwd,
|
|
18
|
+
env: "active",
|
|
19
|
+
pid_path: "tmp/pids/waxx.pid",
|
|
20
|
+
daemonize: false,
|
|
21
|
+
log_path: "log/waxx.log",
|
|
22
|
+
user: ENV['USER'],
|
|
23
|
+
group: nil,
|
|
24
|
+
debug: false,
|
|
25
|
+
to: "stage",
|
|
26
|
+
app: "all",
|
|
27
|
+
format: "yaml"
|
|
28
|
+
}
|
|
29
|
+
headline = ["Waxx", "The high-performance flexible framework"].compact.join(" - ")
|
|
30
|
+
OptionParser.new do |opts|
|
|
31
|
+
opts.summary_width = 25
|
|
32
|
+
opts.banner = [headline, "\n\n",
|
|
33
|
+
"Usage: waxx command [-b base_dir] [-p port] [-P pid_file] [-d] [-e env_name] [-l file] [-u user] [-g group] [-f format]\n",
|
|
34
|
+
"Commands: #{commands.join(" ")}\n",
|
|
35
|
+
" waxx help:\n"].compact.join("")
|
|
36
|
+
opts.separator ""
|
|
37
|
+
|
|
38
|
+
opts.on("-p", "--port PORT", Integer, "Specify port", "(default: #{options[:port]})") do |v|
|
|
39
|
+
options[:port] = v
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
opts.on("-b", "--base DIR", String, "The base/root directory of the app. Should contain: app, bin, opt, log, etc.", "(default: cwd: #{options[:base]})") do |v|
|
|
43
|
+
options[:base] = v.sub(/\/$/,"")
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
opts.on("-e", "--env ENVIRONMENT", String, "The env to find the config.yaml file.", "(default: #{options[:env]})") do |v|
|
|
47
|
+
options[:env] = v
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
opts.on("-P", "--pid FILE", String, "save PID in FILE when using -d option.", "(default: #{options[:pid_path]})") do |v|
|
|
51
|
+
options[:pid_path] = File.expand_path(v)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
opts.on("-d", "--daemon", "Daemonize mode", "(default: false)") do |v|
|
|
55
|
+
options[:daemonize] = v
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
opts.on("-l", "--log FILE", String, "Logfile for output", "(default: /var/log/#{@name}.log)") do |v|
|
|
59
|
+
options[:log_path] = v
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
opts.on("-n", "--name NAME", String, "The name of the migration", "(default: ask)") do |name|
|
|
63
|
+
options[:name] = name
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
opts.on("-t", "--to TO", String, "Where to deploy to (defined in opt/deploy.yaml)", "(default: stage)") do |to|
|
|
67
|
+
options[:to] = to
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
opts.on("-u", "--user USER", String, "User to run as", "(default: current user)") do |user|
|
|
71
|
+
options[:user] = user
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
opts.on("-g", "--group GROUP", String, "Group to run as", "(default: current user's primary group)") do |group|
|
|
75
|
+
options[:group] = group
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
opts.on("-D", "--debug", "Output debug messages (console only) 0-9","(default: 0)") do |level|
|
|
79
|
+
options[:debug] = level
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
opts.on("-a", "--app app_name or all", "The app to test.","(default: all)") do |app|
|
|
83
|
+
options[:app] = app
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
opts.on("-f", "--format FORMAT", String, "The format output that supports it (tests and config) (yaml or json).","(default: yaml)") do |format|
|
|
87
|
+
options[:format] = format
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
opts.on_tail("-h", "--help", "Display this usage information.") do
|
|
91
|
+
puts "#{opts}\n"
|
|
92
|
+
exit
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
end.parse!
|
|
96
|
+
options
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
opts = parse_options(commands)
|
|
100
|
+
require_relative '../lib/waxx'
|
|
101
|
+
$:.unshift "#{opts[:base]}"
|
|
102
|
+
if %w(init help).include? command
|
|
103
|
+
Waxx::Conf["opts"] = opts
|
|
104
|
+
else
|
|
105
|
+
Waxx::Conf.load_yaml(opts[:base], opts[:env])
|
|
106
|
+
Waxx::Conf["opts"] = opts
|
|
107
|
+
require "#{opts[:base]}/app/app"
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
if Waxx::Console::Command.respond_to? command
|
|
111
|
+
if %w(migration).include? command
|
|
112
|
+
Waxx::Console::Command.send(command, ARGV[1], ARGV[2], opts)
|
|
113
|
+
elsif %w(get post put delete patch test deploy migration migrate).include? command
|
|
114
|
+
Waxx::Console::Command.send(command, ARGV[1], opts)
|
|
115
|
+
else
|
|
116
|
+
Waxx::Console::Command.send(command, opts)
|
|
117
|
+
end
|
|
118
|
+
else
|
|
119
|
+
puts "The #{command} command has not been implemented yet. opts: #{opts.inspect} conf: #{Waxx::Conf.data.inspect}"
|
|
120
|
+
end
|
data/lib/waxx/app.rb
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
# Waxx Copyright (c) 2016 ePark labs Inc. & Daniel J. Fitzpatrick <dan@eparklabs.com> All rights reserved.
|
|
2
|
+
# Released under the Apache Version 2 License. See LICENSE.txt.
|
|
3
|
+
|
|
4
|
+
##
|
|
5
|
+
# Defines the applications handlers and runs the handlers
|
|
6
|
+
#
|
|
7
|
+
# `@runs` holds a hash of the entire app (routes) with the methods for each
|
|
8
|
+
#
|
|
9
|
+
module Waxx::App
|
|
10
|
+
extend self
|
|
11
|
+
|
|
12
|
+
Root = Waxx::Root + '/app'
|
|
13
|
+
|
|
14
|
+
class ParameterParseError < StandardError; end
|
|
15
|
+
|
|
16
|
+
# `@runs` holds a hash of the entire app (routes) with the methods for each
|
|
17
|
+
attr :runs
|
|
18
|
+
|
|
19
|
+
def init
|
|
20
|
+
@runs = {}
|
|
21
|
+
Waxx::Server.require_apps
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
##
|
|
25
|
+
# Return website page or an error message with status 404
|
|
26
|
+
# `App.not_found(x, title: "Not Found", message: "The record you requested was not found.")`
|
|
27
|
+
# The layout of the error page (html) is defined in app/app/error/html.rb
|
|
28
|
+
def not_found(x, title:"Not Found", message:nil)
|
|
29
|
+
begin
|
|
30
|
+
if message.nil?
|
|
31
|
+
return @runs[:website][:page][:get].call(x, *(x.args))
|
|
32
|
+
end
|
|
33
|
+
rescue => e
|
|
34
|
+
message = e.to_s
|
|
35
|
+
end
|
|
36
|
+
error(x, status: 404, type: "request", title: title, message: message)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
##
|
|
40
|
+
# Set an app runner
|
|
41
|
+
# You don't normally call this directly (see Waxx::Object.runs)
|
|
42
|
+
def []=(name, opts)
|
|
43
|
+
@runs[name.to_sym] = opts
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
##
|
|
47
|
+
# Get an app runner
|
|
48
|
+
# You don't normally call this directly (see Waxx::Object.runs)
|
|
49
|
+
def [](name)
|
|
50
|
+
@runs[name.to_sym]
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def csrf_failure(x)
|
|
54
|
+
error(x, status:400, type:"request", title:"Cross Site Request Forgery Error", message:"The request is missing the correct CSRF token.", args: [])
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
##
|
|
58
|
+
# Run an app
|
|
59
|
+
#
|
|
60
|
+
# Can run the request method (get post put patch delete) or the generic "run".
|
|
61
|
+
#
|
|
62
|
+
# 1. x
|
|
63
|
+
# 2. app: The name of the app (Symbol)
|
|
64
|
+
# 3. act: The act to run (String or Symbol - type must match definition)
|
|
65
|
+
# 4, meth: The request method (Symbol)
|
|
66
|
+
# 5. args: The args to pass to the method (after x) (Array)
|
|
67
|
+
#
|
|
68
|
+
# Example: `App.run(x, :person, :record, :get, [1])` will call the get method with the parameter "1" of the record handler defined in App::Person
|
|
69
|
+
def run(x, app, act, meth, args)
|
|
70
|
+
if @runs[app.to_sym][act][meth.to_sym]
|
|
71
|
+
begin
|
|
72
|
+
@runs[app.to_sym][act][meth.to_sym][x, *args]
|
|
73
|
+
rescue ArgumentError => e
|
|
74
|
+
if Waxx['debug']['on_screen']
|
|
75
|
+
error(x, status: 405, type: "request", title: "Argument Error", message: "#{e.to_s}\n\n#{e.backtrace.join("\n")}")
|
|
76
|
+
else
|
|
77
|
+
Waxx.debug e
|
|
78
|
+
App.not_found(x)
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
elsif @runs[app.to_sym][act][:run]
|
|
82
|
+
begin
|
|
83
|
+
@runs[app.to_sym][act][:run][x, *args]
|
|
84
|
+
rescue ArgumentError => e
|
|
85
|
+
if Waxx['debug']['on_screen']
|
|
86
|
+
error(x, status: 405, type: "request", title: "Argument Error", message: "#{e.to_s}\n\n#{e.backtrace.join("\n")}")
|
|
87
|
+
else
|
|
88
|
+
Waxx.debug e
|
|
89
|
+
App.not_found(x)
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
else
|
|
93
|
+
error(x, status: 405, type: "request", title: "Method Not Implemented", message: "The HTTP method requested is not implemented for this interface.")
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
##
|
|
98
|
+
# Return an error to the client
|
|
99
|
+
# Format is dependant on the request extention x.req.ext.
|
|
100
|
+
# Layouts in app/app/error/*
|
|
101
|
+
def error(x, status:200, type:"request", title:"An error occurred", message:"", args: [])
|
|
102
|
+
x.res.status = status
|
|
103
|
+
App[:app_error][type.to_sym][:get][x, title, message, *args]
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
##
|
|
107
|
+
# Return an alert/error to the client
|
|
108
|
+
# Format is dependant on the request extention x.req.ext.
|
|
109
|
+
# Layouts in app/app/error/*
|
|
110
|
+
def alert(x, status:200, type:"request", title:"Alert", message:"", args: [])
|
|
111
|
+
x.res.status = status
|
|
112
|
+
App[:app_error][type.to_sym][:get][x, title, message, *args]
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
##
|
|
116
|
+
# Determine if the client or user has access to the handler method.
|
|
117
|
+
# See Waxx::Object.runs for details
|
|
118
|
+
def access?(x, acl:nil)
|
|
119
|
+
return true if acl.nil?
|
|
120
|
+
return true if %w(* all any public).include? acl.to_s
|
|
121
|
+
return true if acl.to_s == "user" and x.usr?
|
|
122
|
+
case acl
|
|
123
|
+
when String, Symbol
|
|
124
|
+
return (x.usr["grp"] and x.usr["grp"].include? acl.to_s)
|
|
125
|
+
when Array
|
|
126
|
+
return (x.usr["grp"] and (x.usr["grp"] & acl).size > 0)
|
|
127
|
+
when Hash
|
|
128
|
+
g = nil
|
|
129
|
+
if acl.keys.include? :any or acl.keys.include? :all
|
|
130
|
+
g = acl[:any] || acl[:all]
|
|
131
|
+
elsif acl.keys.include? :read and [:get, :head, :options].include? x.meth
|
|
132
|
+
g = acl[:read]
|
|
133
|
+
elsif acl.keys.include? :write and [:put, :post, :delete, :patch].include? x.meth
|
|
134
|
+
g = acl[:write]
|
|
135
|
+
else
|
|
136
|
+
g = acl[x.meth]
|
|
137
|
+
end
|
|
138
|
+
return false if g.nil?
|
|
139
|
+
return true if %w(* all any public).include? g.to_s
|
|
140
|
+
return access?(x, g)
|
|
141
|
+
when Proc
|
|
142
|
+
return acl.call(x)
|
|
143
|
+
else
|
|
144
|
+
Waxx.debug "No acl type recognized in App.access? for acl: #{acl.inspect}", 1
|
|
145
|
+
false
|
|
146
|
+
end
|
|
147
|
+
false
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
def log(x, cat, name, value=nil, id=nil)
|
|
151
|
+
AppLog.log(x, cat:cat, name:name, value:value, id:id)
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
# Return a random string with no confusing chars (0Oo1iIl etc)
|
|
155
|
+
def random_password(size=10)
|
|
156
|
+
random_string(size, :chars, 'ABCDEFGHJKLMNPQRSTUVWXYabcdefghkmnpqrstuvwxyz23456789#%^&$*i-_+=')
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def login_needed(x)
|
|
160
|
+
if x.ext == "json"
|
|
161
|
+
else
|
|
162
|
+
App::Html.render(x,
|
|
163
|
+
title: "Please Login",
|
|
164
|
+
#message: {type:"info", message: "Please login"},
|
|
165
|
+
content: App::Usr::Html.login(x, return_to: x.req.uri)
|
|
166
|
+
)
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
def debug(str, level=3)
|
|
171
|
+
Waxx.debug(str, level)
|
|
172
|
+
end
|
|
173
|
+
end
|
data/lib/waxx/conf.rb
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Waxx Copyright (c) 2016-2017 ePark labs Inc. & Daniel J. Fitzpatrick <dan@eparklabs.com>
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
##
|
|
16
|
+
# The global Waxx::Conf variable. ex: `Waxx::Conf['site']['name']` or
|
|
17
|
+
# shortcut `Waxx['site']['name']`
|
|
18
|
+
# Data is set in opt/env/config.yaml
|
|
19
|
+
module Waxx::Conf
|
|
20
|
+
extend self
|
|
21
|
+
|
|
22
|
+
##
|
|
23
|
+
# Internal class var for conf data
|
|
24
|
+
attr :data
|
|
25
|
+
@data = {}
|
|
26
|
+
|
|
27
|
+
##
|
|
28
|
+
# Load the yaml config file into the Waxx module
|
|
29
|
+
# Access variables with Waxx['var1']['var2'] or Waxx/:var1/:var2
|
|
30
|
+
def load_yaml(base=ENV['PWD'], env="active")
|
|
31
|
+
env = "dev" if env == "active" and not File.exist? "#{base}/opt/active"
|
|
32
|
+
@data = ::YAML.load_file("#{base}/opt/#{env}/config.yaml")
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
##
|
|
36
|
+
# Get a Waxx variable
|
|
37
|
+
def [](n)
|
|
38
|
+
@data[n]
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
##
|
|
42
|
+
# Set a conf variable
|
|
43
|
+
def []=(n, v)
|
|
44
|
+
@data[n] = v
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
##
|
|
48
|
+
# Get a Waxx variable
|
|
49
|
+
def /(n)
|
|
50
|
+
@data[n.to_s] || @data[n.to_sym]
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
end
|
|
54
|
+
|
data/lib/waxx/console.rb
ADDED
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
# Waxx Copyright (c) 2016 ePark labs Inc. & Daniel J. Fitzpatrick <dan@eparklabs.com> All rights reserved.
|
|
2
|
+
# Released under the Apache Version 2 License. See LICENSE.txt.
|
|
3
|
+
|
|
4
|
+
require 'stringio'
|
|
5
|
+
|
|
6
|
+
##
|
|
7
|
+
# The console module that is available with irb
|
|
8
|
+
# When `waxx console` is called, the dbs are connected and a StringIO class acts as the response container
|
|
9
|
+
module Waxx::Console
|
|
10
|
+
extend self
|
|
11
|
+
attr_accessor :db
|
|
12
|
+
attr_accessor :x
|
|
13
|
+
|
|
14
|
+
##
|
|
15
|
+
# Container for response output when using the console
|
|
16
|
+
class Stringy < StringIO
|
|
17
|
+
attr :out
|
|
18
|
+
# Initialize with StringIO args
|
|
19
|
+
def initialize(*args)
|
|
20
|
+
super *args
|
|
21
|
+
@out = ""
|
|
22
|
+
end
|
|
23
|
+
# Write to the output
|
|
24
|
+
def print(str)
|
|
25
|
+
@out << str
|
|
26
|
+
end
|
|
27
|
+
# Get the output
|
|
28
|
+
def output
|
|
29
|
+
@out
|
|
30
|
+
end
|
|
31
|
+
# Clear the out to run another request
|
|
32
|
+
def reset
|
|
33
|
+
@out = ""
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Initialize the console variables
|
|
38
|
+
def init
|
|
39
|
+
@db = Waxx::Database.connections
|
|
40
|
+
io = Stringy.new "GET /app/ok HTTP1/0\n#{ENV.map{|n,v| "#{n}: #{v}"}.join("\n")}"
|
|
41
|
+
@x = Waxx::Server.process_request(io, @db)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Run a GET request
|
|
45
|
+
def get(path, opts={})
|
|
46
|
+
puts path
|
|
47
|
+
@db ||= Waxx::Database.connections
|
|
48
|
+
io = Stringy.new "GET #{path} HTTP1/0\n#{ENV.map{|n,v| "#{n}: #{v}"}.join("\n")}"
|
|
49
|
+
x = Waxx::Server.process_request(io, @db)
|
|
50
|
+
#if ARGV[0] == "get"
|
|
51
|
+
puts x.res.out
|
|
52
|
+
#else
|
|
53
|
+
# x.res.out.join
|
|
54
|
+
#end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# The x variable used on the console. Singleton.
|
|
58
|
+
def x
|
|
59
|
+
return @x if @x
|
|
60
|
+
@x = Waxx::X.new
|
|
61
|
+
@x.db = Waxx::Database.connections
|
|
62
|
+
@x.usr = {un:ENV['USER']}
|
|
63
|
+
@x.ua = {un:ENV['USER']}
|
|
64
|
+
@x.req = Waxx::Req.new(ENV, nil, :get, "/", {}, {}, {}, Time.new)
|
|
65
|
+
@x.res = Waxx::Res.new(Stringy.new,200,{},[],[],[])
|
|
66
|
+
@x
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
##
|
|
70
|
+
# Handle console commands. These are called on the command line: waxx on, waxx deploy prod, waxx test app, etc.
|
|
71
|
+
module Command
|
|
72
|
+
extend self
|
|
73
|
+
attr :x
|
|
74
|
+
def on(opts)
|
|
75
|
+
Waxx::Process::Runner.new('waxx').execute(daemonize: true, pid_path: opts[:pid_path], log_path: opts[:log_path]){
|
|
76
|
+
::App.start(opts)
|
|
77
|
+
}
|
|
78
|
+
end
|
|
79
|
+
alias start on
|
|
80
|
+
|
|
81
|
+
def off(opts)
|
|
82
|
+
Waxx::Process::Runner.new('waxx').execute(kill: true, pid_path: opts[:pid_path])
|
|
83
|
+
end
|
|
84
|
+
alias stop off
|
|
85
|
+
|
|
86
|
+
def restart(opts)
|
|
87
|
+
stop opts
|
|
88
|
+
sleep 1
|
|
89
|
+
start opts
|
|
90
|
+
end
|
|
91
|
+
alias buff restart
|
|
92
|
+
|
|
93
|
+
def get(url=ARGV[1], opts={})
|
|
94
|
+
Waxx['debug']['level'] = 0
|
|
95
|
+
Waxx::Console.get(url, opts)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def post(opts)
|
|
99
|
+
App.post(ARGV[1], opts)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def put(opts)
|
|
103
|
+
App.put(ARGV[1], opts)
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def delete(opts)
|
|
107
|
+
App.delete(ARGV[1], opts)
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def console(opts)
|
|
111
|
+
if File.exist? 'app/app.rb'
|
|
112
|
+
require 'irb'
|
|
113
|
+
puts "waxx console"
|
|
114
|
+
#help = "Use the source, Luke"
|
|
115
|
+
x = Waxx::Console.x
|
|
116
|
+
binding.irb
|
|
117
|
+
#IRB.setup(nil)
|
|
118
|
+
#workspace = IRB::WorkSpace.new(self)
|
|
119
|
+
#irb = IRB::Irb.new(workspace)
|
|
120
|
+
#IRB.conf[:MAIN_CONTEXT] = irb.context
|
|
121
|
+
#irb.eval_input
|
|
122
|
+
#require 'lib/waxx/irb.rb'
|
|
123
|
+
#@x = Waxx::Console.x
|
|
124
|
+
#IRB.start_session(self) #"#{opts[:base]}/lib/waxx/irb_env.rb")
|
|
125
|
+
else
|
|
126
|
+
puts "Error: You need to call 'waxx console' from the root of a waxx installation."
|
|
127
|
+
exit 1
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def config(opts)
|
|
132
|
+
puts Waxx.data.send("to_#{opts[:format]}")
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def deploy(target, opts)
|
|
136
|
+
dep = YAML.load_file("#{opts[:base]}/opt/deploy.yaml")
|
|
137
|
+
dep[target.to_s].each{|n,v|
|
|
138
|
+
puts "Deploying #{target} to #{n}"
|
|
139
|
+
`ssh #{v['user']}@#{v['host']} '#{v['command']}'`
|
|
140
|
+
}
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def init(opts)
|
|
144
|
+
require_relative 'init'
|
|
145
|
+
Waxx::Init.init(x, opts)
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def migrate(db='app', opts={})
|
|
149
|
+
Waxx::Database.migrate db, opts
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def migration(db='app', name=nil, opts={})
|
|
153
|
+
dt = Time.new.strftime('%Y%m%d%H%M')
|
|
154
|
+
if name.nil?
|
|
155
|
+
puts "Enter the name of the migration: "
|
|
156
|
+
name = gets.chomp
|
|
157
|
+
end
|
|
158
|
+
m_file = "db/#{db}/#{dt}-#{name.gsub(/\W/,"-")}.sql"
|
|
159
|
+
File.open(m_file, "w"){|f|
|
|
160
|
+
f.puts "BEGIN;\n\n\n\nCOMMIT;"
|
|
161
|
+
}
|
|
162
|
+
system "/usr/bin/env #{ENV['EDITOR']} #{m_file}"
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def test(target, opts)
|
|
166
|
+
require_relative 'test'
|
|
167
|
+
start_time = Time.new
|
|
168
|
+
re = {}
|
|
169
|
+
total_tests = 0
|
|
170
|
+
total_passed = 0
|
|
171
|
+
if target == "waxx"
|
|
172
|
+
tests = []
|
|
173
|
+
Dir.entries(opts[:base] + '/test').each{|f|
|
|
174
|
+
next if f =~ /^\./
|
|
175
|
+
tests << f.sub(/\.rb$/,"")
|
|
176
|
+
path = opts[:base] + '/test/' + f
|
|
177
|
+
puts path
|
|
178
|
+
require path
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
tests.each{|waxx_module_test|
|
|
182
|
+
re[waxx_module_test] = Waxx.send(waxx_module_test)
|
|
183
|
+
re[waxx_module_test].each{|file, mod|
|
|
184
|
+
mod.map{|meth, test|
|
|
185
|
+
total_tests += test['tests']
|
|
186
|
+
total_passed += test['tests_passed']
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
elsif target == "all" or target.nil?
|
|
191
|
+
puts "app testing not impletemented yet: all"
|
|
192
|
+
else
|
|
193
|
+
puts "app testing not impletemented yet: #{target} #{opts[:format]}"
|
|
194
|
+
end
|
|
195
|
+
re["total_tests"] = total_tests
|
|
196
|
+
re["total_passed"] = total_passed
|
|
197
|
+
duration = ((Time.new - start_time) * 100000).to_i/100.0
|
|
198
|
+
re["performance"] = "#{((total_passed.to_f / total_tests.to_f) * 100).to_i}% in #{duration} ms"
|
|
199
|
+
puts re.send("to_#{opts[:format]}")
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
end
|
data/lib/waxx/csrf.rb
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Waxx Copyright (c) 2016 ePark labs Inc. & Daniel J. Fitzpatrick <dan@eparklabs.com> All rights reserved.
|
|
2
|
+
# Released under the Apache Version 2 License. See LICENSE.txt.
|
|
3
|
+
|
|
4
|
+
module Waxx::Csrf
|
|
5
|
+
extend self
|
|
6
|
+
|
|
7
|
+
def ok?(x)
|
|
8
|
+
x['csrf'] == x.usr['uk']
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def ht(x)
|
|
12
|
+
%(<input type="hidden" name="csrf" value="#{x.usr['uk']}">)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# Waxx Copyright (c) 2016 ePark labs Inc. & Daniel J. Fitzpatrick <dan@eparklabs.com> All rights reserved.
|
|
2
|
+
# Released under the Apache Version 2 License. See LICENSE.txt.
|
|
3
|
+
|
|
4
|
+
module Waxx::Database
|
|
5
|
+
extend self
|
|
6
|
+
|
|
7
|
+
def parse_uri(uri)
|
|
8
|
+
_, schema, user, pass, host, port, database, opts = uri.split(/^(\w*):\/\/(\w*):?(.*)@([\w\-]*):?([0-9]*)?\/([\w\-]*)\??(.*)?$/)
|
|
9
|
+
{
|
|
10
|
+
type: schema,
|
|
11
|
+
user: user,
|
|
12
|
+
pass: pass,
|
|
13
|
+
host: host,
|
|
14
|
+
database: database,
|
|
15
|
+
opts: Waxx::Http.query_string_to_hash(opts)
|
|
16
|
+
}
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def connect(conf=Waxx['database'])
|
|
20
|
+
# Parse the conf string to load the correct db engine
|
|
21
|
+
engine = conf.split(":").first
|
|
22
|
+
case engine.downcase
|
|
23
|
+
when 'postgresql', 'pg'
|
|
24
|
+
Waxx::Pg.connect(conf)
|
|
25
|
+
when 'mysql2', 'mysql'
|
|
26
|
+
# Parse the string
|
|
27
|
+
uri = parse_uri(conf)
|
|
28
|
+
# Merge the opts into the params
|
|
29
|
+
config = {
|
|
30
|
+
username: uri/:user,
|
|
31
|
+
password: uri/:pass,
|
|
32
|
+
host: uri/:host,
|
|
33
|
+
port: uri/:port,
|
|
34
|
+
database: uri/:database
|
|
35
|
+
}
|
|
36
|
+
config.merge!(uri/:opts)
|
|
37
|
+
Waxx::Mysql2.connect(config)
|
|
38
|
+
when 'sqlite3', 'sqlite'
|
|
39
|
+
Waxx::Sqlite3.connect(conf.sub('sqlite3://',''))
|
|
40
|
+
when 'mongodb', 'mongo'
|
|
41
|
+
Waxx::Mongodb.connect(conf)
|
|
42
|
+
else
|
|
43
|
+
raise 'Unknown Database Type'
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Define database connections in config.yaml or pass in a hash
|
|
48
|
+
# {
|
|
49
|
+
# app: connection_string,
|
|
50
|
+
# blog: connection_string
|
|
51
|
+
# }
|
|
52
|
+
def connections(dbs=Waxx['databases'])
|
|
53
|
+
c = {}
|
|
54
|
+
return c if dbs.nil?
|
|
55
|
+
dbs.each{|name, conf|
|
|
56
|
+
c[name.to_sym] = connect(conf)
|
|
57
|
+
c.define_singleton_method(name){self[name.to_sym]}
|
|
58
|
+
}
|
|
59
|
+
c
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def migrate(db_only=nil, opts={})
|
|
63
|
+
dbs = connections
|
|
64
|
+
dbs.each{|name, db|
|
|
65
|
+
next if db_only and db_only != db
|
|
66
|
+
puts "Migrating: db.#{name}"
|
|
67
|
+
# get the latest version
|
|
68
|
+
latest = db.exec("SELECT value FROM waxx WHERE name = 'db.#{name}.migration.last'").first['value']
|
|
69
|
+
Dir.entries("#{opts[:base]}/db/#{name}/").sort.each{|f|
|
|
70
|
+
if f =~ /\.sql$/ and f > latest
|
|
71
|
+
puts " #{f}"
|
|
72
|
+
db.exec(File.read("#{opts[:base]}/db/#{name}/#{f}"))
|
|
73
|
+
db.exec("UPDATE waxx SET value = $1 WHERE name = 'db.#{name}.migration.last'",[f])
|
|
74
|
+
end
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
puts "Migration complete"
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
end
|
data/lib/waxx/encrypt.rb
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Waxx Copyright (c) 2016 ePark labs Inc. & Daniel J. Fitzpatrick <dan@eparklabs.com> All rights reserved.
|
|
2
|
+
# Released under the Apache Version 2 License. See LICENSE.txt.
|
|
3
|
+
|
|
4
|
+
module Waxx::Encrypt
|
|
5
|
+
extend self
|
|
6
|
+
def encrypt(str, encode:'b64', cipher: Waxx['encryption']['cipher'], key:Waxx['encryption']['key'], iv:Waxx['encryption']['iv'])
|
|
7
|
+
aes = OpenSSL::Cipher.new(cipher)
|
|
8
|
+
aes.encrypt
|
|
9
|
+
aes.key = key
|
|
10
|
+
aes.iv = iv if iv
|
|
11
|
+
case encode.to_sym
|
|
12
|
+
when :b64
|
|
13
|
+
Base64.encode64(aes.update(str.to_s) + aes.final).chomp
|
|
14
|
+
when :url
|
|
15
|
+
http_escape(Base64.encode64(aes.update(str.to_s) + aes.final).chomp)
|
|
16
|
+
when :bin
|
|
17
|
+
aes.update(str.to_s) + aes.final
|
|
18
|
+
else
|
|
19
|
+
throw "Encoding not defined"
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
def decrypt(str, encode:'b64', cipher: Waxx['encryption']['cipher'], key:Waxx['encryption']['key'], iv:Waxx['encryption']['iv'])
|
|
23
|
+
aes = OpenSSL::Cipher.new(cipher)
|
|
24
|
+
aes.decrypt
|
|
25
|
+
aes.key = key
|
|
26
|
+
aes.iv = iv if iv
|
|
27
|
+
case encode.to_sym
|
|
28
|
+
when :b64
|
|
29
|
+
aes.update(Base64.decode64(str.to_s + "\n")) + aes.final
|
|
30
|
+
when :url
|
|
31
|
+
aes.update(Base64.decode64(http_unescape(str.to_s) + "\n")) + aes.final
|
|
32
|
+
when :bin
|
|
33
|
+
aes.update(str.to_s) + aes.final
|
|
34
|
+
else
|
|
35
|
+
throw "Encoding not defined"
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|