From 0faf426121cc5147aef4a0878882adb579381b5d Mon Sep 17 00:00:00 2001 From: "Jesse C. Fisher" Date: Fri, 29 Sep 2023 17:59:13 +0000 Subject: [PATCH] Add doodads --- app/assets/javascripts/doodads.coffee | 3 + app/assets/javascripts/eyecandy.js | 2 +- app/assets/stylesheets/application.css.sass | 33 +++--- app/assets/stylesheets/doodads.sass | 11 ++ app/controllers/application_controller.rb | 8 +- app/controllers/doodads_controller.rb | 73 ++++++++++++ app/controllers/visitors_controller.rb | 1 + app/helpers/application_helper.rb | 104 ++++++++++++++++++ app/helpers/doodads_helper.rb | 2 + app/models/doodad.rb | 3 + app/models/user.rb | 35 +++++- app/policies/canister_policy.rb | 2 +- app/policies/doodad_policy.rb | 56 ++++++++++ app/views/doodads/_doodad.html.haml | 3 + app/views/doodads/_doodad.json.jbuilder | 2 + app/views/doodads/_form.html.haml | 10 ++ app/views/doodads/edit.html.haml | 5 + app/views/doodads/index.html.haml | 33 ++++++ app/views/doodads/index.json.jbuilder | 1 + app/views/doodads/new.html.haml | 5 + app/views/doodads/show.html.haml | 15 +++ app/views/doodads/show.json.jbuilder | 1 + app/views/layouts/_navigation_links.html.erb | 1 + .../layouts/_navigation_wallet.html.haml | 19 ++++ app/views/layouts/application.html.erb | 4 +- app/views/visitors/index.html.haml | 44 +++++--- config/routes.rb | 1 + db/migrate/20230929144450_create_doodads.rb | 11 ++ db/schema.rb | 12 +- spec/factories/doodads.rb | 7 ++ spec/models/doodad_spec.rb | 5 + 31 files changed, 472 insertions(+), 40 deletions(-) create mode 100644 app/assets/javascripts/doodads.coffee create mode 100644 app/assets/stylesheets/doodads.sass create mode 100644 app/controllers/doodads_controller.rb create mode 100644 app/helpers/doodads_helper.rb create mode 100644 app/models/doodad.rb create mode 100644 app/policies/doodad_policy.rb create mode 100644 app/views/doodads/_doodad.html.haml create mode 100644 app/views/doodads/_doodad.json.jbuilder create mode 100644 app/views/doodads/_form.html.haml create mode 100644 app/views/doodads/edit.html.haml create mode 100644 app/views/doodads/index.html.haml create mode 100644 app/views/doodads/index.json.jbuilder create mode 100644 app/views/doodads/new.html.haml create mode 100644 app/views/doodads/show.html.haml create mode 100644 app/views/doodads/show.json.jbuilder create mode 100644 app/views/layouts/_navigation_wallet.html.haml create mode 100644 db/migrate/20230929144450_create_doodads.rb create mode 100644 spec/factories/doodads.rb create mode 100644 spec/models/doodad_spec.rb diff --git a/app/assets/javascripts/doodads.coffee b/app/assets/javascripts/doodads.coffee new file mode 100644 index 00000000..24f83d18 --- /dev/null +++ b/app/assets/javascripts/doodads.coffee @@ -0,0 +1,3 @@ +# Place all the behaviors and hooks related to the matching controller here. +# All this logic will automatically be available in application.js. +# You can use CoffeeScript in this file: http://coffeescript.org/ diff --git a/app/assets/javascripts/eyecandy.js b/app/assets/javascripts/eyecandy.js index 17ebd62a..dbea8598 100644 --- a/app/assets/javascripts/eyecandy.js +++ b/app/assets/javascripts/eyecandy.js @@ -111,7 +111,7 @@ $('.eyecandy').marqueeify({ // $( ".eyecandy" ).draggable({ // addClasses: true // }); - $("#home-headline").draggable({ + $(".home-headline,#home-headline").draggable({ addClasses: true }); }); diff --git a/app/assets/stylesheets/application.css.sass b/app/assets/stylesheets/application.css.sass index 0f0cbb82..d3f74c50 100644 --- a/app/assets/stylesheets/application.css.sass +++ b/app/assets/stylesheets/application.css.sass @@ -1,18 +1,3 @@ -/* - * This is a manifest file that'll be compiled into application.css, which will include all the files - * listed below. - * - * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets, - * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path. - * - * You're free to add application-wide styles to this file and they'll appear at the bottom of the - * compiled file so the styles you add here take precedence over styles defined in any styles - * defined in the other CSS/SCSS files in this directory. It is generally better to create a new - * file per style scope. - * - *= require_tree . - *= require_self - */ html box-sizing: border-box @@ -28,6 +13,7 @@ body margin: 0 background: image-url('backgrounds/felt-green.png') font-size: 2vmin + // overflow: hidden a text-decoration: none @@ -68,7 +54,7 @@ header align-items: center -#home-headline +#home-headline, .home-headline margin-top: 6em flex: 1 1 auto text-align: center @@ -126,6 +112,7 @@ header border-radius: 10em overflow: hidden &.icypepe + zoom: 70% border-radius: 600em padding: 1em 5em 1em 2em cursor: pointer @@ -191,3 +178,17 @@ footer width: 100% height: 100% object-fit: fill + +// form + width: 100% + padding: 1em + +textarea + width: 100% + min-height: 8em + +.navigation-wallet + text-align: right + padding: 0.5em + +@import doodads diff --git a/app/assets/stylesheets/doodads.sass b/app/assets/stylesheets/doodads.sass new file mode 100644 index 00000000..843acada --- /dev/null +++ b/app/assets/stylesheets/doodads.sass @@ -0,0 +1,11 @@ +.doodad + padding: 1em + background: darkgoldenrod + box-shadow: 0px -2px 8px black + +.doodads-view + form + width: 100% + padding: 1em + + diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index efb3cb00..37bcf595 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -14,9 +14,15 @@ class ApplicationController < ActionController::Base private + def add_body_css_class(css_class) + @body_css_classes ||= [] + @body_css_classes << css_class + end + def user_not_authorized(exception) policy_name = exception.policy.class.to_s.underscore - flash[:alert] = "#{policy_name}.#{exception.query}" + # flash[:alert] = "#{policy_name}.#{exception.query}" + flash[:alert] = "Unable to #{exception.query[0..-2]} #{policy_name.split("_")[0].capitalize}" redirect_to (request.referrer || root_path) end end diff --git a/app/controllers/doodads_controller.rb b/app/controllers/doodads_controller.rb new file mode 100644 index 00000000..f8a27c37 --- /dev/null +++ b/app/controllers/doodads_controller.rb @@ -0,0 +1,73 @@ +class DoodadsController < ApplicationController + before_action :set_doodad, only: %i[ show edit update destroy ] + + # GET /doodads or /doodads.json + def index + @doodads = authorize policy_scope(Doodad) + end + + # GET /doodads/1 or /doodads/1.json + def show + authorize @doodad + end + + # GET /doodads/new + def new + authorize @doodad = current_user.doodads.new + end + + # GET /doodads/1/edit + def edit + authorize @doodad + end + + # POST /doodads or /doodads.json + def create + authorize @doodad = Doodad.new(doodad_params) + + respond_to do |format| + if @doodad.save + format.html { redirect_to @doodad, notice: "Doodad was successfully created." } + format.json { render :show, status: :created, location: @doodad } + else + format.html { render :new, status: :unprocessable_entity } + format.json { render json: @doodad.errors, status: :unprocessable_entity } + end + end + end + + # PATCH/PUT /doodads/1 or /doodads/1.json + def update + authorize @doodad + respond_to do |format| + if @doodad.update(doodad_params) + format.html { redirect_to @doodad, notice: "Doodad was successfully updated." } + format.json { render :show, status: :ok, location: @doodad } + else + format.html { render :edit, status: :unprocessable_entity } + format.json { render json: @doodad.errors, status: :unprocessable_entity } + end + end + end + + # DELETE /doodads/1 or /doodads/1.json + def destroy + authorize @doodad + @doodad.destroy + respond_to do |format| + format.html { redirect_to doodads_url, notice: "Doodad was successfully destroyed." } + format.json { head :no_content } + end + end + + private + # Use callbacks to share common setup or constraints between actions. + def set_doodad + @doodad = Doodad.find(params[:id]) + end + + # Only allow a list of trusted parameters through. + def doodad_params + params.require(:doodad).permit(:body, :user_id, :is_public) + end +end diff --git a/app/controllers/visitors_controller.rb b/app/controllers/visitors_controller.rb index 488087cd..30fa7d47 100644 --- a/app/controllers/visitors_controller.rb +++ b/app/controllers/visitors_controller.rb @@ -2,6 +2,7 @@ class VisitorsController < ApplicationController before_action :skip_authorization def index + @doodads = authorize Doodad.all @canisters = authorize Canister.all end end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index de6be794..27268654 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -1,2 +1,106 @@ module ApplicationHelper + def body_css_class + @body_css_classes ||= [] + # view_css_class = [controller_path.split('/'), action_name, 'view'].flatten.join('-') + view_css_class = [controller_path.split('/'), action_name, 'view'].flatten[0] + "-view" + @body_css_classes.unshift(view_css_class).join(' ') + end + + def currency_balance(principal, currency_symbol, dfx_id = nil) + canisters = { + ICYPEES: "es3he-kyaaa-aaaah-abzna-cai", + EVL: "7wqow-haaaa-aaaao-ahbpq-cai", + "SNS-1": "zfcdd-tqaaa-aaaaq-aaaga-cai", + TENDY: "72uqs-pqaaa-aaaak-aes7a-cai", + YC: "5gxp5-jyaaa-aaaag-qarma-cai", + CZECH: "fkhzl-saaaa-aaaan-qd26a-cai", + ICL: "5573k-xaaaa-aaaak-aacnq-cai", + OT: "imeri-bqaaa-aaaai-qnpla-cai", + "01": "6ohjj-4qaaa-aaaai-aapua-cai", + BABYAROFdip20: "iy6hh-xaaaa-aaaan-qauza-cai"} + multipliers = { + TENDY: 100000000, + ICYPEES: 100000000, + CZECH: 100000000, + OT: 100000000, + EVL: 100000000, + "SNS-1": 100000000, + ICL: 100000000, + "01": 100000, + BABYAROFDIP20: 100000000 + } + begin + # if currency_symbol == "ICL" + # binding.pry + # end + if ["SNS-1"].any?{ |s| s.casecmp(currency_symbol)==0 } + wallet_currency_balance = `dfx canister --network ic call #{canisters[:"#{currency_symbol}"]} #{currency_symbol == "SNS-1" ? "icrc1_balance_of" : "balanceOf"} '(record { owner = principal "#{principal}"})'`.gsub("_","").match(/\d+/)[0].to_f/(multipliers[:"#{currency_symbol}"]) + elsif ["BTC"].any?{ |s| s.casecmp(currency_symbol)==0 } + puts "BTC" + `bitcoin-core.cli loadwallet #{dfx_id}` + wallet_currency_balance = `bitcoin-core.cli getbalance`.strip + if wallet_currency_balance.to_s.empty? + `bitcoin-core.cli createwallet "#{dfx_id}"` + `bitcoin-core.cli loadwallet #{dfx_id}` + end + wallet_currency_balance = `bitcoin-core.cli getbalance`.strip + `bitcoin-core.cli unloadwallet #{dfx_id}` + elsif ["testBTC"].any?{ |s| s.casecmp(currency_symbol)==0 } + puts "testBTC" + `bitcoin-core.cli loadwallet #{dfx_id}` + wallet_currency_balance = `bitcoin-core.cli -testnet getbalance`.strip + if wallet_currency_balance.to_s.empty? + `bitcoin-core.cli -testnet createwallet "#{dfx_id}"` + end + `bitcoin-core.cli -testnet loadwallet #{dfx_id}` + wallet_currency_balance = `bitcoin-core.cli -testnet getbalance`.strip + `bitcoin-core.cli -testnet unloadwallet #{dfx_id}` + elsif ["ICP"].any?{ |s| s.casecmp(currency_symbol)==0 } + wallet_currency_balance = icp_balance(dfx_id) + elsif ["ETH"].any?{ |s| s.casecmp(currency_symbol)==0 } + wallet_currency_balance = `eth address:balance -n mainnet #{dfx_id}`.strip + if wallet_currency_balance.empty? + new_address = JSON.parse `eth address:random` + `eth address:add #{dfx_id} #{new_address["privateKey"]}` + wallet_currency_balance = `eth address:balance -n mainnet #{dfx_id}`.strip + end + elsif ["goerliBaseETH"].any?{ |s| s.casecmp(currency_symbol)==0 } + wallet_currency_balance = `eth address:balance -n goerliBase #{dfx_id}`.strip + if wallet_currency_balance.empty? + new_address = JSON.parse `eth address:random` + `eth address:add #{dfx_id} #{new_address["privateKey"]}` + wallet_currency_balance = `eth address:balance -n goerliBase #{dfx_id}`.strip + end + elsif ["goerliETH"].any?{ |s| s.casecmp(currency_symbol)==0 } + wallet_currency_balance = `eth address:balance -n goerli #{dfx_id}`.strip + if wallet_currency_balance.empty? + new_address = JSON.parse `eth address:random` + `eth address:add #{dfx_id} #{new_address["privateKey"]}` + wallet_currency_balance = `eth address:balance -n goerli #{dfx_id}`.strip + end + elsif ["sepETH"].any?{ |s| s.casecmp(currency_symbol)==0 } + wallet_currency_balance = `eth address:balance -n sep #{dfx_id}`.strip + if wallet_currency_balance.empty? + new_address = JSON.parse `eth address:random` + `eth address:add #{dfx_id} #{new_address["privateKey"]}` + wallet_currency_balance = `eth address:balance -n sep #{dfx_id}`.strip + end + elsif canisters.keys.map{|k| k.to_s}.any?{ |s| s.casecmp(currency_symbol)==0 } + # binding.pry + wallet_currency_balance = `dfx canister --network ic call #{canisters[:"#{currency_symbol.upcase}"]} balanceOf '(principal "#{principal}")'`.gsub("_","").match(/\d+/)[0].to_f/(multipliers[:"#{currency_symbol.upcase}"]) + else + return "Currency not found" + end + rescue + return "Error fetching balance" + end + if wallet_currency_balance.to_s.empty? + return "Error fetching " + else + return wallet_currency_balance + end + end + + + end diff --git a/app/helpers/doodads_helper.rb b/app/helpers/doodads_helper.rb new file mode 100644 index 00000000..8e28d788 --- /dev/null +++ b/app/helpers/doodads_helper.rb @@ -0,0 +1,2 @@ +module DoodadsHelper +end diff --git a/app/models/doodad.rb b/app/models/doodad.rb new file mode 100644 index 00000000..10ef1c74 --- /dev/null +++ b/app/models/doodad.rb @@ -0,0 +1,3 @@ +class Doodad < ActiveRecord::Base + belongs_to :user +end diff --git a/app/models/user.rb b/app/models/user.rb index 9070412f..be50847a 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -4,6 +4,30 @@ class User < ActiveRecord::Base validates :email, presence: true, uniqueness: true validates :soft_token, presence: true, uniqueness: true has_many :canisters + has_many :doodads + + def icid + stp = SoftTokenPrincipal.where(soft_token: self.soft_token).first_or_initialize + if stp.principal.nil? + #TODO use principal + if !soft_token.nil? + if `dfx identity use #{soft_token}; echo $?`.to_i == 255 + `dfx identity new #{soft_token} --disable-encryption` + `dfx identity use #{soft_token}` + @principal = `dfx identity get-principal` + @icid = `dfx ledger account-id` + `dfx identity use anonymous` + stp.principal = @principal + stp.save + end + end + elsif + `dfx identity use #{soft_token}` + @icid = `dfx ledger account-id` + `dfx identity use anonymous` + end + return @icid.strip + end def principal stp = SoftTokenPrincipal.where(soft_token: self.soft_token).first_or_initialize @@ -20,9 +44,18 @@ class User < ActiveRecord::Base end end end - return stp.principal + return stp.principal.strip end + def icp_balance + `dfx identity use #{soft_token}` + balance = `dfx ledger --network ic balance` + `dfx identity use anonymous` + return balance.strip + end + + + def set_default_role self.role ||= :user end diff --git a/app/policies/canister_policy.rb b/app/policies/canister_policy.rb index 17e7cad8..ac53019a 100644 --- a/app/policies/canister_policy.rb +++ b/app/policies/canister_policy.rb @@ -19,7 +19,7 @@ class CanisterPolicy end def new? - @current_user.admin? + @current_user.present? end def edit? diff --git a/app/policies/doodad_policy.rb b/app/policies/doodad_policy.rb new file mode 100644 index 00000000..654eabab --- /dev/null +++ b/app/policies/doodad_policy.rb @@ -0,0 +1,56 @@ +class DoodadPolicy + attr_reader :user, :doodad + + def initialize(user, doodad) + @user = user || User.new + @doodad = doodad + end + + class Scope + def initialize(user, scope) + @user = user + @scope = scope + end + + def resolve + if user.admin? + scope.all + else + scope.where(is_public: true) + end + end + + private + + attr_reader :user, :scope + end + + def index? + true + end + + def show? + @user.admin? || @user == @doodad.user || @doodad.is_public? + end + + def create? + @user.admin? || true + end + + def new? + @user.present? + end + + def edit? + @user.admin? || @user == @doodad.user || @doodad.user.nil? + end + + def update? + @user.admin? || @user == @doodad.user || @doodad.user.nil? + end + + def destroy? + @user.admin? || @user == @doodad.user || @doodad.user.nil? + end + +end diff --git a/app/views/doodads/_doodad.html.haml b/app/views/doodads/_doodad.html.haml new file mode 100644 index 00000000..3ffd8e4c --- /dev/null +++ b/app/views/doodads/_doodad.html.haml @@ -0,0 +1,3 @@ +.doodad + = doodad.body.html_safe + = link_to 'Edit', edit_doodad_path(doodad) diff --git a/app/views/doodads/_doodad.json.jbuilder b/app/views/doodads/_doodad.json.jbuilder new file mode 100644 index 00000000..2a752d11 --- /dev/null +++ b/app/views/doodads/_doodad.json.jbuilder @@ -0,0 +1,2 @@ +json.extract! doodad, :id, :body, :user_id, :is_public, :created_at, :updated_at +json.url doodad_url(doodad, format: :json) diff --git a/app/views/doodads/_form.html.haml b/app/views/doodads/_form.html.haml new file mode 100644 index 00000000..92ed62d3 --- /dev/null +++ b/app/views/doodads/_form.html.haml @@ -0,0 +1,10 @@ += simple_form_for(@doodad) do |f| + = f.error_notification + + .form-inputs + = f.input :body + = f.hidden_field :user_id + = f.input :is_public + + .form-actions + = f.button :submit diff --git a/app/views/doodads/edit.html.haml b/app/views/doodads/edit.html.haml new file mode 100644 index 00000000..9df91dc9 --- /dev/null +++ b/app/views/doodads/edit.html.haml @@ -0,0 +1,5 @@ +%h1 Editing doodad + += render 'form' + += link_to 'Cancel', doodads_path diff --git a/app/views/doodads/index.html.haml b/app/views/doodads/index.html.haml new file mode 100644 index 00000000..ce9fa0e4 --- /dev/null +++ b/app/views/doodads/index.html.haml @@ -0,0 +1,33 @@ +%h1 Listing doodads + +%p= link_to '+ Build New Doodad', new_doodad_path + +%table + %thead + %tr + %th Body + %th User + %th Is public + %th + %th + %th + + %tbody + - @doodads.each do |doodad| + %tr + %td= doodad.body.html_safe + %td= doodad.user + %td= doodad.is_public + - if policy(doodad).show? + %td= link_to 'Show', doodad + - else + %td + - if policy(doodad).edit? + %td= link_to 'Edit', edit_doodad_path(doodad) + - else + %td + - if policy(doodad).destroy? + %td= link_to 'Destroy', doodad, method: :delete, data: { confirm: 'Are you sure?' } + - else + %td + diff --git a/app/views/doodads/index.json.jbuilder b/app/views/doodads/index.json.jbuilder new file mode 100644 index 00000000..5d78f768 --- /dev/null +++ b/app/views/doodads/index.json.jbuilder @@ -0,0 +1 @@ +json.array! @doodads, partial: "doodads/doodad", as: :doodad diff --git a/app/views/doodads/new.html.haml b/app/views/doodads/new.html.haml new file mode 100644 index 00000000..bfb0e587 --- /dev/null +++ b/app/views/doodads/new.html.haml @@ -0,0 +1,5 @@ +%h1 New doodad + += render 'form' + += link_to 'Back', doodads_path diff --git a/app/views/doodads/show.html.haml b/app/views/doodads/show.html.haml new file mode 100644 index 00000000..8548ac36 --- /dev/null +++ b/app/views/doodads/show.html.haml @@ -0,0 +1,15 @@ +%p#notice= notice + +%p + %b Body: + = @doodad.body.html_safe +%p + %b User: + = @doodad.user +%p + %b Is public: + = @doodad.is_public + += link_to 'Edit', edit_doodad_path(@doodad) if policy(@doodad).edit? +\| += link_to 'Back', doodads_path diff --git a/app/views/doodads/show.json.jbuilder b/app/views/doodads/show.json.jbuilder new file mode 100644 index 00000000..b43afa84 --- /dev/null +++ b/app/views/doodads/show.json.jbuilder @@ -0,0 +1 @@ +json.partial! "doodads/doodad", doodad: @doodad diff --git a/app/views/layouts/_navigation_links.html.erb b/app/views/layouts/_navigation_links.html.erb index ba673739..be44691f 100644 --- a/app/views/layouts/_navigation_links.html.erb +++ b/app/views/layouts/_navigation_links.html.erb @@ -1,6 +1,7 @@