From 940ea3051b007d435b13134fae914e1643316bd3 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Wed, 20 Mar 2019 11:01:53 +0100 Subject: [PATCH] chain historyValues with sha256 footprints --- app/models/history_value.rb | 28 +++ app/models/invoice.rb | 2 +- app/models/invoice_item.rb | 2 +- ...0091148_add_footprint_to_history_values.rb | 5 + db/schema.rb | 183 +++++++++--------- lib/tasks/fablab/setup.rake | 7 + 6 files changed, 134 insertions(+), 93 deletions(-) create mode 100644 db/migrate/20190320091148_add_footprint_to_history_values.rb diff --git a/app/models/history_value.rb b/app/models/history_value.rb index 902acf022..07a7660be 100644 --- a/app/models/history_value.rb +++ b/app/models/history_value.rb @@ -1,4 +1,32 @@ +# frozen_string_literal: true + +require 'checksum' + +# Setting values, kept history of modifications class HistoryValue < ActiveRecord::Base belongs_to :setting belongs_to :user + + def chain_record + self.footprint = compute_footprint + save! + end + + def check_footprint + footprint == compute_footprint + end + + private + + def compute_footprint + max_date = created_at || Time.current + previous = HistoryValue.where('created_at < ?', max_date) + .order('created_at DESC') + .limit(1) + + columns = HistoryValue.columns.map(&:name) + .delete_if { |c| %w[footprint updated_at].include? c } + + Checksum.text("#{columns.map { |c| self[c] }.join}#{previous.first ? previous.first.footprint : ''}") + end end diff --git a/app/models/invoice.rb b/app/models/invoice.rb index 19ce53a85..33aa18b68 100644 --- a/app/models/invoice.rb +++ b/app/models/invoice.rb @@ -230,7 +230,7 @@ class Invoice < ActiveRecord::Base invoice_items.map(&:check_footprint).all? && footprint == compute_footprint end - # private + private def generate_and_send_invoice unless Rails.env.test? diff --git a/app/models/invoice_item.rb b/app/models/invoice_item.rb index 6183a016a..7967b4347 100644 --- a/app/models/invoice_item.rb +++ b/app/models/invoice_item.rb @@ -20,7 +20,7 @@ class InvoiceItem < ActiveRecord::Base footprint == compute_footprint end - # private + private def compute_footprint max_date = created_at || Time.current diff --git a/db/migrate/20190320091148_add_footprint_to_history_values.rb b/db/migrate/20190320091148_add_footprint_to_history_values.rb new file mode 100644 index 000000000..0afbb1bc7 --- /dev/null +++ b/db/migrate/20190320091148_add_footprint_to_history_values.rb @@ -0,0 +1,5 @@ +class AddFootprintToHistoryValues < ActiveRecord::Migration + def change + add_column :history_values, :footprint, :string + end +end diff --git a/db/schema.rb b/db/schema.rb index 341bc9b70..18c91bd5f 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,12 +11,12 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20190314095931) do +ActiveRecord::Schema.define(version: 20190320091148) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" - enable_extension "unaccent" enable_extension "pg_trgm" + enable_extension "unaccent" create_table "abuses", force: :cascade do |t| t.integer "signaled_id" @@ -44,14 +44,14 @@ ActiveRecord::Schema.define(version: 20190314095931) do end create_table "addresses", force: :cascade do |t| - t.string "address" - t.string "street_number" - t.string "route" - t.string "locality" - t.string "country" - t.string "postal_code" + t.string "address", limit: 255 + t.string "street_number", limit: 255 + t.string "route", limit: 255 + t.string "locality", limit: 255 + t.string "country", limit: 255 + t.string "postal_code", limit: 255 t.integer "placeable_id" - t.string "placeable_type" + t.string "placeable_type", limit: 255 t.datetime "created_at" t.datetime "updated_at" end @@ -67,9 +67,9 @@ ActiveRecord::Schema.define(version: 20190314095931) do create_table "assets", force: :cascade do |t| t.integer "viewable_id" - t.string "viewable_type" - t.string "attachment" - t.string "type" + t.string "viewable_type", limit: 255 + t.string "attachment", limit: 255 + t.string "type", limit: 255 t.datetime "created_at" t.datetime "updated_at" end @@ -86,12 +86,12 @@ ActiveRecord::Schema.define(version: 20190314095931) do create_table "availabilities", force: :cascade do |t| t.datetime "start_at" t.datetime "end_at" - t.string "available_type" + t.string "available_type", limit: 255 t.datetime "created_at" t.datetime "updated_at" t.integer "nb_total_places" - t.boolean "destroying", default: false - t.boolean "lock", default: false + t.boolean "destroying", default: false + t.boolean "lock", default: false end create_table "availability_tags", force: :cascade do |t| @@ -105,7 +105,7 @@ ActiveRecord::Schema.define(version: 20190314095931) do add_index "availability_tags", ["tag_id"], name: "index_availability_tags_on_tag_id", using: :btree create_table "categories", force: :cascade do |t| - t.string "name" + t.string "name", limit: 255 t.datetime "created_at" t.datetime "updated_at" t.string "slug" @@ -114,7 +114,7 @@ ActiveRecord::Schema.define(version: 20190314095931) do add_index "categories", ["slug"], name: "index_categories_on_slug", unique: true, using: :btree create_table "components", force: :cascade do |t| - t.string "name", null: false + t.string "name", limit: 255, null: false end create_table "coupons", force: :cascade do |t| @@ -132,7 +132,7 @@ ActiveRecord::Schema.define(version: 20190314095931) do create_table "credits", force: :cascade do |t| t.integer "creditable_id" - t.string "creditable_type" + t.string "creditable_type", limit: 255 t.integer "plan_id" t.integer "hours" t.datetime "created_at" @@ -173,7 +173,7 @@ ActiveRecord::Schema.define(version: 20190314095931) do add_index "event_themes", ["slug"], name: "index_event_themes_on_slug", unique: true, using: :btree create_table "events", force: :cascade do |t| - t.string "title" + t.string "title", limit: 255 t.text "description" t.datetime "created_at" t.datetime "updated_at" @@ -211,10 +211,10 @@ ActiveRecord::Schema.define(version: 20190314095931) do add_index "exports", ["user_id"], name: "index_exports_on_user_id", using: :btree create_table "friendly_id_slugs", force: :cascade do |t| - t.string "slug", null: false - t.integer "sluggable_id", null: false + t.string "slug", limit: 255, null: false + t.integer "sluggable_id", null: false t.string "sluggable_type", limit: 50 - t.string "scope" + t.string "scope", limit: 255 t.datetime "created_at" end @@ -224,10 +224,10 @@ ActiveRecord::Schema.define(version: 20190314095931) do add_index "friendly_id_slugs", ["sluggable_type"], name: "index_friendly_id_slugs_on_sluggable_type", using: :btree create_table "groups", force: :cascade do |t| - t.string "name" + t.string "name", limit: 255 t.datetime "created_at" t.datetime "updated_at" - t.string "slug" + t.string "slug", limit: 255 t.boolean "disabled" end @@ -239,6 +239,7 @@ ActiveRecord::Schema.define(version: 20190314095931) do t.string "value" t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.string "footprint" end add_index "history_values", ["setting_id"], name: "index_history_values_on_setting_id", using: :btree @@ -246,7 +247,7 @@ ActiveRecord::Schema.define(version: 20190314095931) do create_table "invoice_items", force: :cascade do |t| t.integer "invoice_id" - t.string "stp_invoice_item_id" + t.string "stp_invoice_item_id", limit: 255 t.integer "amount" t.datetime "created_at" t.datetime "updated_at" @@ -260,17 +261,17 @@ ActiveRecord::Schema.define(version: 20190314095931) do create_table "invoices", force: :cascade do |t| t.integer "invoiced_id" - t.string "invoiced_type" - t.string "stp_invoice_id" + t.string "invoiced_type", limit: 255 + t.string "stp_invoice_id", limit: 255 t.integer "total" t.datetime "created_at" t.datetime "updated_at" t.integer "user_id" - t.string "reference" - t.string "avoir_mode" + t.string "reference", limit: 255 + t.string "avoir_mode", limit: 255 t.datetime "avoir_date" t.integer "invoice_id" - t.string "type" + t.string "type", limit: 255 t.boolean "subscription_to_expire" t.text "description" t.integer "wallet_amount" @@ -287,17 +288,17 @@ ActiveRecord::Schema.define(version: 20190314095931) do add_index "invoices", ["wallet_transaction_id"], name: "index_invoices_on_wallet_transaction_id", using: :btree create_table "licences", force: :cascade do |t| - t.string "name", null: false + t.string "name", limit: 255, null: false t.text "description" end create_table "machines", force: :cascade do |t| - t.string "name", null: false + t.string "name", limit: 255, null: false t.text "description" t.text "spec" t.datetime "created_at" t.datetime "updated_at" - t.string "slug" + t.string "slug", limit: 255 t.boolean "disabled" end @@ -314,14 +315,14 @@ ActiveRecord::Schema.define(version: 20190314095931) do create_table "notifications", force: :cascade do |t| t.integer "receiver_id" t.integer "attached_object_id" - t.string "attached_object_type" + t.string "attached_object_type", limit: 255 t.integer "notification_type_id" - t.boolean "is_read", default: false + t.boolean "is_read", default: false t.datetime "created_at" t.datetime "updated_at" t.string "receiver_type" - t.boolean "is_send", default: false - t.jsonb "meta_data", default: {} + t.boolean "is_send", default: false + t.jsonb "meta_data", default: {} end add_index "notifications", ["notification_type_id"], name: "index_notifications_on_notification_type_id", using: :btree @@ -390,20 +391,20 @@ ActiveRecord::Schema.define(version: 20190314095931) do add_index "organizations", ["profile_id"], name: "index_organizations_on_profile_id", using: :btree create_table "plans", force: :cascade do |t| - t.string "name" + t.string "name", limit: 255 t.integer "amount" - t.string "interval" + t.string "interval", limit: 255 t.integer "group_id" - t.string "stp_plan_id" + t.string "stp_plan_id", limit: 255 t.datetime "created_at" t.datetime "updated_at" - t.integer "training_credit_nb", default: 0 - t.boolean "is_rolling", default: true + t.integer "training_credit_nb", default: 0 + t.boolean "is_rolling", default: true t.text "description" t.string "type" t.string "base_name" - t.integer "ui_weight", default: 0 - t.integer "interval_count", default: 1 + t.integer "ui_weight", default: 0 + t.integer "interval_count", default: 1 t.string "slug" t.boolean "disabled" end @@ -433,11 +434,11 @@ ActiveRecord::Schema.define(version: 20190314095931) do create_table "profiles", force: :cascade do |t| t.integer "user_id" - t.string "first_name" - t.string "last_name" + t.string "first_name", limit: 255 + t.string "last_name", limit: 255 t.boolean "gender" t.date "birthday" - t.string "phone" + t.string "phone", limit: 255 t.text "interest" t.text "software_mastered" t.datetime "created_at" @@ -467,7 +468,7 @@ ActiveRecord::Schema.define(version: 20190314095931) do t.integer "project_id" t.datetime "created_at" t.datetime "updated_at" - t.string "title" + t.string "title", limit: 255 t.integer "step_nb" end @@ -478,27 +479,27 @@ ActiveRecord::Schema.define(version: 20190314095931) do t.integer "user_id" t.datetime "created_at" t.datetime "updated_at" - t.boolean "is_valid", default: false - t.string "valid_token" + t.boolean "is_valid", default: false + t.string "valid_token", limit: 255 end add_index "project_users", ["project_id"], name: "index_project_users_on_project_id", using: :btree add_index "project_users", ["user_id"], name: "index_project_users_on_user_id", using: :btree create_table "projects", force: :cascade do |t| - t.string "name" + t.string "name", limit: 255 t.text "description" t.datetime "created_at" t.datetime "updated_at" t.integer "author_id" t.text "tags" t.integer "licence_id" - t.string "state" - t.string "slug" + t.string "state", limit: 255 + t.string "slug", limit: 255 t.datetime "published_at" end - add_index "projects", ["slug"], name: "index_projects_on_slug", unique: true, using: :btree + add_index "projects", ["slug"], name: "index_projects_on_slug", using: :btree create_table "projects_components", force: :cascade do |t| t.integer "project_id" @@ -538,19 +539,19 @@ ActiveRecord::Schema.define(version: 20190314095931) do t.datetime "created_at" t.datetime "updated_at" t.integer "reservable_id" - t.string "reservable_type" - t.string "stp_invoice_id" + t.string "reservable_type", limit: 255 + t.string "stp_invoice_id", limit: 255 t.integer "nb_reserve_places" end - add_index "reservations", ["reservable_type", "reservable_id"], name: "index_reservations_on_reservable_type_and_reservable_id", using: :btree + add_index "reservations", ["reservable_id", "reservable_type"], name: "index_reservations_on_reservable_id_and_reservable_type", using: :btree add_index "reservations", ["stp_invoice_id"], name: "index_reservations_on_stp_invoice_id", using: :btree add_index "reservations", ["user_id"], name: "index_reservations_on_user_id", using: :btree create_table "roles", force: :cascade do |t| - t.string "name" + t.string "name", limit: 255 t.integer "resource_id" - t.string "resource_type" + t.string "resource_type", limit: 255 t.datetime "created_at" t.datetime "updated_at" end @@ -624,18 +625,18 @@ ActiveRecord::Schema.define(version: 20190314095931) do create_table "statistic_fields", force: :cascade do |t| t.integer "statistic_index_id" - t.string "key" - t.string "label" + t.string "key", limit: 255 + t.string "label", limit: 255 t.datetime "created_at" t.datetime "updated_at" - t.string "data_type" + t.string "data_type", limit: 255 end add_index "statistic_fields", ["statistic_index_id"], name: "index_statistic_fields_on_statistic_index_id", using: :btree create_table "statistic_graphs", force: :cascade do |t| t.integer "statistic_index_id" - t.string "chart_type" + t.string "chart_type", limit: 255 t.integer "limit" t.datetime "created_at" t.datetime "updated_at" @@ -644,17 +645,17 @@ ActiveRecord::Schema.define(version: 20190314095931) do add_index "statistic_graphs", ["statistic_index_id"], name: "index_statistic_graphs_on_statistic_index_id", using: :btree create_table "statistic_indices", force: :cascade do |t| - t.string "es_type_key" - t.string "label" + t.string "es_type_key", limit: 255 + t.string "label", limit: 255 t.datetime "created_at" t.datetime "updated_at" - t.boolean "table", default: true - t.boolean "ca", default: true + t.boolean "table", default: true + t.boolean "ca", default: true end create_table "statistic_sub_types", force: :cascade do |t| - t.string "key" - t.string "label" + t.string "key", limit: 255 + t.string "label", limit: 255 t.datetime "created_at" t.datetime "updated_at" end @@ -671,8 +672,8 @@ ActiveRecord::Schema.define(version: 20190314095931) do create_table "statistic_types", force: :cascade do |t| t.integer "statistic_index_id" - t.string "key" - t.string "label" + t.string "key", limit: 255 + t.string "label", limit: 255 t.boolean "graph" t.datetime "created_at" t.datetime "updated_at" @@ -690,7 +691,7 @@ ActiveRecord::Schema.define(version: 20190314095931) do create_table "subscriptions", force: :cascade do |t| t.integer "plan_id" t.integer "user_id" - t.string "stp_subscription_id" + t.string "stp_subscription_id", limit: 255 t.datetime "created_at" t.datetime "updated_at" t.datetime "expiration_date" @@ -709,7 +710,7 @@ ActiveRecord::Schema.define(version: 20190314095931) do add_index "tags", ["name"], name: "index_tags_on_name", unique: true, using: :btree create_table "themes", force: :cascade do |t| - t.string "name", null: false + t.string "name", limit: 255, null: false end create_table "tickets", force: :cascade do |t| @@ -724,13 +725,13 @@ ActiveRecord::Schema.define(version: 20190314095931) do add_index "tickets", ["reservation_id"], name: "index_tickets_on_reservation_id", using: :btree create_table "trainings", force: :cascade do |t| - t.string "name" + t.string "name", limit: 255 t.datetime "created_at" t.datetime "updated_at" t.integer "nb_total_places" - t.string "slug" + t.string "slug", limit: 255 t.text "description" - t.boolean "public_page", default: true + t.boolean "public_page", default: true t.boolean "disabled" end @@ -786,31 +787,31 @@ ActiveRecord::Schema.define(version: 20190314095931) do add_index "user_trainings", ["user_id"], name: "index_user_trainings_on_user_id", using: :btree create_table "users", force: :cascade do |t| - t.string "email", default: "", null: false - t.string "encrypted_password", default: "", null: false - t.string "reset_password_token" + t.string "email", limit: 255, default: "", null: false + t.string "encrypted_password", limit: 255, default: "", null: false + t.string "reset_password_token", limit: 255 t.datetime "reset_password_sent_at" t.datetime "remember_created_at" - t.integer "sign_in_count", default: 0, null: false + t.integer "sign_in_count", default: 0, null: false t.datetime "current_sign_in_at" t.datetime "last_sign_in_at" - t.string "current_sign_in_ip" - t.string "last_sign_in_ip" - t.string "confirmation_token" + t.string "current_sign_in_ip", limit: 255 + t.string "last_sign_in_ip", limit: 255 + t.string "confirmation_token", limit: 255 t.datetime "confirmed_at" t.datetime "confirmation_sent_at" - t.string "unconfirmed_email" - t.integer "failed_attempts", default: 0, null: false - t.string "unlock_token" + t.string "unconfirmed_email", limit: 255 + t.integer "failed_attempts", default: 0, null: false + t.string "unlock_token", limit: 255 t.datetime "locked_at" t.datetime "created_at" t.datetime "updated_at" - t.boolean "is_allow_contact", default: true + t.boolean "is_allow_contact", default: true t.integer "group_id" - t.string "stp_customer_id" - t.string "username" - t.string "slug" - t.boolean "is_active", default: true + t.string "stp_customer_id", limit: 255 + t.string "username", limit: 255 + t.string "slug", limit: 255 + t.boolean "is_active", default: true t.string "provider" t.string "uid" t.string "auth_token" diff --git a/lib/tasks/fablab/setup.rake b/lib/tasks/fablab/setup.rake index 00bd54fca..6ca8fed92 100644 --- a/lib/tasks/fablab/setup.rake +++ b/lib/tasks/fablab/setup.rake @@ -16,6 +16,13 @@ namespace :fablab do InvoiceItem.order(:created_at).all.each(&:chain_record) end + desc 'assign all footprints to existing HistoryValue records' + task chain_history_values_records: :environment do + raise "Footprints were already generated, won't regenerate" if HistoryValue.where.not(footprint: nil).count.positive? + + HistoryValue.order(:created_at).all.each(&:chain_record) + end + desc 'assign environment value to all invoices' task set_environment_to_invoices: :environment do Invoice.all.each do |i|