mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2025-10-02 09:54:37 +08:00
Asset sync model and endpoints [SCI-9465] (#6399)
This commit is contained in:
parent
5972140fd0
commit
7376b363a8
9 changed files with 133 additions and 1 deletions
43
app/controllers/asset_sync_controller.rb
Normal file
43
app/controllers/asset_sync_controller.rb
Normal file
|
@ -0,0 +1,43 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AssetSyncController < ApplicationController
|
||||
skip_before_action :authenticate_user!, only: :update
|
||||
skip_before_action :verify_authenticity_token, only: :update
|
||||
before_action :authenticate_asset_sync_token!, only: :update
|
||||
|
||||
def show
|
||||
asset = Asset.find_by(params[:asset_id])
|
||||
|
||||
head :forbidden unless asset && can_manage_asset?(asset)
|
||||
|
||||
asset_sync_token = current_user.asset_sync_tokens.find_or_create_by(asset_id: params[:asset_id])
|
||||
|
||||
unless asset_sync_token.token_valid?
|
||||
asset_sync_token = current_user.asset_sync_tokens.create(asset_id: params[:asset_id])
|
||||
end
|
||||
|
||||
render json: AssetSyncTokenSerializer.new(asset_sync_token).as_json
|
||||
end
|
||||
|
||||
def update
|
||||
head(:conflict) and return if @asset_sync_token.conflicts?(request.headers['VersionToken'])
|
||||
|
||||
@asset.file.attach(io: request.body, filename: @asset.file.filename)
|
||||
@asset.touch
|
||||
|
||||
render json: AssetSyncTokenSerializer.new(@asset_sync_token).as_json
|
||||
end
|
||||
|
||||
# private
|
||||
|
||||
def authenticate_asset_sync_token!
|
||||
@asset_sync_token = AssetSyncToken.find_by(token: request.headers['Authentication'])
|
||||
|
||||
head(:unauthorized) and return unless @asset_sync_token&.token_valid?
|
||||
|
||||
@asset = @asset_sync_token.asset
|
||||
@current_user = @asset_sync_token.user
|
||||
|
||||
head :forbidden unless can_manage_asset?(@asset)
|
||||
end
|
||||
end
|
|
@ -44,6 +44,7 @@ class Asset < ApplicationRecord
|
|||
dependent: :nullify
|
||||
has_many :report_elements, inverse_of: :asset, dependent: :destroy
|
||||
has_one :asset_text_datum, inverse_of: :asset, dependent: :destroy
|
||||
has_many :asset_sync_tokens, dependent: :destroy
|
||||
|
||||
scope :sort_assets, lambda { |sort_value = 'new'|
|
||||
sort = case sort_value
|
||||
|
|
33
app/models/asset_sync_token.rb
Normal file
33
app/models/asset_sync_token.rb
Normal file
|
@ -0,0 +1,33 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AssetSyncToken < ApplicationRecord
|
||||
belongs_to :user
|
||||
belongs_to :asset
|
||||
|
||||
after_initialize :generate_token
|
||||
after_initialize :set_default_expiration
|
||||
|
||||
validates :token, uniqueness: true, presence: true
|
||||
|
||||
def version_token
|
||||
asset.updated_at.to_i.to_s
|
||||
end
|
||||
|
||||
def token_valid?
|
||||
!revoked_at? && expires_at > Time.current
|
||||
end
|
||||
|
||||
def conflicts?(token)
|
||||
version_token != token
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def generate_token
|
||||
self.token ||= SecureRandom.urlsafe_base64(32)
|
||||
end
|
||||
|
||||
def set_default_expiration
|
||||
self.expires_at ||= Constants::ASSET_SYNC_TOKEN_EXPIRATION.from_now
|
||||
end
|
||||
end
|
|
@ -318,6 +318,7 @@ class User < ApplicationRecord
|
|||
has_many :access_tokens, class_name: 'Doorkeeper::AccessToken',
|
||||
foreign_key: :resource_owner_id,
|
||||
dependent: :delete_all
|
||||
has_many :asset_sync_tokens, dependent: :destroy
|
||||
|
||||
has_many :hidden_repository_cell_reminders, dependent: :destroy
|
||||
|
||||
|
|
19
app/serializers/asset_sync_token_serializer.rb
Normal file
19
app/serializers/asset_sync_token_serializer.rb
Normal file
|
@ -0,0 +1,19 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AssetSyncTokenSerializer < ActiveModel::Serializer
|
||||
include Rails.application.routes.url_helpers
|
||||
|
||||
attributes :url, :asset_id, :filename, :token, :asset_id, :version_token, :checksum
|
||||
|
||||
def checksum
|
||||
object.asset.file.checksum
|
||||
end
|
||||
|
||||
def url
|
||||
object.asset.file.url
|
||||
end
|
||||
|
||||
def filename
|
||||
object.asset.file.filename
|
||||
end
|
||||
end
|
|
@ -416,6 +416,8 @@ class Constants
|
|||
FAST_STATUS_POLLING_INTERVAL = 5000
|
||||
SLOW_STATUS_POLLING_INTERVAL = 10000
|
||||
|
||||
ASSET_SYNC_TOKEN_EXPIRATION = 1.year
|
||||
|
||||
# ) \ / (
|
||||
# /|\ )\_/( /|\
|
||||
# * / | \ (/\|/\) / | \ *
|
||||
|
|
|
@ -1002,6 +1002,9 @@ Rails.application.routes.draw do
|
|||
end
|
||||
end
|
||||
|
||||
get 'asset_sync/:asset_id', to: 'asset_sync#show'
|
||||
put 'asset_sync', to: 'asset_sync#update'
|
||||
|
||||
post 'global_activities', to: 'global_activities#index'
|
||||
|
||||
constraints WopiSubdomain do
|
||||
|
|
15
db/migrate/20231006141428_create_asset_sync_tokens.rb
Normal file
15
db/migrate/20231006141428_create_asset_sync_tokens.rb
Normal file
|
@ -0,0 +1,15 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class CreateAssetSyncTokens < ActiveRecord::Migration[7.0]
|
||||
def change
|
||||
create_table :asset_sync_tokens do |t|
|
||||
t.references :user, null: false, foreign_key: true
|
||||
t.references :asset, null: false, foreign_key: true
|
||||
t.string :token, index: { unique: true }
|
||||
t.timestamp :expires_at
|
||||
t.timestamp :revoked_at
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
end
|
||||
end
|
17
db/schema.rb
17
db/schema.rb
|
@ -10,7 +10,7 @@
|
|||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema[7.0].define(version: 2023_10_03_114337) do
|
||||
ActiveRecord::Schema[7.0].define(version: 2023_10_06_141428) do
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "btree_gist"
|
||||
enable_extension "pg_trgm"
|
||||
|
@ -76,6 +76,19 @@ ActiveRecord::Schema[7.0].define(version: 2023_10_03_114337) do
|
|||
t.datetime "updated_at", null: false
|
||||
end
|
||||
|
||||
create_table "asset_sync_tokens", force: :cascade do |t|
|
||||
t.bigint "user_id", null: false
|
||||
t.bigint "asset_id", null: false
|
||||
t.string "token"
|
||||
t.datetime "expires_at", precision: nil
|
||||
t.datetime "revoked_at", precision: nil
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.index ["asset_id"], name: "index_asset_sync_tokens_on_asset_id"
|
||||
t.index ["token"], name: "index_asset_sync_tokens_on_token", unique: true
|
||||
t.index ["user_id"], name: "index_asset_sync_tokens_on_user_id"
|
||||
end
|
||||
|
||||
create_table "asset_text_data", force: :cascade do |t|
|
||||
t.text "data", null: false
|
||||
t.bigint "asset_id", null: false
|
||||
|
@ -1309,6 +1322,8 @@ ActiveRecord::Schema[7.0].define(version: 2023_10_03_114337) do
|
|||
add_foreign_key "activities", "my_modules"
|
||||
add_foreign_key "activities", "projects"
|
||||
add_foreign_key "activities", "users", column: "owner_id"
|
||||
add_foreign_key "asset_sync_tokens", "assets"
|
||||
add_foreign_key "asset_sync_tokens", "users"
|
||||
add_foreign_key "asset_text_data", "assets"
|
||||
add_foreign_key "assets", "users", column: "created_by_id"
|
||||
add_foreign_key "assets", "users", column: "last_modified_by_id"
|
||||
|
|
Loading…
Add table
Reference in a new issue