diff --git a/app/controllers/assets_controller.rb b/app/controllers/assets_controller.rb index 1d917ae53..664f116a4 100644 --- a/app/controllers/assets_controller.rb +++ b/app/controllers/assets_controller.rb @@ -72,8 +72,9 @@ class AssetsController < ApplicationController @action_url = append_wd_params(@asset .get_action_url(current_user, 'edit', false)) @favicon_url = @asset.favicon_url('edit') - @token = current_user.get_wopi_token - @ttl = (current_user.wopi_token_ttl * 1000).to_s + tkn = current_user.get_wopi_token + @token = tkn.token + @ttl = (tkn.ttl * 1000).to_s create_wopi_file_activity(current_user, true) render layout: false @@ -83,8 +84,9 @@ class AssetsController < ApplicationController @action_url = append_wd_params(@asset .get_action_url(current_user, 'view', false)) @favicon_url = @asset.favicon_url('view') - @token = current_user.get_wopi_token - @ttl = (current_user.wopi_token_ttl * 1000).to_s + tkn = current_user.get_wopi_token + @token = tkn.token + @ttl = (tkn.ttl * 1000).to_s render layout: false end diff --git a/app/models/asset.rb b/app/models/asset.rb index aa583e160..49b09465b 100644 --- a/app/models/asset.rb +++ b/app/models/asset.rb @@ -302,10 +302,18 @@ class Asset < ActiveRecord::Base end def can_perform_action(action) - file_ext = file_file_name.split('.').last - action = get_action(file_ext, action) - return false if action.nil? - true + if (ENV['WOPI_ENABLED'] == "true") + file_ext = file_file_name.split('.').last + + if (file_ext=="wopitest" && (!ENV['WOPI_TEST_ENABLED'] || ENV['WOPI_TEST_ENABLED'] == "false")) + return false + end + action = get_action(file_ext, action) + return false if action.nil? + true + else + false + end end def get_action_url(user, action, with_tokens = true) @@ -325,8 +333,9 @@ class Asset < ActiveRecord::Base ) action_url += "WOPISrc=#{rest_url}" if with_tokens - action_url + "&access_token=#{user.get_wopi_token}"\ - "&access_token_ttl=#{(user.wopi_token_ttl * 1000)}" + token = user.get_wopi_token + action_url + "&access_token=#{token.token}"\ + "&access_token_ttl=#{(token.ttl * 1000)}" else action_url end diff --git a/app/models/token.rb b/app/models/token.rb new file mode 100644 index 000000000..c5c22d5e1 --- /dev/null +++ b/app/models/token.rb @@ -0,0 +1,8 @@ +class Token < ActiveRecord::Base + + validates :token, presence: true + validates :ttl, presence: true + + belongs_to :user, foreign_key: 'user_id', class_name: 'User', inverse_of: :tokens + +end \ No newline at end of file diff --git a/app/models/user.rb b/app/models/user.rb index 5e67ee19e..7608f6d76 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -84,6 +84,7 @@ class User < ActiveRecord::Base has_many :added_protocols, class_name: 'Protocol', foreign_key: 'added_by_id', inverse_of: :added_by has_many :archived_protocols, class_name: 'Protocol', foreign_key: 'archived_by_id', inverse_of: :archived_by has_many :restored_protocols, class_name: 'Protocol', foreign_key: 'restored_by_id', inverse_of: :restored_by + has_many :tokens, class_name: 'Token', foreign_key: 'user_id', inverse_of: :user # If other errors besides parameter "avatar" exist, # they will propagate to "avatar" also, so remove them @@ -254,23 +255,30 @@ class User < ActiveRecord::Base def self.find_by_valid_wopi_token(token) Rails.logger.warn "WOPI: searching by token #{token}" - User.where('wopi_token = ?', token).first - end - - def token_valid - !wopi_token.nil? && (wopi_token_ttl.zero? || wopi_token_ttl > Time.now.to_i) + User + .joins("LEFT OUTER JOIN tokens ON user_id = users.id") + .where('tokens.token = ?', token) + .where('tokens.ttl = 0 OR tokens.ttl > ?', Time.now.to_i) + .first end def get_wopi_token - unless token_valid - # If current token is not valid generate a new one with a one day TTL - self.wopi_token = Devise.friendly_token(20) + # WOPI does not have a good way to request a new token, so a new token should be provided each time this is called, while keeping any old tokens + # as long as they have not yet expired + + tokens = Token.where("user_id = ?", id).distinct + + for token in tokens + if (token.ttl < Time.now.to_i) + token.delete + end + end + + token_string = Devise.friendly_token(20) # WOPI uses millisecond TTLs - self.wopi_token_ttl = (Time.now + 1.days).to_i - save - Rails.logger.warn("WOPI: generating new token #{wopi_token}") - end - Rails.logger.warn("WOPI: returning token #{wopi_token}") + ttl = (Time.now + 1.days).to_i + wopi_token = Token.create(token: token_string, ttl: ttl, user_id: id) + Rails.logger.warn("WOPI: generating new token #{wopi_token.token}") wopi_token end diff --git a/db/migrate/20160728145000_add_wopi.rb b/db/migrate/20161129111100_add_wopi.rb similarity index 84% rename from db/migrate/20160728145000_add_wopi.rb rename to db/migrate/20161129111100_add_wopi.rb index f368bb254..8c89d7efd 100644 --- a/db/migrate/20160728145000_add_wopi.rb +++ b/db/migrate/20161129111100_add_wopi.rb @@ -1,7 +1,5 @@ class AddWopi < ActiveRecord::Migration def up - add_column :users, :wopi_token, :string - add_column :users, :wopi_token_ttl, :integer add_column :assets, :lock, :string, limit: 1024 add_column :assets, :lock_ttl, :integer @@ -28,15 +26,20 @@ class AddWopi < ActiveRecord::Migration t.integer :wopi_app_id, null: false end + create_table :tokens do |t| + t.string :token, null: false + t.integer :ttl, null: false + t.integer :user_id, null: false + end + add_foreign_key :wopi_actions, :wopi_apps, column: :wopi_app_id add_foreign_key :wopi_apps, :wopi_discoveries, column: :wopi_discovery_id + add_foreign_key :tokens, :users, column: :user_id add_index :wopi_actions, [:extension, :action] end def down - remove_column :users, :wopi_token - remove_column :users, :wopi_token_ttl remove_column :assets, :lock remove_column :assets, :lock_ttl @@ -45,5 +48,6 @@ class AddWopi < ActiveRecord::Migration drop_table :wopi_actions drop_table :wopi_apps drop_table :wopi_discoveries + drop_table :tokens end end diff --git a/db/schema.rb b/db/schema.rb index 3151280b9..4f187fadf 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20160809074757) do +ActiveRecord::Schema.define(version: 20161129111100) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -569,6 +569,12 @@ ActiveRecord::Schema.define(version: 20160809074757) do t.datetime "file_updated_at" end + create_table "tokens", force: :cascade do |t| + t.string "token", null: false + t.integer "ttl", null: false + t.integer "user_id", null: false + end + create_table "user_my_modules", force: :cascade do |t| t.integer "user_id", null: false t.integer "my_module_id", null: false @@ -640,8 +646,6 @@ ActiveRecord::Schema.define(version: 20160809074757) do t.string "invited_by_type" t.integer "invitations_count", default: 0 t.integer "tutorial_status", default: 0, null: false - t.string "wopi_token" - t.integer "wopi_token_ttl" end add_index "users", ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true, using: :btree @@ -783,6 +787,7 @@ ActiveRecord::Schema.define(version: 20160809074757) do add_foreign_key "tags", "projects" add_foreign_key "tags", "users", column: "created_by_id" add_foreign_key "tags", "users", column: "last_modified_by_id" + add_foreign_key "tokens", "users" add_foreign_key "user_my_modules", "my_modules" add_foreign_key "user_my_modules", "users" add_foreign_key "user_my_modules", "users", column: "assigned_by_id"