chook 1.0.1.b2 → 1.1.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CHANGES.md +56 -0
- data/README.md +363 -127
- data/bin/chook-server +31 -1
- data/data/chook.conf.example +183 -0
- data/data/com.pixar.chook-server.plist +20 -0
- data/data/sample_handlers/RestAPIOperation.rb +11 -11
- data/data/sample_handlers/SmartGroupComputerMembershipChange.rb +3 -6
- data/data/sample_jsons/SmartGroupComputerMembershipChange.json +3 -1
- data/data/sample_jsons/SmartGroupMobileDeviceMembershipChange.json +3 -1
- data/lib/chook/configuration.rb +27 -8
- data/lib/chook/event.rb +6 -1
- data/lib/chook/event/handled_event.rb +36 -9
- data/lib/chook/event/handled_event/handlers.rb +260 -98
- data/lib/chook/event/handled_event_logger.rb +86 -0
- data/lib/chook/event_handling.rb +1 -0
- data/lib/chook/foundation.rb +3 -0
- data/lib/chook/procs.rb +17 -1
- data/lib/chook/server.rb +73 -72
- data/lib/chook/server/auth.rb +164 -0
- data/lib/chook/server/log.rb +215 -0
- data/lib/chook/server/public/css/chook.css +133 -0
- data/lib/chook/server/public/imgs/ChookLogoAlMcWhiggin.png +0 -0
- data/lib/chook/server/public/js/chook.js +126 -0
- data/lib/chook/server/public/js/logstream.js +101 -0
- data/lib/chook/server/routes.rb +28 -0
- data/lib/chook/server/routes/handle_by_name.rb +65 -0
- data/lib/chook/server/routes/handle_webhook_event.rb +27 -3
- data/lib/chook/server/routes/handlers.rb +52 -0
- data/lib/chook/server/routes/home.rb +48 -1
- data/lib/chook/server/routes/log.rb +105 -0
- data/lib/chook/server/routes/login_logout.rb +48 -0
- data/lib/chook/server/views/admin.haml +11 -0
- data/lib/chook/server/views/bak.haml +48 -0
- data/lib/chook/server/views/config.haml +15 -0
- data/lib/chook/server/views/handlers.haml +63 -0
- data/lib/chook/server/views/layout.haml +64 -0
- data/lib/chook/server/views/logstream.haml +33 -0
- data/lib/chook/server/views/sketch_admin +44 -0
- data/lib/chook/subject.rb +13 -2
- data/lib/chook/subject/dep_device.rb +81 -0
- data/lib/chook/subject/policy_finished.rb +43 -0
- data/lib/chook/subject/smart_group.rb +6 -0
- data/lib/chook/version.rb +1 -1
- metadata +79 -19
@@ -29,9 +29,33 @@ module Chook
|
|
29
29
|
class Server < Sinatra::Base
|
30
30
|
|
31
31
|
post '/handle_webhook_event' do
|
32
|
-
|
33
|
-
|
34
|
-
|
32
|
+
# enforce http basic auth if needed
|
33
|
+
protect_via_basic_auth!
|
34
|
+
|
35
|
+
# rewind to ensure read-pointer is at the start
|
36
|
+
request.body.rewind #
|
37
|
+
raw_json = request.body.read
|
38
|
+
|
39
|
+
event = Chook::HandledEvent.parse_event raw_json
|
40
|
+
if event.nil?
|
41
|
+
logger.error "Empty JSON from #{request.ip}"
|
42
|
+
result = 400
|
43
|
+
else
|
44
|
+
|
45
|
+
event.logger.debug "START From #{request.ip}, WebHook '#{event.webhook_name}' (id: #{event.webhook_id})"
|
46
|
+
event.logger.debug "Thread id: #{Thread.current.object_id}; JSON: #{raw_json}"
|
47
|
+
|
48
|
+
result = event.handle
|
49
|
+
|
50
|
+
event.logger.debug "END #{result}"
|
51
|
+
end
|
52
|
+
|
53
|
+
# this route shouldn't have a session expiration
|
54
|
+
# And when it does, the date format is wrong, and the
|
55
|
+
# JAMFSoftwareServerLog complains about it for every
|
56
|
+
# webhook sent.
|
57
|
+
env['rack.session.options'].delete :expire_after
|
58
|
+
result
|
35
59
|
end # post
|
36
60
|
|
37
61
|
end # class
|
@@ -0,0 +1,52 @@
|
|
1
|
+
### Copyright 2017 Pixar
|
2
|
+
|
3
|
+
###
|
4
|
+
### Licensed under the Apache License, Version 2.0 (the "Apache License")
|
5
|
+
### with the following modification; you may not use this file except in
|
6
|
+
### compliance with the Apache License and the following modification to it:
|
7
|
+
### Section 6. Trademarks. is deleted and replaced with:
|
8
|
+
###
|
9
|
+
### 6. Trademarks. This License does not grant permission to use the trade
|
10
|
+
### names, trademarks, service marks, or product names of the Licensor
|
11
|
+
### and its affiliates, except as required to comply with Section 4(c) of
|
12
|
+
### the License and to reproduce the content of the NOTICE file.
|
13
|
+
###
|
14
|
+
### You may obtain a copy of the Apache License at
|
15
|
+
###
|
16
|
+
### http://www.apache.org/licenses/LICENSE-2.0
|
17
|
+
###
|
18
|
+
### Unless required by applicable law or agreed to in writing, software
|
19
|
+
### distributed under the Apache License with the above modification is
|
20
|
+
### distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
21
|
+
### KIND, either express or implied. See the Apache License for the specific
|
22
|
+
### language governing permissions and limitations under the Apache License.
|
23
|
+
###
|
24
|
+
###
|
25
|
+
|
26
|
+
module Chook
|
27
|
+
|
28
|
+
# see server.rb
|
29
|
+
class Server < Sinatra::Base
|
30
|
+
|
31
|
+
# reload the handlers
|
32
|
+
get '/reload_handlers' do
|
33
|
+
logger.info 'Reloading handlers'
|
34
|
+
Chook::HandledEvent::Handlers.load_handlers reload: true
|
35
|
+
'Handlers reloaded'
|
36
|
+
end # get /
|
37
|
+
|
38
|
+
# used by javascript to fetch the content of a handler file
|
39
|
+
get '/handler_code' do
|
40
|
+
file = Pathname.new params[:filepath]
|
41
|
+
|
42
|
+
# only if its a known handler path
|
43
|
+
if Chook::HandledEvent::Handlers.all_handler_paths.include?(file) && file.file?
|
44
|
+
body file.read
|
45
|
+
else
|
46
|
+
404
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
end # class
|
51
|
+
|
52
|
+
end # module
|
@@ -29,7 +29,54 @@ module Chook
|
|
29
29
|
class Server < Sinatra::Base
|
30
30
|
|
31
31
|
get '/' do
|
32
|
-
|
32
|
+
|
33
|
+
# a list of current handlers for the admin page
|
34
|
+
@handlers_for_admin_page = []
|
35
|
+
|
36
|
+
Chook::HandledEvent::Handlers.handlers.keys.sort.each do |eventname|
|
37
|
+
Chook::HandledEvent::Handlers.handlers[eventname].each do |handler|
|
38
|
+
if handler.is_a? Pathname
|
39
|
+
file = handler
|
40
|
+
type = :external
|
41
|
+
else
|
42
|
+
file = handler.handler_file
|
43
|
+
type = :internal
|
44
|
+
end # if else
|
45
|
+
@handlers_for_admin_page << { event: eventname, file: file, type: type }
|
46
|
+
end # handlers each
|
47
|
+
end # Handlers.handlers.each
|
48
|
+
|
49
|
+
# a list of current named handlers for the admin page
|
50
|
+
@named_handlers_for_admin_page = []
|
51
|
+
|
52
|
+
Chook::HandledEvent::Handlers.named_handlers.each do |name, handler|
|
53
|
+
if handler.is_a? Pathname
|
54
|
+
file = handler
|
55
|
+
type = :external
|
56
|
+
else
|
57
|
+
file = handler.handler_file
|
58
|
+
type = :internal
|
59
|
+
end # if else
|
60
|
+
@named_handlers_for_admin_page << { file: file, type: type }
|
61
|
+
end # handlers each
|
62
|
+
|
63
|
+
|
64
|
+
# the current config, for the admin page
|
65
|
+
@config_text =
|
66
|
+
if Chook::Configuration::DEFAULT_CONF_FILE.file?
|
67
|
+
@config_src = Chook::Configuration::DEFAULT_CONF_FILE.to_s
|
68
|
+
Chook::Configuration::DEFAULT_CONF_FILE.read
|
69
|
+
|
70
|
+
elsif Chook::Configuration::SAMPLE_CONF_FILE.file?
|
71
|
+
@config_src = "Using default values, showing sample config file at #{Chook::Configuration::SAMPLE_CONF_FILE}"
|
72
|
+
Chook::Configuration::SAMPLE_CONF_FILE.read
|
73
|
+
|
74
|
+
else
|
75
|
+
@config_src = "No #{Chook::Configuration::DEFAULT_CONF_FILE} or sample config file found."
|
76
|
+
@config_src
|
77
|
+
end
|
78
|
+
|
79
|
+
haml :admin
|
33
80
|
end # get /
|
34
81
|
|
35
82
|
end # class
|
@@ -0,0 +1,105 @@
|
|
1
|
+
### Copyright 2017 Pixar
|
2
|
+
|
3
|
+
###
|
4
|
+
### Licensed under the Apache License, Version 2.0 (the "Apache License")
|
5
|
+
### with the following modification; you may not use this file except in
|
6
|
+
### compliance with the Apache License and the following modification to it:
|
7
|
+
### Section 6. Trademarks. is deleted and replaced with:
|
8
|
+
###
|
9
|
+
### 6. Trademarks. This License does not grant permission to use the trade
|
10
|
+
### names, trademarks, service marks, or product names of the Licensor
|
11
|
+
### and its affiliates, except as required to comply with Section 4(c) of
|
12
|
+
### the License and to reproduce the content of the NOTICE file.
|
13
|
+
###
|
14
|
+
### You may obtain a copy of the Apache License at
|
15
|
+
###
|
16
|
+
### http://www.apache.org/licenses/LICENSE-2.0
|
17
|
+
###
|
18
|
+
### Unless required by applicable law or agreed to in writing, software
|
19
|
+
### distributed under the Apache License with the above modification is
|
20
|
+
### distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
21
|
+
### KIND, either express or implied. See the Apache License for the specific
|
22
|
+
### language governing permissions and limitations under the Apache License.
|
23
|
+
###
|
24
|
+
###
|
25
|
+
|
26
|
+
module Chook
|
27
|
+
|
28
|
+
# see server.rb
|
29
|
+
class Server < Sinatra::Base
|
30
|
+
|
31
|
+
# External Handlers can use this route to make log entries.
|
32
|
+
#
|
33
|
+
# The request body must be a JSON object (Hash) wth 2 keys 'level' and 'message'
|
34
|
+
# where both values are strings
|
35
|
+
#
|
36
|
+
# Here's an example with curl, split to multi-line for clarity:
|
37
|
+
#
|
38
|
+
# curl -H "Content-Type: application/json" \
|
39
|
+
# -X POST \
|
40
|
+
# --data '{"level":"debug", "message":"It Worked"}' \
|
41
|
+
# https://user:passwd@chookserver.myorg.org:443/log
|
42
|
+
#
|
43
|
+
post '/log' do
|
44
|
+
protect_via_basic_auth!
|
45
|
+
|
46
|
+
request.body.rewind # in case someone already read it
|
47
|
+
raw = request.body.read
|
48
|
+
|
49
|
+
begin
|
50
|
+
logentry = JSON.parse raw, symbolize_names: true
|
51
|
+
raise if logentry[:level].to_s.empty? || logentry[:message].to_s.empty?
|
52
|
+
rescue
|
53
|
+
Chook::Server::Log.logger.error "Malformed log entry JSON from #{request.ip}: #{raw}"
|
54
|
+
halt 409, "Malformed log entry JSON: #{raw}"
|
55
|
+
end
|
56
|
+
|
57
|
+
level = logentry[:level].to_sym
|
58
|
+
level = :unknown unless Chook::Server::Log::LOG_LEVELS.key? level
|
59
|
+
Chook::Server::Log.logger.send level, "ExternalEntry: #{logentry[:message]}"
|
60
|
+
|
61
|
+
{ result: 'logged', level: level }.to_json
|
62
|
+
end # post /
|
63
|
+
|
64
|
+
# AJAXy access to a log stream
|
65
|
+
# When an admin displays the log on the chook admin/home page,
|
66
|
+
# the page's javascript starts the stream as an EventSource
|
67
|
+
# from this url.
|
68
|
+
#
|
69
|
+
# The innards are taken almost verbatim from the Sinatra README
|
70
|
+
# docs.
|
71
|
+
#
|
72
|
+
# See also logstream.js and views/admin.haml
|
73
|
+
#
|
74
|
+
#
|
75
|
+
get '/subscribe_to_log_stream', provides: 'text/event-stream' do
|
76
|
+
content_type 'text/event-stream'
|
77
|
+
cache_control 'no-cache'
|
78
|
+
|
79
|
+
# register a client's interest in server events
|
80
|
+
stream(:keep_open) do |outbound_stream|
|
81
|
+
# add this connection to the array of streams
|
82
|
+
Chook::Server::Log.log_streams[outbound_stream] = request.ip
|
83
|
+
logger.debug "Added log stream for #{request.ip}"
|
84
|
+
# purge dead connections
|
85
|
+
Chook::Server::Log.clean_log_streams
|
86
|
+
end # stream
|
87
|
+
end
|
88
|
+
|
89
|
+
# set the log level via the admin page.
|
90
|
+
put '/set_log_level/:level' do
|
91
|
+
level = params[:level].to_sym
|
92
|
+
level = :unknown unless Chook::Server::Log::LOG_LEVELS.key? level
|
93
|
+
Chook.logger.level = level
|
94
|
+
Chook.logger.unknown "Log level changed, now: #{level}"
|
95
|
+
{ result: 'level changed', level: level }.to_json
|
96
|
+
end
|
97
|
+
|
98
|
+
# get the log level via the admin page.
|
99
|
+
get '/current_log_level' do
|
100
|
+
Chook::Server::Log::LOG_LEVELS.invert[Chook.logger.level].to_s
|
101
|
+
end
|
102
|
+
|
103
|
+
end # class
|
104
|
+
|
105
|
+
end # module
|
@@ -0,0 +1,48 @@
|
|
1
|
+
### Copyright 2017 Pixar
|
2
|
+
|
3
|
+
###
|
4
|
+
### Licensed under the Apache License, Version 2.0 (the "Apache License")
|
5
|
+
### with the following modification; you may not use this file except in
|
6
|
+
### compliance with the Apache License and the following modification to it:
|
7
|
+
### Section 6. Trademarks. is deleted and replaced with:
|
8
|
+
###
|
9
|
+
### 6. Trademarks. This License does not grant permission to use the trade
|
10
|
+
### names, trademarks, service marks, or product names of the Licensor
|
11
|
+
### and its affiliates, except as required to comply with Section 4(c) of
|
12
|
+
### the License and to reproduce the content of the NOTICE file.
|
13
|
+
###
|
14
|
+
### You may obtain a copy of the Apache License at
|
15
|
+
###
|
16
|
+
### http://www.apache.org/licenses/LICENSE-2.0
|
17
|
+
###
|
18
|
+
### Unless required by applicable law or agreed to in writing, software
|
19
|
+
### distributed under the Apache License with the above modification is
|
20
|
+
### distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
21
|
+
### KIND, either express or implied. See the Apache License for the specific
|
22
|
+
### language governing permissions and limitations under the Apache License.
|
23
|
+
###
|
24
|
+
###
|
25
|
+
|
26
|
+
module Chook
|
27
|
+
|
28
|
+
# see server.rb
|
29
|
+
class Server < Sinatra::Base
|
30
|
+
|
31
|
+
# reload the handlers
|
32
|
+
get '/logout' do
|
33
|
+
session[:authed_admin] = nil
|
34
|
+
session[:auth_failed] = nil
|
35
|
+
redirect '/'
|
36
|
+
end # get /
|
37
|
+
|
38
|
+
# reload the handlers
|
39
|
+
post '/login' do
|
40
|
+
Chook.logger.debug "Attempting to log in #{params[:username]}"
|
41
|
+
session[:auth_failed] = !authenticate_admin(params[:username], params[:password])
|
42
|
+
redirect '/'
|
43
|
+
end # get /
|
44
|
+
|
45
|
+
|
46
|
+
end # class
|
47
|
+
|
48
|
+
end # module
|
@@ -0,0 +1,48 @@
|
|
1
|
+
%hr/
|
2
|
+
.section_label#log_label
|
3
|
+
The Live Chook Log
|
4
|
+
|
5
|
+
%button#view_log_btn{ type: 'button', onClick: 'view_log();', title: 'view the live Chook log' }
|
6
|
+
View
|
7
|
+
%button#hide_log_btn{ type: 'button', onClick: 'hide_log();', title: 'hide the live Chook log' }
|
8
|
+
Hide
|
9
|
+
Log Level:
|
10
|
+
%select#log_level_select{ onchange: 'change_log_level();' }
|
11
|
+
%option{ value: 'fatal', selected: Chook.logger.level == Logger::FATAL } fatal
|
12
|
+
%option{ value: 'error', selected: Chook.logger.level == Logger::ERROR } error
|
13
|
+
%option{ value: 'warn', selected: Chook.logger.level == Logger::WARN } warn
|
14
|
+
%option{ value: 'info', selected: Chook.logger.level == Logger::INFO } info
|
15
|
+
%option{ value: 'debug', selected: Chook.logger.level == Logger::DEBUG } debug
|
16
|
+
|
17
|
+
#logbox_div
|
18
|
+
#logbox_btns
|
19
|
+
%input#pause_log{ type: 'checkbox', checked: false, onclick: 'update_logbox();' }
|
20
|
+
Pause
|
21
|
+
|
22
|
+
%button#clear_log_btn{ type: 'button', onClick: 'clear_log();', title: 'clear the live Chook log' }
|
23
|
+
Clear
|
24
|
+
|
25
|
+
// Log Level: [popup list] (set)
|
26
|
+
%textarea.monospaced#logbox{ readonly: true, rows: 20, cols: 150 }
|
27
|
+
|
28
|
+
%hr/
|
29
|
+
.section_label#handlers_label
|
30
|
+
Current Webhook Handlers (#{@handlers_for_admin_page.size})
|
31
|
+
|
32
|
+
|
33
|
+
%button#view_handlers_btn{ type: 'button', onClick: 'view_handlers();', title: 'view the handler list' }
|
34
|
+
View
|
35
|
+
%button#hide_handlers_btn{ type: 'button', onClick: 'hide_handlers();', title: 'hide the handler list' }
|
36
|
+
Hide
|
37
|
+
|
38
|
+
|
39
|
+
Handler Directory:
|
40
|
+
%span.monospaced
|
41
|
+
= Chook.config.handler_dir.to_s
|
42
|
+
|
43
|
+
#handlers_div
|
44
|
+
%table#handlers_table
|
45
|
+
%tr
|
46
|
+
%th Event
|
47
|
+
%th Handler Type
|
48
|
+
%th File Name
|
@@ -0,0 +1,15 @@
|
|
1
|
+
.section_label#config_label
|
2
|
+
%button#view_config_btn{ type: 'button', onClick: 'view_config();', title: 'view the config file' }
|
3
|
+
View
|
4
|
+
%button#hide_config_btn{ type: 'button', onClick: 'hide_config();', title: 'hide the config file' }
|
5
|
+
Hide
|
6
|
+
|
7
|
+
|
8
|
+
Configuration
|
9
|
+
|
10
|
+
#config_div
|
11
|
+
Config file:
|
12
|
+
%span.monospaced= @config_src
|
13
|
+
|
14
|
+
#config_viewer_div
|
15
|
+
%textarea.monospaced#config_box{ readonly: true, rows: 20, cols: 150 }= @config_text
|
@@ -0,0 +1,63 @@
|
|
1
|
+
.section_label#handlers_label
|
2
|
+
%button#view_handlers_btn{ type: 'button', onClick: 'view_handlers();', title: 'view the handler list' }
|
3
|
+
View
|
4
|
+
%button#hide_handlers_btn{ type: 'button', onClick: 'hide_handlers();', title: 'hide the handler list' }
|
5
|
+
Hide
|
6
|
+
|
7
|
+
|
8
|
+
Current Webhook Handlers (#{@handlers_for_admin_page.size + @named_handlers_for_admin_page.size})
|
9
|
+
|
10
|
+
%button#reload_all_handlers_btn{ type: 'button', onClick: 'reload_handlers();', title: 'reload all handlers' }
|
11
|
+
Reload All
|
12
|
+
|
13
|
+
%span#reloaded_notification
|
14
|
+
|
15
|
+
#handlers_div
|
16
|
+
General Handler Directory:
|
17
|
+
%span.monospaced= Chook.config.handler_dir.to_s
|
18
|
+
|
19
|
+
|
20
|
+
%table#handlers_table
|
21
|
+
%tr#handlers_table_header_row
|
22
|
+
%th.handlers_table_cell File Name
|
23
|
+
%th.handlers_table_cell{ width: '10%' } Handler Type
|
24
|
+
%th.handlers_table_cell Actions
|
25
|
+
|
26
|
+
- @handlers_for_admin_page.each do |hndlr_info|
|
27
|
+
%tr
|
28
|
+
%td.handlers_table_cell= hndlr_info[:file].basename.to_s
|
29
|
+
%td.handlers_table_cell= hndlr_info[:type].to_s
|
30
|
+
%td.handlers_table_cell
|
31
|
+
%button.edit_handler_btn{ type: 'button', onClick: "view_handler_code('#{hndlr_info[:file]}', '#{hndlr_info[:type]}');", title: 'View this handler' }
|
32
|
+
View
|
33
|
+
%br
|
34
|
+
%br
|
35
|
+
Named Handler Directory:
|
36
|
+
%span.monospaced= Chook.config.handler_dir.to_s + "/#{Chook::HandledEvent::Handlers::NAMED_HANDLER_SUBDIR}"
|
37
|
+
|
38
|
+
|
39
|
+
%table#handlers_table
|
40
|
+
%tr#handlers_table_header_row
|
41
|
+
%th.handlers_table_cell File Name
|
42
|
+
%th.handlers_table_cell{ width: '10%' } Handler Type
|
43
|
+
%th.handlers_table_cell Actions
|
44
|
+
|
45
|
+
- @named_handlers_for_admin_page.each do |hndlr_info|
|
46
|
+
%tr
|
47
|
+
%td.handlers_table_cell= hndlr_info[:file].basename.to_s
|
48
|
+
%td.handlers_table_cell= hndlr_info[:type].to_s
|
49
|
+
%td.handlers_table_cell
|
50
|
+
%button.edit_handler_btn{ type: 'button', onClick: "view_handler_code('#{hndlr_info[:file]}', '#{hndlr_info[:type]}');", title: 'View this handler' }
|
51
|
+
View
|
52
|
+
|
53
|
+
#handler_viewer_div
|
54
|
+
%input#currently_viewing_handler_file{ name: 'currently_viewing_handler_file', type: :hidden }
|
55
|
+
%input#currently_editing_handler_type{ name: 'currently_editing_handler_type', type: :hidden }
|
56
|
+
#currently_viewing_handler_label
|
57
|
+
%button#hide_handler_viewer_btn{ type: 'button', onClick: 'hide_handler_viewer();', title: 'hide the handler editor' }
|
58
|
+
Hide
|
59
|
+
|
60
|
+
%span.monospaced#currently_viewing_filename -nothing-
|
61
|
+
|
62
|
+
|
63
|
+
%textarea.monospaced#handler_viewer{ rows: 35 , readonly: true }
|
@@ -0,0 +1,64 @@
|
|
1
|
+
!!!
|
2
|
+
%html{ lang: 'en' }
|
3
|
+
|
4
|
+
%head
|
5
|
+
|
6
|
+
%meta{ charset: 'UTF-8' }
|
7
|
+
%title
|
8
|
+
Chook
|
9
|
+
|
10
|
+
/ CSS
|
11
|
+
%link{ href: '/css/chook.css', rel: 'stylesheet' }
|
12
|
+
|
13
|
+
/ JavaScript
|
14
|
+
%script{ type: 'text/javascript', language: 'javascript', src: '/js/chook.js' }
|
15
|
+
%script{ type: 'text/javascript', language: 'javascript', src: '/js/logstream.js' }
|
16
|
+
|
17
|
+
%body
|
18
|
+
/ Top
|
19
|
+
#pageheader
|
20
|
+
%table{ width: '100%' }
|
21
|
+
%tr
|
22
|
+
%td{ valign: 'bottom', width: '120' }
|
23
|
+
#header_logo
|
24
|
+
%img{ alt: '', height: '120', src: '/imgs/ChookLogoAlMcWhiggin.png', width: '120' }
|
25
|
+
#header_version
|
26
|
+
v#{Chook::VERSION}
|
27
|
+
%td
|
28
|
+
#definition
|
29
|
+
%span.chook_title Chook
|
30
|
+
%br/
|
31
|
+
%span.def_pronunciation /tʃʊk/ (also chookie /ˈtʃʊki/ )
|
32
|
+
%br/
|
33
|
+
%span.def_part_of_speech noun
|
34
|
+
%span.def_dialect Australian/NZ informal
|
35
|
+
%br/
|
36
|
+
%span.def_definition a chicken or fowl
|
37
|
+
%td#serverstats{ valign: 'bottom' }
|
38
|
+
Server started: #{Chook::Server.starttime.strftime '%Y-%m-%d %H:%M:%S'}
|
39
|
+
%br/
|
40
|
+
(#{Chook::Server.uptime})
|
41
|
+
|
42
|
+
%hr/
|
43
|
+
- if Chook.config.admin_user
|
44
|
+
#login_logout_div
|
45
|
+
|
46
|
+
- if session[:authed_admin]
|
47
|
+
%a{ href: '/logout' }
|
48
|
+
%button#logout_btn{ type: 'button' } Log Out
|
49
|
+
= yield
|
50
|
+
|
51
|
+
- else
|
52
|
+
%form#login_form{ name: 'login_form', method: 'POST', action: '/login' }
|
53
|
+
- if Chook.config.admin_user == Chook::Server::Auth::USE_JAMF_ADMIN_USER
|
54
|
+
Jamf Pro
|
55
|
+
Username:
|
56
|
+
%input#username{ type: :text, name: 'username' }
|
57
|
+
Password:
|
58
|
+
%input#password{ type: :password, name: 'password' }
|
59
|
+
%input#login_btn{ type: :submit, value: 'Log In' }
|
60
|
+
- if session[:auth_failed]
|
61
|
+
%span#login_incorrect Login Incorrect!
|
62
|
+
|
63
|
+
- else
|
64
|
+
= yield
|