mirror of
https://github.com/mistergibson/gxg-server.git
synced 2026-08-15 02:15:59 -07:00
Various changes - added api system
This commit is contained in:
parent
e2ae775dd1
commit
0f9f967c77
8 changed files with 277 additions and 40 deletions
File diff suppressed because one or more lines are too long
|
|
@ -835,18 +835,22 @@ accounting_service = ::GxG::Services::Service.new(:accounting)
|
|||
# ### Define Public Command Interface:
|
||||
accounting_service.on(:start, {:description => "Accounting Service Start", :usage => "{ :start => nil }"}) do
|
||||
::GxG::SERVICES[:accounting].start
|
||||
::GxG::SERVICES[:accounting].publish_api
|
||||
end
|
||||
accounting_service.on(:stop, {:description => "Accounting Service Stop", :usage => "{ :stop => nil }"}) do
|
||||
::GxG::SERVICES[:accounting].stop
|
||||
::GxG::SERVICES[:accounting].unpublish_api
|
||||
end
|
||||
accounting_service.on(:restart, {:description => "Accounting Service Restart", :usage => "{ :restart => nil }"}) do
|
||||
::GxG::SERVICES[:accounting].restart
|
||||
end
|
||||
accounting_service.on(:pause, {:description => "Accounting Service Pause", :usage => "{ :pause => nil }"}) do
|
||||
::GxG::SERVICES[:accounting].pause
|
||||
::GxG::SERVICES[:accounting].unpublish_api
|
||||
end
|
||||
accounting_service.on(:resume, {:description => "Accounting Service Resume", :usage => "{ :resume => nil }"}) do
|
||||
::GxG::SERVICES[:accounting].resume
|
||||
::GxG::SERVICES[:accounting].publish_api
|
||||
end
|
||||
# ### Define Internal Service Control Events:
|
||||
accounting_service.on(:at_start, {:description => "Accounting Startup", :usage => "{ :at_start => (service-object) }"}) do |service, credential|
|
||||
|
|
|
|||
|
|
@ -389,6 +389,17 @@ module GxG
|
|||
def fs_root()
|
||||
::File.expand_path("#{::GxG::SYSTEM.gxg_root()}/#{self.vfs_root()}")
|
||||
end
|
||||
# ### API Support
|
||||
def publish_api()
|
||||
if ::GxG::Services::service_available?(:www)
|
||||
::GxG::SERVICES[:www].call_event({:publish_api => {:service => self, :path => "/#{@provides.to_s}"}}, ::GxG::DB[:administrator])
|
||||
end
|
||||
end
|
||||
def unpublish_api()
|
||||
if ::GxG::Services::service_available?(:www)
|
||||
::GxG::SERVICES[:www].call_event({:unpublish_api => {:path => "/#{@provides.to_s}"}}, ::GxG::DB[:administrator])
|
||||
end
|
||||
end
|
||||
# ### Service Management
|
||||
def provides()
|
||||
@provides
|
||||
|
|
|
|||
|
|
@ -1079,18 +1079,22 @@ exchange_service.require_service(:accounting)
|
|||
# ### Define Public Command Interface:
|
||||
exchange_service.on(:start, {:description => "Exchange Service Start", :usage => "{ :start => nil }"}) do
|
||||
::GxG::SERVICES[:exchange].start
|
||||
::GxG::SERVICES[:exchange].publish_api
|
||||
end
|
||||
exchange_service.on(:stop, {:description => "Exchange Service Stop", :usage => "{ :stop => nil }"}) do
|
||||
::GxG::SERVICES[:exchange].stop
|
||||
::GxG::SERVICES[:exchange].unpublish_api
|
||||
end
|
||||
exchange_service.on(:restart, {:description => "Exchange Service Restart", :usage => "{ :restart => nil }"}) do
|
||||
::GxG::SERVICES[:exchange].restart
|
||||
end
|
||||
exchange_service.on(:pause, {:description => "Exchange Service Pause", :usage => "{ :pause => nil }"}) do
|
||||
::GxG::SERVICES[:exchange].pause
|
||||
::GxG::SERVICES[:exchange].unpublish_api
|
||||
end
|
||||
exchange_service.on(:resume, {:description => "Exchange Service Resume", :usage => "{ :resume => nil }"}) do
|
||||
::GxG::SERVICES[:exchange].resume
|
||||
::GxG::SERVICES[:exchange].publish_api
|
||||
end
|
||||
# ### Define Internal Service Control Events:
|
||||
exchange_service.on(:at_start, {:description => "Exchange Startup", :usage => "{ :at_start => (service-object) }"}) do |service|
|
||||
|
|
|
|||
|
|
@ -289,6 +289,18 @@ www_service.on(:at_stop, {:description => "WWW Stop", :usage => "{ :at_stop => (
|
|||
#
|
||||
{:result => true}
|
||||
end
|
||||
www_service.on(:publish_api, {:description => "Publish Service API", :usage => "{ :publish_api => {:service => (service-object), :path => '/path'} }", :public => false}) do |data, credential|
|
||||
#
|
||||
::GxGwww::publish_api(data[:service], data[:path])
|
||||
#
|
||||
{:result => true}
|
||||
end
|
||||
www_service.on(:unpublish_api, {:description => "Unpublish Service API", :usage => "{ :unpublish_api => {:path => '/path'} }", :public => false}) do |data, credential|
|
||||
#
|
||||
::GxGwww::unpublish_api(data[:path])
|
||||
#
|
||||
{:result => true}
|
||||
end
|
||||
# ### Service Installation
|
||||
unless ::GxG::Services::service_available?(:www)
|
||||
# Set Configuration Defaults
|
||||
|
|
|
|||
|
|
@ -16,7 +16,194 @@ module GxGwww
|
|||
end
|
||||
the_value
|
||||
end
|
||||
# ### API toolbox
|
||||
API = {}
|
||||
API_SESSIONS = {}
|
||||
API_THREAD_SAFETY = ::Mutex.new
|
||||
def self.publish_api(the_service=nil, the_path=nil)
|
||||
if the_service && the_path
|
||||
the_controller = ::GxGwww::APIController.new(the_service, the_path)
|
||||
if the_controller
|
||||
::GxGwww::API_THREAD_SAFETY.synchronize {
|
||||
::GxGwww::API[(the_path.to_sym)] = the_controller
|
||||
}
|
||||
true
|
||||
else
|
||||
false
|
||||
end
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
#
|
||||
def self.unpublish_api(the_path="/unknown")
|
||||
if the_path
|
||||
::GxGwww::API_THREAD_SAFETY.synchronize {
|
||||
::GxGwww::API.delete(the_path.to_sym)
|
||||
}
|
||||
end
|
||||
true
|
||||
end
|
||||
#
|
||||
def self.api_login(session_id=nil, credential=:"00000000-0000-4000-0000-000000000000")
|
||||
if session_id
|
||||
::GxGwww::API_THREAD_SAFETY.synchronize {
|
||||
::GxGwww::API_SESSIONS[(session_id.to_sym)] = credential
|
||||
}
|
||||
true
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
#
|
||||
def self.api_logout(session_id=nil)
|
||||
if session_id
|
||||
::GxGwww::API_THREAD_SAFETY.synchronize {
|
||||
::GxGwww::API_SESSIONS.delete(session_id.to_sym)
|
||||
}
|
||||
true
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
#
|
||||
def self.api_credential(session_id=nil)
|
||||
result = :"00000000-0000-4000-0000-000000000000"
|
||||
if session_id
|
||||
::GxGwww::API_THREAD_SAFETY.synchronize {
|
||||
result = (::GxGwww::API_SESSIONS[(session_id.to_sym)] || :"00000000-0000-4000-0000-000000000000")
|
||||
}
|
||||
end
|
||||
result
|
||||
end
|
||||
#
|
||||
class APIController
|
||||
def initialize(the_service=nil, the_path="/unknown")
|
||||
@service = the_service
|
||||
@path = the_path
|
||||
end
|
||||
def service
|
||||
@service
|
||||
end
|
||||
def path
|
||||
@path
|
||||
end
|
||||
#
|
||||
def process(the_method=nil, the_request=nil, the_session=nil)
|
||||
credential = ::GxGwww::api_credential(the_session['session_id'])
|
||||
# Pre-processing
|
||||
response = nil
|
||||
operation = nil
|
||||
begin
|
||||
if the_method
|
||||
case the_method
|
||||
when :get
|
||||
if the_request["details"].to_s == "eyJpbnRyb2R1Y3Rpb24iOnRydWV9"
|
||||
response = [200, {"content-type" => "application/text"}, ({:csrf => the_session["csrf"]}.gxg_export.to_json.encode64)]
|
||||
else
|
||||
operation = (::JSON::parse(URI.unescape(URI.unescape(the_request.params["details"].to_s.decode64.decrypt(the_session["csrf"]))), {:symbolize_names => true}))
|
||||
unless operation.is_a?(::Hash)
|
||||
response = [500, {"content-type" => "application/text"}, "Malformed query."]
|
||||
end
|
||||
end
|
||||
when :put
|
||||
if the_request.body.respond_to?(:rewind) && the_request.body.respond_to?(:read)
|
||||
the_request.body.rewind
|
||||
operation = (::JSON::parse(URI.unescape(URI.unescape(the_request.body.read().to_s.decode64.decrypt(the_session["csrf"]))), {:symbolize_names => true}))
|
||||
unless operation.is_a?(::Hash)
|
||||
response = [500, {"content-type" => "application/text"}, "Malformed payload."]
|
||||
end
|
||||
else
|
||||
log_warn("Abnormal PUT Body #{the_request.body.inspect}")
|
||||
response = [500, {"content-type" => "application/text"}, "Malformed payload."]
|
||||
end
|
||||
else
|
||||
response = [500, {"content-type" => "application/text"}, "Provide a get or put method."]
|
||||
end
|
||||
else
|
||||
response = [500, {"content-type" => "application/text"}, "No http method provided."]
|
||||
end
|
||||
rescue Exception => the_error
|
||||
response = [500, {"content-type" => "application/text"}, the_error.to_s]
|
||||
end
|
||||
# Processing
|
||||
unless response
|
||||
response = [403, {"content-type" => "application/text"}, "You don't have permissions to do that."]
|
||||
# Operation formatting
|
||||
if operation.is_a?(::Hash)
|
||||
operation = ::Hash::gxg_import(operation)
|
||||
operation.search do |the_value, the_selector, the_container|
|
||||
if the_value.is_a?(::Hash)
|
||||
if the_value[:formats].is_a?(::Hash) && the_value[:records].is_a?(::Array)
|
||||
imported_list = ::GxG::Database::Database::detached_package_import(the_value)
|
||||
if imported_list.size > 1
|
||||
the_container[(the_selector)] = imported_list
|
||||
else
|
||||
the_container[(the_selector)] = imported_list[0]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
#
|
||||
if operation
|
||||
case operation.keys[0].to_sym
|
||||
when :upgrade_credential
|
||||
new_credential = ::GxG::DB[:authority].user_credential(operation[:upgrade_credential][:username].to_s, operation[:upgrade_credential][:password].to_s)
|
||||
if new_credential
|
||||
response = [200, {"content-type" => "application/text"}, {:result => ::GxGwww::api_login(the_session['session_id'], new_credential), :error => nil}.gxg_export.to_json.encrypt(the_session["csrf"]).encode64]
|
||||
else
|
||||
response = [403, {"content-type" => "application/text"}, {:result => nil, :error => "Bad username or password."}.gxg_export.to_json.encrypt(the_session["csrf"]).encode64]
|
||||
end
|
||||
when :downgrade_credential
|
||||
response = [200, {"content-type" => "application/text"}, {:result => ::GxGwww::api_logout(the_session['session_id']), :error => nil}.gxg_export.to_json.encrypt(the_session["csrf"]).encode64]
|
||||
when :interface
|
||||
response = [200, {"content-type" => "application/text"}, @service.interface(credential).gxg_export.to_json.encrypt(the_session["csrf"]).encode64]
|
||||
else
|
||||
begin
|
||||
call_response = @service.call_event(operation, , credential)
|
||||
if call_response.is_a?(::Hash)
|
||||
call_response.search do |the_value, the_selector, the_container|
|
||||
if the_value.is_any?(::GxG::Database::PersistedHash, ::GxG::Database::DetachedHash)
|
||||
the_container[(the_selector)] = the_value.export_package()
|
||||
end
|
||||
end
|
||||
end
|
||||
response = [200, {"content-type" => "application/text"}, call_response.gxg_export.to_json.encrypt(the_session["csrf"]).encode64]
|
||||
rescue Exception => the_error
|
||||
response = [500, {"content-type" => "application/text"}, the_error.to_s]
|
||||
end
|
||||
end
|
||||
# the_manifest = GxG::SERVICES[:www][:manifests][(the_session['session_id'])]
|
||||
end
|
||||
end
|
||||
#
|
||||
response
|
||||
# API ????
|
||||
# @service.call_event(operation_envelope=nil, credential)
|
||||
# GxG::SERVICES[:www][:manifests][(the_session['session_id'])]
|
||||
# unless the_manifest
|
||||
# the_manifest = ::GxGwww::Manifest.new({:credential => :'00000000-0000-4000-0000-000000000000'})
|
||||
# # manifest format: {:credential => :'00000000-0000-4000-0000-000000000000', :displays => {}, :timers => {}, :connectors => {}, :status => :none}
|
||||
# GxG::SERVICES[:www][:manifests][(the_session['session_id'])] = the_manifest
|
||||
# end
|
||||
# operations = []
|
||||
# case the_method
|
||||
# when :get
|
||||
# if the_request.params["details"].to_s.size > 0
|
||||
# operations = (::JSON::parse(URI.unescape(URI.unescape(the_request.params["details"].to_s.decode64)), {:symbolize_names => true}))
|
||||
# end
|
||||
# when :put
|
||||
# if the_request.body.respond_to?(:rewind) && the_request.body.respond_to?(:read)
|
||||
# the_request.body.rewind
|
||||
# operations = (::JSON::parse(URI.unescape(URI.unescape(the_request.body.read())), {:symbolize_names => true}))
|
||||
# else
|
||||
# log_warn("Abnormal PUT Body #{the_request.body.inspect}")
|
||||
# end
|
||||
# end
|
||||
end
|
||||
end
|
||||
# ### Application Support
|
||||
module Applications
|
||||
MENU = []
|
||||
def self.refresh_application_menu()
|
||||
|
|
@ -956,7 +1143,24 @@ module GxGwww
|
|||
# puts "Got Request Path: #{request_path}"
|
||||
# ????
|
||||
case the_method
|
||||
when :get
|
||||
when :get, :put
|
||||
if request_path.to_s.downcase[(0..3)].include?("/api")
|
||||
# Filter for API controller match
|
||||
the_controller = nil
|
||||
::GxGwww::API_THREAD_SAFETY.synchronize {
|
||||
::GxGwww::API.each_pair do |the_path, the_handler|
|
||||
if request_path.to_s[(4..-1)] == the_path.to_s
|
||||
the_controller = the_handler
|
||||
break
|
||||
end
|
||||
end
|
||||
}
|
||||
if the_controller
|
||||
response = the_controller.process(the_method, the_request, the_session)
|
||||
else
|
||||
response = [404, {"content-type" => "application/text"}, "Endpoint Not Found"]
|
||||
end
|
||||
else
|
||||
if ["", "/", "/index"].include?(request_path) || ::GxG::SERVICES[:core][:resources].exist?("/Public/www/content/pages#{request_path}")
|
||||
# Send bootstrap html page and wait for xhr requests
|
||||
# content = GxGwww::CACHE.fetch("/page.html",the_session[:credential])
|
||||
|
|
@ -979,7 +1183,7 @@ module GxGwww
|
|||
end
|
||||
end
|
||||
end
|
||||
when :put
|
||||
end
|
||||
when :post
|
||||
# if the_request.path.include?("/display/")
|
||||
# if the_request.params["operation"] == "close"
|
||||
|
|
|
|||
|
|
@ -326,7 +326,8 @@ module GxGwww
|
|||
:".tr"=>{:display=>"table-row", :margin=>0, :padding=>0},
|
||||
:".td"=>{:display=>"table-cell", :margin=>0, :padding=>0},
|
||||
:".default-background-color" => {:"background-color" => "#f2f2f2"},
|
||||
:".default-highlite-color" => {:"background-color" => "#87acd5"}
|
||||
:".default-highlite-color" => {:"background-color" => "#87acd5"},
|
||||
:"menu-item-disabled" => {:color => "#655e7a"}
|
||||
}
|
||||
#
|
||||
if GxG::VFS.exist?("/Public/www/content/themes/setup")
|
||||
|
|
@ -389,7 +390,8 @@ module GxGwww
|
|||
:".tr"=>{:display=>"table-row", :margin=>0, :padding=>0},
|
||||
:".td"=>{:display=>"table-cell", :margin=>0, :padding=>0},
|
||||
:".default-background-color" => {:"background-color" => "#f2f2f2"},
|
||||
:".default-highlite-color" => {:"background-color" => "#87acd5"}
|
||||
:".default-highlite-color" => {:"background-color" => "#87acd5"},
|
||||
:"menu-item-disabled" => {:color => "#655e7a"}
|
||||
}
|
||||
#
|
||||
if GxG::VFS.exist?("/Public/www/content/themes/default")
|
||||
|
|
|
|||
Binary file not shown.
Loading…
Reference in a new issue