diff --git a/hosts/hainich/configuration.nix b/hosts/hainich/configuration.nix index 8e0bc9f..9c87b27 100644 --- a/hosts/hainich/configuration.nix +++ b/hosts/hainich/configuration.nix @@ -16,6 +16,7 @@ ./services/gitlab-runner.nix ./services/lantifa.nix ./services/hasenloch.nix + ./services/wink.nix ./services/syncthing.nix ./services/monitoring.nix ./services/workadventure.nix diff --git a/hosts/hainich/services/wink.nix b/hosts/hainich/services/wink.nix new file mode 100644 index 0000000..9d7e3b1 --- /dev/null +++ b/hosts/hainich/services/wink.nix @@ -0,0 +1,91 @@ +# for documentation on how this container works, have a look at +# https://wiki.infra4future.de/books/voc-infra/page/wink-65b + +{ pkgs, config, ...}: + +{ + containers.wink = { + autoStart = true; + privateNetwork = true; + hostAddress = "192.168.100.10"; + localAddress = "192.168.100.11"; + + + config = {pkgs, config, ...}: { + networking.firewall.allowedTCPPorts = [ 8000 ]; + environment.systemPackages = [ pkgs.wink pkgs.v8 ]; + + systemd.services.wink = { + enable = true; + description = "Wo ist meine Winkekatze?"; + wantedBy = [ "multi-user.target" ]; + serviceConfig.type = "simple"; + environment.HOME = "/var/lib/wink/home"; + path = [ pkgs.wink pkgs.v8 ]; + script = '' + mkdir -p /var/lib/wink/home + cd /var/lib/wink + cp -r ${pkgs.wink.outPath}/* . + if [ ! -f database.exists ] + then + rails-wrapped db:migrate db:seed RAILS_ENV=development + touch database.exists + fi + rails-wrapped server -b [::] -p 3000 + ''; + }; + + services.oauth2_proxy = + let keycloakurl = "https://auth.infra4future.de/auth/realms/forfuture/protocol/openid-connect"; + in { + enable = true; + #nginx.virtualHosts = [ "matrix.hacc.space" ]; + upstream = "http://localhost:3000"; + httpAddress = "http//0.0.0.0:8000"; + + email.domains = [ "*" ]; + cookie.domain = "wink2.hacc.space"; + + # for the keycloak side of the configuration, see the documentation at + # https://oauth2-proxy.github.io/oauth2-proxy/docs/configuration/oauth_provider#keycloak-auth-provider + provider = "keycloak"; + clientID = "winktest"; # TODO + loginURL = "${keycloakurl}/auth"; + redeemURL = "${keycloakurl}/token"; + profileURL = "${keycloakurl}/userinfo"; + validateURL = "${keycloakurl}/userinfo"; + + # must contain OAUTH2_PROXY_COOKIE_SECRET and OAUTH2_PROXY_CLIENT_SECRET + keyFile = "/var/lib/oauth2_proxy/secrets"; + + extraConfig = { + # log format (default would also log ip addresses / users) + auth-logging-format = "[{{.Timestamp}}] [{{.Status}}] {{.Message}}"; + #allowed_group = "hacc"; + }; + }; + + services.coredns = { + enable = true; + config = '' + .:53 { + forward . 1.1.1.1 + } + ''; + }; + }; + }; + + + services.nginx.virtualHosts."wink2.hacc.space" = { + locations."/".proxyPass = "http://${config.containers.wink.localAddress}:8000"; + forceSSL = true; + enableACME = true; + }; + + networking.nat.enable = true; + networking.nat.internalInterfaces = ["ve-wink"]; + networking.nat.externalInterface = "enp6s0"; + + +} diff --git a/pkgs/default.nix b/pkgs/default.nix index 193f443..94100c2 100644 --- a/pkgs/default.nix +++ b/pkgs/default.nix @@ -34,7 +34,10 @@ let ''; }); + wink = callPackage ./wink {}; + inherit (unstable) bottom; + }; in pkgs.extend(_: _: newpkgs) diff --git a/pkgs/wink/default.nix b/pkgs/wink/default.nix new file mode 100644 index 0000000..3561042 --- /dev/null +++ b/pkgs/wink/default.nix @@ -0,0 +1,96 @@ + +# high-level notes: +# - wink uses the execjs gem, which needs some javascript runtime +# to be available. Wink usually uses the mini_racer gem for this, +# which unfortunately refuses to work on nix, so instead we have +# to patch it out of wink's dependencies and replace it with +# something else +# - execjs actually just takes any compatible js runtime it can find; +# this packages uses v8 by default, but you can easily override it +# with e.g. nodejs and wink should still work. + +{ stdenv +, bundlerEnv +, fetchFromGitHub +, zlib +, sqlite +, ruby +, makeWrapper +# v8 may be replaced with e.g. nodejs — see docs for execjs for a list +# of accaptable backends, all of which should all work out of the box +, v8 +, ... }: + +let + sources-patched = stdenv.mkDerivation { + name = "wink-sources-patched"; + + # wink sources from the c3VOC + src = fetchFromGitHub { + owner = "voc"; + repo = "wink"; + rev = "9f1d312b7bf6457fc23aaa9348a43c3900046a6c"; + sha256 = "1xyb4n4ys93mzyj779mdd6ngiials38xfql3ivddxc1l5rk11hbi"; + }; + + phases = [ "patchPhase" "installPhase" ]; + + # remove mini_racer and libv8 (its sole dependency) from wink's deps + patchPhase = '' + cp -r $src/* . + sed -i "s/gem 'mini_racer', platforms: :ruby/#removed mini_racer/g" Gemfile + sed -i "s/mini_racer (0.2.0)/ /g" Gemfile.lock + sed -i "s/libv8 (>= 6.3)/ /g" Gemfile.lock + ''; + + installPhase = '' + mkdir -p $out + cp -r * $out/ + ''; + }; + + # use the patched dependencies to generate derivations for all the + # ruby dependencies (using a `gemset.nix` generated with bundix) + gems = bundlerEnv { + name = "wink-gems"; + inherit ruby; + gemConfig = { + nokogiri = attrs: { + buildInputs = [ zlib ]; + }; + sqlite3 = attr: { + buildInputs = [ sqlite ]; + }; + }; + gemfile = sources-patched.outPath + "/Gemfile"; + lockfile = sources-patched.outPath + "/Gemfile.lock"; + + # Open question: we could generate this dynamically, would that be + # a good idea? + gemset = ./gemset.nix; + }; +in + stdenv.mkDerivation { + name = "wink-without-wrapping"; + + src = sources-patched.outPath; + + buildInputs = [ + gems + ruby + makeWrapper + v8 + ]; + + # need to wrap the executables so ruby can find its gems + installPhase = + let gempath = "${gems.outPath}/lib/ruby/gems/2.6.0"; + in '' + mkdir -p $out + cp -r * $out + + makeWrapper $out/bin/rails $out/bin/rails-wrapped --set GEM_PATH ${gempath} + makeWrapper $out/bin/rake $out/bin/rake-wrapped --set GEM_PATH ${gempath} + ''; + + } diff --git a/pkgs/wink/gemset.nix b/pkgs/wink/gemset.nix new file mode 100644 index 0000000..f9aea01 --- /dev/null +++ b/pkgs/wink/gemset.nix @@ -0,0 +1,994 @@ +{ + actioncable = { + dependencies = ["actionpack" "nio4r" "websocket-driver"]; + groups = ["default"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "17vdxn0afi5rfnbs09nl0m0cyj7yvpi445bmi8pkmzbaqzqkq3ff"; + type = "gem"; + }; + version = "5.2.1"; + }; + actionmailer = { + dependencies = ["actionpack" "actionview" "activejob" "mail" "rails-dom-testing"]; + groups = ["default"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "0h1nqg47jap0wzp0dhlnck4xjijfvdfw49aipjp8y2ihdpvyqrx6"; + type = "gem"; + }; + version = "5.2.1"; + }; + actionpack = { + dependencies = ["actionview" "activesupport" "rack" "rack-test" "rails-dom-testing" "rails-html-sanitizer"]; + groups = ["default" "development" "test"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "19zv9ix9iwpd8dxi5hyxgwrc1gh0fvx0a2vjhmic8dn8six41f4f"; + type = "gem"; + }; + version = "5.2.1"; + }; + actionview = { + dependencies = ["activesupport" "builder" "erubi" "rails-dom-testing" "rails-html-sanitizer"]; + groups = ["default" "development" "test"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "0dxanjs7ngpny4ig7dg93ywmg9ljswzg8risdlff6ag8fzvsnidf"; + type = "gem"; + }; + version = "5.2.1"; + }; + active_link_to = { + dependencies = ["actionpack" "addressable"]; + groups = ["default"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "1firn5hw8dkqlz1c2plprrzja5f0xs606qpwx7qrsn0l7mxq8c28"; + type = "gem"; + }; + version = "1.0.5"; + }; + activejob = { + dependencies = ["activesupport" "globalid"]; + groups = ["default"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "1m4l7z08cx1lybfswfggy7y1rxnwr6gi15h0g9kkkkvmmn6klf3r"; + type = "gem"; + }; + version = "5.2.1"; + }; + activemodel = { + dependencies = ["activesupport"]; + groups = ["default" "development"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "043nnxaf3cfq8jijls0jh1bg3a8v5zd9slc62zc2acp2n2wkjnd4"; + type = "gem"; + }; + version = "5.2.1"; + }; + activerecord = { + dependencies = ["activemodel" "activesupport" "arel"]; + groups = ["default"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "0pc7cycvhzjpw0swil2inka6c0fvcxhln793czp52pidg0654g7g"; + type = "gem"; + }; + version = "5.2.1"; + }; + activestorage = { + dependencies = ["actionpack" "activerecord" "marcel"]; + groups = ["default"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "0wncr3h94jsjmmqqmmips9vgy2kf1zhb96rlv5fbrgqplfhvpyag"; + type = "gem"; + }; + version = "5.2.1"; + }; + activesupport = { + dependencies = ["concurrent-ruby" "i18n" "minitest" "tzinfo"]; + groups = ["default" "development" "test"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "0ziy6xk31k4fs115cdkba1ys4i8nzcyri7a2jig7nx7k5h7li6l2"; + type = "gem"; + }; + version = "5.2.1"; + }; + addressable = { + dependencies = ["public_suffix"]; + groups = ["default" "test"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "0viqszpkggqi8hq87pqp0xykhvz60g99nwmkwsb0v45kc2liwxvk"; + type = "gem"; + }; + version = "2.5.2"; + }; + archive-zip = { + dependencies = ["io-like"]; + groups = ["default" "test"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "1h9fc1ry1cgpzi6rn1r46znawvwgpn38m1ya6v8d7g7id35d41q6"; + type = "gem"; + }; + version = "0.11.0"; + }; + arel = { + groups = ["default"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "1jk7wlmkr61f6g36w9s2sn46nmdg6wn2jfssrhbhirv5x9n95nk0"; + type = "gem"; + }; + version = "9.0.0"; + }; + bindex = { + groups = ["default" "development"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "1wvhf4v8sk5x8li03pcc0v0wglmyv7ikvvg05bnms83dfy7s4k8i"; + type = "gem"; + }; + version = "0.5.0"; + }; + bootsnap = { + dependencies = ["msgpack"]; + groups = ["default"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "1i3llrdqkndxzhv1a7a2yjpavmdabyq5ps296vmb32hv8fy95xk9"; + type = "gem"; + }; + version = "1.3.1"; + }; + builder = { + groups = ["default" "development" "test"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "0qibi5s67lpdv1wgcj66wcymcr04q6j4mzws6a479n0mlrmh5wr1"; + type = "gem"; + }; + version = "3.2.3"; + }; + byebug = { + groups = ["development" "test"]; + platforms = [{ + engine = "maglev"; + } { + engine = "mingw"; + } { + engine = "mingw"; + } { + engine = "ruby"; + }]; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "10znc1hjv8n686hhpl08f3m2g6h08a4b83nxblqwy2kqamkxcqf8"; + type = "gem"; + }; + version = "10.0.2"; + }; + capybara = { + dependencies = ["addressable" "mini_mime" "nokogiri" "rack" "rack-test" "xpath"]; + groups = ["test"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "1pn7jijww60kpcgf9g6yk430hqi867mwkxz89lzj694xrn87gzbc"; + type = "gem"; + }; + version = "3.6.0"; + }; + childprocess = { + dependencies = ["ffi"]; + groups = ["default" "test"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "0a61922kmvcxyj5l70fycapr87gz1dzzlkfpq85rfqk5vdh3d28p"; + type = "gem"; + }; + version = "0.9.0"; + }; + chromedriver-helper = { + dependencies = ["archive-zip" "nokogiri"]; + groups = ["test"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "0x1inglq11k0ab1n33xzvqcxybcsgn6psj6si2gnls6yh0zx14h3"; + type = "gem"; + }; + version = "1.2.0"; + }; + coffee-rails = { + dependencies = ["coffee-script" "railties"]; + groups = ["default"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "0jp81gjcid66ialk5n242y27p3payy0cz6c6i80ik02nx54mq2h8"; + type = "gem"; + }; + version = "4.2.2"; + }; + coffee-script = { + dependencies = ["coffee-script-source" "execjs"]; + groups = ["default"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "0rc7scyk7mnpfxqv5yy4y5q1hx3i7q3ahplcp4bq2g5r24g2izl2"; + type = "gem"; + }; + version = "2.4.1"; + }; + coffee-script-source = { + groups = ["default"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "1907v9q1zcqmmyqzhzych5l7qifgls2rlbnbhy5vzyr7i7yicaz1"; + type = "gem"; + }; + version = "1.12.2"; + }; + concurrent-ruby = { + groups = ["default" "development" "test"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "183lszf5gx84kcpb779v6a2y0mx9sssy8dgppng1z9a505nj1qcf"; + type = "gem"; + }; + version = "1.0.5"; + }; + crass = { + groups = ["default" "development" "test"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "0bpxzy6gjw9ggjynlxschbfsgmx8lv3zw1azkjvnb8b9i895dqfi"; + type = "gem"; + }; + version = "1.0.4"; + }; + diff-lcs = { + groups = ["default" "development" "test"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "18w22bjz424gzafv6nzv98h0aqkwz3d9xhm7cbr1wfbyas8zayza"; + type = "gem"; + }; + version = "1.3"; + }; + docile = { + groups = ["default" "development" "test"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "04d2izkna3ahfn6fwq4xrcafa715d3bbqczxm16fq40fqy87xn17"; + type = "gem"; + }; + version = "1.3.1"; + }; + erubi = { + groups = ["default" "development" "test"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "0bws86na9k565raiz0kk61yy5pxxp0fmwyzpibdwjkq0xzx8q6q1"; + type = "gem"; + }; + version = "1.7.1"; + }; + execjs = { + groups = ["default"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "1yz55sf2nd3l666ms6xr18sm2aggcvmb8qr3v53lr4rir32y1yp1"; + type = "gem"; + }; + version = "2.7.0"; + }; + ffi = { + groups = ["default" "development" "test"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "0jpm2dis1j7zvvy3lg7axz9jml316zrn7s0j59vyq3qr127z0m7q"; + type = "gem"; + }; + version = "1.9.25"; + }; + globalid = { + dependencies = ["activesupport"]; + groups = ["default"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "02smrgdi11kziqi9zhnsy9i6yr2fnxrqlv3lllsvdjki3cd4is38"; + type = "gem"; + }; + version = "0.4.1"; + }; + haml = { + dependencies = ["temple" "tilt"]; + groups = ["default"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "1q0a9fvqh8kn6wm97fcks6qzbjd400bv8bx748w8v87m7p4klhac"; + type = "gem"; + }; + version = "5.0.4"; + }; + i18n = { + dependencies = ["concurrent-ruby"]; + groups = ["default" "development" "test"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "0ppvmla21hssvrfm8g1n2fnb4lxn4yhy9qmmba0imanflgldrjmr"; + type = "gem"; + }; + version = "1.1.0"; + }; + io-like = { + groups = ["default" "test"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "04nn0s2wmgxij3k760h3r8m1dgih5dmd9h4v1nn085yi824i5z6k"; + type = "gem"; + }; + version = "0.3.0"; + }; + jbuilder = { + dependencies = ["activesupport" "multi_json"]; + groups = ["default"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "1n3myqk2hdnidzzbgcdz2r1y4cr5vpz5nkfzs0lz4y9gkjbjyh2j"; + type = "gem"; + }; + version = "2.7.0"; + }; + jquery-rails = { + dependencies = ["rails-dom-testing" "railties" "thor"]; + groups = ["default"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "02ii77vwxc49f2lrkbdzww2168bp5nihwzakc9mqyrsbw394w7ki"; + type = "gem"; + }; + version = "4.3.1"; + }; + jquery-ui-rails = { + dependencies = ["railties"]; + groups = ["default"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "1mbwwbbwzp836l7mc21amnaqmf5wbrw5hzls48hscrcgh0vig812"; + type = "gem"; + }; + version = "6.0.1"; + }; + json = { + groups = ["default" "development" "test"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "01v6jjpvh3gnq6sgllpfqahlgxzj50ailwhj9b3cd20hi2dx0vxp"; + type = "gem"; + }; + version = "2.1.0"; + }; + listen = { + dependencies = ["rb-fsevent" "rb-inotify" "ruby_dep"]; + groups = ["development"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "01v5mrnfqm6sgm8xn2v5swxsn1wlmq7rzh2i48d4jzjsc7qvb6mx"; + type = "gem"; + }; + version = "3.1.5"; + }; + loofah = { + dependencies = ["crass" "nokogiri"]; + groups = ["default" "development" "test"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "0yjs6wbcj3n06d3xjqpy3qbpx0bfa12h3x2rbpc2k33ldjlkx6zy"; + type = "gem"; + }; + version = "2.2.2"; + }; + mail = { + dependencies = ["mini_mime"]; + groups = ["default"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "10dyifazss9mgdzdv08p47p344wmphp5pkh5i73s7c04ra8y6ahz"; + type = "gem"; + }; + version = "2.7.0"; + }; + marcel = { + dependencies = ["mimemagic"]; + groups = ["default"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "0v1kncmyh0yn9h28zri6hkfdqzr8bf26ar9bvglhgzy0chqr9dp8"; + type = "gem"; + }; + version = "0.3.2"; + }; + method_source = { + groups = ["default" "development" "test"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "0xqj21j3vfq4ldia6i2akhn2qd84m0iqcnsl49kfpq3xk6x0dzgn"; + type = "gem"; + }; + version = "0.9.0"; + }; + mimemagic = { + groups = ["default"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "00ibc1mhvdfyfyl103xwb45621nwyqxf124cni5hyfhag0fn1c3q"; + type = "gem"; + }; + version = "0.3.2"; + }; + mini_mime = { + groups = ["default" "test"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "1q4pshq387lzv9m39jv32vwb8wrq3wc4jwgl4jk209r4l33v09d3"; + type = "gem"; + }; + version = "1.0.1"; + }; + mini_portile2 = { + groups = ["default" "development" "test"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "13d32jjadpjj6d2wdhkfpsmy68zjx90p49bgf8f7nkpz86r1fr11"; + type = "gem"; + }; + version = "2.3.0"; + }; + minitest = { + groups = ["default" "development" "test"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "0icglrhghgwdlnzzp4jf76b0mbc71s80njn5afyfjn4wqji8mqbq"; + type = "gem"; + }; + version = "5.11.3"; + }; + mqtt = { + groups = ["default"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "0d1khsry5mf63y03r6v91f4vrbn88277ksv7d69z3xmqs9sgpri9"; + type = "gem"; + }; + version = "0.5.0"; + }; + msgpack = { + groups = ["default"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "09xy1wc4wfbd1jdrzgxwmqjzfdfxbz0cqdszq2gv6rmc3gv1c864"; + type = "gem"; + }; + version = "1.2.4"; + }; + multi_json = { + groups = ["default"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "1rl0qy4inf1mp8mybfk56dfga0mvx97zwpmq5xmiwl5r770171nv"; + type = "gem"; + }; + version = "1.13.1"; + }; + nio4r = { + groups = ["default"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "1a41ca1kpdmrypjp9xbgvckpy8g26zxphkja9vk7j5wl4n8yvlyr"; + type = "gem"; + }; + version = "2.3.1"; + }; + nokogiri = { + dependencies = ["mini_portile2"]; + groups = ["default" "development" "test"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "1h9nml9h3m0mpvmh8jfnqvblnz5n5y3mmhgfc38avfmfzdrq9bgc"; + type = "gem"; + }; + version = "1.8.4"; + }; + public_suffix = { + groups = ["default" "test"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "1x5h1dh1i3gwc01jbg01rly2g6a1qwhynb1s8a30ic507z1nh09s"; + type = "gem"; + }; + version = "3.0.2"; + }; + puma = { + groups = ["default"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "1k7dqxnq0dnf5rxkgs9rknclkn3ah7lsdrk6nrqxla8qzy31wliq"; + type = "gem"; + }; + version = "3.12.0"; + }; + rack = { + groups = ["default" "development" "test"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "158hbn7rlc3czp2vivvam44dv6vmzz16qrh5dbzhfxbfsgiyrqw1"; + type = "gem"; + }; + version = "2.0.5"; + }; + rack-test = { + dependencies = ["rack"]; + groups = ["default" "development" "test"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "0rh8h376mx71ci5yklnpqqn118z3bl67nnv5k801qaqn1zs62h8m"; + type = "gem"; + }; + version = "1.1.0"; + }; + rails = { + dependencies = ["actioncable" "actionmailer" "actionpack" "actionview" "activejob" "activemodel" "activerecord" "activestorage" "activesupport" "railties" "sprockets-rails"]; + groups = ["default"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "1307cv1p6cj350hq2mi00dfgjb77rzvlhrr3h0bjz5s0a6jgwv3p"; + type = "gem"; + }; + version = "5.2.1"; + }; + rails-dom-testing = { + dependencies = ["activesupport" "nokogiri"]; + groups = ["default" "development" "test"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "1lfq2a7kp2x64dzzi5p4cjcbiv62vxh9lyqk2f0rqq3fkzrw8h5i"; + type = "gem"; + }; + version = "2.0.3"; + }; + rails-html-sanitizer = { + dependencies = ["loofah"]; + groups = ["default" "development" "test"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "1gv7vr5d9g2xmgpjfq4nxsqr70r9pr042r9ycqqnfvw5cz9c7jwr"; + type = "gem"; + }; + version = "1.0.4"; + }; + railties = { + dependencies = ["actionpack" "activesupport" "method_source" "rake" "thor"]; + groups = ["default" "development" "test"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "19y343dvb7vih82q2ssyhp1cirmp5sp1vpw4k5zmd1bxxkjix9qv"; + type = "gem"; + }; + version = "5.2.1"; + }; + rake = { + groups = ["default" "development" "test"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "1idi53jay34ba9j68c3mfr9wwkg3cd9qh0fn9cg42hv72c6q8dyg"; + type = "gem"; + }; + version = "12.3.1"; + }; + rb-fsevent = { + groups = ["default" "development"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "1lm1k7wpz69jx7jrc92w3ggczkjyjbfziq5mg62vjnxmzs383xx8"; + type = "gem"; + }; + version = "0.10.3"; + }; + rb-inotify = { + dependencies = ["ffi"]; + groups = ["default" "development"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "0yfsgw5n7pkpyky6a9wkf1g9jafxb0ja7gz0qw0y14fd2jnzfh71"; + type = "gem"; + }; + version = "0.9.10"; + }; + rspec-core = { + dependencies = ["rspec-support"]; + groups = ["default" "development" "test"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "1p1s5bnbqp3sxk67y0fh0x884jjym527r0vgmhbm81w7aq6b7l4p"; + type = "gem"; + }; + version = "3.8.0"; + }; + rspec-expectations = { + dependencies = ["diff-lcs" "rspec-support"]; + groups = ["default" "development" "test"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "0vfqqcjmhdq25jrc8rd7nx4n8xid7s1ynv65ph06bk2xafn3rgll"; + type = "gem"; + }; + version = "3.8.1"; + }; + rspec-mocks = { + dependencies = ["diff-lcs" "rspec-support"]; + groups = ["default" "development" "test"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "06y508cjqycb4yfhxmb3nxn0v9xqf17qbd46l1dh4xhncinr4fyp"; + type = "gem"; + }; + version = "3.8.0"; + }; + rspec-rails = { + dependencies = ["actionpack" "activesupport" "railties" "rspec-core" "rspec-expectations" "rspec-mocks" "rspec-support"]; + groups = ["development" "test"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "0bm1md49c6skjvqmi6p7jd036ikn8sgiy9lj2pvjmm8ibslpflg7"; + type = "gem"; + }; + version = "3.8.0"; + }; + rspec-support = { + groups = ["default" "development" "test"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "0p3m7drixrlhvj2zpc38b11x145bvm311x6f33jjcxmvcm0wq609"; + type = "gem"; + }; + version = "3.8.0"; + }; + ruby_dep = { + groups = ["default" "development"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "1c1bkl97i9mkcvkn1jks346ksnvnnp84cs22gwl0vd7radybrgy5"; + type = "gem"; + }; + version = "1.5.0"; + }; + rubyzip = { + groups = ["default" "test"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "06js4gznzgh8ac2ldvmjcmg9v1vg9llm357yckkpylaj6z456zqz"; + type = "gem"; + }; + version = "1.2.1"; + }; + sass = { + dependencies = ["sass-listen"]; + groups = ["default"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "1sy7xsbgpcy90j5ynbq967yplffp74pvph3r8ivn2sv2b44q6i61"; + type = "gem"; + }; + version = "3.5.7"; + }; + sass-listen = { + dependencies = ["rb-fsevent" "rb-inotify"]; + groups = ["default"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "0xw3q46cmahkgyldid5hwyiwacp590zj2vmswlll68ryvmvcp7df"; + type = "gem"; + }; + version = "4.0.0"; + }; + sass-rails = { + dependencies = ["railties" "sass" "sprockets" "sprockets-rails" "tilt"]; + groups = ["default"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "1wa63sbsimrsf7nfm8h0m1wbsllkfxvd7naph5d1j6pbc555ma7s"; + type = "gem"; + }; + version = "5.0.7"; + }; + selenium-webdriver = { + dependencies = ["childprocess" "rubyzip"]; + groups = ["test"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "0mv8c667sfdd01dcc1z1yh4fgmrr3fj57sgiv44r85kbhqr5j1aa"; + type = "gem"; + }; + version = "3.14.0"; + }; + simplecov = { + dependencies = ["docile" "json" "simplecov-html"]; + groups = ["development" "test"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "1sfyfgf7zrp2n42v7rswkqgk3bbwk1bnsphm24y7laxv3f8z0947"; + type = "gem"; + }; + version = "0.16.1"; + }; + simplecov-html = { + groups = ["default" "development" "test"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "1lihraa4rgxk8wbfl77fy9sf0ypk31iivly8vl3w04srd7i0clzn"; + type = "gem"; + }; + version = "0.10.2"; + }; + spring = { + dependencies = ["activesupport"]; + groups = ["development"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "168yz9c1fv21wc5i8q7n43b9nk33ivg3ws1fn6x0afgryz3ssx75"; + type = "gem"; + }; + version = "2.0.2"; + }; + spring-watcher-listen = { + dependencies = ["listen" "spring"]; + groups = ["development"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "1ybz9nsngfz4psvgnbr3gdk5ibqqhq47lsjkwh5yq4f8brpr10yz"; + type = "gem"; + }; + version = "2.0.1"; + }; + sprockets = { + dependencies = ["concurrent-ruby" "rack"]; + groups = ["default"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "182jw5a0fbqah5w9jancvfmjbk88h8bxdbwnl4d3q809rpxdg8ay"; + type = "gem"; + }; + version = "3.7.2"; + }; + sprockets-rails = { + dependencies = ["actionpack" "activesupport" "sprockets"]; + groups = ["default"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "0ab42pm8p5zxpv3sfraq45b9lj39cz9mrpdirm30vywzrwwkm5p1"; + type = "gem"; + }; + version = "3.2.1"; + }; + sqlite3 = { + groups = ["default"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "01ifzp8nwzqppda419c9wcvr8n82ysmisrs0hph9pdmv1lpa4f5i"; + type = "gem"; + }; + version = "1.3.13"; + }; + temple = { + groups = ["default"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "00nxf610nzi4n1i2lkby43nrnarvl89fcl6lg19406msr0k3ycmq"; + type = "gem"; + }; + version = "0.8.0"; + }; + thor = { + groups = ["default" "development" "test"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "0nmqpyj642sk4g16nkbq6pj856adpv91lp4krwhqkh2iw63aszdl"; + type = "gem"; + }; + version = "0.20.0"; + }; + thread_safe = { + groups = ["default" "development" "test"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "0nmhcgq6cgz44srylra07bmaw99f5271l0dpsvl5f75m44l0gmwy"; + type = "gem"; + }; + version = "0.3.6"; + }; + tilt = { + groups = ["default"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "0020mrgdf11q23hm1ddd6fv691l51vi10af00f137ilcdb2ycfra"; + type = "gem"; + }; + version = "2.0.8"; + }; + turbolinks = { + dependencies = ["turbolinks-source"]; + groups = ["default"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "16zy97lw64hf1gwh5kakx86dngyc5zvwpn0wzh6m9np48bsq8drj"; + type = "gem"; + }; + version = "5.1.1"; + }; + turbolinks-source = { + groups = ["default"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "17jqbf7h3s40js4zjlpjw1knpydi27hinhjfsxhlrjcrz5a15gkw"; + type = "gem"; + }; + version = "5.1.0"; + }; + tzinfo = { + dependencies = ["thread_safe"]; + groups = ["default" "development" "test"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "1fjx9j327xpkkdlxwmkl3a8wqj7i4l4jwlrv3z13mg95z9wl253z"; + type = "gem"; + }; + version = "1.2.5"; + }; + uglifier = { + dependencies = ["execjs"]; + groups = ["default"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "14r283lkhisq2sdccv8ngf10f2f18ly4nc3chz3kliw5nylbgznw"; + type = "gem"; + }; + version = "4.1.18"; + }; + web-console = { + dependencies = ["actionview" "activemodel" "bindex" "railties"]; + groups = ["development"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "0brz15hzn3yi9x2ccc8asin0xv5cvsf98x8xbgk0vsinmfcka6ri"; + type = "gem"; + }; + version = "3.6.2"; + }; + websocket-driver = { + dependencies = ["websocket-extensions"]; + groups = ["default"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "1551k3fs3kkb3ghqfj3n5lps0ikb9pyrdnzmvgfdxy8574n4g1dn"; + type = "gem"; + }; + version = "0.7.0"; + }; + websocket-extensions = { + groups = ["default"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "034sdr7fd34yag5l6y156rkbhiqgmy395m231dwhlpcswhs6d270"; + type = "gem"; + }; + version = "0.1.3"; + }; + xpath = { + dependencies = ["nokogiri"]; + groups = ["default" "test"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "1y61ijvv04bwga802s8py5xd7fcxci6478wgr9wkd35p45x20jzi"; + type = "gem"; + }; + version = "3.1.0"; + }; +}