Merge pull request #489 from RickCarlino/mqtt_monorepo
Converge API and MQTT into monorepopull/491/head
commit
c47e0b5195
|
@ -71,3 +71,6 @@ test/tmp
|
|||
test/version_tmp
|
||||
tmp
|
||||
verify.*.js*
|
||||
rabbitmq/*
|
||||
rabbitmq/
|
||||
mqtt/conf/rabbitmq.config
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
# Notes About This File
|
||||
|
||||
Parts of this document may be out of date or reflect practices that are no longer relevant to the latest version of the Web App.
|
||||
|
||||
Please raise an issue if you hit any issues during deployment.
|
||||
|
||||
# Run on a Local Machine (fast)
|
||||
|
||||
If you want to run a server on a LAN for personal use, this is the easiest and cheapest option.
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
rails: rails s -e development -p 3000 -b 0.0.0.0
|
||||
webpack: ./node_modules/.bin/webpack-dev-server --config config/webpack.config.js
|
||||
worker: rake jobs:work
|
||||
mqtt: rails mqtt:start
|
||||
|
||||
|
||||
# UNCOMMENT THIS LINE IF YOU ARE DOING MOBILE TESTING:
|
||||
# Get started with `npm install weinre -g`
|
||||
|
|
10
README.md
10
README.md
|
@ -8,15 +8,13 @@
|
|||
|
||||
# Q: Do I need this?
|
||||
|
||||
This repository is intended for *software developers* who wish to modify the [Farmbot Web App](http://my.farmbot.io/). **If you are not a developer**, you are highly encouraged to use [the publicly available web app](http://my.farmbot.io/). Running a server is a non-trivial task which will require an intermediate background in Ruby, SQL and Linux system administration.
|
||||
This repository is intended for *software developers* who wish to modify the [Farmbot Web App](http://my.farmbot.io/). **If you are not a developer**, you are highly encouraged to use [the publicly available web app](http://my.farmbot.io/). Running a server is *a non-trivial task with security implications*. It requires an intermediate background in Ruby, SQL and Linux system administration.
|
||||
|
||||
If you are a developer interested in contributing or would like to provision your own server, you are in the right place.
|
||||
|
||||
# Q: What is the Farmbot Web App?
|
||||
|
||||
This repo contains FarmBot's web based user interface, as well as a RESTful JSON API. The API stores data such as user account information, plant data, authorization tokens and a variety of other resources.
|
||||
|
||||
The key responsibility of the API is *information and permissions management*. This should not be confused with device control, which is done via [MQTT](https://github.com/FarmBot/mqtt-gateway).
|
||||
This repo contains FarmBot's web based user interface, a RESTful JSON API and a Dockerized MQTT server. The API stores data such as user account information, plant data, authorization tokens and a variety of other resources. The MQTT server facilitates realtime messaging from the browser to the device.
|
||||
|
||||
# Q: Can I see some example API requests?
|
||||
|
||||
|
@ -29,6 +27,7 @@ For a list of example API requests and responses, see our [reference documentati
|
|||
You will need the following:
|
||||
|
||||
1. A Linux or Mac based machine. We do not support windows at this time.
|
||||
0. [Docker 17.06.0-ce or greater](https://docs.docker.com/engine/installation/)
|
||||
0. [Ruby 2.4.1](http://rvm.io/rvm/install)
|
||||
0. [ImageMagick](https://www.imagemagick.org/script/index.php) (`brew install imagemagick` (Mac) or `sudo apt-get install imagemagick` (Ubuntu))
|
||||
0. [Node JS > v6](https://nodejs.org/en/download/)
|
||||
|
@ -46,9 +45,8 @@ You will need the following:
|
|||
0. Give permission to create a database*
|
||||
0. `rake db:create:all db:migrate db:seed`
|
||||
0. (optional) Verify installation with `RAILS_ENV=test rake db:create db:migrate && rspec spec` (API) and `npm run test` (Frontend).
|
||||
0. Start server with `npm run dev`. Make sure you set an `MQTT_HOST` entry in `application.yml` pointing to the IP address or domain of the (soon-to-be-installed) MQTT server. You will need to set that up next.
|
||||
0. Start server with `npm run dev`. Make sure you set an `MQTT_HOST` entry in `application.yml` pointing to the IP address or domain of MQTT server. If you are not running the MQTT server on a separate machine, `MQTT_HOST` and `API_HOST` will point to the same server. **Important note:** You may be required to enter a sudo because [docker requires root access](https://docs.docker.com/engine/security/security/#docker-daemon-attack-surface).
|
||||
0. Open [localhost:3000](http://localhost:3000).
|
||||
0. Although you can now try things out in your browser, you will still need to [provision an MQTT server](https://github.com/FarmBot/mqtt-gateway) before you can control a FarmBot.
|
||||
0. [Raise an issue](https://github.com/FarmBot/Farmbot-Web-App/issues/new?title=Installation%20Failure) if you hit problems with any of these steps. *We can't fix issues we don't know about.*
|
||||
|
||||
\*Give permission to `user` to create database:
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
# Generates a JSON Web Token (JWT) for a given user. Typically placed in the
|
||||
# `Authorization` header, or used a password to gain access to the MQTT server.
|
||||
class SessionToken < AbstractJwtToken
|
||||
MUST_VERIFY = "Verify account first"
|
||||
DEFAULT_OS = "https://api.github.com/repos/" \
|
||||
"farmbot/farmbot_os/releases/latest"
|
||||
DEFAULT_FW = "https://api.github.com/repos/FarmBot/farmbot-arduino-firmware/"\
|
||||
"releases/latest"
|
||||
MUST_VERIFY = "Verify account first"
|
||||
DEFAULT_OS = "https://api.github.com/repos/" \
|
||||
"farmbot/farmbot_os/releases/latest"
|
||||
DEFAULT_FW = "https://api.github.com/repos/FarmBot/farmbot-"\
|
||||
"arduino-firmware/releases/latest"
|
||||
OS_RELEASE = ENV.fetch("OS_UPDATE_SERVER") { DEFAULT_OS }
|
||||
FW_RELEASE = ENV.fetch("FW_UPDATE_SERVER") { DEFAULT_FW }
|
||||
MQTT = ENV.fetch("MQTT_HOST")
|
||||
# If you are not using the standard MQTT broker (eg: you use a 3rd party
|
||||
# MQTT vendor), you will need to change this line.
|
||||
|
@ -25,8 +24,8 @@ class SessionToken < AbstractJwtToken
|
|||
aud: AbstractJwtToken::UNKNOWN_AUD)
|
||||
|
||||
unless user.verified?
|
||||
raise Errors::Forbidden, MUST_VERIFY
|
||||
Rollbar.info("Verification Error", email: user.email)
|
||||
raise Errors::Forbidden, MUST_VERIFY
|
||||
end
|
||||
|
||||
self.new([{ aud: aud,
|
||||
|
|
|
@ -5,7 +5,6 @@ unless Rails.env == "production"
|
|||
DATE_RANGE_HI = 3..8
|
||||
ENV['MQTT_HOST'] = "blooper.io"
|
||||
ENV['OS_UPDATE_SERVER'] = "http://blah.com"
|
||||
ENV['FW_UPDATE_SERVER'] = "http://test.com"
|
||||
Point.destroy_all
|
||||
Device.destroy_all
|
||||
User.destroy_all
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
namespace :mqtt do
|
||||
desc "Bootstraps the MQTT config file"
|
||||
task start: :environment do
|
||||
require_relative '../../mqtt/server.rb'
|
||||
end
|
||||
end
|
|
@ -0,0 +1,12 @@
|
|||
FROM rabbitmq:3.6.11-management
|
||||
|
||||
COPY jwt_plugin/plugins/rabbit_auth_backend_jwt* /plugins
|
||||
COPY jwt_plugin/plugins/jwt* /plugins
|
||||
COPY jwt_plugin/plugins/jsx* /plugins
|
||||
COPY jwt_plugin/plugins/base64url* /plugins
|
||||
|
||||
RUN rabbitmq-plugins enable --offline rabbitmq_management rabbitmq_web_mqtt
|
||||
|
||||
EXPOSE 4369 5671 5672 25672 15671 15672 15675
|
||||
|
||||
CMD ["rabbitmq-server"]
|
|
@ -0,0 +1,5 @@
|
|||
[
|
||||
rabbitmq_management,
|
||||
rabbitmq_web_mqtt,
|
||||
rabbit_auth_backend_jwt
|
||||
].
|
|
@ -0,0 +1,14 @@
|
|||
.sw?
|
||||
.*.sw?
|
||||
*.beam
|
||||
/.erlang.mk/
|
||||
/cover/
|
||||
/deps/
|
||||
/doc/
|
||||
/ebin/
|
||||
/logs/
|
||||
/plugins/
|
||||
|
||||
test/config_schema_SUITE_data/schema/
|
||||
|
||||
rabbit_auth_backend_jwt.d
|
|
@ -0,0 +1,2 @@
|
|||
erlang 19.3
|
||||
elixir 1.5.0
|
|
@ -0,0 +1,28 @@
|
|||
PROJECT = rabbit_auth_backend_jwt
|
||||
PROJECT_DESCRIPTION = RabbitMQ JSON Web token authorization
|
||||
PROJECT_MOD = rabbit_auth_backend_jwt_app
|
||||
|
||||
define PROJECT_ENV
|
||||
[
|
||||
|
||||
]
|
||||
endef
|
||||
|
||||
define PROJECT_APP_EXTRA_KEYS
|
||||
{broker_version_requirements, []}
|
||||
endef
|
||||
|
||||
LOCAL_DEPS = inets
|
||||
DEPS = rabbit_common rabbit amqp_client jwt
|
||||
|
||||
DEP_EARLY_PLUGINS = rabbit_common/mk/rabbitmq-early-plugin.mk
|
||||
DEP_PLUGINS = rabbit_common/mk/rabbitmq-plugin.mk
|
||||
|
||||
# FIXME: Use erlang.mk patched for RabbitMQ, while waiting for PRs to be
|
||||
# reviewed and merged.
|
||||
|
||||
ERLANG_MK_REPO = https://github.com/rabbitmq/erlang.mk.git
|
||||
ERLANG_MK_COMMIT = rabbitmq-tmp
|
||||
|
||||
include rabbitmq-components.mk
|
||||
include erlang.mk
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,330 @@
|
|||
ifeq ($(.DEFAULT_GOAL),)
|
||||
# Define default goal to `all` because this file defines some targets
|
||||
# before the inclusion of erlang.mk leading to the wrong target becoming
|
||||
# the default.
|
||||
.DEFAULT_GOAL = all
|
||||
endif
|
||||
|
||||
# PROJECT_VERSION defaults to:
|
||||
# 1. the version exported by rabbitmq-server-release;
|
||||
# 2. the version stored in `git-revisions.txt`, if it exists;
|
||||
# 3. a version based on git-describe(1), if it is a Git clone;
|
||||
# 4. 0.0.0
|
||||
|
||||
PROJECT_VERSION := 0.0.1
|
||||
|
||||
# ifeq ($(PROJECT_VERSION),)
|
||||
# PROJECT_VERSION := $(shell \
|
||||
# if test -f git-revisions.txt; then \
|
||||
# head -n1 git-revisions.txt | \
|
||||
# awk '{print $$$(words $(PROJECT_DESCRIPTION) version);}'; \
|
||||
# else \
|
||||
# (git describe --dirty --abbrev=7 --tags --always --first-parent \
|
||||
# 2>/dev/null || echo rabbitmq_v0_0_0) | \
|
||||
# sed -e 's/^rabbitmq_v//' -e 's/^v//' -e 's/_/./g' -e 's/-/+/' \
|
||||
# -e 's/-/./g'; \
|
||||
# fi)
|
||||
# endif
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# RabbitMQ components.
|
||||
# --------------------------------------------------------------------
|
||||
|
||||
# For RabbitMQ repositories, we want to checkout branches which match
|
||||
# the parent project. For instance, if the parent project is on a
|
||||
# release tag, dependencies must be on the same release tag. If the
|
||||
# parent project is on a topic branch, dependencies must be on the same
|
||||
# topic branch or fallback to `stable` or `master` whichever was the
|
||||
# base of the topic branch.
|
||||
|
||||
dep_amqp_client = git_rmq rabbitmq-erlang-client $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbit = git_rmq rabbitmq-server $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbit_common = git_rmq rabbitmq-common $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_amqp1_0 = git_rmq rabbitmq-amqp1.0 $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_auth_backend_amqp = git_rmq rabbitmq-auth-backend-amqp $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_auth_backend_cache = git_rmq rabbitmq-auth-backend-cache $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_auth_backend_http = git_rmq rabbitmq-auth-backend-http $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_auth_backend_ldap = git_rmq rabbitmq-auth-backend-ldap $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_auth_mechanism_ssl = git_rmq rabbitmq-auth-mechanism-ssl $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_aws = git_rmq rabbitmq-aws $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_boot_steps_visualiser = git_rmq rabbitmq-boot-steps-visualiser $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_clusterer = git_rmq rabbitmq-clusterer $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_cli = git_rmq rabbitmq-cli $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_codegen = git_rmq rabbitmq-codegen $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_consistent_hash_exchange = git_rmq rabbitmq-consistent-hash-exchange $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_ct_client_helpers = git_rmq rabbitmq-ct-client-helpers $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_ct_helpers = git_rmq rabbitmq-ct-helpers $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_delayed_message_exchange = git_rmq rabbitmq-delayed-message-exchange $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_dotnet_client = git_rmq rabbitmq-dotnet-client $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_event_exchange = git_rmq rabbitmq-event-exchange $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_federation = git_rmq rabbitmq-federation $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_federation_management = git_rmq rabbitmq-federation-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_java_client = git_rmq rabbitmq-java-client $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_jms_client = git_rmq rabbitmq-jms-client $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_jms_cts = git_rmq rabbitmq-jms-cts $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_jms_topic_exchange = git_rmq rabbitmq-jms-topic-exchange $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_lvc = git_rmq rabbitmq-lvc-plugin $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_management = git_rmq rabbitmq-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_management_agent = git_rmq rabbitmq-management-agent $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_management_exchange = git_rmq rabbitmq-management-exchange $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_management_themes = git_rmq rabbitmq-management-themes $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_management_visualiser = git_rmq rabbitmq-management-visualiser $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_message_timestamp = git_rmq rabbitmq-message-timestamp $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_metronome = git_rmq rabbitmq-metronome $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_mqtt = git_rmq rabbitmq-mqtt $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_objc_client = git_rmq rabbitmq-objc-client $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_peer_discovery_aws = git_rmq rabbitmq-peer-discovery-aws $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_peer_discovery_common = git_rmq rabbitmq-peer-discovery-common $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_peer_discovery_consul = git_rmq rabbitmq-peer-discovery-consul $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_peer_discovery_etcd = git_rmq rabbitmq-peer-discovery-etcd $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_peer_discovery_k8s = git_rmq rabbitmq-peer-discovery-k8s $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_recent_history_exchange = git_rmq rabbitmq-recent-history-exchange $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_routing_node_stamp = git_rmq rabbitmq-routing-node-stamp $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_rtopic_exchange = git_rmq rabbitmq-rtopic-exchange $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_server_release = git_rmq rabbitmq-server-release $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_sharding = git_rmq rabbitmq-sharding $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_shovel = git_rmq rabbitmq-shovel $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_shovel_management = git_rmq rabbitmq-shovel-management $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_stomp = git_rmq rabbitmq-stomp $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_toke = git_rmq rabbitmq-toke $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_top = git_rmq rabbitmq-top $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_tracing = git_rmq rabbitmq-tracing $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_trust_store = git_rmq rabbitmq-trust-store $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_test = git_rmq rabbitmq-test $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_web_dispatch = git_rmq rabbitmq-web-dispatch $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_web_stomp = git_rmq rabbitmq-web-stomp $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_web_stomp_examples = git_rmq rabbitmq-web-stomp-examples $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_web_mqtt = git_rmq rabbitmq-web-mqtt $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_web_mqtt_examples = git_rmq rabbitmq-web-mqtt-examples $(current_rmq_ref) $(base_rmq_ref) master
|
||||
dep_rabbitmq_website = git_rmq rabbitmq-website $(current_rmq_ref) $(base_rmq_ref) live master
|
||||
dep_toke = git_rmq toke $(current_rmq_ref) $(base_rmq_ref) master
|
||||
|
||||
dep_rabbitmq_public_umbrella = git_rmq rabbitmq-public-umbrella $(current_rmq_ref) $(base_rmq_ref) master
|
||||
|
||||
# Third-party dependencies version pinning.
|
||||
#
|
||||
# We do that in this file, which is copied in all projects, to ensure
|
||||
# all projects use the same versions. It avoids conflicts and makes it
|
||||
# possible to work with rabbitmq-public-umbrella.
|
||||
|
||||
dep_cowboy_commit = 1.1.2
|
||||
dep_mochiweb = git git://github.com/basho/mochiweb.git v2.9.0p2
|
||||
dep_ranch_commit = 1.3.2
|
||||
dep_sockjs = git https://github.com/rabbitmq/sockjs-erlang.git 405990ea62353d98d36dbf5e1e64942d9b0a1daf
|
||||
dep_webmachine_commit = 1.10.8p2
|
||||
dep_ranch_proxy_protocol = git git://github.com/heroku/ranch_proxy_protocol.git 1.4.2
|
||||
|
||||
RABBITMQ_COMPONENTS = amqp_client \
|
||||
rabbit \
|
||||
rabbit_common \
|
||||
rabbitmq_amqp1_0 \
|
||||
rabbitmq_auth_backend_amqp \
|
||||
rabbitmq_auth_backend_cache \
|
||||
rabbitmq_auth_backend_http \
|
||||
rabbitmq_auth_backend_ldap \
|
||||
rabbitmq_auth_mechanism_ssl \
|
||||
rabbitmq_aws \
|
||||
rabbitmq_boot_steps_visualiser \
|
||||
rabbitmq_clusterer \
|
||||
rabbitmq_cli \
|
||||
rabbitmq_codegen \
|
||||
rabbitmq_consistent_hash_exchange \
|
||||
rabbitmq_ct_client_helpers \
|
||||
rabbitmq_ct_helpers \
|
||||
rabbitmq_delayed_message_exchange \
|
||||
rabbitmq_dotnet_client \
|
||||
rabbitmq_event_exchange \
|
||||
rabbitmq_federation \
|
||||
rabbitmq_federation_management \
|
||||
rabbitmq_java_client \
|
||||
rabbitmq_jms_client \
|
||||
rabbitmq_jms_cts \
|
||||
rabbitmq_jms_topic_exchange \
|
||||
rabbitmq_lvc \
|
||||
rabbitmq_management \
|
||||
rabbitmq_management_agent \
|
||||
rabbitmq_management_exchange \
|
||||
rabbitmq_management_themes \
|
||||
rabbitmq_management_visualiser \
|
||||
rabbitmq_message_timestamp \
|
||||
rabbitmq_metronome \
|
||||
rabbitmq_mqtt \
|
||||
rabbitmq_objc_client \
|
||||
rabbitmq_peer_discovery_aws \
|
||||
rabbitmq_peer_discovery_common \
|
||||
rabbitmq_peer_discovery_consul \
|
||||
rabbitmq_peer_discovery_etcd \
|
||||
rabbitmq_peer_discovery_k8s \
|
||||
rabbitmq_recent_history_exchange \
|
||||
rabbitmq_routing_node_stamp \
|
||||
rabbitmq_rtopic_exchange \
|
||||
rabbitmq_server_release \
|
||||
rabbitmq_sharding \
|
||||
rabbitmq_shovel \
|
||||
rabbitmq_shovel_management \
|
||||
rabbitmq_stomp \
|
||||
rabbitmq_toke \
|
||||
rabbitmq_top \
|
||||
rabbitmq_tracing \
|
||||
rabbitmq_trust_store \
|
||||
rabbitmq_web_dispatch \
|
||||
rabbitmq_web_mqtt \
|
||||
rabbitmq_web_mqtt_examples \
|
||||
rabbitmq_web_stomp \
|
||||
rabbitmq_web_stomp_examples \
|
||||
rabbitmq_website
|
||||
|
||||
# Several components have a custom erlang.mk/build.config, mainly
|
||||
# to disable eunit. Therefore, we can't use the top-level project's
|
||||
# erlang.mk copy.
|
||||
NO_AUTOPATCH += $(RABBITMQ_COMPONENTS)
|
||||
|
||||
ifeq ($(origin current_rmq_ref),undefined)
|
||||
ifneq ($(wildcard .git),)
|
||||
current_rmq_ref := $(shell (\
|
||||
ref=$$(git branch --list | awk '/^\* \(.*detached / {ref=$$0; sub(/.*detached [^ ]+ /, "", ref); sub(/\)$$/, "", ref); print ref; exit;} /^\* / {ref=$$0; sub(/^\* /, "", ref); print ref; exit}');\
|
||||
if test "$$(git rev-parse --short HEAD)" != "$$ref"; then echo "$$ref"; fi))
|
||||
else
|
||||
current_rmq_ref := master
|
||||
endif
|
||||
endif
|
||||
export current_rmq_ref
|
||||
|
||||
ifeq ($(origin base_rmq_ref),undefined)
|
||||
ifneq ($(wildcard .git),)
|
||||
base_rmq_ref := $(shell \
|
||||
(git rev-parse --verify -q stable >/dev/null && \
|
||||
git merge-base --is-ancestor $$(git merge-base master HEAD) stable && \
|
||||
echo stable) || \
|
||||
echo master)
|
||||
else
|
||||
base_rmq_ref := master
|
||||
endif
|
||||
endif
|
||||
export base_rmq_ref
|
||||
|
||||
# Repository URL selection.
|
||||
#
|
||||
# First, we infer other components' location from the current project
|
||||
# repository URL, if it's a Git repository:
|
||||
# - We take the "origin" remote URL as the base
|
||||
# - The current project name and repository name is replaced by the
|
||||
# target's properties:
|
||||
# eg. rabbitmq-common is replaced by rabbitmq-codegen
|
||||
# eg. rabbit_common is replaced by rabbitmq_codegen
|
||||
#
|
||||
# If cloning from this computed location fails, we fallback to RabbitMQ
|
||||
# upstream which is GitHub.
|
||||
|
||||
# Maccro to transform eg. "rabbit_common" to "rabbitmq-common".
|
||||
rmq_cmp_repo_name = $(word 2,$(dep_$(1)))
|
||||
|
||||
# Upstream URL for the current project.
|
||||
RABBITMQ_COMPONENT_REPO_NAME := $(call rmq_cmp_repo_name,$(PROJECT))
|
||||
RABBITMQ_UPSTREAM_FETCH_URL ?= https://github.com/rabbitmq/$(RABBITMQ_COMPONENT_REPO_NAME).git
|
||||
RABBITMQ_UPSTREAM_PUSH_URL ?= git@github.com:rabbitmq/$(RABBITMQ_COMPONENT_REPO_NAME).git
|
||||
|
||||
# Current URL for the current project. If this is not a Git clone,
|
||||
# default to the upstream Git repository.
|
||||
ifneq ($(wildcard .git),)
|
||||
git_origin_fetch_url := $(shell git config remote.origin.url)
|
||||
git_origin_push_url := $(shell git config remote.origin.pushurl || git config remote.origin.url)
|
||||
RABBITMQ_CURRENT_FETCH_URL ?= $(git_origin_fetch_url)
|
||||
RABBITMQ_CURRENT_PUSH_URL ?= $(git_origin_push_url)
|
||||
else
|
||||
RABBITMQ_CURRENT_FETCH_URL ?= $(RABBITMQ_UPSTREAM_FETCH_URL)
|
||||
RABBITMQ_CURRENT_PUSH_URL ?= $(RABBITMQ_UPSTREAM_PUSH_URL)
|
||||
endif
|
||||
|
||||
# Macro to replace the following pattern:
|
||||
# 1. /foo.git -> /bar.git
|
||||
# 2. /foo -> /bar
|
||||
# 3. /foo/ -> /bar/
|
||||
subst_repo_name = $(patsubst %/$(1)/%,%/$(2)/%,$(patsubst %/$(1),%/$(2),$(patsubst %/$(1).git,%/$(2).git,$(3))))
|
||||
|
||||
# Macro to replace both the project's name (eg. "rabbit_common") and
|
||||
# repository name (eg. "rabbitmq-common") by the target's equivalent.
|
||||
#
|
||||
# This macro is kept on one line because we don't want whitespaces in
|
||||
# the returned value, as it's used in $(dep_fetch_git_rmq) in a shell
|
||||
# single-quoted string.
|
||||
dep_rmq_repo = $(if $(dep_$(2)),$(call subst_repo_name,$(PROJECT),$(2),$(call subst_repo_name,$(RABBITMQ_COMPONENT_REPO_NAME),$(call rmq_cmp_repo_name,$(2)),$(1))),$(pkg_$(1)_repo))
|
||||
|
||||
dep_rmq_commits = $(if $(dep_$(1)), \
|
||||
$(wordlist 3,$(words $(dep_$(1))),$(dep_$(1))), \
|
||||
$(pkg_$(1)_commit))
|
||||
|
||||
define dep_fetch_git_rmq
|
||||
fetch_url1='$(call dep_rmq_repo,$(RABBITMQ_CURRENT_FETCH_URL),$(1))'; \
|
||||
fetch_url2='$(call dep_rmq_repo,$(RABBITMQ_UPSTREAM_FETCH_URL),$(1))'; \
|
||||
if test "$$$$fetch_url1" != '$(RABBITMQ_CURRENT_FETCH_URL)' && \
|
||||
git clone -q -n -- "$$$$fetch_url1" $(DEPS_DIR)/$(call dep_name,$(1)); then \
|
||||
fetch_url="$$$$fetch_url1"; \
|
||||
push_url='$(call dep_rmq_repo,$(RABBITMQ_CURRENT_PUSH_URL),$(1))'; \
|
||||
elif git clone -q -n -- "$$$$fetch_url2" $(DEPS_DIR)/$(call dep_name,$(1)); then \
|
||||
fetch_url="$$$$fetch_url2"; \
|
||||
push_url='$(call dep_rmq_repo,$(RABBITMQ_UPSTREAM_PUSH_URL),$(1))'; \
|
||||
fi; \
|
||||
cd $(DEPS_DIR)/$(call dep_name,$(1)) && ( \
|
||||
$(foreach ref,$(call dep_rmq_commits,$(1)), \
|
||||
git checkout -q $(ref) >/dev/null 2>&1 || \
|
||||
) \
|
||||
(echo "error: no valid pathspec among: $(call dep_rmq_commits,$(1))" \
|
||||
1>&2 && false) ) && \
|
||||
(test "$$$$fetch_url" = "$$$$push_url" || \
|
||||
git remote set-url --push origin "$$$$push_url")
|
||||
endef
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# Component distribution.
|
||||
# --------------------------------------------------------------------
|
||||
|
||||
list-dist-deps::
|
||||
@:
|
||||
|
||||
prepare-dist::
|
||||
@:
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# rabbitmq-components.mk checks.
|
||||
# --------------------------------------------------------------------
|
||||
|
||||
# If this project is under the Umbrella project, we override $(DEPS_DIR)
|
||||
# to point to the Umbrella's one. We also disable `make distclean` so
|
||||
# $(DEPS_DIR) is not accidentally removed.
|
||||
|
||||
ifneq ($(wildcard ../../UMBRELLA.md),)
|
||||
UNDER_UMBRELLA = 1
|
||||
else ifneq ($(wildcard UMBRELLA.md),)
|
||||
UNDER_UMBRELLA = 1
|
||||
endif
|
||||
|
||||
ifeq ($(UNDER_UMBRELLA),1)
|
||||
ifneq ($(PROJECT),rabbitmq_public_umbrella)
|
||||
DEPS_DIR ?= $(abspath ..)
|
||||
endif
|
||||
|
||||
ifneq ($(filter distclean distclean-deps,$(MAKECMDGOALS)),)
|
||||
SKIP_DEPS = 1
|
||||
endif
|
||||
endif
|
||||
|
||||
UPSTREAM_RMQ_COMPONENTS_MK = $(DEPS_DIR)/rabbit_common/mk/rabbitmq-components.mk
|
||||
|
||||
check-rabbitmq-components.mk:
|
||||
$(verbose) cmp -s rabbitmq-components.mk \
|
||||
$(UPSTREAM_RMQ_COMPONENTS_MK) || \
|
||||
(echo "error: rabbitmq-components.mk must be updated!" 1>&2; \
|
||||
false)
|
||||
|
||||
ifeq ($(PROJECT),rabbit_common)
|
||||
rabbitmq-components-mk:
|
||||
@:
|
||||
else
|
||||
rabbitmq-components-mk:
|
||||
$(gen_verbose) cp -a $(UPSTREAM_RMQ_COMPONENTS_MK) .
|
||||
ifeq ($(DO_COMMIT),yes)
|
||||
$(verbose) git diff --quiet rabbitmq-components.mk \
|
||||
|| git commit -m 'Update rabbitmq-components.mk' rabbitmq-components.mk
|
||||
endif
|
||||
endif
|
|
@ -0,0 +1,90 @@
|
|||
%% The contents of this file are subject to the Mozilla Public License
|
||||
%% Version 1.1 (the "License"); you may not use this file except in
|
||||
%% compliance with the License. You may obtain a copy of the License
|
||||
%% at http://www.mozilla.org/MPL/
|
||||
%%
|
||||
%% Software distributed under the License is distributed on an "AS IS"
|
||||
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
|
||||
%% the License for the specific language governing rights and
|
||||
%% limitations under the License.
|
||||
%%
|
||||
%% The Original Code is RabbitMQ HTTP authentication.
|
||||
%%
|
||||
%% The Initial Developer of the Original Code is VMware, Inc.
|
||||
%% Copyright (c) 2007-2017 Pivotal Software, Inc. All rights reserved.
|
||||
%%
|
||||
|
||||
-module(rabbit_auth_backend_jwt).
|
||||
|
||||
-include_lib("rabbit_common/include/rabbit.hrl").
|
||||
|
||||
-behaviour(rabbit_authn_backend).
|
||||
-behaviour(rabbit_authz_backend).
|
||||
|
||||
-export([description/0]).
|
||||
|
||||
-export([user_login_authentication/2, user_login_authorization/1,
|
||||
check_vhost_access/3, check_resource_access/3, check_topic_access/4]).
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
description() ->
|
||||
[{name, <<"JWT">>},
|
||||
{description, <<"JWT authentication / authorisation">>}].
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
%% Decide if the user gave us a valid JWT.
|
||||
user_login_authentication(Username, AuthProps) ->
|
||||
% Step 1: Validate that the JWT is is real.
|
||||
% io:fwrite("authn: ~s ~w\n\n", [Username, AuthProps]),
|
||||
{password, Jwt} = lists:keyfind(password, 1, AuthProps),
|
||||
|
||||
case rabbit_auth_backend_jwt_decoder:decode(Jwt) of
|
||||
{ok, _Bot} -> {ok, #auth_user{username = Username, tags = [], impl = none}};
|
||||
{error, Reason} -> {refused, Reason, []}
|
||||
end.
|
||||
|
||||
user_login_authorization(Username) ->
|
||||
% io:fwrite("authz: ~s\n\n", [Username]),
|
||||
case user_login_authentication(Username, []) of
|
||||
{ok, #auth_user{impl = Impl}} -> {ok, Impl};
|
||||
Else -> Else
|
||||
end.
|
||||
|
||||
check_vhost_access(_AuthUser, Vhost, _) ->
|
||||
% Is this a performance issue? Can it be cached? - RC
|
||||
{ok, ExpectedVhost} = application:get_env(rabbit_auth_backend_jwt, farmbot_vhost),
|
||||
io:fwrite("INCOMING MQTT", []),
|
||||
case Vhost of
|
||||
ExpectedVhost -> true;
|
||||
_ -> false
|
||||
end.
|
||||
|
||||
check_resource_access(AuthUser, Resource, Permission) ->
|
||||
% {auth_user,<<100,101,118,105,99,101,95,50>>,[],none}
|
||||
% {resource,<<47>>,exchange,<<97,109,113,46,116,111,112,105,99>>} write
|
||||
{auth_user, User, _Something, _Somethingelse} = AuthUser,
|
||||
{resource, Vhost, Resource2, Arg} = Resource,
|
||||
io:fwrite("resource access: user: ~s vhost: ~s resource: ~s arg: ~s\n\n", [User, Vhost, Resource2, Arg]),
|
||||
case check_vhost_access(AuthUser, Vhost, Permission) of
|
||||
true ->
|
||||
case Resource2 of
|
||||
topic -> check_topic(User, Arg);
|
||||
_ -> true
|
||||
end;
|
||||
false -> false
|
||||
end.
|
||||
|
||||
check_topic(User, Topic) ->
|
||||
% Check if topic matches bot/#{topic}/
|
||||
ExpectedThing = lists:flatten(io_lib:format('bot/~s/', [User])),
|
||||
io:fwrite("Checking expected: ~s vs: topic: ~s\r\n", [ExpectedThing, Topic]),
|
||||
lists:prefix(ExpectedThing, Topic).
|
||||
|
||||
|
||||
check_topic_access(AuthUser, Resource, Permission, Context) ->
|
||||
io:fwrite("topic access: ~w ~w ~w ~w\n\n", [AuthUser, Resource, Permission, Context]),
|
||||
true.
|
||||
|
||||
%%--------------------------------------------------------------------
|
|
@ -0,0 +1,40 @@
|
|||
%% The contents of this file are subject to the Mozilla Public License
|
||||
%% Version 1.1 (the "License"); you may not use this file except in
|
||||
%% compliance with the License. You may obtain a copy of the License
|
||||
%% at http://www.mozilla.org/MPL/
|
||||
%%
|
||||
%% Software distributed under the License is distributed on an "AS IS"
|
||||
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
|
||||
%% the License for the specific language governing rights and
|
||||
%% limitations under the License.
|
||||
%%
|
||||
%% The Original Code is RabbitMQ HTTP authentication.
|
||||
%%
|
||||
%% The Initial Developer of the Original Code is VMware, Inc.
|
||||
%% Copyright (c) 2007-2017 Pivotal Software, Inc. All rights reserved.
|
||||
%%
|
||||
|
||||
-module(rabbit_auth_backend_jwt_app).
|
||||
|
||||
-behaviour(application).
|
||||
-export([start/2, stop/1]).
|
||||
|
||||
-behaviour(supervisor).
|
||||
-export([init/1]).
|
||||
|
||||
start(_Type, _StartArgs) ->
|
||||
io:fwrite("Starting JWT Auth app.\n"),
|
||||
%% Deleteme
|
||||
supervisor:start_link({local,?MODULE},?MODULE,[]).
|
||||
|
||||
stop(_State) -> ok.
|
||||
|
||||
%%----------------------------------------------------------------------------
|
||||
|
||||
init([]) ->
|
||||
Mod = rabbit_auth_backend_jwt_pub_key_fetcher,
|
||||
Id = Mod,
|
||||
Mfa = {Mod, start_link, []},
|
||||
Modules = [Mod],
|
||||
Child = {Id, Mfa, permanent, brutal_kill, worker, Modules},
|
||||
{ok, {{one_for_one,3,10}, [Child]}}.
|
|
@ -0,0 +1,33 @@
|
|||
-module(rabbit_auth_backend_jwt_decoder).
|
||||
|
||||
-export([decode/1]).
|
||||
-export([find_alg/1]).
|
||||
|
||||
decode(JwtBin) ->
|
||||
%% check alg header
|
||||
case binary:split(JwtBin, <<".">>, [global]) of
|
||||
%% Expected
|
||||
[HeaderBin, _BodyBin, _Sig] ->
|
||||
HeadList = jsx:decode(base64:decode(HeaderBin)),
|
||||
case find_alg(HeadList) of
|
||||
%% Correct alg
|
||||
{ok, <<"RS256">>} ->
|
||||
{ok, RSAKey} = rabbit_auth_backend_jwt_pub_key_fetcher:fetch(),
|
||||
case jwt:decode(JwtBin, RSAKey) of
|
||||
{ok, Claims} -> {ok, maps:get(<<"bot">>, Claims)};
|
||||
Err -> Err
|
||||
end;
|
||||
{ok, _wrong_alg} -> {error, "bad alg"};
|
||||
Err -> Err
|
||||
end;
|
||||
_ -> {error, "bad jwt"}
|
||||
end.
|
||||
|
||||
find_alg([{<<"alg">>, Alg} | _T]) ->
|
||||
{ok, Alg};
|
||||
|
||||
find_alg([_ | T]) ->
|
||||
find_alg(T);
|
||||
|
||||
find_alg([]) ->
|
||||
{error, "No alg."}.
|
|
@ -0,0 +1,42 @@
|
|||
%%% Fetch an encryption key from the FarmBot server.
|
||||
|
||||
-module(rabbit_auth_backend_jwt_pub_key_fetcher).
|
||||
-behaviour(gen_server).
|
||||
|
||||
%% GenServer
|
||||
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).
|
||||
|
||||
%% API
|
||||
-export([start_link/0, fetch/0]).
|
||||
|
||||
%% Fetch and store the key.
|
||||
start_link() ->
|
||||
gen_server:start_link({global, ?MODULE}, ?MODULE, [], [{name, ?MODULE}]).
|
||||
|
||||
%% Fetch the key from memory.
|
||||
fetch() ->
|
||||
gen_server:call({global, ?MODULE}, fetch).
|
||||
|
||||
init([]) ->
|
||||
% HTTP get
|
||||
{ok, Url} = application:get_env(rabbit_auth_backend_jwt, farmbot_api_key_url),
|
||||
io:fwrite("Trying to fetch public key from: ~s\n", [Url]),
|
||||
|
||||
|
||||
case httpc:request(get, {Url, [{"connection", "close"}]}, [], [{body_format, binary}]) of
|
||||
{ok, {{_, 200, _}, _, PubKeyBin }} ->
|
||||
[RSAEntry] = public_key:pem_decode(PubKeyBin),
|
||||
RSAKey = public_key:pem_entry_decode(RSAEntry),
|
||||
{ok, RSAKey};
|
||||
Error -> {stop, Error}
|
||||
end.
|
||||
|
||||
handle_call(fetch, _Arg, Key) -> {reply, {ok, Key}, Key}.
|
||||
|
||||
handle_cast(_Cast, Key) -> {noreply, Key}.
|
||||
|
||||
handle_info(_Info, Key) -> {noreply, Key}.
|
||||
|
||||
terminate(_, _) -> ok.
|
||||
|
||||
code_change(_OldVersion, Library, _Extra) -> {ok, Library}.
|
|
@ -0,0 +1,30 @@
|
|||
% THIS FILE IS AUTO GENERATED BY `rabbitmq.config.erb`.
|
||||
% DO NOT MODIFY `rabbitmq.config` MANUALLY!
|
||||
|
||||
[
|
||||
{
|
||||
rabbit, [
|
||||
{ loopback_users, [] },
|
||||
{ tcp_listeners, [5672] },
|
||||
{ ssl_listeners, [ ] },
|
||||
{ hipe_compile, false },
|
||||
{
|
||||
auth_backends, [
|
||||
rabbit_auth_backend_internal,
|
||||
rabbit_auth_backend_jwt
|
||||
]}
|
||||
] },
|
||||
|
||||
{ rabbitmq_web_mqtt, [{ port, 3002 }]},
|
||||
{
|
||||
rabbitmq_management, [{
|
||||
listener, [
|
||||
{ port, 15672 },
|
||||
{ ssl, false }
|
||||
] } ] },
|
||||
|
||||
{ rabbit_auth_backend_jwt, [
|
||||
{ farmbot_api_key_url, "<%= farmbot_api_key_url %>" },
|
||||
{ farmbot_vhost, <<"<%= farmbot_vhost %>">>}
|
||||
]}
|
||||
].
|
|
@ -0,0 +1,51 @@
|
|||
require 'erb'
|
||||
puts "=== Retrieving container info"
|
||||
DOCKER_IMG_NAME = "farmbot-mqtt"
|
||||
IS_BUILT = `cd mqtt; sudo docker images`.include?(DOCKER_IMG_NAME)
|
||||
|
||||
puts "=== Setting config data"
|
||||
CONFIG_PATH = "./mqtt/conf"
|
||||
CONFIG_FILENAME = "rabbitmq.config"
|
||||
CONFIG_OUTPUT = "#{CONFIG_PATH}/#{CONFIG_FILENAME}"
|
||||
NO_API_HOST = "You need to set API_HOST to a real IP address or " +
|
||||
"domain name (not localhost)."
|
||||
TEMPLATE_FILE = "./mqtt/rabbitmq.config.erb"
|
||||
TEMPLATE = File.read(TEMPLATE_FILE)
|
||||
RENDERER = ERB.new(TEMPLATE)
|
||||
PROTO = ENV["FORCE_SSL"] ? "https:" : "http:"
|
||||
VHOST = ENV.fetch("MQTT_VHOST") { "/" }
|
||||
|
||||
puts "=== Building JWT plugin config"
|
||||
farmbot_api_key_url = "#{PROTO}#{$API_URL}/api/public_key"
|
||||
farmbot_vhost = VHOST
|
||||
|
||||
# Write the config file.
|
||||
File.write(CONFIG_OUTPUT, RENDERER.result(binding))
|
||||
|
||||
# Re-init docker stuff
|
||||
|
||||
puts "=== Stopping any pre-existing farmbot containers"
|
||||
`cd mqtt; sudo docker rm $(sudo docker ps -a -f "name=farmbot-mqtt" -q)`
|
||||
|
||||
if IS_BUILT
|
||||
puts "=== Destroying old docker images"
|
||||
`cd mqtt; sudo docker rmi #{DOCKER_IMG_NAME} --force`
|
||||
end
|
||||
|
||||
puts "=== Building docker image"
|
||||
`cd mqtt; sudo docker build -t farmbot-mqtt .`
|
||||
|
||||
puts "=== Starting MQTT"
|
||||
exec [
|
||||
'cd mqtt;',
|
||||
'sudo docker run',
|
||||
'-p "15672:15672"',
|
||||
'-p "5672:5672"',
|
||||
'-p "3002:15675"',
|
||||
'-p "8883:8883"',
|
||||
'-p "1883:1883"',
|
||||
'--name "farmbot-mqtt"',
|
||||
'-v "$(pwd)/conf:/etc/rabbitmq"',
|
||||
'-v "$(pwd)/rabbitmq:/var/lib/rabbitmq"',
|
||||
'farmbot-mqtt'
|
||||
].join(" ")
|
|
@ -40,4 +40,11 @@ describe SessionToken do
|
|||
expect(result.success?).to be(false)
|
||||
expect(result.errors.values.first.message).to include("is not valid")
|
||||
end
|
||||
|
||||
it "doesn't mint tokens for unverified users" do
|
||||
user.update_attributes!(verified_at: nil)
|
||||
expect {
|
||||
SessionToken.issue_to(user, iat: 000, exp: 1, iss: "//lycos.com:9867")
|
||||
}.to raise_error(Errors::Forbidden)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
ENV['MQTT_HOST'] = "blooper.io"
|
||||
ENV['OS_UPDATE_SERVER'] = "http://blah.com"
|
||||
ENV['FW_UPDATE_SERVER'] = "http://test.com"
|
||||
require 'simplecov'
|
||||
#Ignore anything with the word 'spec' in it. No need to test your tests.
|
||||
SimpleCov.start do
|
||||
|
|
|
@ -9,9 +9,7 @@ export let auth: Everything["auth"] = {
|
|||
"exp": 1499025084,
|
||||
"mqtt": "10.0.0.6",
|
||||
"os_update_server": "https://api.github.com/repos/farmbot/" +
|
||||
"farmbot_os/releases/latest",
|
||||
"fw_update_server": "https://api.github.com/repos/FarmBot/" +
|
||||
"farmbot-arduino-firmware/releases/latest"
|
||||
"farmbot_os/releases/latest"
|
||||
},
|
||||
"encoded": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJhZG1pbk" +
|
||||
"BhZG1pbi5jb20iLCJpYXQiOjE0OTU1NjkwODQsImp0aSI6ImIzODkxNWNhLTNkN2Et" +
|
||||
|
|
|
@ -21,8 +21,7 @@ const fakeAuth = (jti = "456"): AuthState => ({
|
|||
iss: "---",
|
||||
exp: 456,
|
||||
mqtt: "---",
|
||||
os_update_server: "---",
|
||||
fw_update_server: "---"
|
||||
os_update_server: "---"
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -7,8 +7,7 @@ const mockAuth = (jti = "456"): AuthState => ({
|
|||
iss: "---",
|
||||
exp: 456,
|
||||
mqtt: "---",
|
||||
os_update_server: "---",
|
||||
fw_update_server: "---"
|
||||
os_update_server: "---"
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -20,8 +20,6 @@ export interface UnencodedToken {
|
|||
mqtt: string;
|
||||
/** Where to download RPi software */
|
||||
os_update_server: string;
|
||||
/** Where to download firmware. */
|
||||
fw_update_server: string;
|
||||
}
|
||||
|
||||
export interface User {
|
||||
|
|
Loading…
Reference in New Issue