Compare commits

...

26 Commits

Author SHA1 Message Date
8ae1fd1c55 remove old 2023-06-23 13:54:18 +04:00
b472709542 fix restore changes 2023-06-23 13:00:45 +04:00
38c439c817 ruby-raw: history prelatest 2023-06-22 10:21:44 +04:00
a172afc904 ruby-raw: history restore 2023-06-20 18:15:05 +04:00
0b5692f085 ruby-raw: history next 2023-06-20 17:21:34 +04:00
87cdf95c17 ruby-raw: history done+- 2023-06-20 13:59:41 +04:00
060cc1f0cc ruby-raw: history 2023-06-16 19:59:28 +04:00
321e48bad2 ruby-raw: history 2023-06-15 18:37:52 +04:00
30aaaa2b67 ruby-raw: history, storage 2023-06-14 18:52:15 +04:00
43368fd9fa ruby-raw: restore endpoint 2023-06-14 09:55:07 +04:00
1c5b64bba7 ruby: add receipt stages to build and up containers 2023-06-13 15:23:03 +04:00
df93bbda77 ruby: add containerization 2023-06-13 15:21:03 +04:00
3754bb6b03 ruby: add receipt stages to generate bin files 2023-06-13 14:40:48 +04:00
a51fad84e9 ruby: delete files that should be ignored 2023-06-13 14:39:28 +04:00
1469ce6c0f ruby: move example-specific ignored files to the root of the example 2023-06-13 14:36:23 +04:00
c534989cb3 ruby: remove sqlite3 dependency as it's not used 2023-06-13 14:32:45 +04:00
f57292a3ae ruby: add a recipe to start the server in the Makefile 2023-06-13 14:30:12 +04:00
4961da4c11 ruby: simplify server configuration 2023-06-13 14:29:42 +04:00
c21f87bdb0 ruby: standardize the format of the URIs in the configuration 2023-06-13 10:42:55 +04:00
bd98cd4e54 ruby: support for private network communication 2023-06-11 23:28:24 +04:00
9429e080b2 ruby: support for configuration via environment variables 2023-06-11 23:14:20 +04:00
26a9de9250 ruby: add lint recipe to Makefile 2023-06-09 21:31:27 +04:00
874f551318 ruby: add install recipe to Makefile 2023-06-09 21:31:08 +04:00
5e50db62f2 ruby: add help recipe to Makefile 2023-06-09 21:30:47 +04:00
64fdfe62d9 ruby: add sorbet as a type-checker dependency 2023-06-09 21:30:15 +04:00
036b1e50d4 ruby: add rubocop as a lint dependency 2023-06-09 12:17:30 +04:00
57 changed files with 1997 additions and 769 deletions

5
.gitignore vendored
View File

@ -22,8 +22,3 @@
/web/documentserver-example/csharp/packages
/web/documentserver-example/csharp-mvc/packages
/web/documentserver-example/java-spring/documents/
/web/documentserver-example/ruby/.bundle
/web/documentserver-example/ruby/db/*.sqlite3
/web/documentserver-example/ruby/db/*.sqlite3-journal
/web/documentserver-example/ruby/log/*
/web/documentserver-example/ruby/tmp

View File

@ -0,0 +1,16 @@
# User-specific files: editor, system, etc.
.DS_Store
.idea
.project
.settings
.vs
.vscode
*.suo
*.user
# Project files.
bin
db
log
sorbet
tmp

View File

@ -0,0 +1,17 @@
FROM ruby:3.2.2-alpine3.18 AS example
WORKDIR /srv
COPY . .
RUN \
apk update && \
apk add --no-cache \
build-base \
gcompat \
git \
make \
nodejs && \
gem install bundler -v 2.3.7 && \
make prod
CMD ["make", "prod-server"]
FROM nginx:1.23.4-alpine3.17 AS proxy
COPY proxy/nginx.conf /etc/nginx/nginx.conf

View File

@ -2,15 +2,19 @@ source "https://rubygems.org"
gem "byebug", "~> 11.1", :groups => [:development, :test]
gem "coffee-rails", "~> 5.0"
gem "dalli", "~> 3.2", :group => :development
gem "jbuilder", "~> 2.11"
gem "jquery-rails", "~> 4.5"
gem "jwt", "~> 2.7"
gem "mimemagic", github: "mimemagicrb/mimemagic", ref: "01f92d86d15d85cfd0f20dabd025dcbd36a8a60f"
gem "rack-cors", "~> 2.0"
gem "rails", "~> 7.0"
gem "rubocop", "~> 1.52", :group => :development
gem "sass-rails", "~> 6.0"
gem "sdoc", "~> 2.6", :group => :doc
gem "sqlite3", "1.4.2"
gem "sorbet", "~> 0.5.10871", :group => :development
gem "sorbet-runtime", "~> 0.5.10871"
gem "tapioca", "~> 0.11.6", :group => :development
gem "turbolinks", "~> 5.2"
gem "tzinfo-data", "~> 1.2023"
gem "uglifier", "~> 4.2"

View File

@ -73,6 +73,7 @@ GEM
i18n (>= 1.6, < 2)
minitest (>= 5.1)
tzinfo (~> 2.0)
ast (2.4.2)
bindex (0.8.1)
builder (3.2.4)
byebug (11.1.3)
@ -85,7 +86,9 @@ GEM
coffee-script-source (1.12.2)
concurrent-ruby (1.2.2)
crass (1.0.6)
dalli (3.2.4)
date (3.3.3)
diff-lcs (1.5.0)
erubi (1.12.0)
execjs (2.8.1)
ffi (1.15.5)
@ -100,6 +103,7 @@ GEM
rails-dom-testing (>= 1, < 3)
railties (>= 4.2.0)
thor (>= 0.14, < 2.0)
json (2.6.3)
jwt (2.7.0)
loofah (2.21.3)
crass (~> 1.0.2)
@ -124,6 +128,7 @@ GEM
timeout
net-smtp (0.3.3)
net-protocol
netrc (0.11.0)
nio4r (2.5.9)
nokogiri (1.15.2-arm64-darwin)
racc (~> 1.4)
@ -131,6 +136,10 @@ GEM
racc (~> 1.4)
nokogiri (1.15.2-x86_64-linux)
racc (~> 1.4)
parallel (1.23.0)
parser (3.2.2.3)
ast (~> 2.4.1)
racc
psych (5.1.0)
stringio
racc (1.7.0)
@ -166,9 +175,30 @@ GEM
rake (>= 12.2)
thor (~> 1.0)
zeitwerk (~> 2.5)
rainbow (3.1.1)
rake (13.0.6)
rbi (0.0.16)
ast
parser (>= 2.6.4.0)
sorbet-runtime (>= 0.5.9204)
unparser
rdoc (6.5.0)
psych (>= 4.0.0)
regexp_parser (2.8.0)
rexml (3.2.5)
rubocop (1.52.0)
json (~> 2.3)
parallel (~> 1.10)
parser (>= 3.2.0.0)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 1.8, < 3.0)
rexml (>= 3.2.5, < 4.0)
rubocop-ast (>= 1.28.0, < 2.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 2.4.0, < 3.0)
rubocop-ast (1.29.0)
parser (>= 3.2.1.0)
ruby-progressbar (1.13.0)
sass-rails (6.0.0)
sassc-rails (~> 2.1, >= 2.1.1)
sassc (2.4.0)
@ -181,6 +211,18 @@ GEM
tilt
sdoc (2.6.1)
rdoc (>= 5.0)
sorbet (0.5.10871)
sorbet-static (= 0.5.10871)
sorbet-runtime (0.5.10871)
sorbet-static (0.5.10871-universal-darwin-22)
sorbet-static (0.5.10871-x86_64-linux)
sorbet-static-and-runtime (0.5.10871)
sorbet (= 0.5.10871)
sorbet-runtime (= 0.5.10871)
spoom (1.2.1)
sorbet (>= 0.5.10187)
sorbet-runtime (>= 0.5.9204)
thor (>= 0.19.2)
sprockets (4.2.0)
concurrent-ruby (~> 1.0)
rack (>= 2.2.4, < 4)
@ -188,9 +230,17 @@ GEM
actionpack (>= 5.2)
activesupport (>= 5.2)
sprockets (>= 3.0.0)
sqlite3 (1.4.2)
stringio (3.0.7)
systemu (2.6.5)
tapioca (0.11.6)
bundler (>= 2.2.25)
netrc (>= 0.11.0)
parallel (>= 1.21.0)
rbi (~> 0.0.0, >= 0.0.16)
sorbet-static-and-runtime (>= 0.5.10187)
spoom (~> 1.2.0, >= 1.2.0)
thor (>= 1.2.0)
yard-sorbet
thor (1.2.2)
tilt (2.2.0)
timeout (0.3.2)
@ -203,6 +253,10 @@ GEM
tzinfo (>= 1.0.0)
uglifier (4.2.0)
execjs (>= 0.3.0, < 3)
unicode-display_width (2.4.2)
unparser (0.6.7)
diff-lcs (~> 1.3)
parser (>= 3.2.0)
uuid (2.3.9)
macaddr (~> 1.0)
web-console (4.2.0)
@ -214,6 +268,10 @@ GEM
websocket-driver (0.7.5)
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.5)
yard (0.9.34)
yard-sorbet (0.8.1)
sorbet-runtime (>= 0.5)
yard (>= 0.9)
zeitwerk (2.6.8)
PLATFORMS
@ -224,15 +282,19 @@ PLATFORMS
DEPENDENCIES
byebug (~> 11.1)
coffee-rails (~> 5.0)
dalli (~> 3.2)
jbuilder (~> 2.11)
jquery-rails (~> 4.5)
jwt (~> 2.7)
mimemagic!
rack-cors (~> 2.0)
rails (~> 7.0)
rubocop (~> 1.52)
sass-rails (~> 6.0)
sdoc (~> 2.6)
sqlite3 (= 1.4.2)
sorbet (~> 0.5.10871)
sorbet-runtime (~> 0.5.10871)
tapioca (~> 0.11.6)
turbolinks (~> 5.2)
tzinfo-data (~> 1.2023)
uglifier (~> 4.2)

View File

@ -0,0 +1,36 @@
.DEFAULT_GOAL := help
.PHONY: help
help: # Show help message for each of the Makefile recipes.
@grep -E "^[a-z-]+: #" $(MAKEFILE_LIST) | \
sort --dictionary-order | \
awk 'BEGIN {FS = ": # "}; {printf "%s: %s\n", $$1, $$2}'
.PHONY: dev
dev: # Install development dependencies and initialize the project.
@bundle install
@rake app:update:bin
@bundle exec tapioca init
.PHONY: dev-server
dev-server: # Start the development server on localhost at $PORT (default: 3000).
@rails server --using webrick
.PHONY: lint
lint: # Lint the source code for style and check for types.
@bundle exec rubocop
@bundle exec srb tc
.PHONY: prod
prod: # Install production dependencies.
@bundle install --without development doc test
@rake app:update:bin
.PHONY: prod-server
prod-server: # Start the poruction server on 0.0.0.0 at $PORT (default: 3000).
@rails server --environment production --using webrick
.PHONY: up
up: # Build and up docker containers.
@docker-compose build
@docker-compose up -d

View File

@ -1,6 +1,3 @@
# Add your own tasks in files placed in lib/tasks ending in .rake,
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
require File.expand_path('../config/application', __FILE__)
require_relative 'config/application'
Rails.application.load_tasks

View File

@ -0,0 +1,102 @@
#
# (c) Copyright Ascensio System SIA 2023
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# frozen_string_literal: true
# typed: true
# rubocop:disable Metrics/MethodLength
require 'jwt'
require_relative 'models/configuration_manager'
require_relative 'response'
class AuthorizationManager
extend T::Sig
sig { params(config: ConfigurationManager).void }
def initialize(config:)
@config = config
end
sig { params(headers: ActionDispatch::Http::Headers).returns(T::Boolean) }
def authorize(headers:)
enabled ? verify(headers:) : true
end
sig { returns(T::Boolean) }
def enabled
!@config.jwt_secret.empty?
end
sig { params(headers: ActionDispatch::Http::Headers).returns(T::Boolean) }
def document_server_authorize(headers:)
document_server_enabled ? verify(headers:) : true
end
sig { returns(T::Boolean) }
def document_server_enabled
enabled && @config.jwt_use_for_request
end
sig { params(headers: ActionDispatch::Http::Headers).returns(T::Boolean) }
def verify(headers:)
header = headers[@config.jwt_header]
return false unless header
token = header.sub('Bearer ', '')
decoded = decode(token)
!decoded.nil?
end
sig { params(payload: T.untyped).returns(String) }
def encode(payload:)
JWT.encode(
payload,
@config.jwt_secret,
AuthorizationManager.algorithm
)
end
sig { params(payload: String).returns(T.untyped) }
def decode(payload:)
decoded = JWT.decode(
payload,
@config.jwt_secret,
true,
{
algorithm: AuthorizationManager.algorithm
}
)
decoded[0]
rescue StandardError
nil
end
def self.algorithm
'HS256'
end
end
class AuthorizationResponseError
include ResponseError
extend T::Sig
sig { returns(AuthorizationResponseError) }
def self.forbidden
AuthorizationResponseError.new(
'forbidden'
)
end
end

View File

@ -14,6 +14,13 @@
# limitations under the License.
#
# typed: true
# rubocop:disable Metrics/ClassLength
# rubocop:disable Metrics/MethodLength
# rubocop:disable Metrics/AbcSize
# rubocop:disable Metrics/CyclomaticComplexity
# rubocop:disable Metrics/PerceivedComplexity
require 'net/http'
require 'mimemagic'
@ -92,7 +99,7 @@ class HomeController < ApplicationController
end
body = JSON.parse(file_data)
file_name = File.basename(body["filename"])
lang = cookies[:ulang] ? cookies[:ulang] : "en"
file_pass = body["filePass"] ? body["filePass"] : nil
@ -144,45 +151,6 @@ class HomeController < ApplicationController
end
# downloading a history file from public
def downloadhistory
begin
file_name = File.basename(params[:fileName])
user_address = params[:userAddress]
version = params[:ver]
file = params[:file]
isEmbedded = params[:dmode]
if JwtHelper.is_enabled && JwtHelper.use_for_request
jwtHeader = Rails.configuration.header.empty? ? "Authorization" : Rails.configuration.header;
if request.headers[jwtHeader]
hdr = request.headers[jwtHeader]
hdr.slice!(0, "Bearer ".length)
token = JwtHelper.decode(hdr)
if !token || token.eql?("")
render plain: "JWT validation failed", :status => 403
return
end
else
render plain: "JWT validation failed", :status => 403
return
end
end
hist_path = DocumentHelper.storage_path(file_name, user_address) + "-hist" # or to the original document
file_path = File.join(hist_path, version, file)
# add headers to the response to specify the page parameters
response.headers['Content-Length'] = File.size(file_path).to_s
response.headers['Content-Type'] = MimeMagic.by_path(file_path).eql?(nil) ? nil : MimeMagic.by_path(file_path).type
response.headers['Content-Disposition'] = "attachment;filename*=UTF-8\'\'" + ERB::Util.url_encode(file)
send_file file_path, :x_sendfile => true
rescue => ex
render plain: '{ "error": "File not found"}'
end
end
# tracking file changes
def track
file_data = TrackHelper.read_body(request) # read the request body
@ -325,7 +293,7 @@ class HomeController < ApplicationController
res = http.request(req)
data = res.body
if data.size <= 0 || data.size > Rails.configuration.fileSizeMax
if data.size <= 0 || data.size > ConfigurationManager.new.maximum_file_size
render plain: '{"error": "File size is incorrect"}'
return
end
@ -368,7 +336,7 @@ class HomeController < ApplicationController
def reference
body = JSON.parse(request.body.read)
fileName = ""
if body.key?("referenceData")
referenceData = body["referenceData"]
@ -411,4 +379,4 @@ class HomeController < ApplicationController
render plain: data.to_json
end
end
end

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,203 @@
#
# (c) Copyright Ascensio System SIA 2023
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# frozen_string_literal: true
# typed: true
require 'uri'
# The Configuration class provides the environment based configuration for the
# example instance.
# rubocop:disable Metrics/ClassLength
class ConfigurationManager
extend T::Sig
def initialize
@version = T.let('1.5.1', String)
end
# The URI through which an example instance can be accessed.
sig { returns(T.nilable(URI::Generic)) }
def example_uri
url = ENV['EXAMPLE_URL']
return nil if url.nil?
URI.parse(url)
end
# The public URI through which a document-server instance can be accessed.
# For example, it can be used to grant the user's browser access to a
# document-server.
sig { returns(URI::Generic) }
def document_server_public_uri
url = ENV['DOCUMENT_SERVER_PUBLIC_URL'] || 'http://document-server'
URI.parse(url)
end
# The private URI through which a document-server instance can be accessed.
# If no private URI is specified, it will be redirected to the public URI.
# For example, it can be used when both an example instance and a
# document-server instance are on the same closed network.
sig { returns(URI::Generic) }
def document_server_private_uri
url = ENV['DOCUMENT_SERVER_PRIVATE_URL']
return document_server_public_uri if url.nil?
URI.parse(url)
end
sig { returns(URI::Generic) }
def document_server_api_uri
path =
ENV['DOCUMENT_SERVER_API_PATH'] ||
'/web-apps/apps/api/documents/api.js'
URI.join(document_server_public_uri.to_s, path)
end
sig { returns(URI::Generic) }
def document_server_preloader_uri
path =
ENV['DOCUMENT_SERVER_PRELOADER_PATH'] ||
'/web-apps/apps/api/documents/cache-scripts.html'
URI.join(document_server_public_uri.to_s, path)
end
sig { returns(URI::Generic) }
def document_server_command_uri
path =
ENV['DOCUMENT_SERVER_COMMAND_PATH'] ||
'/coauthoring/CommandService.ashx'
URI.join(document_server_private_uri.to_s, path)
end
sig { returns(URI::Generic) }
def document_server_converter_uri
path =
ENV['DOCUMENT_SERVER_CONVERTER_PATH'] ||
'/ConvertService.ashx'
URI.join(document_server_private_uri.to_s, path)
end
sig { returns(String) }
def jwt_secret
ENV['JWT_SECRET'] || ''
end
sig { returns(String) }
def jwt_header
ENV['JWT_HEADER'] || 'Authorization'
end
sig { returns(T::Boolean) }
def jwt_use_for_request
env = ENV['JWT_USE_FOR_REQUEST']
return ActiveModel::Type::Boolean.new.cast(env) if env
true
end
sig { returns(T::Boolean) }
def ssl_verify_peer_mode_enabled
env = ENV['SSL_VERIFY_PEER_MODE_ENABLED']
return ActiveModel::Type::Boolean.new.cast(env) if env
false
end
sig { returns(String) }
def storage_path
ENV['STORAGE_PATH'] || 'app_data'
end
sig { returns(Numeric) }
def maximum_file_size
env = ENV['MAXIMUM_FILE_SIZE']
return env.to_i if env
5 * 1024 * 1024
end
sig { returns(Numeric) }
def convertation_timeout
120
end
sig { returns(T::Array[String]) }
def fillable_file_extensions
'.docx|.oform'
.split('|')
end
sig { returns(T::Array[String]) }
def viewable_file_extensions
'.djvu|.oxps|.pdf|.xps'
.split('|')
end
sig { returns(T::Array[String]) }
def editable_file_extensions
'.csv|.docm|.docx|.docxf|.dotm|.dotx|.epub|.fb2|.html|.odp|.ods|.odt|.otp|.ots|.ott|.potm|.potx|.ppsm|.ppsx|.pptm|.pptx|.rtf|.txt|.xlsm|.xlsx|.xltm|.xltx'
.split('|')
end
sig { returns(T::Array[String]) }
def convertable_file_extensions
'.doc|.dot|.dps|.dpt|.epub|.et|.ett|.fb2|.fodp|.fods|.fodt|.htm|.html|.mht|.mhtml|.odp|.ods|.odt|.otp|.ots|.ott|.pot|.pps|.ppt|.rtf|.stw|.sxc|.sxi|.sxw|.wps|.wpt|.xls|.xlsb|.xlt|.xml'
.split('|')
end
sig { returns(T::Hash[String, String]) }
def languages
{
'en' => 'English',
'hy' => 'Armenian',
'az' => 'Azerbaijani',
'eu' => 'Basque',
'be' => 'Belarusian',
'bg' => 'Bulgarian',
'ca' => 'Catalan',
'zh' => 'Chinese (Simplified)',
'zh-TW' => 'Chinese (Traditional)',
'cs' => 'Czech',
'da' => 'Danish',
'nl' => 'Dutch',
'fi' => 'Finnish',
'fr' => 'French',
'gl' => 'Galego',
'de' => 'German',
'el' => 'Greek',
'hu' => 'Hungarian',
'id' => 'Indonesian',
'it' => 'Italian',
'ja' => 'Japanese',
'ko' => 'Korean',
'lo' => 'Lao',
'lv' => 'Latvian',
'ms' => 'Malay (Malaysia)',
'no' => 'Norwegian',
'pl' => 'Polish',
'pt' => 'Portuguese (Brazil)',
'pt-PT' => 'Portuguese (Portugal)',
'ro' => 'Romanian',
'ru' => 'Russian',
'si' => 'Sinhala (Sri Lanka)',
'sk' => 'Slovak',
'sl' => 'Slovenian',
'es' => 'Spanish',
'sv' => 'Swedish',
'tr' => 'Turkish',
'uk' => 'Ukrainian',
'vi' => 'Vietnamese',
'aa-AA' => 'Test Language'
}
end
end
# rubocop:enable Metrics/ClassLength

View File

@ -14,6 +14,8 @@
# limitations under the License.
#
# rubocop:disable all
class DocumentHelper
@@runtime_cache = {}
@ -29,11 +31,8 @@ class DocumentHelper
# define max file size
def file_size_max
if Rails.configuration.fileSizeMax == nil
5 * 1024 * 1024
else
Rails.configuration.fileSizeMax # or get it from the config
end
config = ConfigurationManager.new
config.maximum_file_size
end
# all the supported file extensions
@ -42,38 +41,26 @@ class DocumentHelper
end
def fill_forms_exts
if Rails.configuration.fillDocs.empty?
[]
else
Rails.configuration.fillDocs.split("|")
end
config = ConfigurationManager.new
config.fillable_file_extensions
end
# file extensions that can be viewed
def viewed_exts
if Rails.configuration.viewedDocs.empty?
[]
else
Rails.configuration.viewedDocs.split("|")
end
config = ConfigurationManager.new
config.viewable_file_extensions
end
# file extensions that can be edited
def edited_exts
if Rails.configuration.editedDocs.empty?
[]
else
Rails.configuration.editedDocs.split("|")
end
config = ConfigurationManager.new
config.editable_file_extensions
end
# file extensions that can be converted
def convert_exts
if Rails.configuration.convertDocs.empty?
[]
else
Rails.configuration.convertDocs.split("|")
end
config = ConfigurationManager.new
config.convertable_file_extensions
end
# get current user host address
@ -83,8 +70,9 @@ class DocumentHelper
# get the storage path of the given file
def storage_path(file_name, user_address)
directory = File.absolute_path?(Rails.configuration.storagePath) ? Rails.configuration.storagePath
: Rails.root.join('public', Rails.configuration.storagePath, cur_user_host_address(user_address)) # get the path to the directory for the host address
config = ConfigurationManager.new
directory = File.absolute_path?(config.storage_path) ? config.storage_path
: Rails.root.join('public', config.storage_path, cur_user_host_address(user_address)) # get the path to the directory for the host address
# create a new directory if it doesn't exist
unless File.directory?(directory)
@ -97,8 +85,9 @@ class DocumentHelper
# get the path to the forcesaved file version
def forcesave_path(file_name, user_address, create)
directory = File.absolute_path?(Rails.configuration.storagePath) ? Rails.configuration.storagePath
: Rails.root.join('public', Rails.configuration.storagePath, cur_user_host_address(user_address))
config = ConfigurationManager.new
directory = File.absolute_path?(config.storage_path) ? config.storage_path
: Rails.root.join('public', config.storage_path, cur_user_host_address(user_address))
# the directory with host address doesn't exist
unless File.directory?(directory)
@ -151,7 +140,8 @@ class DocumentHelper
Dir.foreach(hist_dir) {|e| # run through all the file versions
next if e.eql?(".")
next if e.eql?("..")
if File.directory?(File.join(hist_dir, e))
path = File.join(hist_dir, e)
if File.directory?(path) && !Dir.empty?(path)
ver += 1 # and count them
end
}
@ -176,8 +166,9 @@ class DocumentHelper
# get all the stored files from the folder
def get_stored_files(user_address)
directory = File.absolute_path?(Rails.configuration.storagePath) ? Rails.configuration.storagePath
: Rails.root.join('public', Rails.configuration.storagePath, cur_user_host_address(user_address))
config = ConfigurationManager.new
directory = File.absolute_path?(config.storage_path) ? config.storage_path
: Rails.root.join('public', config.storage_path, cur_user_host_address(user_address))
arr = [];
@ -230,26 +221,20 @@ class DocumentHelper
# get file url
def get_file_uri(file_name, for_document_server)
uri = get_server_url(for_document_server) + '/' + Rails.configuration.storagePath + '/' + cur_user_host_address(nil) + '/' + ERB::Util.url_encode(file_name)
config = ConfigurationManager.new
uri = get_server_url(for_document_server) + '/' + config.storage_path + '/' + cur_user_host_address(nil) + '/' + ERB::Util.url_encode(file_name)
return uri
end
# get history path url
def get_historypath_uri(file_name,version,file,is_serverUrl=true)
# for redirection to my link
user_host = is_serverUrl ? '&userAddress=' + cur_user_host_address(nil) : ""
uri = get_server_url(is_serverUrl) + '/downloadhistory/?fileName=' + ERB::Util.url_encode(file_name) + '&ver='+ version.to_s + '&file='+ ERB::Util.url_encode(file) + user_host
return uri
end
# get server url
def get_server_url(for_document_server)
if for_document_server && !Rails.configuration.urlExample.empty?
return Rails.configuration.urlExample
config = ConfigurationManager.new
if for_document_server && config.example_uri
return config.example_uri.to_s
else
return @@base_url
end
end
end
# get callback url
@ -323,7 +308,7 @@ class DocumentHelper
"contentLength" => "#{(File.size(directory)/ 1024.0).round(2)} KB",
"pureContentLength" => File.size(directory),
"title" => fileName,
"updated" => File.mtime(directory)
"updated" => File.mtime(directory)
}
if file_id == nil # if file id is undefined
@ -344,11 +329,11 @@ class DocumentHelper
end
# enable ignore certificate
def verify_ssl(file_uri, http)
if file_uri.start_with?('https') && Rails.configuration.verify_peer_off.eql?('true')
if file_uri.start_with?('https') && ConfigurationManager.new.ssl_verify_peer_mode_enabled
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE # set the flags for the server certificate verification at the beginning of SSL session
end
end
end
end
end

View File

@ -14,6 +14,8 @@
# limitations under the License.
#
# rubocop:disable all
class FileModel
attr_accessor :file_name, :mode, :type, :user_ip, :lang, :user, :action_data, :direct_url
@ -39,14 +41,10 @@ class FileModel
File.extname(@file_name).downcase
end
# get file url
def file_uri
DocumentHelper.get_file_uri(@file_name, true)
end
# get file uri for document server
def file_uri_user
File.absolute_path?(Rails.configuration.storagePath) ? download_url + "&dmode=emb" : DocumentHelper.get_file_uri(@file_name, false)
config = ConfigurationManager.new
File.absolute_path?(config.storage_path) ? download_url + "&dmode=emb" : DocumentHelper.get_file_uri(@file_name, false)
end
# get document type from its name (word, cell or slide)
@ -146,7 +144,7 @@ class FileModel
:lang => @lang ? @lang : "en",
:callbackUrl => callback_url, # absolute URL to the document storage service
:coEditing => editorsmode.eql?("view") && @user.id.eql?("uid-0") ? {
:mode => "strict",
:mode => "strict",
:change => false
} : nil,
:createUrl => !@user.id.eql?("uid-0") ? create_url : nil,
@ -164,7 +162,7 @@ class FileModel
},
:customization => { # the parameters for the editor interface
:about => true, # the About section display
:comments => true,
:comments => true,
:feedback => true, # the Feedback & Support menu button display
:forcesave => false, # adding the request for the forced file saving to the callback handler
:submitForm => submitForm, # the Submit form button state
@ -182,111 +180,6 @@ class FileModel
return config
end
# get document history
def get_history
file_name = @file_name
file_ext = File.extname(file_name).downcase
doc_key = key()
doc_uri = file_uri()
hist_dir = DocumentHelper.history_dir(DocumentHelper.storage_path(@file_name, nil)) # get the path to the file history
cur_ver = DocumentHelper.get_file_version(hist_dir) # get the file version
if (cur_ver > 0) # if file was modified
hist = []
histData = {}
for i in 1..cur_ver # run through all the file versions
obj = {}
dataObj = {}
ver_dir = DocumentHelper.version_dir(hist_dir, i) # get the path to the given file version
# get document key
cur_key = doc_key
if (i != cur_ver)
File.open(File.join(ver_dir, "key.txt"), 'r') do |file|
cur_key = file.read()
end
end
obj["key"] = cur_key
obj["version"] = i
if (i == 1) # check if the version number is equal to 1
if File.file?(File.join(hist_dir, "createdInfo.json")) # check if the createdInfo.json file with meta data exists
File.open(File.join(hist_dir, "createdInfo.json"), 'r') do |file| # open it
cr_info = JSON.parse(file.read()) # parse the file content
# write information about changes to the object
obj["created"] = cr_info["created"]
obj["user"] = {
:id => cr_info["uid"],
:name => cr_info["uname"]
}
end
end
end
# get the history data from the previous file version and write key and url information about it
dataObj["fileType"] = file_ext[1..file_ext.length]
dataObj["key"] = cur_key
dataObj["url"] = i == cur_ver ? doc_uri : DocumentHelper.get_historypath_uri(file_name, i, "prev#{file_ext}")
if is_enable_direct_url == true
dataObj["directUrl"] = i == cur_ver ? download_url(false) : DocumentHelper.get_historypath_uri(file_name, i, "prev#{file_ext}", false)
end
dataObj["version"] = i
if (i > 1) # check if the version number is greater than 1
changes = nil
change = nil
File.open(File.join(DocumentHelper.version_dir(hist_dir, i - 1), "changes.json"), 'r') do |file| # get the path to the changes.json file
changes = JSON.parse(file.read()) # and parse its content
end
change = changes["changes"][0]
# write information about changes to the object
obj["changes"] = change ? changes["changes"] : nil
obj["serverVersion"] = changes["serverVersion"]
obj["created"] = change ? change["created"] : nil
obj["user"] = change ? change["user"] : nil
prev = histData[(i - 2).to_s] # get the history data from the previous file version
dataObj["previous"] = is_enable_direct_url == true ? { # write key and url information about previous file version with optional direct url
:fileType => prev["fileType"],
:key => prev["key"],
:url => prev["url"],
:directUrl => prev["directUrl"]
} : {
:fileType => prev["fileType"],
:key => prev["key"],
:url => prev["url"]
}
# write the path to the diff.zip archive with differences in this file version
dataObj["changesUrl"] = DocumentHelper.get_historypath_uri(file_name, i - 1, "diff.zip")
end
if JwtHelper.is_enabled # check if a secret key to generate token exists or not
dataObj["token"] = JwtHelper.encode(dataObj) # encode a payload object into a token and write it to the data object
end
hist.push(obj) # add object dictionary to the hist list
histData[(i - 1).to_s] = dataObj # write data object information to the history data
end
return {
:hist => { # write history information about the current file version to the hist
:currentVersion => cur_ver,
:history => hist
},
:histData => histData
}
end
return nil
end
# get image information
def get_insert_image
insert_image = is_enable_direct_url == true ? {
@ -319,7 +212,7 @@ class FileModel
if JwtHelper.is_enabled # check if a secret key to generate token exists or not
compare_file["token"] = JwtHelper.encode(compare_file) # encode a payload object into a token and write it to the compare_file object
end
return compare_file
end
@ -351,4 +244,4 @@ class FileModel
return @direct_url != nil && @direct_url == "true"
end
end
end

View File

@ -18,9 +18,9 @@ require 'jwt'
class JwtHelper
@jwt_secret = Rails.configuration.jwtSecret
@token_use_for_request = Rails.configuration.token_use_for_request
@jwt_secret = ConfigurationManager.new.jwt_secret
@token_use_for_request = ConfigurationManager.new.jwt_use_for_request
class << self
# check if a secret key to generate token exists or not
def is_enabled

View File

@ -0,0 +1,60 @@
#
# (c) Copyright Ascensio System SIA 2023
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# frozen_string_literal: true
# typed: true
require 'uri'
# The Proxy class provides interfaces that may be useful if a document-server
# instance and an example instance communicate through a proxy server.
class Proxy
extend T::Sig
sig { params(configuration: ConfigurationManager).void }
def initialize(configuration)
@config = configuration
end
# Resolves with a private document-server URI if the specified URI based on a
# public document-server URI.
sig { params(url: String).returns(URI::Generic) }
def resolve_document_server_uri(url)
uri = URI(url)
return uri unless equal_document_server_public_uri(uri)
swap_docuemnt_server_public_uri(uri)
end
private
sig { params(uri: URI::Generic).returns(T::Boolean) }
def equal_document_server_public_uri(uri)
uri.scheme == @config.document_server_public_uri.scheme && \
uri.host == @config.document_server_public_uri.host && \
uri.port == @config.document_server_public_uri.port
end
sig { params(uri: URI::Generic).returns(URI::Generic) }
def swap_docuemnt_server_public_uri(uri)
swaped_uri = uri
swaped_uri.scheme = @config.document_server_private_uri.scheme
swaped_uri.host = @config.document_server_private_uri.host
swaped_uri.port = @config.document_server_private_uri.port
swaped_uri
end
end

View File

@ -16,8 +16,8 @@
class ServiceConverter
@@convert_timeout = Rails.configuration.timeout # get the convertion timeout from the config
@@document_converter_url = Rails.configuration.urlSite + Rails.configuration.urlConverter # get the converter url from the config
@@convert_timeout = ConfigurationManager.new.convertation_timeout
@@document_converter_url = ConfigurationManager.new.document_server_converter_uri.to_s
class << self

View File

@ -17,6 +17,7 @@
require 'net/http'
class TrackHelper
@@document_command_url = ConfigurationManager.new.document_server_command_uri.to_s
class << self
@ -60,8 +61,34 @@ class TrackHelper
return file_data
end
def resolve_file_data(file_data)
config = ConfigurationManager.new
proxy = Proxy.new(config)
url = file_data['url']
file_data['url'] = proxy.resolve_document_server_uri(url).to_s if url
changesurl = file_data['changesurl']
file_data['changesurl'] = proxy.resolve_document_server_uri(changesurl).to_s if changesurl
home = file_data['home']
if home
home_url = home['url']
home['url'] = proxy.resolve_document_server_uri(home_url).to_s if home_url
home_changesurl = home['changesurl']
home['changesurl'] = proxy.resolve_document_server_uri(home_changesurl).to_s if home_changesurl
file_data['home'] = home
end
file_data
end
# file saving process
def process_save(file_data, file_name, user_address)
def process_save(raw_file_data, file_name, user_address)
file_data = resolve_file_data(raw_file_data)
download_uri = file_data['url']
if download_uri.eql?(nil)
saved = 1
@ -211,8 +238,6 @@ class TrackHelper
# send the command request
def command_request(method, key, meta = nil)
document_command_url = Rails.configuration.urlSite + Rails.configuration.commandUrl # get the document command url
# create a payload object with the method and key
payload = {
:c => method,
@ -226,10 +251,10 @@ class TrackHelper
data = nil
begin
uri = URI.parse(document_command_url) # parse the document command url
uri = URI.parse(@@document_command_url) # parse the document command url
http = Net::HTTP.new(uri.host, uri.port) # create a connection to the http server
DocumentHelper.verify_ssl(document_command_url, http)
DocumentHelper.verify_ssl(@@document_command_url, http)
req = Net::HTTP::Post.new(uri.request_uri) # create the post request
req.add_field("Content-Type", "application/json") # set headers

View File

@ -0,0 +1,57 @@
#
# (c) Copyright Ascensio System SIA 2023
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# frozen_string_literal: true
# typed: true
require 'uri'
require_relative 'models/configuration_manager'
class ProxyManager
extend T::Sig
sig do
params(
config: ConfigurationManager,
base_url: String,
remote_ip: String,
user_host: T.nilable(String)
)
.void
end
def initialize(
config:,
base_url:,
remote_ip:,
user_host: nil
)
@config = config
@base_url = base_url
@remote_ip = remote_ip
@user_host = user_host
end
sig { returns(URI::Generic) }
def example_uri
@config.example_uri || URI(@base_url)
end
sig { returns(String) }
def user_host
(@user_host || @remote_ip).gsub(/[^0-9\-.a-zA-Z_=]/, '_')
end
end

View File

@ -0,0 +1,39 @@
#
# (c) Copyright Ascensio System SIA 2023
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# frozen_string_literal: true
# typed: true
module ResponseError
extend T::Sig
sig { params(error: String).void }
def initialize(error)
@error = error
@success = false
end
def to_json(*options)
as_json.to_json(*options)
end
def as_json(_ = {})
{
error: @error,
success: @success
}
end
end

View File

@ -0,0 +1,72 @@
#
# (c) Copyright Ascensio System SIA 2023
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# frozen_string_literal: true
# typed: true
require 'pathname'
require_relative 'models/configuration_manager'
require_relative 'proxy'
# ```text
# /application_directory
# └─ storage_directory
# └─ user_directory
# └─ source_file
#
# /srv
# └─ storage
# └─ 172.19.0.1
# └─ document.docx
# ```
class StorageManager
extend T::Sig
sig do
params(
config: ConfigurationManager,
proxy_manager: ProxyManager,
source_basename: String
)
.void
end
def initialize(config:, proxy_manager:, source_basename:)
@config = config
@proxy_manager = proxy_manager
@source_basename = source_basename
end
sig { returns(Pathname) }
def source_file
user_directory.join(@source_basename)
end
sig { returns(Pathname) }
def user_directory
directory = storage_directory.join(@proxy_manager.user_host)
FileUtils.mkdir(directory) unless directory.exist?
directory
end
sig { returns(Pathname) }
def storage_directory
# TODO: move to the Configuration.
path = Pathname.new(@config.storage_path)
storage_path = path.absolute? ? path : Rails.root.join('public', path)
FileUtils.mkdir(storage_path) unless storage_path.exist?
storage_path
end
end

View File

@ -21,7 +21,7 @@
</div>
</div>
<script src="<%= Rails.configuration.urlSite + Rails.configuration.urlApi %>"></script>
<script src="<%= ConfigurationManager.new.document_server_api_uri.to_s %>"></script>
<script type="text/javascript" language="javascript">
@ -109,13 +109,67 @@
// the user is trying to select document for comparing by clicking the Document from Storage button
var onRequestCompareFile = function() {
docEditor.setRevisedFile(<%= raw @file.get_compare_file.to_json %>); // select a document for comparing
};
};
// the user is trying to select recipients data by clicking the Mail merge button
var onRequestMailMergeRecipients = function (event) {
docEditor.setMailMergeRecipients(<%= raw @file.dataMailMergeRecipients.to_json %>); // insert recipient data for mail merge into the file
};
function onRequestHistory() {
const fileName = "<%= @file.file_name %>"
// const directURL
const request = new XMLHttpRequest()
request.open("GET", `history/${fileName}`)
request.send()
request.onload = function () {
response = JSON.parse(request.response)
if (request.status != 200) {
innerAlert(response.error)
return
}
docEditor.refreshHistory(response)
}
}
function onRequestHistoryData(event) {
const fileName = "<%= @file.file_name %>"
const version = event.data
// const directURL
const request = new XMLHttpRequest()
request.open("GET", `history/${fileName}/${version}/data`)
request.send()
request.onload = function () {
response = JSON.parse(request.response)
if (request.status != 200) {
innerAlert(response.error)
return
}
docEditor.setHistoryData(response)
}
}
function onRequestHistoryClose() {
document.location.reload()
}
function onRequestRestore(event) {
const fileName = "<%= @file.file_name %>"
const userID = "<%= @file.user.id %>"
const version = event.data.version
const request = new XMLHttpRequest()
request.open("PUT", `history/${fileName}/${version}/restore?user_id=${userID}`)
request.send()
request.onload = function () {
if (request.status != 200) {
response = JSON.parse(request.response)
innerAlert(response.error)
return
}
onRequestHistory()
}
}
var onRequestSaveAs = function (event) { // the user is trying to save file by clicking Save Copy as... button
var title = event.data.title;
var url = event.data.url;
@ -152,7 +206,7 @@
};
var onRequestReferenceData = function(event) { // user refresh external data source
event.data.directUrl = !!config.document.directUrl;
let xhr = new XMLHttpRequest();
xhr.open("POST", "reference");
@ -179,30 +233,18 @@
'onMetaChange': onMetaChange,
'onRequestInsertImage': onRequestInsertImage,
'onRequestCompareFile': onRequestCompareFile,
'onRequestMailMergeRecipients': onRequestMailMergeRecipients,
'onRequestMailMergeRecipients': onRequestMailMergeRecipients
};
<%
history = @file.get_history
usersMentions = @file.get_users_mentions %>
if (config.editorConfig.user.id) {
<% if history %>
// the user is trying to show the document version history
config.events['onRequestHistory'] = function () {
docEditor.refreshHistory(<%= raw history[:hist].to_json %>); // show the document version history
};
// the user is trying to click the specific document version in the document version history
config.events['onRequestHistoryData'] = function (event) {
var ver = event.data;
var histData = <%= raw history[:histData].to_json %>;
docEditor.setHistoryData(histData[ver - 1]); // send the link to the document for viewing the version history
};
// the user is trying to go back to the document from viewing the document version history
config.events['onRequestHistoryClose'] = function () {
document.location.reload();
};
<% end %>
config.events.onRequestHistory = onRequestHistory
config.events.onRequestHistoryData = onRequestHistoryData
config.events.onRequestHistoryClose = onRequestHistoryClose
config.events.onRequestRestore = onRequestRestore
// add mentions for not anonymous users
config.events['onRequestUsers'] = function () {
docEditor.setUsers({ // set a list of users to mention in the comments
@ -241,4 +283,4 @@
window.attachEvent("load", сonnectEditor);
}
</script>
</script>

View File

@ -75,7 +75,7 @@
data-tooltip="Choose the language for ONLYOFFICE editors interface"
src="assets/info.svg" />
<select class="select-user" id="language">
<% Rails.configuration.languages.each { |key, language|%>
<% ConfigurationManager.new.languages.each { |key, language|%>
<option value="<%=key %>"> <%=language %> </option>
<% } %>
</select>
@ -304,7 +304,7 @@
</div>
</div>
<span id="loadScripts" data-docs="<%= Rails.configuration.urlSite + Rails.configuration.urlPreloader %>"></span>
<span id="loadScripts" data-docs="<%= ConfigurationManager.new.document_server_preloader_uri.to_s %>"></span>
<footer>
<div class="center">

View File

@ -1,3 +0,0 @@
#!/usr/bin/env ruby.exe
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
load Gem.bin_path('bundler', 'bundle')

View File

@ -1,4 +0,0 @@
#!/usr/bin/env ruby.exe
APP_PATH = File.expand_path('../../config/application', __FILE__)
require_relative '../config/boot'
require 'rails/commands'

View File

@ -1,4 +0,0 @@
#!/usr/bin/env ruby.exe
require_relative '../config/boot'
require 'rake'
Rake.application.run

View File

@ -1,29 +0,0 @@
#!/usr/bin/env ruby.exe
require 'pathname'
# path to your application root.
APP_ROOT = Pathname.new File.expand_path('../../', __FILE__)
Dir.chdir APP_ROOT do
# This script is a starting point to setup your application.
# Add necessary setup steps to this file:
puts "== Installing dependencies =="
system "gem install bundler --conservative"
system "bundle check || bundle install"
# puts "\n== Copying sample files =="
# unless File.exist?("config/database.yml")
# system "cp config/database.yml.sample config/database.yml"
# end
puts "\n== Preparing database =="
system "bin/rake db:setup"
puts "\n== Removing old logs and tempfiles =="
system "rm -f log/*"
system "rm -rf tmp/cache"
puts "\n== Restarting application server =="
system "touch tmp/restart.txt"
end

View File

@ -1,15 +1,4 @@
# This file is used by Rack-based servers to start the application.
require_relative 'config/application'
require ::File.expand_path('../config/environment', __FILE__)
Rails.application.initialize!
run Rails.application
require 'rack/cors'
use Rack::Cors do
allow do
origins '*'
resource '*',
:headers => :any,
:methods => [:get]
end
end

View File

@ -1,97 +1,106 @@
require File.expand_path('../boot', __FILE__)
# rubocop:disable Metrics/BlockLength
# Pick the frameworks you want:
require "active_model/railtie"
require "active_job/railtie"
require "active_record/railtie"
require "action_controller/railtie"
require "action_mailer/railtie"
require "action_view/railtie"
require "sprockets/railtie"
# require "rails/test_unit/railtie"
require_relative 'boot'
require 'active_model/railtie'
require 'action_controller/railtie'
require 'action_view/railtie'
require 'sprockets/railtie'
# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)
module OnlineEditorsExampleRuby
require_relative '../app/controllers/application_controller'
require_relative '../app/history'
module Example
class Application < Rails::Application
# TODO: move to the Convifgutaion.
# It needs to be moved to the Configuration, but it can't be done at the
# moment because replacing it causes the application to crash.
Rails.configuration.header = 'Authorization'
config.middleware.insert_before 0, Rack::Cors do
allow do
origins '*'
resource '*',
headers: :any,
methods: [:get, :post, :patch, :delete, :put, :options]
resource '*', headers: :any, methods: %i[get post patch delete put options]
end
end
Rails.configuration.version="1.5.1"
config.action_controller.perform_caching = true
config.active_support.deprecation = :log
config.assets.debug = false
config.assets.digest = true
config.cache_classes = true
config.consider_all_requests_local = true
config.eager_load = true
config.require_master_key = false
config.secret_key_base = SecureRandom.uuid
Rails.configuration.fileSizeMax=5242880
Rails.configuration.storagePath="app_data"
Rails.configuration.timeout=120
routes.append do
root to: 'home#index'
match '/convert', to: 'home#convert', via: 'post'
match '/csv', to: 'home#csv', via: 'get'
match '/download', to: 'home#download', via: 'get'
match '/downloadhistory', to: 'home#downloadhistory', via: 'get'
match '/editor', to: 'home#editor', via: 'get'
match '/files', to: 'home#files', via: 'get'
match '/index', to: 'home#index', via: 'get'
match '/reference', to: 'home#reference', via: 'post'
match '/remove', to: 'home#remove', via: 'get'
match '/rename', to: 'home#rename', via: 'post'
match '/restore', to: 'home#restore', via: 'put'
match '/sample', to: 'home#sample', via: 'get'
match '/saveas', to: 'home#saveas', via: 'post'
match '/track', to: 'home#track', via: 'post'
match '/upload', to: 'home#upload', via: 'post'
Rails.configuration.fillDocs=".docx|.oform"
Rails.configuration.viewedDocs=".djvu|.oxps|.pdf|.xps"
Rails.configuration.editedDocs=".csv|.docm|.docx|.docxf|.dotm|.dotx|.epub|.fb2|.html|.odp|.ods|.odt|.otp|.ots|.ott|.potm|.potx|.ppsm|.ppsx|.pptm|.pptx|.rtf|.txt|.xlsm|.xlsx|.xltm|.xltx"
Rails.configuration.convertDocs=".doc|.dot|.dps|.dpt|.epub|.et|.ett|.fb2|.fodp|.fods|.fodt|.htm|.html|.mht|.mhtml|.odp|.ods|.odt|.otp|.ots|.ott|.pot|.pps|.ppt|.rtf|.stw|.sxc|.sxi|.sxw|.wps|.wpt|.xls|.xlsb|.xlt|.xml"
file_basename_constraint = /[^\/]*/
Rails.configuration.urlSite="http://documentserver/"
Rails.configuration.urlConverter="ConvertService.ashx"
Rails.configuration.urlApi="web-apps/apps/api/documents/api.js"
Rails.configuration.urlPreloader="web-apps/apps/api/documents/cache-scripts.html"
Rails.configuration.commandUrl="coauthoring/CommandService.ashx"
Rails.configuration.urlExample=""
Rails.configuration.jwtSecret = ""
Rails.configuration.header="Authorization"
Rails.configuration.token_use_for_request=true
Rails.configuration.verify_peer_off = "true"
Rails.configuration.languages={
'en' => 'English',
'hy' => 'Armenian',
'az' => 'Azerbaijani',
'eu' => 'Basque',
'be' => 'Belarusian',
'bg' => 'Bulgarian',
'ca' => 'Catalan',
'zh' => 'Chinese (Simplified)',
'zh-TW' => 'Chinese (Traditional)',
'cs' => 'Czech',
'da' => 'Danish',
'nl' => 'Dutch',
'fi' => 'Finnish',
'fr' => 'French',
'gl' => 'Galego',
'de' => 'German',
'el' => 'Greek',
'hu' => 'Hungarian',
'id' => 'Indonesian',
'it' => 'Italian',
'ja' => 'Japanese',
'ko' => 'Korean',
'lo' => 'Lao',
'lv' => 'Latvian',
'ms' => 'Malay (Malaysia)',
'no' => 'Norwegian',
'pl' => 'Polish',
'pt' => 'Portuguese (Brazil)',
'pt-PT' => 'Portuguese (Portugal)',
'ro' => 'Romanian',
'ru' => 'Russian',
'si' => 'Sinhala (Sri Lanka)',
'sk' => 'Slovak',
'sl' => 'Slovenian',
'es' => 'Spanish',
'sv' => 'Swedish',
'tr' => 'Turkish',
'uk' => 'Ukrainian',
'vi' => 'Vietnamese',
'aa-AA' => 'Test Language'
}
get(
'/history/:source_basename',
to: HistoryController.action('history'),
format: false,
defaults: {
format: 'html'
},
constraints: {
source_basename: file_basename_constraint
}
)
get(
'/history/:source_basename/:version/data',
to: HistoryController.action('data'),
format: false,
defaults: {
format: 'html'
},
constraints: {
source_basename: file_basename_constraint
}
)
get(
'/history/:source_basename/:version/download/:requested_basename',
to: HistoryController.action('download'),
format: false,
defaults: {
foramt: 'html'
},
constraints: {
source_basename: file_basename_constraint,
requested_basename: file_basename_constraint
}
)
put(
'/history/:source_basename/:version/restore',
to: HistoryController.action('restore'),
format: false,
defaults: {
foramt: 'html'
},
constraints: {
source_basename: file_basename_constraint
}
)
end
end
end

View File

@ -1,3 +1,3 @@
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)
require 'bundler/setup' # Set up gems listed in the Gemfile.
require 'bundler/setup'

View File

@ -1,25 +0,0 @@
# SQLite version 3.x
# gem install sqlite3
#
# Ensure the SQLite 3 gem is defined in your Gemfile
# gem 'sqlite3'
#
default: &default
adapter: sqlite3
pool: 5
timeout: 5000
development:
<<: *default
database: db/development.sqlite3
# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
<<: *default
database: db/test.sqlite3
production:
<<: *default
database: db/production.sqlite3

View File

@ -1,5 +0,0 @@
# Load the Rails application.
require File.expand_path('../application', __FILE__)
# Initialize the Rails application.
Rails.application.initialize!

View File

@ -1,41 +0,0 @@
Rails.application.configure do
# Settings specified here will take precedence over those in config/application.rb.
# In the development environment your application's code is reloaded on
# every request. This slows down response time but is perfect for development
# since you don't have to restart the web server when you make code changes.
config.cache_classes = false
# Do not eager load code on boot.
config.eager_load = false
# Show full error reports and disable caching.
config.consider_all_requests_local = true
config.action_controller.perform_caching = false
# Don't care if the mailer can't send.
config.action_mailer.raise_delivery_errors = false
# Print deprecation notices to the Rails logger.
config.active_support.deprecation = :log
# Raise an error on page load if there are pending migrations.
config.active_record.migration_error = :page_load
# Debug mode disables concatenation and preprocessing of assets.
# This option may cause significant delays in view rendering with a large
# number of complex assets.
config.assets.debug = true
# Asset digests allow you to set far-future HTTP expiration dates on all assets,
# yet still be able to expire them through the digest params.
config.assets.digest = true
# Adds additional error checking when serving assets at runtime.
# Checks for improperly declared sprockets dependencies.
# Raises helpful error messages.
config.assets.raise_runtime_errors = true
# Raises error for missing translations
# config.action_view.raise_on_missing_translations = true
end

View File

@ -1,79 +0,0 @@
Rails.application.configure do
# Settings specified here will take precedence over those in config/application.rb.
# Code is not reloaded between requests.
config.cache_classes = true
# Eager load code on boot. This eager loads most of Rails and
# your application in memory, allowing both threaded web servers
# and those relying on copy on write to perform better.
# Rake tasks automatically ignore this option for performance.
config.eager_load = true
# Full error reports are disabled and caching is turned on.
config.consider_all_requests_local = false
config.action_controller.perform_caching = true
# Enable Rack::Cache to put a simple HTTP cache in front of your application
# Add `rack-cache` to your Gemfile before enabling this.
# For large-scale production use, consider using a caching reverse proxy like
# NGINX, varnish or squid.
# config.action_dispatch.rack_cache = true
# Disable serving static files from the `/public` folder by default since
# Apache or NGINX already handles this.
config.serve_static_files = ENV['RAILS_SERVE_STATIC_FILES'].present?
# Compress JavaScripts and CSS.
config.assets.js_compressor = :uglifier
# config.assets.css_compressor = :sass
# Do not fallback to assets pipeline if a precompiled asset is missed.
config.assets.compile = false
# Asset digests allow you to set far-future HTTP expiration dates on all assets,
# yet still be able to expire them through the digest params.
config.assets.digest = true
# `config.assets.precompile` and `config.assets.version` have moved to config/initializers/assets.rb
# Specifies the header that your server uses for sending files.
# config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache
# config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX
# Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
# config.force_ssl = true
# Use the lowest log level to ensure availability of diagnostic information
# when problems arise.
config.log_level = :debug
# Prepend all log lines with the following tags.
# config.log_tags = [ :subdomain, :uuid ]
# Use a different logger for distributed setups.
# config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new)
# Use a different cache store in production.
# config.cache_store = :mem_cache_store
# Enable serving of images, stylesheets, and JavaScripts from an asset server.
# config.action_controller.asset_host = 'http://assets.example.com'
# Ignore bad email addresses and do not raise email delivery errors.
# Set this to true and configure the email server for immediate delivery to raise delivery errors.
# config.action_mailer.raise_delivery_errors = false
# Enable locale fallbacks for I18n (makes lookups for any locale fall back to
# the I18n.default_locale when a translation cannot be found).
config.i18n.fallbacks = true
# Send deprecation notices to registered listeners.
config.active_support.deprecation = :notify
# Use default logging formatter so that PID and timestamp are not suppressed.
config.log_formatter = ::Logger::Formatter.new
# Do not dump schema after migrations.
config.active_record.dump_schema_after_migration = false
end

View File

@ -1,42 +0,0 @@
Rails.application.configure do
# Settings specified here will take precedence over those in config/application.rb.
# The test environment is used exclusively to run your application's
# test suite. You never need to work with it otherwise. Remember that
# your test database is "scratch space" for the test suite and is wiped
# and recreated between test runs. Don't rely on the data there!
config.cache_classes = true
# Do not eager load code on boot. This avoids loading your whole application
# just for the purpose of running a single test. If you are using a tool that
# preloads Rails for running tests, you may have to set it to true.
config.eager_load = false
# Configure static file server for tests with Cache-Control for performance.
config.serve_static_files = true
config.static_cache_control = 'public, max-age=3600'
# Show full error reports and disable caching.
config.consider_all_requests_local = true
config.action_controller.perform_caching = false
# Raise exceptions instead of rendering exception templates.
config.action_dispatch.show_exceptions = false
# Disable request forgery protection in test environment.
config.action_controller.allow_forgery_protection = false
# Tell Action Mailer not to deliver emails to the real world.
# The :test delivery method accumulates sent emails in the
# ActionMailer::Base.deliveries array.
config.action_mailer.delivery_method = :test
# Randomize the order test cases are executed.
config.active_support.test_order = :random
# Print deprecation notices to the stderr.
config.active_support.deprecation = :stderr
# Raises error for missing translations
# config.action_view.raise_on_missing_translations = true
end

View File

@ -1,15 +0,0 @@
# Be sure to restart your server when you modify this file.
# Version of your assets, change this if you want to expire all your assets.
Rails.application.config.assets.version = '1.0'
Rails.application.config.assets.precompile += %w( editor.css )
Rails.application.config.assets.precompile += %w( jquery-ui.css )
Rails.application.config.assets.precompile += %w( stylesheet.css )
Rails.application.config.assets.precompile += %w( media.css )
# Add additional assets to the asset load path
# Rails.application.config.assets.paths << Emoji.images_path
# Precompile additional assets.
# application.js, application.css, and all non-JS/CSS in app/assets folder are already added.
# Rails.application.config.assets.precompile += %w( search.js )

View File

@ -1,7 +0,0 @@
# Be sure to restart your server when you modify this file.
# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }
# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code.
# Rails.backtrace_cleaner.remove_silencers!

View File

@ -1,3 +0,0 @@
# Be sure to restart your server when you modify this file.
Rails.application.config.action_dispatch.cookies_serializer = :json

View File

@ -1,4 +0,0 @@
# Be sure to restart your server when you modify this file.
# Configure sensitive parameters which will be filtered from the log file.
Rails.application.config.filter_parameters += [:password]

View File

@ -1,16 +0,0 @@
# Be sure to restart your server when you modify this file.
# Add new inflection rules using the following format. Inflections
# are locale specific, and you may define rules for as many different
# locales as you wish. All of these examples are active by default:
# ActiveSupport::Inflector.inflections(:en) do |inflect|
# inflect.plural /^(ox)$/i, '\1en'
# inflect.singular /^(ox)en/i, '\1'
# inflect.irregular 'person', 'people'
# inflect.uncountable %w( fish sheep )
# end
# These inflection rules are supported but not enabled by default:
# ActiveSupport::Inflector.inflections(:en) do |inflect|
# inflect.acronym 'RESTful'
# end

View File

@ -1,4 +0,0 @@
# Be sure to restart your server when you modify this file.
# Add new mime types for use in respond_to blocks:
# Mime::Type.register "text/richtext", :rtf

View File

@ -1,3 +0,0 @@
# Be sure to restart your server when you modify this file.
Rails.application.config.session_store :cookie_store, key: '_OnlineEditorsExampleRuby_session'

View File

@ -1,14 +0,0 @@
# Be sure to restart your server when you modify this file.
# This file contains settings for ActionController::ParamsWrapper which
# is enabled by default.
# Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
ActiveSupport.on_load(:action_controller) do
wrap_parameters format: [:json] if respond_to?(:wrap_parameters)
end
# To enable root element in JSON for ActiveRecord objects.
# ActiveSupport.on_load(:active_record) do
# self.include_root_in_json = true
# end

View File

@ -1,23 +0,0 @@
# Files in the config/locales directory are used for internationalization
# and are automatically loaded by Rails. If you want to use locales other
# than English, add the necessary files in this directory.
#
# To use the locales, use `I18n.t`:
#
# I18n.t 'hello'
#
# In views, this is aliased to just `t`:
#
# <%= t('hello') %>
#
# To use a different locale, set it with `I18n.locale`:
#
# I18n.locale = :es
#
# This would use the information in config/locales/es.yml.
#
# To learn more, please read the Rails Internationalization guide
# available at http://guides.rubyonrails.org/i18n.html.
en:
hello: "Hello world"

View File

@ -1,73 +0,0 @@
Rails.application.routes.draw do
root 'home#index'
match '/index', to: 'home#index', via: 'get'
match '/editor', to: 'home#editor', via: 'get'
match '/sample', to: 'home#sample', via: 'get'
match '/remove', to: 'home#remove', via: 'get'
match '/upload', to: 'home#upload', via: 'post'
match '/download', to: 'home#download', via: 'get'
match '/downloadhistory', to: 'home#downloadhistory', via: 'get'
match '/convert', to: 'home#convert', via: 'post'
match '/track', to: 'home#track', via: 'post'
match '/csv', to: 'home#csv', via: 'get'
match '/files', to: 'home#files', via: 'get'
match '/saveas', to: 'home#saveas', via: 'post'
match '/rename', to: 'home#rename', via: 'post'
match '/reference', to: 'home#reference', via: 'post'
# The priority is based upon order of creation: first created -> highest priority.
# See how all your routes lay out with "rake routes".
# You can have the root of your site routed with "root"
# root 'welcome#index'
# Example of regular route:
# get 'products/:id' => 'catalog#view'
# Example of named route that can be invoked with purchase_url(id: product.id)
# get 'products/:id/purchase' => 'catalog#purchase', as: :purchase
# Example resource route (maps HTTP verbs to controller actions automatically):
# resources :products
# Example resource route with options:
# resources :products do
# member do
# get 'short'
# post 'toggle'
# end
#
# collection do
# get 'sold'
# end
# end
# Example resource route with sub-resources:
# resources :products do
# resources :comments, :sales
# resource :seller
# end
# Example resource route with more complex sub-resources:
# resources :products do
# resources :comments
# resources :sales do
# get 'recent', on: :collection
# end
# end
# Example resource route with concerns:
# concern :toggleable do
# post 'toggle'
# end
# resources :posts, concerns: :toggleable
# resources :photos, concerns: :toggleable
# Example resource route within a namespace:
# namespace :admin do
# # Directs /admin/products/* to Admin::ProductsController
# # (app/controllers/admin/products_controller.rb)
# resources :products
# end
end

View File

@ -1,22 +0,0 @@
# Be sure to restart your server when you modify this file.
# Your secret key is used for verifying the integrity of signed cookies.
# If you change this key, all old signed cookies will become invalid!
# Make sure the secret is at least 30 characters and all random,
# no regular words or you'll be exposed to dictionary attacks.
# You can use `rake secret` to generate a secure secret key.
# Make sure the secrets in this file are kept private
# if you're sharing your code publicly.
development:
secret_key_base: fadb8c51b54ebcb061791161d507fdaaa6df77e2ed6611101903bf48a20fffe0164a1fe9da16b5b400453de6b05dd46810de12ee468b3d695a4aa618801402a4
test:
secret_key_base: 96b983c551091cb89dae1538233bbdba38f8ca742b61b2320fa7f9aa6a3f146bfda53da2c8cdf2001f66626826f8519eab4327a521d5485ab434f4241fe4d74f
# Do not keep production secrets in the repository,
# instead read values from the environment.
production:
secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>

View File

@ -1,7 +0,0 @@
# This file should contain all the record creation needed to seed the database with its default values.
# The data can then be loaded with the rake db:seed (or created alongside the db with db:setup).
#
# Examples:
#
# cities = City.create([{ name: 'Chicago' }, { name: 'Copenhagen' }])
# Mayor.create(name: 'Emanuel', city: cities.first)

View File

@ -0,0 +1,33 @@
version: "3.8"
services:
document-server:
container_name: document-server
image: onlyoffice/documentserver:7.3.3.50
expose:
- "80"
environment:
- JWT_SECRET=your-256-bit-secret
example:
container_name: example
build:
context: .
target: example
expose:
- "80"
environment:
- DOCUMENT_SERVER_PRIVATE_URL=http://proxy:3000
- DOCUMENT_SERVER_PUBLIC_URL=http://localhost:3000
- EXAMPLE_URL=http://proxy:8080
- JWT_SECRET=your-256-bit-secret
- PORT=80
proxy:
container_name: proxy
build:
context: .
target: proxy
ports:
- "8080:8080"
- "3000:3000"

View File

@ -0,0 +1,38 @@
worker_processes auto;
events {
worker_connections 512;
}
http {
include /etc/nginx/mime.types;
server {
listen 8080;
server_name localhost;
location / {
proxy_http_version 1.1;
proxy_pass http://example;
}
}
server {
listen 3000;
server_name localhost;
location / {
client_max_body_size 100m;
proxy_http_version 1.1;
proxy_pass http://document-server;
proxy_redirect off;
proxy_set_header Connection "upgrade";
proxy_set_header Host $http_host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $http_x_forwarded_host;
proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
proxy_set_header X-Real-IP $remote_addr;
}
}
}