diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..ca311af Binary files /dev/null and b/.DS_Store differ diff --git a/README.md b/README.md index 544d46b..d104fe0 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ A library for building [crystal](crystal-lang.org/) applications that utilise Pl ## Usage -When initialialized via the host environment, the key `PLACE_URI` is expected. +When initialized via the host environment, the key `PLACE_URI` is expected. ### Authentication diff --git a/spec/placeos/api_wrapper/authority_spec.cr b/spec/placeos/api_wrapper/authority_spec.cr index 55f787a..1c1aa7d 100644 --- a/spec/placeos/api_wrapper/authority_spec.cr +++ b/spec/placeos/api_wrapper/authority_spec.cr @@ -29,10 +29,10 @@ module PlaceOS authority = authority_api.fetch authority.id.should eq("sgrp-oOO6aZj1-J") authority.name.should eq(DOMAIN) - authority.description.should be_nil + authority.description.should eq(nil) authority.login_url.should eq("/login?continue={{url}}") authority.logout_url.should eq("/") - authority.config["universe"].as_i.should eq(42) + authority.config.not_nil!["universe"].as_i.should eq(42) end end end diff --git a/spec/placeos/api_wrapper/auths/saml_spec.cr b/spec/placeos/api_wrapper/auths/saml_spec.cr index 7a8823b..3c810bd 100644 --- a/spec/placeos/api_wrapper/auths/saml_spec.cr +++ b/spec/placeos/api_wrapper/auths/saml_spec.cr @@ -4,5 +4,11 @@ module PlaceOS describe Client::APIWrapper::Saml do api = Client::APIWrapper.new DOMAIN Client::APIWrapper::Saml.new api + + it "#create" do + end + + it "#update" do + end end end diff --git a/spec/placeos/api_wrapper/brokers_spec.cr b/spec/placeos/api_wrapper/brokers_spec.cr new file mode 100644 index 0000000..5728593 --- /dev/null +++ b/spec/placeos/api_wrapper/brokers_spec.cr @@ -0,0 +1,75 @@ +require "../../spec_helper" + +module PlaceOS + describe Client::APIWrapper::Repositories do + api = PlaceOS::Client::APIWrapper.new DOMAIN + client = Client::APIWrapper::Brokers.new api + + brokers_json = {name: "hello"}.to_json + + # brokers = Array(JSON::Any).from_json(brokers_json).map &.to_json + + pending "#index" do + WebMock + .stub(:get, DOMAIN + client.base) + .to_return(body: brokers_json) + result = client.index + result.size.should eq(1) + # br = result.first + # br.should be_a(PlaceOS::Model::Broker) + # br.attribute.should be_a(attribute_value) + end + + # describe "#create" do + # it "posts to the brokers endpoint" do + # WebMock + # .stub(:post, DOMAIN + client.base) + # .with( + # headers: {"Content-Type" => "application/json"}, + # body: { + # driver_id: "abc-123", + # }.to_json + # ) + # .to_return(body: brokers.first) + # result = client.create driver_id: "abc-123" + # result.should be_a(PlaceOS::Model::Broker) + # end + # end + + # describe "#fetch" do + # it "inspects broker metadata" do + # broker_id = "" + # WebMock + # .stub(:get, DOMAIN + "#{client.base}/#{broker_id}") + # .to_return(body: brokers.first) + # result = client.fetch broker_id + # result.should be_a(PlaceOS::Model::Broker) + # end + # end + + # describe "#update" do + # it "send a put request to the brokers endpoint" do + # broker_id = "" + # WebMock + # .stub(:put, DOMAIN + "#{client.base}/#{broker_id}") + # .with( + # headers: {"Content-Type" => "application/json"}, + # body: {ignore_connected: true}.to_json + # ) + # .to_return(body: brokers.first) + # result = client.update broker_id, ignore_connected: true + # result.should be_a(PlaceOS::Model::Broker) + # end + # end + + # describe "#delete" do + # it "sends a delete request" do + # broker_id = "" + # WebMock + # .stub(:delete, DOMAIN + "#{client.base}/#{broker_id}") + # result = client.destroy broker_id + # result.should be_nil + # end + # end + end +end diff --git a/spec/placeos/api_wrapper/cluster_spec.cr b/spec/placeos/api_wrapper/cluster_spec.cr new file mode 100644 index 0000000..dc6ea73 --- /dev/null +++ b/spec/placeos/api_wrapper/cluster_spec.cr @@ -0,0 +1,23 @@ +require "../../spec_helper" + +module PlaceOS + describe Client::APIWrapper::Cluster do + # api = PlaceOS::Client::APIWrapper.new DOMAIN + # client = Client::APIWrapper::Cluster.new api + + describe "#search" do + # WebMock + # .stub(:get, DOMAIN + client.base) + # .with(query: {include_status: "true"}) + # .to_return(body: %()) + # result = client.version + # result.should be_a(PlaceOS::Client::API::Models::Cluster) + end + + describe "#fetch" do + end + + describe "#destroy" do + end + end +end diff --git a/spec/placeos/api_wrapper/domains_spec.cr b/spec/placeos/api_wrapper/domains_spec.cr new file mode 100644 index 0000000..a0e9887 --- /dev/null +++ b/spec/placeos/api_wrapper/domains_spec.cr @@ -0,0 +1,43 @@ +require "../../spec_helper" + +module PlaceOS + describe Client::APIWrapper::Domains do + api = PlaceOS::Client::APIWrapper.new DOMAIN + client = Client::APIWrapper::Domains.new api + + it "#search" do + WebMock + .stub(:get, DOMAIN + client.base) + .with(query: {"offset" => "0", "limit" => "20"}) + .to_return(body: %([{"created_at":1603948254,"updated_at":1603948254,"name":"localhost:8443/backoffice","description":"","domain":"localhost","login_url":"/login?continue={{url}}","logout_url":"/auth/logout","internals":{},"config":{},"id":"authority-G03OrvJj~5j"}])) + result = client.search offset: 0 + result.size.should eq(1) + domain = result.first + domain.should be_a(PlaceOS::Model::Authority) + domain.should eq(Array(PlaceOS::Model::Authority).from_json(%([{"created_at":1603948254,"updated_at":1603948254,"name":"localhost:8443/backoffice","description":"","domain":"localhost","login_url":"/login?continue={{url}}","logout_url":"/auth/logout","internals":{},"config":{},"id":"authority-G03OrvJj~5j"}]))[0]) + end + + it "#fetch" do + WebMock + .stub(:get, DOMAIN + client.base + "/authority-G03OrvJj~5j") + .to_return(body: %({"created_at":1603948254,"updated_at":1603948254,"name":"localhost:8443/backoffice","description":"","domain":"localhost","login_url":"/login?continue={{url}}","logout_url":"/auth/logout","internals":{},"config":{},"id":"authority-G03OrvJj~5j"})) + result = client.fetch id: "authority-G03OrvJj~5j", complete: true + result.should be_a(PlaceOS::Model::Authority) + end + + it "#destroy" do + WebMock + .stub(:delete, DOMAIN + "#{client.base}/authority-G0S_7R1hW3R") + result = client.destroy "authority-G0S_7R1hW3R" + result.should be_nil + end + + it "#create" do + WebMock + .stub(:post, DOMAIN + client.base) + .to_return(body: %({"created_at":1604030519,"updated_at":1604030519,"name":"1234","description":"This is a test domain","domain":"localhost","login_url":"localhost:1234/login","logout_url":"localhost:1234/logout","internals":{},"config":{},"id":"authority-G0S_7R1hW3R"})) + result = client.create name: "1234", description: "This is a test domain", domain: "localhost", login_url: "localhost:1234/login", logout_url: "localhost:1234/logout" + result.should be_a(PlaceOS::Model::Authority) + end + end +end diff --git a/spec/placeos/api_wrapper/driver_spec.cr b/spec/placeos/api_wrapper/driver_spec.cr new file mode 100644 index 0000000..c6b8652 --- /dev/null +++ b/spec/placeos/api_wrapper/driver_spec.cr @@ -0,0 +1,125 @@ +require "../../spec_helper" +require "placeos-models" + +module PlaceOS + include Client::API::Models # require for Role definitions, would like to dpened on Role definition in placeos-models + include PlaceOS::Model + + describe Client::APIWrapper::Drivers do + api = PlaceOS::Client::APIWrapper.new DOMAIN + client = Client::APIWrapper::Drivers.new api + + drivers_json = {{ read_file("#{__DIR__}/mocks/drivers.json") }} + drivers = Array(JSON::Any).from_json(drivers_json).map &.to_json + + describe "#search" do + it "enumerates all drivers" do + WebMock + .stub(:get, DOMAIN + client.base) + .with(query: {"limit" => "20", "offset" => "0"}, headers: HEADERS) + .to_return(body: drivers_json) + result = client.search + result.size.should eq(2) + driver = result.first + driver.should be_a(PlaceOS::Client::API::Models::Driver) + driver.name.should eq("Place") + end + + it "provides driver search" do + WebMock + .stub(:get, DOMAIN + client.base) + .with(query: {"q" => "Place", "limit" => "20", "offset" => "0"}, headers: HEADERS) + .to_return(body: drivers_json) + result = client.search q: "Place" + result.size.should eq(2) + result.first.name.should eq("Place") + end + + # TODO + # expecting 1 getting 2. + pending "can limit pages correctly" do + WebMock + .stub(:get, DOMAIN + client.base) + .with(query: {"limit" => "1", "offset" => "0"}, headers: HEADERS) + .to_return(body: drivers_json) + result = client.search limit: 1 + result.size.should eq(1) + # result.first.name.should eq("Place") + end + end + + describe "#create" do + it "posts to the drivers endpoint" do + body = {name: "Place", role: 1, commit: "string", file_name: "string", module_name: "string", repository_id: "string"}.to_json + WebMock + .stub(:post, DOMAIN + client.base) + .with( + headers: HTTP::Headers{"Content-Type" => "application/json"}, + body: body + ) + .to_return(body: drivers.first) + result = client.create(name: "Place", role: 1, commit: "string", file_name: "string", module_name: "string", repository_id: "string") + result.should be_a(PlaceOS::Client::API::Models::Driver) + # result.to_json.should eq("{\"created_at\":1562041110,\"updated_at\":1562041120,\"name\":\"Place\",\"description\":\"null\",\"default_uri\":\"hello\",\"default_port\":80,\"role\":1,\"file_name\":\"string\",\"commit\":\"string\",\"repository_id\":\"string\",\"module_name\":\"string\",\"ignore_connected\":true}") + result.commit.should eq("string") + end + end + + describe "#fetch" do + it "inspects a drivers metadata" do + WebMock + .stub(:get, DOMAIN + "#{client.base}/driver-oOj2lGgsz") + .to_return(body: drivers.first) + result = client.fetch "driver-oOj2lGgsz" + result.should be_a(PlaceOS::Client::API::Models::Driver) + # result.to_json.should eq("{\"created_at\":1562041110,\"updated_at\":1562041120,\"name\":\"Place\",\"description\":\"null\",\"default_uri\":\"hello\",\"default_port\":80,\"role\":1,\"file_name\":\"string\",\"commit\":\"string\",\"repository_id\":\"string\",\"module_name\":\"string\",\"ignore_connected\":true}") + end + end + + describe "#update" do + it "send a put request to the drivers endpoint" do + WebMock + .stub(:put, DOMAIN + "#{client.base}/driver-oOj2lGgsz") + .with( + headers: {"Content-Type" => "application/json"}, + body: {name: "Foo"}.to_json + ) + .to_return(body: drivers.first) + result = client.update "driver-oOj2lGgsz", name: "Foo" + result.should be_a(PlaceOS::Client::API::Models::Driver) + # result.to_json.should eq("{\"created_at\":1562041110,\"updated_at\":1562041120,\"name\":\"Place\",\"description\":\"null\",\"default_uri\":\"hello\",\"default_port\":80,\"role\":1,\"file_name\":\"string\",\"commit\":\"string\",\"repository_id\":\"string\",\"module_name\":\"string\",\"ignore_connected\":true}") + end + end + + describe "#destroy" do + it "execs a delete request" do + WebMock + .stub(:delete, DOMAIN + "#{client.base}/driver-oOj2lGgsz") + result = client.destroy "driver-oOj2lGgsz" + result.should be_nil + end + end + + describe "#recompile" do + it "execs recompile" do + WebMock + .stub(:post, DOMAIN + "#{client.base}/driver-oOj2lGgsz/recompile") + .to_return(body: drivers.first) + result = client.recompile "driver-oOj2lGgsz" + result.should be_a(PlaceOS::Client::API::Models::Driver) + # result.to_json.should eq("{\"created_at\":1562041110,\"updated_at\":1562041120,\"name\":\"Place\",\"description\":\"null\",\"default_uri\":\"hello\",\"default_port\":80,\"role\":1,\"file_name\":\"string\",\"commit\":\"string\",\"repository_id\":\"string\",\"module_name\":\"string\",\"ignore_connected\":true}") + end + end + + describe "#compiled" do + it "execs compile" do + WebMock + .stub(:get, DOMAIN + "#{client.base}/driver-oOj2lGgsz/compiled") + .to_return(body: drivers.first) + result = client.compiled "driver-oOj2lGgsz" + result.should be_a(PlaceOS::Client::API::Models::Driver) + # result.to_json.should eq("{\"created_at\":1562041110,\"updated_at\":1562041120,\"name\":\"Place\",\"description\":\"null\",\"default_uri\":\"hello\",\"default_port\":80,\"role\":1,\"file_name\":\"string\",\"commit\":\"string\",\"repository_id\":\"string\",\"module_name\":\"string\",\"ignore_connected\":true}") + end + end + end +end diff --git a/spec/placeos/api_wrapper/metadata_spec.cr b/spec/placeos/api_wrapper/metadata_spec.cr index 8f4e577..d8f699f 100644 --- a/spec/placeos/api_wrapper/metadata_spec.cr +++ b/spec/placeos/api_wrapper/metadata_spec.cr @@ -37,7 +37,7 @@ module PlaceOS mock_metadata = {} of String => String Hash(String, JSON::Any).from_json(metadata_json).each { |key, value| mock_metadata[key] = value.to_json } - describe "fetch" do + describe "#fetch" do it "gets metadata for a parent" do WebMock .stub(:get, DOMAIN + "#{client.base}/zone-oOj2lGgsz") @@ -54,10 +54,14 @@ module PlaceOS end end - pending "children" do + pending "#children" do + # WebMock + # .stub(:get, DOMAIN + "#{client.base}/zone-oOj2lGgsz/children") + # .to_return(status: 200) + # result = client.children("zone-oOj2lGgsz") end - it "update" do + it "#update" do WebMock .stub(:put, DOMAIN + "#{client.base}/zone-oOj2lGgsz") .with(query: {"name" => "Place1"}, body: mock_metadata["Place1"]) @@ -65,7 +69,7 @@ module PlaceOS client.update("zone-oOj2lGgsz", "Place1", {name: "frodo"}, "metadata 1").should eq Client::API::Models::Metadata.from_json(mock_metadata["Place1"]) end - it "delete" do + it "#destroy" do WebMock .stub(:delete, DOMAIN + "#{client.base}/zone-oOj2lGgsz") .with(query: {"name" => "Place1"}) diff --git a/spec/placeos/api_wrapper/mocks/drivers.json b/spec/placeos/api_wrapper/mocks/drivers.json new file mode 100644 index 0000000..4b9c1a7 --- /dev/null +++ b/spec/placeos/api_wrapper/mocks/drivers.json @@ -0,0 +1,32 @@ +[ + { + "id": "driver-oOj2lGgsz", + "name": "Place", + "description": "null", + "default_uri": "hello", + "default_port": 80, + "role": 1, + "file_name": "string", + "commit": "string", + "repository_id": "string", + "module_name": "string", + "ignore_connected": true, + "created_at": 1562041110, + "updated_at": 1562041120 + }, + { + "id": "driver-oOj2lGgsa", + "name": "Place", + "description": "null", + "default_uri": "hello again", + "default_port": 80, + "role": 2, + "file_name": "string", + "commit": "string", + "repository_id": "string", + "module_name": "string", + "ignore_connected": true, + "created_at": 1562041111, + "updated_at": 1562041121 + } +] \ No newline at end of file diff --git a/spec/placeos/api_wrapper/modules_spec.cr b/spec/placeos/api_wrapper/modules_spec.cr index 31d5366..b4ecd8e 100644 --- a/spec/placeos/api_wrapper/modules_spec.cr +++ b/spec/placeos/api_wrapper/modules_spec.cr @@ -42,7 +42,7 @@ module PlaceOS result = client.search result.size.should eq(1) mod = result.first - mod.should be_a(Client::API::Models::Module) + mod.should be_a(PlaceOS::Client::API::Models::Module) mod.ip.should eq("10.45.6.3") end @@ -68,7 +68,7 @@ module PlaceOS ) .to_return(body: modules.first) result = client.create driver_id: "abc-123" - result.should be_a(Client::API::Models::Module) + result.should be_a(PlaceOS::Client::API::Models::Module) end end @@ -78,7 +78,7 @@ module PlaceOS .stub(:get, DOMAIN + "#{client.base}/mod-wJHYeHm6Yn") .to_return(body: modules.first) result = client.fetch "mod-wJHYeHm6Yn" - result.should be_a(Client::API::Models::Module) + result.should be_a(PlaceOS::Client::API::Models::Module) end end @@ -92,7 +92,7 @@ module PlaceOS ) .to_return(body: modules.first) result = client.update "mod-wJHYeHm6Yn", ignore_connected: true - result.should be_a(Client::API::Models::Module) + result.should be_a(PlaceOS::Client::API::Models::Module) end end @@ -142,5 +142,28 @@ module PlaceOS result.as_i.should eq(1) end end + + describe "#ping" do + end + + describe "#settings" do + WebMock + .stub(:get, DOMAIN + "#{client.base}/mod-G03EBWsV9mx/settings") + .to_return(body: %([{"created_at":1603948256,"updated_at":1603948256,"parent_id":"sys-G03RF2BVBxP","encryption_level":0,"settings_string":"test_setting: true","keys":["test_setting"],"parent_type":0,"id":"sets-G039XsPNCiU"}])) + result = client.settings "mod-G03EBWsV9mx" + result[0].should be_a(PlaceOS::Client::API::Models::Settings) + end + + describe "#execute" do + end + + describe "#load" do + WebMock + .stub(:post, DOMAIN + "#{client.base}/mod-G0U3rAFy8d_/load") + .to_return(body: %(true)) + result = client.load "mod-G0U3rAFy8d_" + result.should be_a(Bool) + result.should eq(true) + end end end diff --git a/spec/placeos/api_wrapper/oauth_applications_spec.cr b/spec/placeos/api_wrapper/oauth_applications_spec.cr new file mode 100644 index 0000000..58e667d --- /dev/null +++ b/spec/placeos/api_wrapper/oauth_applications_spec.cr @@ -0,0 +1,96 @@ +require "../../spec_helper" + +module PlaceOS + describe Client::APIWrapper::OAuthApplications do + api = PlaceOS::Client::APIWrapper.new DOMAIN + client = Client::APIWrapper::OAuthApplications.new api + + oauth_applications_json = <<-JSON + [ + { + "id": "oauthapplication-oOj2lGgsz", + "name": "Place", + "authority_id": "authority_id", + "uid": "client_id", + "secret": "client_secret", + "scopes": "scropes", + "owner_id": "owner_id", + "redirect_uri": "redirect_uri", + "skip_authorization": true, + "confidential": true, + "revoked_at": 1555996000, + "created_at": 1555995992, + "updated_at": 1555996000 + } + ] + JSON + + oauth_applications = Array(JSON::Any).from_json(oauth_applications_json).map &.to_json + + describe "#search" do + it "enumerates all oauth applications" do + WebMock + .stub(:get, DOMAIN + client.base) + .with(query: {"limit" => "20", "offset" => "0"}, headers: HEADERS) + .to_return(body: oauth_applications_json) + result = client.search + result.size.should eq(1) + result.first.should be_a(PlaceOS::Client::API::Models::OAuthAuthentication) + result.first.name.should eq("Place") + end + + it "provides oauth application search" do + WebMock + .stub(:get, DOMAIN + client.base) + .with(query: {"q" => "Place", "limit" => "20", "offset" => "0"}, headers: HEADERS) + .to_return(body: oauth_applications_json) + result = client.search q: "Place" + result.size.should eq(1) + result.first.name.should eq("Place") + end + end + + it "#fetch" do + WebMock + .stub(:get, DOMAIN + "#{client.base}/oauthapplication-oOj2lGgsz") + .to_return(body: oauth_applications.first) + result = client.fetch "oauthapplication-oOj2lGgsz" + result.should be_a(PlaceOS::Client::API::Models::OAuthAuthentication) + # result.to_json.should eq("{\"created_at\":1555995992,\"updated_at\":1555996000,\"id\":\"oauthapplication-oOj2lGgsz\",\"name\":\"Place\",\"uid\":\"client_id\",\"secret\":\"client_secret\",\"scopes\":\"scropes\",\"owner_id\":\"owner_id\",\"redirect_uri\":\"redirect_uri\",\"skip_authorization\":true,\"confidential\":true,\"revoked_at\":1555996000}") + end + + it "#destroy" do + WebMock + .stub(:delete, DOMAIN + "#{client.base}/oauthapplication-oOj2lGgsz") + result = client.destroy "oauthapplication-oOj2lGgsz" + result.should be_nil + end + + it "#create" do + body = {name: "Place", uid: "client_id", secret: "client_secret", scopes: "scropes", owner_id: "owner_id", redirect_uri: "redirect_uri", skip_authorization: true, confidential: true}.to_json + WebMock + .stub(:post, DOMAIN + client.base) + .with( + headers: HTTP::Headers{"Content-Type" => "application/json"}, + body: body + ) + .to_return(body: oauth_applications.first) + result = client.create(name: "Place", uid: "client_id", secret: "client_secret", scopes: "scropes", owner_id: "owner_id", redirect_uri: "redirect_uri", skip_authorization: true, confidential: true) + result.should be_a(PlaceOS::Client::API::Models::OAuthAuthentication) + # result.to_json.should eq("{\"created_at\":1555995992,\"updated_at\":1555996000,\"id\":\"oauthapplication-oOj2lGgsz\",\"name\":\"Place\",\"uid\":\"client_id\",\"secret\":\"client_secret\",\"scopes\":\"scropes\",\"owner_id\":\"owner_id\",\"redirect_uri\":\"redirect_uri\",\"skip_authorization\":true,\"confidential\":true,\"revoked_at\":1555996000}") + end + + it "#update" do + WebMock + .stub(:put, DOMAIN + "#{client.base}/oauthapplication-oOj2lGgsz") + .with( + headers: {"Content-Type" => "application/json"}, + body: {name: "Foo"}.to_json + ) + .to_return(body: oauth_applications.first) + result = client.update "oauthapplication-oOj2lGgsz", name: "Foo" + result.should be_a(PlaceOS::Client::API::Models::OAuthAuthentication) + # result.to_json.should eq("{\"created_at\":1555995992,\"updated_at\":1555996000,\"id\":\"oauthapplication-oOj2lGgsz\",\"name\":\"Place\",\"uid\":\"client_id\",\"secret\":\"client_secret\",\"scopes\":\"scropes\",\"owner_id\":\"owner_id\",\"redirect_uri\":\"redirect_uri\",\"skip_authorization\":true,\"confidential\":true,\"revoked_at\":1555996000}") + end + end +end diff --git a/spec/placeos/api_wrapper/repositories_spec.cr b/spec/placeos/api_wrapper/repositories_spec.cr new file mode 100644 index 0000000..80258e5 --- /dev/null +++ b/spec/placeos/api_wrapper/repositories_spec.cr @@ -0,0 +1,155 @@ +require "../../spec_helper" + +module PlaceOS + describe Client::APIWrapper::Repositories do + api = PlaceOS::Client::APIWrapper.new DOMAIN + client = Client::APIWrapper::Repositories.new api + + repositories_json = <<-JSON + [ + { + "id": "repository-oOj2lGgsz", + "name": "Place", + "uri": "uri", + "repo_name": "your-fave-repo", + "username": "GabFitzgerald", + "password": "iheartadamlambert", + "key": "sshhhshsh", + "folder_name": "your-fave-folder", + "description": "description-woo", + "commit_hash": "b930e07d9fd2b682de48e881d5405176888a1de8", + "branch": "master", + "repo_type": 0 + } + ] + JSON + + repositories = Array(JSON::Any).from_json(repositories_json).map &.to_json + + describe "#search" do + it "enumerates all repositories" do + WebMock + .stub(:get, DOMAIN + client.base) + .with(query: {"limit" => "20", "offset" => "0"}, headers: HEADERS) + .to_return(body: repositories_json) + result = client.search + result.size.should eq(1) + result.first.should be_a(PlaceOS::Client::API::Models::Repository) + result.first.name.should eq("Place") + end + + it "provides repositories search" do + WebMock + .stub(:get, DOMAIN + client.base) + .with(query: {"q" => "Place", "limit" => "20", "offset" => "0"}, headers: HEADERS) + .to_return(body: repositories_json) + result = client.search q: "Place" + result.size.should eq(1) + result.first.name.should eq("Place") + end + end + + it "#fetch" do + WebMock + .stub(:get, DOMAIN + "#{client.base}/repository-oOj2lGgsz") + .to_return(body: repositories.first) + result = client.fetch "repository-oOj2lGgsz" + result.should be_a(PlaceOS::Client::API::Models::Repository) + # result.to_json.should eq("{\"created_at\":1603946666,\"updated_at\":1603946666,\"name\":\"Place\",\"description\":\"description-woo\",\"uri\":\"uri\",\"commit_hash\":\"HEAD\",\"branch\":\"master\",\"repo_type\":\"Driver\",\"username\":\"GabFitzgerald\",\"password\":\"iheartadamlambert\",\"key\":\"sshhhshsh\"}") + end + + it "#destroy" do + WebMock + .stub(:delete, DOMAIN + "#{client.base}/repository-oOj2lGgsz") + result = client.destroy "repository-oOj2lGgsz" + result.should be_nil + end + + describe "#create" do + body = {name: "Place", uri: "uri", repo_type: 0, username: "GabFitzgerald", password: "iheartadamlambert", key: "sshhhshsh", folder_name: "your-fave-folder", description: "description description", commit_hash: "b930e07d9fd2b682de48e881d5405176888a1de7"}.to_json + WebMock + .stub(:post, DOMAIN + client.base) + .with( + headers: HTTP::Headers{"Content-Type" => "application/json"}, + body: body + ) + .to_return(body: repositories.last) + result = client.create(name: "Place", uri: "uri", repo_type: 0, username: "GabFitzgerald", password: "iheartadamlambert", key: "sshhhshsh", folder_name: "your-fave-folder", description: "description description", commit_hash: "b930e07d9fd2b682de48e881d5405176888a1de7") + result.should be_a(PlaceOS::Client::API::Models::Repository) + # result.to_json.should eq("{\"id\":\"repository-oOj2lGgsz\",\"name\":\"Place\",\"uri\":\"uri\",\"repo_type\":0,\"username\":\"GabFitzgerald\",\"password\":\"iheartadamlambert\",\"key\":\"sshhhshsh\",\"description\":\"description-woo\",\"branch\":\"master\"}") + end + + it "#update" do + WebMock + .stub(:put, DOMAIN + "#{client.base}/repository-oOj2lGgsz") + .with( + headers: {"Content-Type" => "application/json"}, + body: {username: "GabFitzgerald", password: "asdfgh", key: "key", name: "Foo", uri: "uri", repo_type: 0, folder_name: "folder", description: "new description", commit_hash: "b930e07d9fd2b682de48e881d5405176888a1de6"}.to_json + ) + .to_return(body: repositories.first) + result = client.update id: "repository-oOj2lGgsz", username: "GabFitzgerald", password: "asdfgh", key: "key", name: "Foo", uri: "uri", repo_type: 0, folder_name: "folder", description: "new description", commit_hash: "b930e07d9fd2b682de48e881d5405176888a1de6" + result.should be_a(PlaceOS::Client::API::Models::Repository) + # result.to_json.should eq("{\"id\":\"repository-oOj2lGgsz\",\"name\":\"Place\",\"uri\":\"uri\",\"repo_type\":0,\"username\":\"GabFitzgerald\",\"password\":\"iheartadamlambert\",\"key\":\"sshhhshsh\",\"description\":\"description-woo\",\"branch\":\"master\"}") + end + + it "#pull" do + WebMock + .stub(:post, DOMAIN + "#{client.base}/repo-G03MS-DUJCo/pull") + .to_return(body: %({"commit_hash":"1e2296c"})) + + result = client.pull id: "repo-G03MS-DUJCo" + result.should be_a(NamedTuple(commit_hash: String)) + result.should eq({commit_hash: "1e2296c"}) + end + + describe "#loaded_interfaces" do + WebMock + .stub(:get, DOMAIN + "#{client.base}/interfaces") + .to_return(body: %({"backoffice":"b443da9"})) + result = client.loaded_interfaces + result.should be_a(NamedTuple(backoffice: String)) + result.should eq({backoffice: "b443da9"}) + end + + describe "#drivers" do + WebMock + .stub(:get, DOMAIN + "#{client.base}/repo-G03MS-DUJCo/drivers") + .to_return(body: %(["drivers/place/private_helper.cr", "drivers/place/feature_test.cr"])) + + result = client.drivers id: "repo-G03MS-DUJCo" + result.should be_a(Array(Path)) + result.should eq([Path["drivers/place/private_helper.cr"], Path["drivers/place/feature_test.cr"]]) + end + + describe "#commits" do + WebMock + .stub(:get, DOMAIN + "#{client.base}/repo-G03MS-DUJCo/commits") + .with(query: {"driver" => "drivers/place/private_helper.cr"}) + .to_return(body: %([{"commit":"1b2de89","date":"2020-05-08T16:06:14+10:00","author":"Caspian Baska","subject":"refactor: migrate to Log"},{"commit":"2ee7ab1","date":"2020-04-08T14:08:20+10:00","author":"Stephen von Takach","subject":"feat: add feature test driver"},{"commit":"4be0571","date":"2020-03-12T13:03:00+11:00","author":"Caspian Baska","subject":"feat(place:private_helper): add an echo function"},{"commit":"ca54d2e","date":"2020-03-09T16:04:49+11:00","author":"Caspian Baska","subject":"refactor: `ACAEngine` -> `PlaceOS`"}])) + + result = client.commits id: "repo-G03MS-DUJCo", driver: "drivers/place/private_helper.cr" + result.should be_a(Array(NamedTuple(commit: String, date: Time, author: String, subject: String))) + result.should eq(Array(NamedTuple(commit: String, date: Time, author: String, subject: String)).from_json(%([{"commit":"1b2de89","date":"2020-05-08T16:06:14+10:00","author":"Caspian Baska","subject":"refactor: migrate to Log"},{"commit":"2ee7ab1","date":"2020-04-08T14:08:20+10:00","author":"Stephen von Takach","subject":"feat: add feature test driver"},{"commit":"4be0571","date":"2020-03-12T13:03:00+11:00","author":"Caspian Baska","subject":"feat(place:private_helper): add an echo function"},{"commit":"ca54d2e","date":"2020-03-09T16:04:49+11:00","author":"Caspian Baska","subject":"refactor: `ACAEngine` -> `PlaceOS`"}]))) + end + + describe "#details" do + # WebMock + # .stub(:get, DOMAIN + "#{client.base}/repo-G03N8MjLRnz/details") + # .with(query: {"driver" => "drivers/place/spec_helper.cr", "commit" => "d3d0882"}) + # .to_return(body: %([{"commit":"1b2de89","date":"2020-05-08T16:06:14+10:00","author":"Caspian Baska","subject":"refactor: migrate to Log"},{"commit":"2ee7ab1","date":"2020-04-08T14:08:20+10:00","author":"Stephen von Takach","subject":"feat: add feature test driver"},{"commit":"4be0571","date":"2020-03-12T13:03:00+11:00","author":"Caspian Baska","subject":"feat(place:private_helper): add an echo function"},{"commit":"ca54d2e","date":"2020-03-09T16:04:49+11:00","author":"Caspian Baska","subject":"refactor: `ACAEngine` -> `PlaceOS`"}])) + + # result = client.details id: "repo-G03N8MjLRnz", driver: "drivers/place/spec_helper.cr", commit: "d3d0882" + # result.should be_a(Array(NamedTuple(commit: String, date: Time, author: String, subject: String))) + # result.should eq(Array(NamedTuple(commit: String, date: Time, author: String, subject: String)).from_json(%([{"commit":"1b2de89","date":"2020-05-08T16:06:14+10:00","author":"Caspian Baska","subject":"refactor: migrate to Log"},{"commit":"2ee7ab1","date":"2020-04-08T14:08:20+10:00","author":"Stephen von Takach","subject":"feat: add feature test driver"},{"commit":"4be0571","date":"2020-03-12T13:03:00+11:00","author":"Caspian Baska","subject":"feat(place:private_helper): add an echo function"},{"commit":"ca54d2e","date":"2020-03-09T16:04:49+11:00","author":"Caspian Baska","subject":"refactor: `ACAEngine` -> `PlaceOS`"}]))) + end + + it "#branches" do + # WebMock + # .stub(:get, DOMAIN + "#{client.base}/repository-oOj2lGgsz/branches") + # .to_return(body: "") + # result = client.fetch "repository-oOj2lGgsz" + # result.should be_a(Client::API::Models::Repository) + # result.to_json.should eq("{\"id\":\"repository-oOj2lGgsz\",\"name\":\"Place\",\"uri\":\"uri\",\"repo_type\":0,\"username\":\"GabFitzgerald\",\"password\":\"iheartadamlambert\",\"key\":\"sshhhshsh\",\"description\":\"description-woo\",\"branch\":\"master\"}") + end + end +end diff --git a/spec/placeos/api_wrapper/root_spec.cr b/spec/placeos/api_wrapper/root_spec.cr new file mode 100644 index 0000000..8c1c012 --- /dev/null +++ b/spec/placeos/api_wrapper/root_spec.cr @@ -0,0 +1,37 @@ +require "../../spec_helper" + +module PlaceOS + describe Client::APIWrapper::Root do + api = PlaceOS::Client::APIWrapper.new DOMAIN + client = Client::APIWrapper::Root.new api + + describe "#signal" do + end + + describe "#version" do + # WebMock + # .stub(:get, DOMAIN + client.base + "/version") + # .to_return(body: %({"app":"rest-api","version":"1.17.5","commit":"9c9e8430871f90ec0f198d1bd932487f009acb59","build_time":"Thu Aug 27 22:36:57 UTC 2020\n"})) + # result = client.version + # result.should be_a(PlaceOS::Client::API::Models::Version) + end + + describe "#root" do + end + + describe "#reindex" do + WebMock + .stub(:get, DOMAIN + client.base + "/reindex") + .with(query: {"backfill" => "true"}) + result = client.reindex + result.should eq(nil) + end + + describe "#backfill" do + WebMock + .stub(:get, DOMAIN + client.base + "/backfill") + result = client.backfill + result.should eq(nil) + end + end +end diff --git a/spec/placeos/api_wrapper/settings_spec.cr b/spec/placeos/api_wrapper/settings_spec.cr new file mode 100644 index 0000000..fa266db --- /dev/null +++ b/spec/placeos/api_wrapper/settings_spec.cr @@ -0,0 +1,90 @@ +require "../../spec_helper" + +module PlaceOS + describe Client::APIWrapper::Settings do + api = PlaceOS::Client::APIWrapper.new DOMAIN + client = Client::APIWrapper::Settings.new api + + settings_json = <<-JSON + [ + { + "id": "settings-oOj2lGgsz", + "parent_id": "Place", + "encryption_level": "None", + "parent_type": "Driver" + } + ] + JSON + + settings = Array(JSON::Any).from_json(settings_json).map &.to_json + + describe "#search" do + it "enumerates all settings" do + WebMock + .stub(:get, DOMAIN + client.base) + .with(query: {"limit" => "20", "offset" => "0"}, headers: HEADERS) + .to_return(body: settings_json) + result = client.search + result.size.should eq(1) + result.first.should be_a(PlaceOS::Client::API::Models::Settings) + result.first.parent_id.should eq("Place") + end + + it "provides settings search" do + WebMock + .stub(:get, DOMAIN + client.base) + .with(query: {"q" => "Place", "limit" => "20", "offset" => "0"}, headers: HEADERS) + .to_return(body: settings_json) + result = client.search q: "Place" + result.size.should eq(1) + result.first.parent_id.should eq("Place") + end + end + + it "#fetch" do + WebMock + .stub(:get, DOMAIN + "#{client.base}/settings-oOj2lGgsz") + .to_return(body: settings.first) + result = client.fetch "settings-oOj2lGgsz" + result.should be_a(PlaceOS::Client::API::Models::Settings) + # result.to_json.should eq("{\"encryption_level\":0,\"settings_string\":\"{}\",\"keys\":[],\"parent_id\":\"Place\"}") + end + + it "#destroy" do + WebMock + .stub(:delete, DOMAIN + "#{client.base}/settings-oOj2lGgsz") + result = client.destroy "settings-oOj2lGgsz" + result.should be_nil + end + + it "#create" do + body = {parent_id: "Foo", encryption_level: "None", parent_type: "Driver", settings_string: "settings", settings_id: "unique id", keys: ["key1", "key2"]}.to_json + WebMock + .stub(:post, DOMAIN + client.base) + .with( + headers: HTTP::Headers{"Content-Type" => "application/json"}, + body: body + ) + .to_return(body: settings.first) + result = client.create(parent_id: "Foo", encryption_level: "None", parent_type: "Driver", settings_string: "settings", settings_id: "unique id", keys: ["key1", "key2"]) + result.should be_a(PlaceOS::Client::API::Models::Settings) + # result.to_json.should eq("{\"encryption_level\":0,\"settings_string\":\"{}\",\"keys\":[],\"parent_id\":\"Place\"}") + end + + it "#update" do + WebMock + .stub(:put, DOMAIN + "#{client.base}/settings-oOj2lGgsz") + .with( + headers: {"Content-Type" => "application/json"}, + body: {parent_id: "Foo"}.to_json + ) + .to_return(body: settings.first) + result = client.update "settings-oOj2lGgsz", parent_id: "Foo", encryption_level: nil, parent_type: nil, settings_string: nil, settings_id: nil, keys: nil + result.should be_a(PlaceOS::Client::API::Models::Settings) + # result.to_json.should eq("{\"encryption_level\":0,\"settings_string\":\"{}\",\"keys\":[],\"parent_id\":\"Place\"}") + end + + describe "#history" do + end + end +end diff --git a/spec/placeos/api_wrapper/system_triggers_spec.cr b/spec/placeos/api_wrapper/system_triggers_spec.cr new file mode 100644 index 0000000..7c453c3 --- /dev/null +++ b/spec/placeos/api_wrapper/system_triggers_spec.cr @@ -0,0 +1,81 @@ +require "../../spec_helper" + +module PlaceOS + describe Client::APIWrapper::SystemTriggers do + api = PlaceOS::Client::APIWrapper.new DOMAIN + client = Client::APIWrapper::SystemTriggers.new api + + system_triggers_json = <<-JSON + [ + { + "control_system_id": "Place", + "webhook_secret": "shh it's a secret" + } + ] + JSON + + system_triggers = Array(JSON::Any).from_json(system_triggers_json).map &.to_json + + describe "#search" do + it "enumerates all system triggers" do + WebMock + .stub(:get, DOMAIN + client.base) + .with(query: {"limit" => "20", "offset" => "0"}, headers: HEADERS) + .to_return(body: system_triggers_json) + result = client.search + result.size.should eq(1) + result.first.should be_a(PlaceOS::Client::API::Models::TriggerInstance) + result.first.control_system_id.should eq("Place") + end + + it "provides system trigger search" do + WebMock + .stub(:get, DOMAIN + client.base) + .with(query: {"q" => "Place", "limit" => "20", "offset" => "0"}, headers: HEADERS) + .to_return(body: system_triggers_json) + result = client.search q: "Place" + result.size.should eq(1) + result.first.control_system_id.should eq("Place") + end + end + + it "#fetch" do + WebMock + .stub(:get, DOMAIN + "#{client.base}/systems-trigger-oOj2lGgsz") + .to_return(body: system_triggers.first) + result = client.fetch "systems-trigger-oOj2lGgsz", complete: nil + result.should be_a(PlaceOS::Client::API::Models::TriggerInstance) + # result.to_json.should contain("\"control_system_id\":\"Place\",\"enabled\":true,\"triggered\":false,\"important\":false,\"exec_enabled\":false,\"webhook_secret\":\"shh it's a secret\",\"trigger_count\":0}") + end + + it "#destroy" do + WebMock + .stub(:delete, DOMAIN + "#{client.base}/systems-trigger-oOj2lGgsz") + result = client.destroy "systems-trigger-oOj2lGgsz" + result.should be_nil + end + + describe "#create" do + end + + describe "#update" do + # id = "sys-G03RF2BVBxP" + # trigger_id = "trig-G03JhJhxfUH" + # pp! client.base + + # WebMock + # .stub(:put, DOMAIN + "#{client.base}/#{id}/triggers/#{trigger_id}") + # .with( + # headers: {"Content-Type" => "application/json"}, + # body: {id:"trig-G03JhJhxfUH",name:"TestTrigger-0ede08b5",updated_at:1603948256,debounce_period:-1,important:true,enabled:true,control_system_id:"sys-G03RF2BVBxP",zone_id:"zone-G03PfSG4YRP",system_name:"TestSystem-0ede08b5",enable_webhook:false,supported_methods:["POST"],activated_count:0,version:0}.to_json + # # body: %({"id":"trig-G03JhJhxfUH","name":"TestTrigger-0ede08b5","updated_at":1603948256,"debounce_period":-1,"important":true,"enabled":true,"control_system_id":"sys-G03RF2BVBxP","zone_id":"zone-G03PfSG4YRP","system_name":"TestSystem-0ede08b5","enable_webhook":false,"supported_methods":["POST"],"activated_count":0,"version":0,"actions":{"functions":[],"mailers":[]},"conditions":{"comparisons":[],"time_dependents":[]}}) + # ) + # .to_return(body: %({"created_at":1603948256,"updated_at":1604035745,"control_system_id":"sys-G03RF2BVBxP","trigger_id":"trigger-G03J8Cq3alf","zone_id":"zone-G03PfSG4YRP","enabled":true,"triggered":false,"important":true,"exec_enabled":false,"webhook_secret":"187b32d40116559414714d950bce75b82b16a180ff28d2b95b3c00d08e8e07c2","trigger_count":0,"id":"trig-G03JhJhxfUH"})) + # result = client.update id:"trig-G03JhJhxfUH",name:"TestTrigger-0ede08b5",updated_at:1603948256,debounce_period:-1,important:true,enabled:true,control_system_id:"sys-G03RF2BVBxP",zone_id:"zone-G03PfSG4YRP",system_name:"TestSystem-0ede08b5",enable_webhook:false,supported_methods:["POST"],activated_count:0,version:0 + # result.should be_a(TriggerInstance) + + # # /api/engine/v2/systems/sys-G03RF2BVBxP/triggers/trig-G03JhJhxfUH + # # {"created_at":1603948256,"updated_at":1604035745,"control_system_id":"sys-G03RF2BVBxP","trigger_id":"trigger-G03J8Cq3alf","zone_id":"zone-G03PfSG4YRP","enabled":true,"triggered":false,"important":true,"exec_enabled":false,"webhook_secret":"187b32d40116559414714d950bce75b82b16a180ff28d2b95b3c00d08e8e07c2","trigger_count":0,"id":"trig-G03JhJhxfUH"} + end + end +end diff --git a/spec/placeos/api_wrapper/systems_spec.cr b/spec/placeos/api_wrapper/systems_spec.cr index b9774b6..4543c38 100644 --- a/spec/placeos/api_wrapper/systems_spec.cr +++ b/spec/placeos/api_wrapper/systems_spec.cr @@ -17,7 +17,7 @@ module PlaceOS result = client.search result.size.should eq(3) system = result.first - system.should be_a(Client::API::Models::System) + system.should be_a(PlaceOS::Client::API::Models::ControlSystem) system.name.should eq("Room 1") end @@ -56,7 +56,7 @@ module PlaceOS ) .to_return(body: systems.first) result = client.create name: "Foo", zones: ["a", "b", "c"] - result.should be_a(Client::API::Models::System) + result.should be_a(PlaceOS::Client::API::Models::ControlSystem) end end @@ -66,7 +66,7 @@ module PlaceOS .stub(:get, DOMAIN + "#{client.base}/sys-rJQQlR4Cn7") .to_return(body: systems.first) result = client.fetch "sys-rJQQlR4Cn7" - result.should be_a(Client::API::Models::System) + result.should be_a(PlaceOS::Client::API::Models::ControlSystem) end end @@ -80,11 +80,11 @@ module PlaceOS ) .to_return(body: systems.first) result = client.update "sys-rJQQlR4Cn7", version: 2, name: "Foo" - result.should be_a(Client::API::Models::System) + result.should be_a(PlaceOS::Client::API::Models::ControlSystem) end end - describe "#delete" do + describe "#destroy" do it "execs a delete request" do WebMock .stub(:delete, DOMAIN + "#{client.base}/sys-rJQQlR4Cn7") @@ -213,5 +213,38 @@ module PlaceOS result.first.name.should eq("Room 1") end end + + describe "#settings" do + WebMock + .stub(:get, DOMAIN + "#{client.base}/sys-G03RF2BVBxP/settings") + .to_return(body: %([{"created_at":1603948256,"updated_at":1603948256,"parent_id":"sys-G03RF2BVBxP","encryption_level":0,"settings_string":"test_setting: true","keys":["test_setting"],"parent_type":0,"id":"sets-G039XsPNCiU"}] )) + result = client.settings "sys-G03RF2BVBxP" + result[0].should be_a(PlaceOS::Client::API::Models::Settings) + end + + describe "#add_module" do + id = "sys-G03RF2BVBxP" + module_id = "mod-G0U3rAFy8d_" + + WebMock + .stub(:put, DOMAIN + "#{client.base}/#{id}/module/#{module_id}") + .to_return(body: %({"created_at":1603948255,"updated_at":1604033694,"name":"TestSystem-0ede08b5","description":"","features":["TestModule-0ede08b5","This is a custom name"],"bookable":false,"capacity":0,"support_url":"","version":2,"installed_ui_devices":0,"zones":["zone-G03PfSG4YRP"],"modules":["mod-G03EBWsV9mx","mod-G0U3rAFy8d_"],"id":"sys-G03RF2BVBxP"})) + result = client.add_module id: id, module_id: module_id + result.should be_a(PlaceOS::Client::API::Models::Module) + end + + describe "#remove_module" do + id = "sys-G03RF2BVBxP" + module_id = "mod-G0U3rAFy8d_" + + WebMock + .stub(:delete, DOMAIN + "#{client.base}/#{id}/module/#{module_id}") + .to_return(body: %({"created_at":1603948255,"updated_at":1604035469,"name":"TestSystem-0ede08b5","description":"","features":["TestModule-0ede08b5"],"bookable":false,"capacity":0,"support_url":"","version":3,"installed_ui_devices":0,"zones":["zone-G03PfSG4YRP"],"modules":["mod-G03EBWsV9mx"],"id":"sys-G03RF2BVBxP"})) + result = client.remove_module id: id, module_id: module_id + result.should be_a(PlaceOS::Client::API::Models::Module) + end + + describe "#control" do + end end end diff --git a/spec/placeos/api_wrapper/triggers_spec.cr b/spec/placeos/api_wrapper/triggers_spec.cr new file mode 100644 index 0000000..b47dea1 --- /dev/null +++ b/spec/placeos/api_wrapper/triggers_spec.cr @@ -0,0 +1,97 @@ +require "../../spec_helper" + +module PlaceOS + describe Client::APIWrapper::Triggers do + api = PlaceOS::Client::APIWrapper.new DOMAIN + client = Client::APIWrapper::Triggers.new api + + triggers_json = <<-JSON + [ + { + "control_system_id": "hello", + "name": "Place", + "authority_id": "hello", + "description": null, + "tags": ["org"], + "triggers": [], + "created_at": 1555995992, + "updated_at": 1555996000, + "id": "trigger-oOj2lGgsz", + "count": 0, + "capacity": 2 + } + ] + JSON + + triggers = Array(JSON::Any).from_json(triggers_json).map &.to_json + + describe "#search" do + it "enumerates all triggers" do + WebMock + .stub(:get, DOMAIN + client.base) + .with(query: {"authority_id" => "hello", "limit" => "20", "offset" => "0"}, headers: HEADERS) + .to_return(body: triggers_json) + result = client.search "hello" + result.size.should eq(1) + result.first.should be_a(PlaceOS::Client::API::Models::Trigger) + result.first.name.should eq("Place") + end + + it "provides trigger search" do + WebMock + .stub(:get, DOMAIN + client.base) + .with(query: {"authority_id" => "hello", "limit" => "20", "offset" => "0"}, headers: HEADERS) + .to_return(body: triggers_json) + result = client.search "hello" + result.size.should eq(1) + result.first.name.should eq("Place") + end + end + + it "#fetch" do + WebMock + .stub(:get, DOMAIN + "#{client.base}/trigger-oOj2lGgsz") + .to_return(body: triggers.first) + result = client.fetch "trigger-oOj2lGgsz" + result.should be_a(PlaceOS::Client::API::Models::Trigger) + # result.to_json.should eq("{\"name\":\"Place\",\"control_system_id\":\"hello\"}") + end + + it "#destroy" do + WebMock + .stub(:delete, DOMAIN + "#{client.base}/trigger-oOj2lGgsz") + result = client.destroy "trigger-oOj2lGgsz" + result.should be_nil + end + + it "#create" do + body = {control_system_id: "hello", name: "Place"}.to_json + WebMock + .stub(:post, DOMAIN + client.base) + .with( + headers: HTTP::Headers{"Content-Type" => "application/json"}, + body: body + ) + .to_return(body: triggers.first) + result = client.create(control_system_id: "hello", name: "Place") + result.should be_a(PlaceOS::Client::API::Models::Trigger) + # result.to_json.should eq("{\"name\":\"Place\",\"control_system_id\":\"hello\"}") + end + + it "#update" do + WebMock + .stub(:put, DOMAIN + "#{client.base}/trigger-oOj2lGgsz") + .with( + headers: {"Content-Type" => "application/json"}, + body: {control_system_id: "foo", name: "Foo"}.to_json + ) + .to_return(body: triggers.first) + result = client.update "trigger-oOj2lGgsz", control_system_id: "foo", name: "Foo" + result.should be_a(PlaceOS::Client::API::Models::Trigger) + # result.to_json.should eq("{\"name\":\"Place\",\"control_system_id\":\"hello\"}") + end + + describe "#instances" do + end + end +end diff --git a/spec/placeos/api_wrapper/users_spec.cr b/spec/placeos/api_wrapper/users_spec.cr index d360575..55405d7 100644 --- a/spec/placeos/api_wrapper/users_spec.cr +++ b/spec/placeos/api_wrapper/users_spec.cr @@ -8,27 +8,115 @@ module PlaceOS users_json = <<-JSON [ { - "authority_id": "sgrp-1234", - "id": "user-wJHShR4Ffa", - "email": "john@example.com", - "email_digest": "---", - "name": "John Doe", + "id": "user-oOj2lGgsz", + "name": "Place", + "authority_id": "hello", "created_at": 1555995992, - "updated_at": 1555996000 + "updated_at": 1555996000, + "email_digest": "", + "nickname": "", + "first_name": "", + "last_name": "", + "country": "", + "building": "", + "image": "" } ] JSON + users = Array(JSON::Any).from_json(users_json).map &.to_json + describe "#search" do + it "enumerates all users" do + WebMock + .stub(:get, DOMAIN + client.base) + .with(query: {"limit" => "20", "offset" => "0"}, headers: HEADERS) + .to_return(body: users_json) + result = client.search + result.size.should eq(1) + result.first.should be_a(PlaceOS::Client::API::Models::User) + result.first.name.should eq("Place") + end + it "provides user search" do WebMock .stub(:get, DOMAIN + client.base) - .with(query: {"q" => "\"John Doe\"", "limit" => "20", "offset" => "0"}) + .with(query: {"q" => "Place", "limit" => "20", "offset" => "0"}, headers: HEADERS) .to_return(body: users_json) - result = client.search "\"John Doe\"" + result = client.search q: "Place" result.size.should eq(1) - result.first.email.should eq("john@example.com") + result.first.name.should eq("Place") + end + end + + it "#fetch" do + WebMock + .stub(:get, DOMAIN + "#{client.base}/user-oOj2lGgsz") + .to_return(body: users.first) + result = client.fetch "user-oOj2lGgsz" + result.should be_a(PlaceOS::Client::API::Models::User) + end + + it "#destroy" do + WebMock + .stub(:delete, DOMAIN + "#{client.base}/user-oOj2lGgsz") + result = client.destroy "user-oOj2lGgsz" + result.should be_nil + end + + describe "#create" do + it "should create a user with minimum attributes" do + body = {authority_id: "hello", name: "Place"}.to_json + WebMock + .stub(:post, DOMAIN + client.base) + .with( + headers: HTTP::Headers{"Content-Type" => "application/json"}, + body: body, + ) + .to_return(body: users.first) + result = client.create authority_id: "hello", name: "Place" + result.should be_a(PlaceOS::Client::API::Models::User) + end + + it "should create a user with all the attributes" do + body = {authority_id: "hello", name: "Place", nickname: "place nickname"}.to_json + WebMock + .stub(:post, DOMAIN + client.base) + .with( + headers: HTTP::Headers{"Content-Type" => "application/json"}, + body: body, + ) + .to_return(body: users.first) + result = client.create authority_id: "hello", name: "Place", nickname: "place nickname" + result.should be_a(PlaceOS::Client::API::Models::User) end end + + it "#update" do + res = {"id" => "user-G03JG1kx3yS", "email_digest" => "18270840d5b8357a2175208b63ca52a4", "nickname" => "", "name" => "Place Support (localhost=>8443)", "created_at" => 155599599, "updated_at" => 1555996000, "first_name" => "hello", "last_name" => "", "country" => "", "building" => "", "image" => ""}.to_json + WebMock + .stub(:put, DOMAIN + client.base + "/user-G03JG1kx3yS") + .to_return(body: res) + result = client.update "user-G03JG1kx3yS", authority_id: "authority-G03OrvJj~5j", name: "hello" + result.should be_a(PlaceOS::Client::API::Models::User) + end + + it "#current" do + user_parsed = {"id" => "user-G03JG1kx3yS", "email_digest" => "18270840d5b8357a2175208b63ca52a4", "nickname" => "", "name" => "Place Support (localhost=>8443)", "created_at" => 1555995992, "updated_at" => 1555996000, "first_name" => "hello", "last_name" => "", "country" => "", "building" => "", "image" => ""} + WebMock + .stub(:get, DOMAIN + client.base + "/current") + .to_return(body: user_parsed.to_json) + result = client.current + result.should be_a(PlaceOS::Client::API::Models::User) + end + + describe "#resource_token" do + # WebMock + # .stub(:post, DOMAIN + client.base + "/resource_token") + # .to_return(body: "") + # result = client.resource_token + # result.should be_a(ResourceToken) + # result.to_json.should eq("") + end end end diff --git a/spec/placeos/api_wrapper/webhook_spec.cr b/spec/placeos/api_wrapper/webhook_spec.cr new file mode 100644 index 0000000..deda4e6 --- /dev/null +++ b/spec/placeos/api_wrapper/webhook_spec.cr @@ -0,0 +1,6 @@ +require "../../spec_helper" + +module PlaceOS + describe Client::APIWrapper::Webhook do + end +end diff --git a/spec/placeos/api_wrapper/zones_spec.cr b/spec/placeos/api_wrapper/zones_spec.cr index e699ea3..6b9f517 100644 --- a/spec/placeos/api_wrapper/zones_spec.cr +++ b/spec/placeos/api_wrapper/zones_spec.cr @@ -23,7 +23,7 @@ module PlaceOS zones = Array(JSON::Any).from_json(zones_json).map &.to_json - describe "search" do + describe "#search" do it "enumerates all zones" do WebMock .stub(:get, DOMAIN + client.base) @@ -31,9 +31,8 @@ module PlaceOS .to_return(body: zones_json) result = client.search result.size.should eq(1) - zone = result.first - zone.should be_a(Client::API::Models::Zone) - zone.name.should eq("Place") + result.first.should be_a(PlaceOS::Client::API::Models::Zone) + result.first.name.should eq("Place") end it "provides zone search" do @@ -58,17 +57,17 @@ module PlaceOS ) .to_return(body: zones.first) result = client.create name: "Place" - result.should be_a(Client::API::Models::Zone) + result.should be_a(PlaceOS::Client::API::Models::Zone) end end - describe "#retrieve" do + describe "#fetch" do it "inspects a zones metadata" do WebMock .stub(:get, DOMAIN + "#{client.base}/zone-oOj2lGgsz") .to_return(body: zones.first) result = client.fetch "zone-oOj2lGgsz" - result.should be_a(Client::API::Models::Zone) + result.should be_a(PlaceOS::Client::API::Models::Zone) end end @@ -82,11 +81,11 @@ module PlaceOS ) .to_return(body: zones.first) result = client.update(id: "zone-oOj2lGgsz", name: "Foo") - result.should be_a(Client::API::Models::Zone) + result.should be_a(PlaceOS::Client::API::Models::Zone) end end - describe "#delete" do + describe "#destroy" do it "execs a delete request" do WebMock .stub(:delete, DOMAIN + "#{client.base}/zone-oOj2lGgsz") @@ -94,5 +93,33 @@ module PlaceOS result.should be_nil end end + + describe "#execute" do + # TODO + # Unsure about how this is supposed to work + pending "should exec execute" do + # body = {id: "zone-oOj2lGgsz", method: "string", module_name: "string"}.to_json + WebMock + .stub(:post, DOMAIN + "#{client.base}/zone-oOj2lGgsz/module_name_1/method") + .with( + headers: HTTP::Headers{"Content-Type" => "application/json"}, + body: {id: "zone-oOj2lGgsz", method: "string", module_name: "string"}.to_json, + ) + .to_return(body: zones.first) + result = client.execute id: "zone-oOj2lGgsz", method: "string", module_name: "string" + result.should be_a(PlaceOS::Client::API::Models::Zone) + end + end + + describe "#trigger" do + it "should exec trigger" do + WebMock + .stub(:get, DOMAIN + "#{client.base}/zone-oOj2lGgsz/triggers") + .to_return(body: {"name" => "Place", "control_system_id" => "hello"}.to_json) + result = client.trigger "zone-oOj2lGgsz" + result.should be_a(PlaceOS::Client::API::Models::Trigger) + # result.to_json.should eq("{\"name\":\"Place\",\"control_system_id\":\"hello\"}") + end + end end end diff --git a/src/.DS_Store b/src/.DS_Store new file mode 100644 index 0000000..37171eb Binary files /dev/null and b/src/.DS_Store differ diff --git a/src/placeos/.DS_Store b/src/placeos/.DS_Store new file mode 100644 index 0000000..55f8f1d Binary files /dev/null and b/src/placeos/.DS_Store differ diff --git a/src/placeos/api/.DS_Store b/src/placeos/api/.DS_Store new file mode 100644 index 0000000..09d6131 Binary files /dev/null and b/src/placeos/api/.DS_Store differ diff --git a/src/placeos/api/models.cr b/src/placeos/api/models.cr index f0f02f0..006d968 100644 --- a/src/placeos/api/models.cr +++ b/src/placeos/api/models.cr @@ -2,3 +2,5 @@ module PlaceOS::Client::API::Models end require "./models/**" + +# Original client models : https://github.com/PlaceOS/crystal-client/tree/c907ada0b21eda7824764ed3e9ef9e48b55d9d29/src/placeos/api/models diff --git a/src/placeos/api/models/.DS_Store b/src/placeos/api/models/.DS_Store new file mode 100644 index 0000000..d722a99 Binary files /dev/null and b/src/placeos/api/models/.DS_Store differ diff --git a/src/placeos/api/models/authority.cr b/src/placeos/api/models/authority.cr deleted file mode 100644 index 22eab88..0000000 --- a/src/placeos/api/models/authority.cr +++ /dev/null @@ -1,33 +0,0 @@ -require "./response" - -module PlaceOS::Client::API::Models - # Metadata about the PlaceOS instance connected to. - # - # This provides information that may be of relevance for authentication or - # providing client-side configuration information. - struct Authority < Response - # A universally unique identifier that represents the Authority. - getter id : String - - # Human readable name - getter name : String - - # FQDN or IP address this authority serves. - getter domain : String - - # Authority description (markdown). - getter description : String? - - # Path that clients should use for initiating authentication. - getter login_url : String - - # Path that clients should use for revoking authentication. - getter logout_url : String - - # Additional configuration / context for clients. - getter config : Hash(String, ::JSON::Any) - - # Version of application - getter version : String - end -end diff --git a/src/placeos/api/models/auths/ldap.cr b/src/placeos/api/models/auths/ldap.cr deleted file mode 100644 index 7773220..0000000 --- a/src/placeos/api/models/auths/ldap.cr +++ /dev/null @@ -1,28 +0,0 @@ -require "../response" - -module PlaceOS::Client::API::Models - struct LdapAuthentication < Response - include Timestamps - - getter id : String - getter name : String - getter authority_id : String - getter port : Int32 - - # Options are: plain, ssl, tls - getter auth_method : String - getter uid : String - getter host : String - - # BaseDN such as dc=intridea, dc=com - getter base : String - - # :bind_dn and :password is the default credentials to perform user lookup - getter bind_dn : String - getter password : String - - # LDAP filter like: (&(uid=%{username})(memberOf=cn=myapp-users,ou=groups,dc=example,dc=com)) - # Can be used instead of UID - getter filter : String - end -end diff --git a/src/placeos/api/models/auths/oauth.cr b/src/placeos/api/models/auths/oauth.cr deleted file mode 100644 index d014491..0000000 --- a/src/placeos/api/models/auths/oauth.cr +++ /dev/null @@ -1,41 +0,0 @@ -require "../response" - -module PlaceOS::Client::API::Models - struct OAuthAuthentication < Response - include Timestamps - - getter id : String - getter name : String - getter authority_id : String - - # The client ID and secret configured for this application - getter client_id : String - getter client_secret : String - - # Maps an expected key to a provided key i.e. {used_in_engine => used_by_remote} - getter info_mappings : Hash(String, String) - - # The HTTP URL of the SSO provider - getter site : String - - # The SSO providers URL for authorization, defaults to: `oauth/authorize` - # Google is `/o/oauth2/auth` - getter authorize_url : String - - # If not set it defaults to "post" - getter token_method : String - - # If not set it defaults to "request_body", others include "basic_auth" - getter auth_scheme : String - - # defaults to: `oauth/token` however google is: `/o/oauth2/token` - getter token_url : String - - # Space seperated scope strings - # i.e. `https://www.googleapis.com/auth/devstorage.readonly https://www.googleapis.com/auth/prediction` - getter scope : String - - # URL to call with a valid token to obtain the users profile data (name, email etc) - getter raw_info_url : String - end -end diff --git a/src/placeos/api/models/auths/saml.cr b/src/placeos/api/models/auths/saml.cr deleted file mode 100644 index b6a1adc..0000000 --- a/src/placeos/api/models/auths/saml.cr +++ /dev/null @@ -1,51 +0,0 @@ -require "../response" - -module PlaceOS::Client::API::Models - struct SamlAuthentication < Response - include Timestamps - - getter id : String - getter name : String - getter authority_id : String - - # The name of your application - getter issuer : String - - # mapping of request params that exist during the request phase of OmniAuth that should to be sent to the IdP - getter idp_sso_target_url_runtime_params : Hash(String, String) - - # Describes the format of the username required by this application - getter name_identifier_format : String - - # getter that uniquely identifies the user - # (If unset, the name identifier returned by the IdP is used.) - getter uid_getter : String - - # The URL at which the SAML assertion should be received (SSO Service => Engine URL) - getter assertion_consumer_service_url : String - - # The URL to which the authentication request should be sent (Engine => SSO Service) - getter idp_sso_target_url : String - - # The identity provider's certificate in PEM format (this or fingerprint is required) - getter idp_cert : String - - # The SHA1 fingerprint of the certificate - getter idp_cert_fingerprint : String - - # Name for the getter service (Defaults to Required getters) - getter getter_service_name : String - - # Used to map getter Names in a SAMLResponse to entries in the OmniAuth info hash - getter getter_statements : Hash(String, Array(String)) - - # Used to map getter Names in a SAMLResponse to entries in the OmniAuth info hash - getter request_getters : Array(NamedTuple(name: String, name_format: String, friendly_name: String)) - - # The URL to which the single logout request and response should be sent - getter idp_slo_target_url : String - - # The value to use as default RelayState for single log outs - getter slo_default_relay_state : String - end -end diff --git a/src/placeos/api/models/base.cr b/src/placeos/api/models/base.cr new file mode 100644 index 0000000..18ea877 --- /dev/null +++ b/src/placeos/api/models/base.cr @@ -0,0 +1,41 @@ +require "./response" + +module PlaceOS::Client::API::Models + # # HELPERS + # PlaceOS::Model::Comparison Types + alias Value = StatusVariable | Constant + alias Constant = Int64 | Float64 | String | Bool + alias StatusVariable = NamedTuple( + # Module that defines the status variable + mod: String, + # Unparsed hash of a status variable + status: String, + # Keys to look up in the module + keys: Array(String), + ) + + # Converters Not To Use + FORBID_CONVERTERS = ["JSON::Any::StringConverter"] + + # # Main Macro + {% for subclasses in [PlaceOS::Model::ModelBase.all_subclasses, PlaceOS::Model::SubModel.all_subclasses] %} + {% for mdl in subclasses %} + struct {{mdl.name.id.split("::")[-1].id}} < Response + {% if subclasses == PlaceOS::Model::SubModel %} + include Timestamps + {% end %} + + getter id : String? = nil + + {% for name, opts in mdl.constant("FIELDS") %} + {% if opts[:mass_assign] == true %} + {% if opts[:converter] && !FORBID_CONVERTERS.includes?(opts[:converter].resolve.stringify) %} + @[JSON::Field(converter: {{opts[:converter]}})] + {% end %} + property {{name.id}} : {{opts[:klass]}}? + {% end %} + {% end %} + end + {% end %} + {% end %} +end diff --git a/src/placeos/api/models/cluster.cr b/src/placeos/api/models/cluster.cr deleted file mode 100644 index 252b474..0000000 --- a/src/placeos/api/models/cluster.cr +++ /dev/null @@ -1,6 +0,0 @@ -require "./response" - -module PlaceOS::Client::API::Models - struct Cluster < Response - end -end diff --git a/src/placeos/api/models/function.cr b/src/placeos/api/models/function.cr deleted file mode 100644 index 118ac94..0000000 --- a/src/placeos/api/models/function.cr +++ /dev/null @@ -1,27 +0,0 @@ -require "./response" - -module PlaceOS::Client::API::Models - # Invocation information for interaction with an exposed driver behaviour. - struct Function < Response - # The number of parameters that the function accepts. - getter arity : Int32 - - # Possible parameter kinds. - enum ParameterKind - # Required - Req - - # Optional - Opt - - # A capture all for all trailing arguments. - Rest - end - - # Parameter information as {kind, name}. - alias Parameter = Tuple(ParameterKind, String) - - # Parameter information. - getter params : Array(Parameter) - end -end diff --git a/src/placeos/api/models/metadata.cr b/src/placeos/api/models/metadata.cr deleted file mode 100644 index f23c5e8..0000000 --- a/src/placeos/api/models/metadata.cr +++ /dev/null @@ -1,10 +0,0 @@ -require "./response" - -module PlaceOS::Client::API::Models - struct Metadata < Response - getter name : String - getter description : String - getter details : JSON::Any - getter parent_id : String - end -end diff --git a/src/placeos/api/models/oauth_application.cr b/src/placeos/api/models/oauth_application.cr deleted file mode 100644 index e3c62e8..0000000 --- a/src/placeos/api/models/oauth_application.cr +++ /dev/null @@ -1,18 +0,0 @@ -require "./response" - -module PlaceOS::Client::API::Models - struct OAuthApplication < Response - include Timestamps - getter id : String - getter name : String - getter uid : String - getter secret : String - getter scopes : String - getter owner_id : String - getter redirect_uri : String - getter skip_authorization : Bool - getter confidential : Bool - @[JSON::Field(converter: Time::EpochConverter)] - getter revoked_at : Time - end -end diff --git a/src/placeos/api/models/ping.cr b/src/placeos/api/models/ping.cr deleted file mode 100644 index f50cefe..0000000 --- a/src/placeos/api/models/ping.cr +++ /dev/null @@ -1,10 +0,0 @@ -require "./response" - -module PlaceOS::Client::API::Models - struct Ping < Response - getter host : String - getter pingable : Bool - getter warning : String? - getter exception : String? - end -end diff --git a/src/placeos/api/models/repository.cr b/src/placeos/api/models/repository.cr deleted file mode 100644 index 47c45af..0000000 --- a/src/placeos/api/models/repository.cr +++ /dev/null @@ -1,6 +0,0 @@ -require "./response" - -module PlaceOS::Client::API::Models - struct Repository < Response - end -end diff --git a/src/placeos/api/models/response.cr b/src/placeos/api/models/response.cr index 60df1fc..57a5704 100644 --- a/src/placeos/api/models/response.cr +++ b/src/placeos/api/models/response.cr @@ -1,5 +1,6 @@ require "json" require "uri" +require "placeos-models" module PlaceOS::Client::API::Models # :nodoc: diff --git a/src/placeos/api/models/root.cr b/src/placeos/api/models/root.cr deleted file mode 100644 index e69de29..0000000 diff --git a/src/placeos/api/models/settings.cr b/src/placeos/api/models/settings.cr deleted file mode 100644 index 11872e4..0000000 --- a/src/placeos/api/models/settings.cr +++ /dev/null @@ -1,13 +0,0 @@ -require "placeos-models/utilities/encryption" - -require "./response" - -module PlaceOS::Client::API::Models - struct Settings < Response - getter encryption_level : Encryption::Level - getter settings_string : String = "{}" - getter keys : Array(String) = [] of String - getter settings_id : String? = nil - getter parent_id : String - end -end diff --git a/src/placeos/api/models/trigger.cr b/src/placeos/api/models/trigger.cr deleted file mode 100644 index 8ffcb60..0000000 --- a/src/placeos/api/models/trigger.cr +++ /dev/null @@ -1,80 +0,0 @@ -require "./response" - -module PlaceOS::Client::API::Models - struct Trigger < Response - getter name : String - getter description : String - getter control_system_id : String - - getter actions : Actions - getter conditions : Conditions - - # In milliseconds - getter debounce_period : Int32 - getter important : Bool - - getter enable_webhook : Bool - getter supported_methods : Array(String) - - struct Actions < Response - getter functions : Array(Function) = [] of PlaceOS::Client::API::Models::Trigger::Actions::Function - getter mailers : Array(Email) = [] of PlaceOS::Client::API::Models::Trigger::Actions::Email - - struct Email < Response - getter emails : Array(String) - getter content : String - end - - struct Function < Response - getter mod : String - getter method : String - getter args : Hash(String, JSON::Any) = {} of String => JSON::Any - end - end - - struct Conditions < Response - getter comparisons : Array(Comparison) = [] of PlaceOS::Client::API::Models::Trigger::Conditions::Comparison - getter time_dependents : Array(TimeDependent) = [] of PlaceOS::Client::API::Models::Trigger::Conditions::TimeDependent - - struct Comparison < Response - getter left : Value - getter operator : String - getter right : Value - - alias Value = StatusVariable | Constant - - # Constant value - alias Constant = Int64 | Float64 | String | Bool - - # Status of a Module - alias StatusVariable = NamedTuple( - # Module that defines the status variable - mod: String, - # Unparsed hash of a status variable - status: String, - # Keys to look up in the module - keys: Array(String), - ) - - OPERATORS = { - "equal", "not_equal", "greater_than", "greater_than_or_equal", - "less_than", "less_than_or_equal", "and", "or", "exclusive_or", - } - end - - struct TimeDependent < Response - enum Type - At - Cron - end - - getter type : Type - - @[JSON::Field(converter: Time::EpochConverter)] - getter time : Time? = nil - - getter cron : String? = nil - end - end - end -end diff --git a/src/placeos/api/models/trigger_instance.cr b/src/placeos/api/models/trigger_instance.cr deleted file mode 100644 index eee3f10..0000000 --- a/src/placeos/api/models/trigger_instance.cr +++ /dev/null @@ -1,17 +0,0 @@ -require "./response" - -module PlaceOS::Client::API::Models - struct TriggerInstance < Response - getter control_system_id : String? = nil - getter trigger_id : String? = nil - getter zone_id : String? = nil - - getter enabled : Bool = true - getter triggered : Bool = false - getter important : Bool = false - getter exec_enabled : Bool = false - - getter webhook_secret : String - getter trigger_count : Int32 = 0 - end -end diff --git a/src/placeos/api/models/version.cr b/src/placeos/api/models/version.cr deleted file mode 100644 index c178e24..0000000 --- a/src/placeos/api/models/version.cr +++ /dev/null @@ -1,17 +0,0 @@ -require "./response" - -module PlaceOS::Client::API::Models - struct Version < Response - # The PlaceOS application name - getter app : String - - # The version in the shard yml - getter version : String - - # the commit hash for the running build - getter commit : String - - # The build time of the docker container - getter build_time : String - end -end diff --git a/src/placeos/api/models/websocket/request.cr b/src/placeos/api/models/websocket/request.cr deleted file mode 100644 index a330a79..0000000 --- a/src/placeos/api/models/websocket/request.cr +++ /dev/null @@ -1,35 +0,0 @@ -require "json" - -struct PlaceOS::Client::API::Models::Websocket::Request - include JSON::Serializable - - enum Type - Bind - Unbind - Exec - Debug - Ignore - end - - # A unique identifier to associate with the command. This will be returned as - # part of the response. - getter id : String | Int32 | Int64 - - # The command type. - getter cmd : Type - - # The system identified the command targets. - getter sys : String - - # The module name the command targets. - getter mod : String - - # The module index the command targets. Defaults to 1. - getter index : Int32? - - # Name of the status variable of method being interacted with. - getter name : String - - # Associated arguments for the command. - getter args : Array(::JSON::Any::Type)? -end diff --git a/src/placeos/api/models/websocket/response.cr b/src/placeos/api/models/websocket/response.cr deleted file mode 100644 index 51efd6f..0000000 --- a/src/placeos/api/models/websocket/response.cr +++ /dev/null @@ -1,35 +0,0 @@ -require "json" - -struct PlaceOS::Client::API::Models::Websocket::Response - enum Type - Success - Error - Notify - Debug - - def model - {% begin %} - case self - {% for type in @type.constants %} - when {{type}} then Response::{{type}} - {% end %} - else - # Will never happen, but required to stop nil for sneaking into the - # returned type union. - raise "" - end - {% end %} - end - end - - # Parses a websocket response into a concrete response type. - # - # FIXME: currently this is parsing twice - this is a quick hack to get things - # going. When time allows this should be refactored to work as a single pass, - # or provide a more efficient method for identifying the message type. - def self.from_json(input) - json = JSON.parse input - type = Type.parse json["type"].as_s - type.model.from_json input - end -end diff --git a/src/placeos/api/models/websocket/response/debug.cr b/src/placeos/api/models/websocket/response/debug.cr deleted file mode 100644 index 7da1dce..0000000 --- a/src/placeos/api/models/websocket/response/debug.cr +++ /dev/null @@ -1,30 +0,0 @@ -require "json" -require "./meta" - -struct PlaceOS::Client::API::Models::Websocket::Response::Debug - include JSON::Serializable - - enum Level - Unknown - Fatal - Error - Warn - Info - Debug - end - - # The identifier included with the original request. - getter id : String | Int32 | Int64 - - # ID of the module the event originated from. - getter mod : String - - # Class of the originating message source. - getter klass : String - - # Message verbosity level. - getter level : Level - - # Log message. - getter msg : String -end diff --git a/src/placeos/api/models/websocket/response/error.cr b/src/placeos/api/models/websocket/response/error.cr deleted file mode 100644 index 36a03d7..0000000 --- a/src/placeos/api/models/websocket/response/error.cr +++ /dev/null @@ -1,25 +0,0 @@ -require "json" - -struct PlaceOS::Client::API::Models::Websocket::Response::Error - include JSON::Serializable - - enum Code - ParseError - BadRequest - AccessDenied - RequestFailed - UnknownCommand - SystemNotFound - ModuleNotFound - UnexpectedFailure - end - - # The identifier included with the original request. - getter id : String | Int32 | Int64 - - # Error type. - getter code : Code - - # Additional error info. - getter msg : String -end diff --git a/src/placeos/api/models/websocket/response/meta.cr b/src/placeos/api/models/websocket/response/meta.cr deleted file mode 100644 index b24bf09..0000000 --- a/src/placeos/api/models/websocket/response/meta.cr +++ /dev/null @@ -1,17 +0,0 @@ -require "json" - -struct PlaceOS::Client::API::Models::Websocket::Response::Meta - include JSON::Serializable - - # The system ID. - getter sys : String - - # Module name. - getter mod : String - - # Module index. - getter index : Int32 - - # Name of the method or status key. - getter name : String? -end diff --git a/src/placeos/api/models/websocket/response/notify.cr b/src/placeos/api/models/websocket/response/notify.cr deleted file mode 100644 index 7187985..0000000 --- a/src/placeos/api/models/websocket/response/notify.cr +++ /dev/null @@ -1,16 +0,0 @@ -require "json" -require "./meta" - -# Asyncronous state update from an active binding. -struct PlaceOS::Client::API::Models::Websocket::Response::Notify - include JSON::Serializable - - # The identifier included with the original request. - getter id : String | Int32 | Int64 - - # New status value - getter value : ::JSON::Any - - # Associated metadata. - getter meta : Meta? -end diff --git a/src/placeos/api/models/websocket/response/success.cr b/src/placeos/api/models/websocket/response/success.cr deleted file mode 100644 index 83e80f8..0000000 --- a/src/placeos/api/models/websocket/response/success.cr +++ /dev/null @@ -1,12 +0,0 @@ -require "json" -require "./meta" - -struct PlaceOS::Client::API::Models::Websocket::Response::Success - include JSON::Serializable - - # The identifier included with the original request. - getter id : String | Int32 | Int64 - - # Associated metadata. - getter meta : Meta? -end diff --git a/src/placeos/api_wrapper.cr b/src/placeos/api_wrapper.cr index 0245e45..6b03281 100644 --- a/src/placeos/api_wrapper.cr +++ b/src/placeos/api_wrapper.cr @@ -3,6 +3,7 @@ require "json" require "mutex" require "oauth2" require "uri" +require "placeos-models" # is there a better place for this require? require "./api/**" diff --git a/src/placeos/api_wrapper/authority.cr b/src/placeos/api_wrapper/authority.cr index f57b28e..2790087 100644 --- a/src/placeos/api_wrapper/authority.cr +++ b/src/placeos/api_wrapper/authority.cr @@ -6,7 +6,7 @@ module PlaceOS # Gets the authority metadata for the attached instance. def fetch - get base, as: API::Models::Authority + get base, as: PlaceOS::Client::API::Models::Authority end end end diff --git a/src/placeos/api_wrapper/auths/base.cr b/src/placeos/api_wrapper/auths/base.cr index bff693f..3ec40d6 100644 --- a/src/placeos/api_wrapper/auths/base.cr +++ b/src/placeos/api_wrapper/auths/base.cr @@ -1,5 +1,5 @@ require "../endpoint" -require "../../api/models/auths/*" +require "placeos-models" module PlaceOS abstract class Client::APIWrapper::AuthBase(Model) < Client::APIWrapper::Endpoint @@ -31,12 +31,12 @@ module PlaceOS get base, params: from_args, as: Array(Model) end - def update(**args) - put "#{base}/#{id}", body: from_args, as: Model - end - def create(**args) : Model post base, body: from_args, as: Model end + + def update(**args) + put "#{base}/#{id}", body: from_args, as: Model + end end end diff --git a/src/placeos/api_wrapper/brokers.cr b/src/placeos/api_wrapper/brokers.cr new file mode 100644 index 0000000..70c7bbb --- /dev/null +++ b/src/placeos/api_wrapper/brokers.cr @@ -0,0 +1,13 @@ +require "./endpoint" + +module PlaceOS + class Client::APIWrapper::Brokers < Client::APIWrapper::Endpoint + include Client::APIWrapper::Endpoint::Index(Broker) + include Client::APIWrapper::Endpoint::Fetch(Broker) + include Client::APIWrapper::Endpoint::Create(Broker) + include Client::APIWrapper::Endpoint::Update(Broker) + include Client::APIWrapper::Endpoint::Destroy + + getter base : String = "#{API_ROOT}/brokers" + end +end diff --git a/src/placeos/api_wrapper/cluster.cr b/src/placeos/api_wrapper/cluster.cr index c4700ff..2381dd2 100644 --- a/src/placeos/api_wrapper/cluster.cr +++ b/src/placeos/api_wrapper/cluster.cr @@ -1,7 +1,13 @@ require "./endpoint" +# missing model? + module PlaceOS class Client::APIWrapper::Cluster < Client::APIWrapper::Endpoint + include Client::APIWrapper::Endpoint::Search(Cluster) + include Client::APIWrapper::Endpoint::Fetch(Cluster) + include Client::APIWrapper::Endpoint::Destroy + getter base : String = "#{API_ROOT}/cluster" end end diff --git a/src/placeos/api_wrapper/domains.cr b/src/placeos/api_wrapper/domains.cr index d497606..57546a1 100644 --- a/src/placeos/api_wrapper/domains.cr +++ b/src/placeos/api_wrapper/domains.cr @@ -2,9 +2,12 @@ require "./endpoint" module PlaceOS class Client::APIWrapper::Domains < Client::APIWrapper::Endpoint - include Client::APIWrapper::Endpoint::Fetch(Authority) + include Client::APIWrapper::Endpoint::Search(PlaceOS::Model::Authority) + include Client::APIWrapper::Endpoint::Fetch(PlaceOS::Model::Authority) include Client::APIWrapper::Endpoint::Destroy getter base : String = "#{API_ROOT}/domains" + + __create_update_from_model__(PlaceOS::Model::Authority) end end diff --git a/src/placeos/api_wrapper/drivers.cr b/src/placeos/api_wrapper/drivers.cr index 12a64d2..4c45a64 100644 --- a/src/placeos/api_wrapper/drivers.cr +++ b/src/placeos/api_wrapper/drivers.cr @@ -2,34 +2,17 @@ require "./endpoint" module PlaceOS class Client::APIWrapper::Drivers < Client::APIWrapper::Endpoint + include Client::APIWrapper::Endpoint::Search(Driver) include Client::APIWrapper::Endpoint::Fetch(Driver) + # include Client::APIWrapper::Endpoint::Create(Driver) + # include Client::APIWrapper::Endpoint::Update(Driver) include Client::APIWrapper::Endpoint::Destroy getter base : String = "#{API_ROOT}/drivers" - # List or search for drivers. - # - # Results maybe filtered by specifying a query - *q* - to search across driver - # attributes. A small query language is supported within this: - # - # Operator | Action - # -------- | ------ - # `+` | Matches both terms - # `|` | Matches either terms - # `-` | Negates a single token - # `"` | Wraps tokens to form a phrase - # `(` `)` | Provides precedence - # `~N` | Specifies edit distance (fuzziness) after a word - # `~N` | Specifies slop amount (deviation) after a phrase - # - # Up to *limit* drivers will be returned, with a paging based on *offset*. - def search(q : String? = nil, limit : Int = 20, offset : Int = 0) - get base, params: from_args, as: Array(Driver) - end - def create( name : String, - role : Role, + role : Int32, commit : String, file_name : String, module_name : String, @@ -44,8 +27,8 @@ module PlaceOS def update( id : String, + role : Int32? = nil, name : String? = nil, - role : Role? = nil, commit : String? = nil, file_name : String? = nil, module_name : String? = nil, @@ -56,5 +39,14 @@ module PlaceOS ) put "#{base}/#{id}", body: from_args, as: Driver end + + # Unique Actions + def recompile(id : String) + post "#{base}/#{id}/recompile", as: Driver + end + + def compiled(id : String) + get "#{base}/#{id}/compiled", as: Driver + end end end diff --git a/src/placeos/api_wrapper/endpoint.cr b/src/placeos/api_wrapper/endpoint.cr index 7e6e6ac..5088f0c 100644 --- a/src/placeos/api_wrapper/endpoint.cr +++ b/src/placeos/api_wrapper/endpoint.cr @@ -11,10 +11,55 @@ module PlaceOS def initialize(@client : APIWrapper) end + # List or search. + # + # Results maybe filtered by specifying a query - *q* - to search across + # attributes. A small query language is supported within this: + # + # Operator | Action + # -------- | ------ + # `+` | Matches both terms + # `|` | Matches either terms + # `-` | Negates a single token + # `"` | Wraps tokens to form a phrase + # `(` `)` | Provides precedence + # `~N` | Specifies edit distance (fuzziness) after a word + # `~N` | Specifies slop amount (deviation) after a phrase + # + # Up to *limit* will be returned, with a paging based on *offset*. + module Search(T) + def search( + q : String? = nil, + limit : Int = 20, + offset : Int = 0, + **args + ) : Array(T) + get base, params: from_args, as: Array(T) + end + end + + module Index(T) + def index : Array(T) + get base, params: from_args, as: Array(T) + end + end + module Fetch(T) # Returns a {{ T.id }} - def fetch(id : String) - get "#{base}/#{id}", as: T + def fetch(id : String, **args) : T + get "#{base}/#{id}", params: from_args, as: T + end + end + + module Create(T) + def create(**args) : T + post base, body: from_args, as: T + end + end + + module Update(T) + def update(id, **args) : T + post "#{base}/#{id}", body: from_args, as: T end end @@ -26,6 +71,47 @@ module PlaceOS end end + module StartStop + # Starts a module. + def start(id : String) + post "#{base}/#{id}/start" + nil + end + + # Stops a module. + def stop(id : String) + post "#{base}/#{id}/stop" + nil + end + end + + module Settings + def settings(id : String) + get "#{base}/#{id}/settings", as: Array(PlaceOS::Client::API::Models::Settings) + end + end + + module State + # def state(id : String, lookup : String? = nil) + # path = "#{base}/#{id}/state" + # path += "/#{lookup}" if lookup + + # get path + # end + end + + module Execute + # def execute( + # id : String, + # method : String, + # # module_name : String, + # # index : Int32 = 1, + # args = nil + # ) + # # post "#{base}/#{id}/#{module_name}_#{index}/#{method}", body: args + # end + end + {% for method in %w(get post put head delete patch options) %} # Executes a {{method.id.upcase}} request on the client connection. # @@ -123,6 +209,35 @@ module PlaceOS {% key = arg.name.symbolize == :mod ? "module" : arg.name.stringify %} {{ yield key, arg.name, arg.default_value }} {% end %} + end end +end + +macro __create_from_model__(model) + def create( + {% for name, opts in model.resolve.constant("FIELDS") %} + {% if opts[:mass_assign] == true && !%w(id updated_at created_at).includes?(name.id.stringify) %} + {{name.id}} : {{opts[:klass]}}? = nil, + {% end %} + {% end %} + ) + post base, body: from_args, as: {{model}} + end +end + +macro __update_from_model__(model) + def update( + {% for name, opts in model.resolve.constant("FIELDS") %} + {% if opts[:mass_assign] == true && !%w(updated_at created_at).includes?(name.id.stringify) %} + {{name.id}} : {{opts[:klass]}}? = nil, + {% end %} + {% end %} + ) + put "#{base}/#{id}", body: from_args, as: {{model}} end end + +macro __create_update_from_model__(model) + __create_from_model__({{model}}) + __update_from_model__({{model}}) +end diff --git a/src/placeos/api_wrapper/metadata.cr b/src/placeos/api_wrapper/metadata.cr index 1e0cf38..047de0b 100644 --- a/src/placeos/api_wrapper/metadata.cr +++ b/src/placeos/api_wrapper/metadata.cr @@ -1,4 +1,4 @@ -require "../api/models/metadata" +# require "../api/models/metadata" require "./endpoint" module PlaceOS @@ -9,10 +9,6 @@ module PlaceOS get "#{base}/#{id}", params: from_args, as: Hash(String, API::Models::Metadata) end - def children(id : String, name : String? = nil) - get "#{base}/#{id}/children", params: from_args, as: Array(NamedTuple(zone: API::Models::Zone, metadata: Hash(String, API::Models::Metadata))) - end - def update( id : String, name : String, @@ -28,5 +24,9 @@ module PlaceOS delete "#{base}/#{id}", params: from_args nil end + + def children(id : String, name : String? = nil) + get "#{base}/#{id}/children", params: from_args, as: Array(NamedTuple(zone: API::Models::Zone, metadata: Hash(String, API::Models::Metadata))) + end end end diff --git a/src/placeos/api_wrapper/modules.cr b/src/placeos/api_wrapper/modules.cr index 796038e..8846a68 100644 --- a/src/placeos/api_wrapper/modules.cr +++ b/src/placeos/api_wrapper/modules.cr @@ -1,75 +1,19 @@ -require "../api/models/module" -require "../api/models/ping" - require "./endpoint" module PlaceOS class Client::APIWrapper::Modules < Client::APIWrapper::Endpoint + include Client::APIWrapper::Endpoint::Search(Module) include Client::APIWrapper::Endpoint::Fetch(Module) + # include Client::APIWrapper::Endpoint::Create + # include Client::APIWrapper::Endpoint::Update include Client::APIWrapper::Endpoint::Destroy - - getter base : String = "#{API_ROOT}/modules" - - # Interaction - ########################################################################### - - # Starts a module. - def start(id : String) - post "#{base}/#{id}/start" - nil - end - - # Stops a module. - def stop(id : String) - post "#{base}/#{id}/stop" - nil - end - - # Performs a connectivity check with the associated device or service. - def ping(id : String) - post "#{base}/#{id}/ping", as: API::Models::Ping - end - - # Queries the state exposed by a module. - def state(id : String, lookup : String? = nil) - path = "#{base}/#{id}/state" - path += "/#{lookup}" if lookup - - get path - end - - # Search - ########################################################################### - - # List or search for modules. - # - # Results maybe filtered by specifying a query - *q* - to search across module - # attributes. A small query language is supported within this: - # - # Operator | Action - # -------- | ------ - # `+` | Matches both terms - # `|` | Matches either terms - # `-` | Negates a single token - # `"` | Wraps tokens to form a phrase - # `(` `)` | Provides precedence - # `~N` | Specifies edit distance (fuzziness) after a word - # `~N` | Specifies slop amount (deviation) after a phrase - # - # Up to *limit* systems will be returned, with a paging based on *offset*. - # + include Client::APIWrapper::Endpoint::StartStop + include Client::APIWrapper::Endpoint::Settings # Results my also also be limited to those associated with a specific # *system_id*, that are instances of a *driver_id*, or any combination of # these. - def search( - q : String? = nil, - limit : Int = 20, - offset : Int = 0, - control_system_id : String? = nil, - driver_id : String? = nil - ) - get base, params: from_args, as: Array(API::Models::Module) - end + + getter base : String = "#{API_ROOT}/modules" # Management ########################################################################### @@ -89,7 +33,7 @@ module PlaceOS ignore_connected : Bool? = nil, ignore_startstop : Bool? = nil ) - post base, body: from_args, as: API::Models::Module + post base, body: from_args, as: Module end # Updates module attributes or configuration. @@ -107,7 +51,36 @@ module PlaceOS ignore_connected : Bool? = nil, ignore_startstop : Bool? = nil ) - put "#{base}/#{id}", body: from_args, as: API::Models::Module + put "#{base}/#{id}", body: from_args, as: Module + end + + # Unique Actions + def execute( + id : String, + method : String, + *args : Array(JSON::Any::Type) + ) + post "#{base}/#{id}/exec/#{method}", body: args, as: Module + end + + def load(id : String) + post "#{base}/#{id}/load", as: Bool + end + + # Interaction + ########################################################################### + + # Performs a connectivity check with the associated device or service. + def ping(id : String) + post "#{base}/#{id}/ping", as: Ping + end + + # Queries the state exposed by a module. + def state(id : String, lookup : String? = nil) + path = "#{base}/#{id}/state" + path += "/#{lookup}" if lookup + + get path # spec and type casting requires rest-api specs end end end diff --git a/src/placeos/api_wrapper/oauth_applications.cr b/src/placeos/api_wrapper/oauth_applications.cr index 84f1bd6..6ca8622 100644 --- a/src/placeos/api_wrapper/oauth_applications.cr +++ b/src/placeos/api_wrapper/oauth_applications.cr @@ -2,39 +2,16 @@ require "./endpoint" module PlaceOS class Client::APIWrapper::OAuthApplications < Client::APIWrapper::Endpoint - include Client::APIWrapper::Endpoint::Fetch(OAuthApplication) + include Client::APIWrapper::Endpoint::Search(OAuthAuthentication) + include Client::APIWrapper::Endpoint::Fetch(OAuthAuthentication) + # include Client::APIWrapper::Endpoint::Create + # include Client::APIWrapper::Endpoint::Update include Client::APIWrapper::Endpoint::Destroy getter base : String = "#{API_ROOT}/oauth_apps" - # List or search for applications. - # - # Results maybe filtered by specifying a query - *q* - to search across application - # attributes. A small query language is supported within this: - # - # Operator | Action - # -------- | ------ - # `+` | Matches both terms - # `|` | Matches either terms - # `-` | Negates a single token - # `"` | Wraps tokens to form a phrase - # `(` `)` | Provides precedence - # `~N` | Specifies edit distance (fuzziness) after a word - # `~N` | Specifies slop amount (deviation) after a phrase - # - # Up to *limit* application will be returned, with a paging based on *offset*. - def search( - q : String? = nil, - limit : Int = 20, - offset : Int = 0, - authority : String? = nil - ) - get base, params: from_args, as: Array(OAuthApplication) - end - - def update( - id : String, - name : String? = nil, + def create( + name : String, uid : String? = nil, secret : String? = nil, scopes : String? = nil, @@ -44,11 +21,12 @@ module PlaceOS confidential : Bool? = nil, revoked_at : Time? = nil ) - put "#{base}/#{id}", body: from_args, as: OAuthApplication + post base, body: from_args, as: OAuthAuthentication end - def create( - name : String, + def update( + id : String, + name : String? = nil, uid : String? = nil, secret : String? = nil, scopes : String? = nil, @@ -58,7 +36,7 @@ module PlaceOS confidential : Bool? = nil, revoked_at : Time? = nil ) - post base, body: from_args, as: OAuthApplication + put "#{base}/#{id}", body: from_args, as: OAuthAuthentication end end end diff --git a/src/placeos/api_wrapper/repositories.cr b/src/placeos/api_wrapper/repositories.cr index e4c327c..662f49f 100644 --- a/src/placeos/api_wrapper/repositories.cr +++ b/src/placeos/api_wrapper/repositories.cr @@ -2,9 +2,67 @@ require "./endpoint" module PlaceOS class Client::APIWrapper::Repositories < Client::APIWrapper::Endpoint + include Client::APIWrapper::Endpoint::Search(Repository) include Client::APIWrapper::Endpoint::Fetch(Repository) + # include Client::APIWrapper::Endpoint::Create(Repository) + # include Client::APIWrapper::Endpoint::Update(Repository) include Client::APIWrapper::Endpoint::Destroy getter base : String = "#{API_ROOT}/repositories" + + def create( + name : String, + uri : String, + repo_type : Int32, + username : String? = "", + password : String? = "", + key : String? = "", + folder_name : String? = "", + description : String? = "", + commit_hash : String? = "" + ) + post base, body: from_args, as: Repository + end + + def update( + id : String, + username : String?, + password : String?, + key : String?, + name : String?, + uri : String?, + repo_type : Int32?, + folder_name : String?, + description : String?, + commit_hash : String? + ) + # id not defined, what should I used, or define it somewhere else? + put "#{base}/#{id}", body: from_args, as: Repository + end + + # Unique Actions + def pull(id : String) + post "#{base}/#{id}/pull", as: NamedTuple(commit_hash: String) + end + + def loaded_interfaces + get "#{base}/interfaces", as: NamedTuple(backoffice: String) + end + + def drivers(id : String) + get "#{base}/#{id}/drivers", as: Array(Path) + end + + def commits(id : String, count : Int32? = nil, driver : String? = nil) + get "#{base}/#{id}/commits", params: from_args, as: Array(NamedTuple(commit: String, date: Time, author: String, subject: String)) + end + + def details(id : String, driver : String, commit : String) + get "#{base}/#{id}/details", params: from_args # spec and type casting requires rest-api specs + end + + def branches(id : String) + get "#{base}/#{id}/branches" # spec and type casting requires rest-api specs + end end end diff --git a/src/placeos/api_wrapper/root.cr b/src/placeos/api_wrapper/root.cr index 963e7ed..bbf9bfa 100644 --- a/src/placeos/api_wrapper/root.cr +++ b/src/placeos/api_wrapper/root.cr @@ -15,5 +15,18 @@ module PlaceOS def version get "#{base}/version", as: API::Models::Version end + + # Unique Actions + def root + get "#{base}" + end + + def reindex(backfill : Bool? = true) + get "#{base}/reindex", params: from_args + end + + def backfill + get "#{base}/backfill" + end end end diff --git a/src/placeos/api_wrapper/settings.cr b/src/placeos/api_wrapper/settings.cr index 347a223..80eec3e 100644 --- a/src/placeos/api_wrapper/settings.cr +++ b/src/placeos/api_wrapper/settings.cr @@ -2,9 +2,50 @@ require "./endpoint" module PlaceOS class Client::APIWrapper::Settings < Client::APIWrapper::Endpoint - include Client::APIWrapper::Endpoint::Fetch(API::Models::Settings) + include Client::APIWrapper::Endpoint::Search(PlaceOS::Client::API::Models::Settings) + include Client::APIWrapper::Endpoint::Fetch(PlaceOS::Client::API::Models::Settings) + # include Client::APIWrapper::Endpoint::Create(PlaceOS::Client::API::Models::Settings) + # include Client::APIWrapper::Endpoint::Update(PlaceOS::Client::API::Models::Settings) include Client::APIWrapper::Endpoint::Destroy getter base : String = "#{API_ROOT}/settings" + + # CRUD Actions + # def search( + # parent_id : String?, + # q : String? = nil, + # limit : Int = 20, + # offset : Int = 0 + # ) + # get base, params: from_args, as: Array(API::Models::Settings) + # end + + def create( + parent_id : String, + encryption_level : String, + parent_type : String, + settings_string : String = "{}", + settings_id : String? = nil, + keys : Array(String) = [] of String + ) + post base, body: from_args, as: PlaceOS::Client::API::Models::Settings + end + + def update( + id : String, + parent_id : String, + encryption_level : String?, + parent_type : String?, + settings_string : String?, + settings_id : String?, + keys : Array(String)? + ) + put "#{base}/#{id}", body: from_args, as: PlaceOS::Client::API::Models::Settings + end + + # Unique Actions + def history(id : String, offset : Int32?, limit : Int32?) + get "#{base}/#{id}/history", params: from_args + end end end diff --git a/src/placeos/api_wrapper/system_triggers.cr b/src/placeos/api_wrapper/system_triggers.cr index bab7514..40cd783 100644 --- a/src/placeos/api_wrapper/system_triggers.cr +++ b/src/placeos/api_wrapper/system_triggers.cr @@ -2,7 +2,57 @@ require "./endpoint" module PlaceOS class Client::APIWrapper::SystemTriggers < Client::APIWrapper::Endpoint + include Client::APIWrapper::Endpoint::Search(TriggerInstance) + include Client::APIWrapper::Endpoint::Destroy + # include Client::APIWrapper::Endpoint::Create(TriggerInstance) + include Client::APIWrapper::Endpoint::Update(TriggerInstance) + # SystemTriggers are embedded beneath a systems route getter base : String = "#{API_ROOT}/systems" + + # CRUD Actions + # def search( + # control_system_id : String?, + # trigger_id : String?, + # zone_id : String?, + # q : String? = nil, + # limit : Int = 20, + # offset : Int = 0 + # ) + # get base, params: from_args, as: Array(TriggerInstance) + # end + + def fetch(id : String, complete : Bool?) + get "#{base}/#{id}", params: from_args, as: TriggerInstance + end + + def create( + control_system_id : String, + trigger_id : String, + zone_id : String, + enabled : Bool?, + triggered : Bool?, + important : Bool?, + exec_enabled : Bool?, + webhook_secret : String?, + trigger_count : Int32? + ) + post base, body: from_args, as: TriggerInstance + end + + # def update( + # id : String, + # control_system_id : String?, + # trigger_id : String?, + # zone_id : String?, + # enabled : Bool?, + # triggered : Bool?, + # important : Bool?, + # exec_enabled : Bool?, + # webhook_secret : String?, + # trigger_count : Int32? + # ) + # post "#{base}/#{id}", body: from_args, as: TriggerInstance + # end end end diff --git a/src/placeos/api_wrapper/systems.cr b/src/placeos/api_wrapper/systems.cr index 9d4fd59..f5556e1 100644 --- a/src/placeos/api_wrapper/systems.cr +++ b/src/placeos/api_wrapper/systems.cr @@ -2,25 +2,19 @@ require "./endpoint" module PlaceOS class Client::APIWrapper::Systems < Client::APIWrapper::Endpoint - include Client::APIWrapper::Endpoint::Fetch(System) + # include Client::APIWrapper::Endpoint::Search(ControlSystem) + include Client::APIWrapper::Endpoint::Fetch(ControlSystem) + # include Client::APIWrapper::Endpoint::Create(ControlSystem) + # include Client::APIWrapper::Endpoint::Update(ControlSystem) include Client::APIWrapper::Endpoint::Destroy + include Client::APIWrapper::Endpoint::StartStop + include Client::APIWrapper::Endpoint::Settings + getter base : String = "#{API_ROOT}/systems" # Interaction ########################################################################### - # Start all modules within a system. - def start(id : String) - post "#{base}/#{id}/start" - nil - end - - # Stops all modules within a system. - def stop(id : String) - post "#{base}/#{id}/stop" - nil - end - # Executes a behaviour exposed by a module within the passed system *id*. def execute( id : String, @@ -54,10 +48,6 @@ module PlaceOS get "#{base}/#{id}/types", as: Hash(String, Int32) end - def settings(id : String) - get "#{base}/#{id}/settings", as: Array(Settings) - end - # Management ########################################################################### @@ -77,7 +67,7 @@ module PlaceOS modules : Array(String)? = nil, support_url : String? = nil ) - post base, body: from_args, as: System + post base, body: from_args, as: ControlSystem end # Requests a change to an existing system. @@ -99,7 +89,7 @@ module PlaceOS modules : Array(String)? = nil, support_url : String? = nil ) - put "#{base}/#{id}", params: "version=#{version}", body: from_args, as: System + put "#{base}/#{id}", params: "version=#{version}", body: from_args, as: ControlSystem end # Search @@ -131,7 +121,7 @@ module PlaceOS capacity : Int32? = nil, bookable : Bool? = nil ) - get base, params: from_args, as: Array(System) + get base, params: from_args, as: Array(ControlSystem) end # Returns systems with a specified email address(es) @@ -139,7 +129,24 @@ module PlaceOS def with_emails(list : Array(String) | String) query = list.is_a?(Array) ? list.join(',') : list - get "#{base}/with_emails", params: HTTP::Params{"in" => query}, as: Array(System) + get "#{base}/with_emails", params: HTTP::Params{"in" => query}, as: Array(ControlSystem) + end + + # Unique Actions + def zones(id : String) + get "#{base}/#{id}/zones" + end + + def add_module(id : String, module_id : String) + put "#{base}/#{id}/module/#{module_id}", as: PlaceOS::Client::API::Models::Module + end + + def remove_module(id : String, module_id : String) + delete "#{base}/#{id}/module/#{module_id}", as: PlaceOS::Client::API::Models::Module + end + + def control + ws "#{base}/control" end private getter client diff --git a/src/placeos/api_wrapper/triggers.cr b/src/placeos/api_wrapper/triggers.cr index e1e8c53..8f23981 100644 --- a/src/placeos/api_wrapper/triggers.cr +++ b/src/placeos/api_wrapper/triggers.cr @@ -2,9 +2,58 @@ require "./endpoint" module PlaceOS class Client::APIWrapper::Triggers < Client::APIWrapper::Endpoint + # include Client::APIWrapper::Endpoint::Search(Trigger) include Client::APIWrapper::Endpoint::Fetch(Trigger) + # include Client::APIWrapper::Endpoint::Create(Trigger) + # include Client::APIWrapper::Endpoint::Update(Trigger) include Client::APIWrapper::Endpoint::Destroy getter base : String = "#{API_ROOT}/triggers" + + # CRUD Actions + def search( + authority_id : String?, + q : String? = nil, + limit : Int = 20, + offset : Int = 0 + ) + get base, params: from_args, as: Array(Trigger) + end + + def create( + control_system_id : String, + name : String, + **args + # description : String?, + # actions : String?, + # conditions : String?, + # debounce_period : Int32?, + # important : Bool?, + # enable_webhook : Bool?, + # supported_methods : Array(String)? + ) + post base, body: from_args, as: Trigger + end + + def update( + id : String, + control_system_id : String, + name : String, + **args + # description : String?, + # actions : String?, + # conditions : String?, + # debounce_period : Int32?, + # important : Bool?, + # enable_webhook : Bool?, + # supported_methods : Array(String)? + ) + put "#{base}/#{id}", body: from_args, as: Trigger + end + + # Unique Actions + def instances(id : String) + get "#{base}/#{id}/instance" + end end end diff --git a/src/placeos/api_wrapper/users.cr b/src/placeos/api_wrapper/users.cr index a718c7f..2979454 100644 --- a/src/placeos/api_wrapper/users.cr +++ b/src/placeos/api_wrapper/users.cr @@ -1,15 +1,63 @@ require "./endpoint" module PlaceOS - # TODO: - # - create - # - update class Client::APIWrapper::Users < Client::APIWrapper::Endpoint + include Client::APIWrapper::Endpoint::Search(User) include Client::APIWrapper::Endpoint::Fetch(User) include Client::APIWrapper::Endpoint::Destroy getter base : String = "#{API_ROOT}/users" + def create( + authority_id : String, + name : String, + password : String? = nil, + nickname : String? = nil, + email : String? = nil, + phone : String? = nil, + country : String? = nil, + image : String? = nil, + ui_theme : String? = nil, + misc : String? = nil, + login_name : String? = nil, + staff_id : String? = nil, + first_name : String? = nil, + last_name : String? = nil, + building : String? = nil, + card_number : String? = nil, + groups : Array(String)? = nil, + sys_admin : Bool? = nil, + support : Bool? = nil + ) : User + post base, body: from_args, as: User + end + + def update( + id : String, + authority_id : String, + name : String, + password : String? = nil, + nickname : String? = nil, + email : String? = nil, + phone : String? = nil, + country : String? = nil, + image : String? = nil, + ui_theme : String? = nil, + misc : String? = nil, + first_name : String? = nil, + last_name : String? = nil, + building : String? = nil, + # Admin Attributes + login_name : String? = nil, + staff_id : String? = nil, + card_number : String? = nil, + groups : Array(String)? = nil, + sys_admin : Bool? = nil, + support : Bool? = nil + ) + put "#{base}/#{id}", body: from_args, as: User + end + def current get "#{base}/current", as: User end diff --git a/src/placeos/api_wrapper/webhook.cr b/src/placeos/api_wrapper/webhook.cr index e69de29..6655f83 100644 --- a/src/placeos/api_wrapper/webhook.cr +++ b/src/placeos/api_wrapper/webhook.cr @@ -0,0 +1,6 @@ +require "./endpoint" + +module PlaceOS + class Client::APIWrapper::Webhook + end +end diff --git a/src/placeos/api_wrapper/zones.cr b/src/placeos/api_wrapper/zones.cr index cd81715..fe9ebb5 100644 --- a/src/placeos/api_wrapper/zones.cr +++ b/src/placeos/api_wrapper/zones.cr @@ -1,24 +1,44 @@ -require "../api/models/zone" require "./endpoint" module PlaceOS class Client::APIWrapper::Zones < Client::APIWrapper::Endpoint + # include Client::APIWrapper::Endpoint::Search(Zone) include Client::APIWrapper::Endpoint::Fetch(Zone) + # include Client::APIWrapper::Endpoint::Create(Zone) + # include Client::APIWrapper::Endpoint::Update(Zone) include Client::APIWrapper::Endpoint::Destroy getter base : String = "#{API_ROOT}/zones" - # Interaction + # Search ########################################################################### - def execute( - id : String, - method : String, - module_name : String, - index : Int32 = 1, - args = nil + # List or search for zones. + # + # Results maybe filtered by specifying a query - *q* - to search across zone + # attributes. A small query language is supported within this: + # + # Operator | Action + # -------- | ------ + # `+` | Matches both terms + # `|` | Matches either terms + # `-` | Negates a single token + # `"` | Wraps tokens to form a phrase + # `(` `)` | Provides precedence + # `~N` | Specifies edit distance (fuzziness) after a word + # `~N` | Specifies slop amount (deviation) after a phrase + # + # Up to *limit* zones will be returned, with a paging based on *offset*. + # + # Results my also also be limited to those associated with specific *tags*. + def search( + q : String? = nil, + limit : Int = 20, + offset : Int = 0, + parent : String? = nil, + tags : Array(String) | String? = nil ) - post "#{base}/#{id}/#{module_name}_#{index}/#{method}", body: args + get base, params: from_args, as: Array(Zone) end # Management @@ -32,7 +52,7 @@ module PlaceOS settings : Settings? = nil, triggers : Array(String)? = nil ) - post base, body: from_args, as: API::Models::Zone + post base, body: from_args, as: Zone end # Updates zone attributes or configuration. @@ -44,38 +64,25 @@ module PlaceOS settings : Settings? = nil, triggers : Array(String)? = nil ) - put "#{base}/#{id}", body: from_args, as: API::Models::Zone + put "#{base}/#{id}", body: from_args, as: Zone end - # Search + # Unique Actions + def trigger(id : String) + get "#{base}/#{id}/triggers", as: Trigger + end + + # Interaction ########################################################################### - # List or search for zones. - # - # Results maybe filtered by specifying a query - *q* - to search across zone - # attributes. A small query language is supported within this: - # - # Operator | Action - # -------- | ------ - # `+` | Matches both terms - # `|` | Matches either terms - # `-` | Negates a single token - # `"` | Wraps tokens to form a phrase - # `(` `)` | Provides precedence - # `~N` | Specifies edit distance (fuzziness) after a word - # `~N` | Specifies slop amount (deviation) after a phrase - # - # Up to *limit* zones will be returned, with a paging based on *offset*. - # - # Results my also also be limited to those associated with specific *tags*. - def search( - q : String? = nil, - limit : Int = 20, - offset : Int = 0, - parent : String? = nil, - tags : Array(String) | String? = nil + def execute( + id : String, + method : String, + module_name : String, + index : Int32 = 1, + args = nil ) - get base, params: from_args, as: Array(API::Models::Zone) + post "#{base}/#{id}/#{module_name}_#{index}/#{method}", body: args, as: Zone end private getter client diff --git a/src/placeos/client.cr b/src/placeos/client.cr index 1079086..04c2cdc 100644 --- a/src/placeos/client.cr +++ b/src/placeos/client.cr @@ -117,7 +117,7 @@ module PlaceOS @session end - {% for component in %w(Authority Users Cluster Domains Drivers Modules Settings Systems Zones Ldap OAuth Saml OAuthApplications Root Metadata APIKeys) %} + {% for component in %w(ApiKeys Authority Cluster Domains Drivers Ldap Metadata Modules OAuth OAuthApplications Root Saml Settings Repositories Systems Users Systems Triggers SystemTriggers Users Zones) %} # Provide an object for managing {{component.id}}. See `PlaceOS::Client::APIWrapper::{{component.id}}`. def {{component.id.downcase}} : APIWrapper::{{component.id}} @{{component.id.downcase}} ||= APIWrapper::{{component.id}}.new(api_wrapper)