diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..71f82cb --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +.bundle/ +log/*.log +pkg/ +test/dummy/db/*.sqlite3 +test/dummy/db/*.sqlite3-journal +test/dummy/log/*.log +test/dummy/tmp/ diff --git a/.idea/.rakeTasks b/.idea/.rakeTasks new file mode 100644 index 0000000..c6865d9 --- /dev/null +++ b/.idea/.rakeTasks @@ -0,0 +1,7 @@ + + diff --git a/.idea/boxroom-engine.iml b/.idea/boxroom-engine.iml new file mode 100644 index 0000000..31a7fe2 --- /dev/null +++ b/.idea/boxroom-engine.iml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..0eefe32 --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..de6e841 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..e62cd16 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml new file mode 100644 index 0000000..b08841a --- /dev/null +++ b/.idea/workspace.xml @@ -0,0 +1,30 @@ + + + + + + + + + + 1516812529653 + + + + + + + + + + \ No newline at end of file diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..40aeee6 --- /dev/null +++ b/Gemfile @@ -0,0 +1,14 @@ +source 'https://rubygems.org' + +# Declare your gem's dependencies in boxroom.gemspec. +# Bundler will treat runtime dependencies like base dependencies, and +# development dependencies will be added by default to the :development group. +gemspec + +# Declare any dependencies that are still in development here instead of in +# your gemspec. These might include edge Rails or gems from your path or +# Git. Remember to move these dependencies to your gemspec before releasing +# your gem to rubygems.org. + +# To use a debugger +# gem 'byebug', group: [:development, :test] diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 0000000..de6d594 --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,152 @@ +PATH + remote: . + specs: + boxroom (0.1.0) + acts_as_tree + dynamic_form + jquery-fileupload-rails + paperclip + rails (~> 5.0.2) + +GEM + remote: https://rubygems.org/ + specs: + actioncable (5.0.2) + actionpack (= 5.0.2) + nio4r (>= 1.2, < 3.0) + websocket-driver (~> 0.6.1) + actionmailer (5.0.2) + actionpack (= 5.0.2) + actionview (= 5.0.2) + activejob (= 5.0.2) + mail (~> 2.5, >= 2.5.4) + rails-dom-testing (~> 2.0) + actionpack (5.0.2) + actionview (= 5.0.2) + activesupport (= 5.0.2) + rack (~> 2.0) + rack-test (~> 0.6.3) + rails-dom-testing (~> 2.0) + rails-html-sanitizer (~> 1.0, >= 1.0.2) + actionview (5.0.2) + activesupport (= 5.0.2) + builder (~> 3.1) + erubis (~> 2.7.0) + rails-dom-testing (~> 2.0) + rails-html-sanitizer (~> 1.0, >= 1.0.3) + activejob (5.0.2) + activesupport (= 5.0.2) + globalid (>= 0.3.6) + activemodel (5.0.2) + activesupport (= 5.0.2) + activerecord (5.0.2) + activemodel (= 5.0.2) + activesupport (= 5.0.2) + arel (~> 7.0) + activesupport (5.0.2) + concurrent-ruby (~> 1.0, >= 1.0.2) + i18n (~> 0.7) + minitest (~> 5.1) + tzinfo (~> 1.1) + acts_as_tree (2.7.0) + activerecord (>= 3.0.0) + arel (7.1.4) + builder (3.2.3) + climate_control (0.2.0) + cocaine (0.5.8) + climate_control (>= 0.0.3, < 1.0) + concurrent-ruby (1.0.5) + crass (1.0.2) + dynamic_form (1.1.4) + erubis (2.7.0) + ffi (1.9.18) + globalid (0.4.1) + activesupport (>= 4.2.0) + i18n (0.9.0) + concurrent-ruby (~> 1.0) + jquery-fileupload-rails (0.4.7) + actionpack (>= 3.1) + railties (>= 3.1) + sass (>= 3.2) + loofah (2.1.1) + crass (~> 1.0.2) + nokogiri (>= 1.5.9) + mail (2.7.0) + mini_mime (>= 0.1.1) + method_source (0.8.2) + mime-types (3.1) + mime-types-data (~> 3.2015) + mime-types-data (3.2016.0521) + mimemagic (0.3.2) + mini_mime (0.1.4) + mini_portile2 (2.3.0) + minitest (5.10.3) + nio4r (2.0.0) + nokogiri (1.8.1) + mini_portile2 (~> 2.3.0) + paperclip (5.1.0) + activemodel (>= 4.2.0) + activesupport (>= 4.2.0) + cocaine (~> 0.5.5) + mime-types + mimemagic (~> 0.3.0) + rack (2.0.1) + rack-test (0.6.3) + rack (>= 1.0) + rails (5.0.2) + actioncable (= 5.0.2) + actionmailer (= 5.0.2) + actionpack (= 5.0.2) + actionview (= 5.0.2) + activejob (= 5.0.2) + activemodel (= 5.0.2) + activerecord (= 5.0.2) + activesupport (= 5.0.2) + bundler (>= 1.3.0, < 2.0) + railties (= 5.0.2) + sprockets-rails (>= 2.0.0) + rails-dom-testing (2.0.2) + activesupport (>= 4.2.0, < 6.0) + nokogiri (~> 1.6) + rails-html-sanitizer (1.0.3) + loofah (~> 2.0) + railties (5.0.2) + actionpack (= 5.0.2) + activesupport (= 5.0.2) + method_source + rake (>= 0.8.7) + thor (>= 0.18.1, < 2.0) + rake (12.2.1) + rb-fsevent (0.10.2) + rb-inotify (0.9.10) + ffi (>= 0.5.0, < 2) + sass (3.5.3) + sass-listen (~> 4.0.0) + sass-listen (4.0.0) + rb-fsevent (~> 0.9, >= 0.9.4) + rb-inotify (~> 0.9, >= 0.9.7) + sprockets (3.7.1) + concurrent-ruby (~> 1.0) + rack (> 1, < 3) + sprockets-rails (3.2.1) + actionpack (>= 4.0) + activesupport (>= 4.0) + sprockets (>= 3.0.0) + sqlite3 (1.3.11) + thor (0.20.0) + thread_safe (0.3.6) + tzinfo (1.2.4) + thread_safe (~> 0.1) + websocket-driver (0.6.5) + websocket-extensions (>= 0.1.0) + websocket-extensions (0.1.2) + +PLATFORMS + ruby + +DEPENDENCIES + boxroom! + sqlite3 + +BUNDLED WITH + 1.16.0 diff --git a/MIT-LICENSE b/MIT-LICENSE new file mode 100644 index 0000000..5aa9b99 --- /dev/null +++ b/MIT-LICENSE @@ -0,0 +1,20 @@ +Copyright 2018 Serge Koba + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md index 6766e93..151fa4d 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,29 @@ -# boxroom-engine -Boxroom web file manager Rails engine +# Boxroom +This is a Rails engine built based on code of [Boxroom](https://github.com/mischa78/boxroom) project. + +# Features + + +## Install +- add to Gemfile +- run `rails boxroom:install:migrations` +- run `rails db:migrate` + +## Config +- Create `config/initializers/boxroom.rb` +```ruby +Boxroom.configure do |config| + config.site_name = 'Boxroom' + config.logo = 'boxroom/logo.png' +end +``` +- mount engine in `config/routes.rb` +```ruby +mount Boxroom::Engine => "/boxroom" +``` + +## Contributing +Please feel free to leave an issue or PR. + +## License +The engine is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT). diff --git a/Rakefile b/Rakefile new file mode 100644 index 0000000..add3afd --- /dev/null +++ b/Rakefile @@ -0,0 +1,36 @@ +begin + require 'bundler/setup' +rescue LoadError + puts 'You must `gem install bundler` and `bundle install` to run rake tasks' +end + +require 'rdoc/task' + +RDoc::Task.new(:rdoc) do |rdoc| + rdoc.rdoc_dir = 'rdoc' + rdoc.title = 'Boxroom' + rdoc.options << '--line-numbers' + rdoc.rdoc_files.include('README.md') + rdoc.rdoc_files.include('lib/**/*.rb') +end + +APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__) +load 'rails/tasks/engine.rake' + + +load 'rails/tasks/statistics.rake' + + + +require 'bundler/gem_tasks' + +require 'rake/testtask' + +Rake::TestTask.new(:test) do |t| + t.libs << 'test' + t.pattern = 'test/**/*_test.rb' + t.verbose = false +end + + +task default: :test diff --git a/app/assets/config/boxroom_manifest.js b/app/assets/config/boxroom_manifest.js new file mode 100644 index 0000000..6ca6727 --- /dev/null +++ b/app/assets/config/boxroom_manifest.js @@ -0,0 +1,2 @@ +//= link_directory ../javascripts/boxroom .js +//= link_directory ../stylesheets/boxroom .css diff --git a/app/assets/images/boxroom/.keep b/app/assets/images/boxroom/.keep new file mode 100644 index 0000000..e69de29 diff --git a/app/assets/images/boxroom/clipboard.png b/app/assets/images/boxroom/clipboard.png new file mode 100755 index 0000000..08647f1 Binary files /dev/null and b/app/assets/images/boxroom/clipboard.png differ diff --git a/app/assets/images/boxroom/clipboard_add.png b/app/assets/images/boxroom/clipboard_add.png new file mode 100755 index 0000000..1d0841d Binary files /dev/null and b/app/assets/images/boxroom/clipboard_add.png differ diff --git a/app/assets/images/boxroom/copy.png b/app/assets/images/boxroom/copy.png new file mode 100755 index 0000000..3836257 Binary files /dev/null and b/app/assets/images/boxroom/copy.png differ diff --git a/app/assets/images/boxroom/delete.png b/app/assets/images/boxroom/delete.png new file mode 100755 index 0000000..70b59dc Binary files /dev/null and b/app/assets/images/boxroom/delete.png differ diff --git a/app/assets/images/boxroom/edit.png b/app/assets/images/boxroom/edit.png new file mode 100755 index 0000000..cf0ef85 Binary files /dev/null and b/app/assets/images/boxroom/edit.png differ diff --git a/app/assets/images/boxroom/exclamation.png b/app/assets/images/boxroom/exclamation.png new file mode 100755 index 0000000..721ba1e Binary files /dev/null and b/app/assets/images/boxroom/exclamation.png differ diff --git a/app/assets/images/boxroom/extend.png b/app/assets/images/boxroom/extend.png new file mode 100755 index 0000000..a305904 Binary files /dev/null and b/app/assets/images/boxroom/extend.png differ diff --git a/app/assets/images/boxroom/failed.png b/app/assets/images/boxroom/failed.png new file mode 100755 index 0000000..7a368df Binary files /dev/null and b/app/assets/images/boxroom/failed.png differ diff --git a/app/assets/images/boxroom/file.png b/app/assets/images/boxroom/file.png new file mode 100755 index 0000000..75f92b0 Binary files /dev/null and b/app/assets/images/boxroom/file.png differ diff --git a/app/assets/images/boxroom/file_add.png b/app/assets/images/boxroom/file_add.png new file mode 100755 index 0000000..df35ed6 Binary files /dev/null and b/app/assets/images/boxroom/file_add.png differ diff --git a/app/assets/images/boxroom/fileicons/7z.png b/app/assets/images/boxroom/fileicons/7z.png new file mode 100755 index 0000000..6d6333a Binary files /dev/null and b/app/assets/images/boxroom/fileicons/7z.png differ diff --git a/app/assets/images/boxroom/fileicons/ai.png b/app/assets/images/boxroom/fileicons/ai.png new file mode 100755 index 0000000..9500998 Binary files /dev/null and b/app/assets/images/boxroom/fileicons/ai.png differ diff --git a/app/assets/images/boxroom/fileicons/aif.png b/app/assets/images/boxroom/fileicons/aif.png new file mode 100755 index 0000000..73ce1ca Binary files /dev/null and b/app/assets/images/boxroom/fileicons/aif.png differ diff --git a/app/assets/images/boxroom/fileicons/aiff.png b/app/assets/images/boxroom/fileicons/aiff.png new file mode 100755 index 0000000..73ce1ca Binary files /dev/null and b/app/assets/images/boxroom/fileicons/aiff.png differ diff --git a/app/assets/images/boxroom/fileicons/audio.png b/app/assets/images/boxroom/fileicons/audio.png new file mode 100755 index 0000000..73ce1ca Binary files /dev/null and b/app/assets/images/boxroom/fileicons/audio.png differ diff --git a/app/assets/images/boxroom/fileicons/bz2.png b/app/assets/images/boxroom/fileicons/bz2.png new file mode 100755 index 0000000..6d6333a Binary files /dev/null and b/app/assets/images/boxroom/fileicons/bz2.png differ diff --git a/app/assets/images/boxroom/fileicons/c.png b/app/assets/images/boxroom/fileicons/c.png new file mode 100755 index 0000000..7aca3f8 Binary files /dev/null and b/app/assets/images/boxroom/fileicons/c.png differ diff --git a/app/assets/images/boxroom/fileicons/conf.png b/app/assets/images/boxroom/fileicons/conf.png new file mode 100755 index 0000000..ed841a0 Binary files /dev/null and b/app/assets/images/boxroom/fileicons/conf.png differ diff --git a/app/assets/images/boxroom/fileicons/cpp.png b/app/assets/images/boxroom/fileicons/cpp.png new file mode 100755 index 0000000..d398622 Binary files /dev/null and b/app/assets/images/boxroom/fileicons/cpp.png differ diff --git a/app/assets/images/boxroom/fileicons/cs.png b/app/assets/images/boxroom/fileicons/cs.png new file mode 100755 index 0000000..7745561 Binary files /dev/null and b/app/assets/images/boxroom/fileicons/cs.png differ diff --git a/app/assets/images/boxroom/fileicons/css.png b/app/assets/images/boxroom/fileicons/css.png new file mode 100755 index 0000000..b5769e6 Binary files /dev/null and b/app/assets/images/boxroom/fileicons/css.png differ diff --git a/app/assets/images/boxroom/fileicons/csv.png b/app/assets/images/boxroom/fileicons/csv.png new file mode 100755 index 0000000..99eb086 Binary files /dev/null and b/app/assets/images/boxroom/fileicons/csv.png differ diff --git a/app/assets/images/boxroom/fileicons/divx.png b/app/assets/images/boxroom/fileicons/divx.png new file mode 100755 index 0000000..c8bd259 Binary files /dev/null and b/app/assets/images/boxroom/fileicons/divx.png differ diff --git a/app/assets/images/boxroom/fileicons/doc.png b/app/assets/images/boxroom/fileicons/doc.png new file mode 100755 index 0000000..1beb2e5 Binary files /dev/null and b/app/assets/images/boxroom/fileicons/doc.png differ diff --git a/app/assets/images/boxroom/fileicons/docx.png b/app/assets/images/boxroom/fileicons/docx.png new file mode 100755 index 0000000..1beb2e5 Binary files /dev/null and b/app/assets/images/boxroom/fileicons/docx.png differ diff --git a/app/assets/images/boxroom/fileicons/dot.png b/app/assets/images/boxroom/fileicons/dot.png new file mode 100755 index 0000000..1beb2e5 Binary files /dev/null and b/app/assets/images/boxroom/fileicons/dot.png differ diff --git a/app/assets/images/boxroom/fileicons/fla.png b/app/assets/images/boxroom/fileicons/fla.png new file mode 100755 index 0000000..152da35 Binary files /dev/null and b/app/assets/images/boxroom/fileicons/fla.png differ diff --git a/app/assets/images/boxroom/fileicons/gif.png b/app/assets/images/boxroom/fileicons/gif.png new file mode 100755 index 0000000..c485c20 Binary files /dev/null and b/app/assets/images/boxroom/fileicons/gif.png differ diff --git a/app/assets/images/boxroom/fileicons/gz.png b/app/assets/images/boxroom/fileicons/gz.png new file mode 100755 index 0000000..6d6333a Binary files /dev/null and b/app/assets/images/boxroom/fileicons/gz.png differ diff --git a/app/assets/images/boxroom/fileicons/htm.png b/app/assets/images/boxroom/fileicons/htm.png new file mode 100755 index 0000000..f355d31 Binary files /dev/null and b/app/assets/images/boxroom/fileicons/htm.png differ diff --git a/app/assets/images/boxroom/fileicons/html.png b/app/assets/images/boxroom/fileicons/html.png new file mode 100755 index 0000000..f355d31 Binary files /dev/null and b/app/assets/images/boxroom/fileicons/html.png differ diff --git a/app/assets/images/boxroom/fileicons/image.png b/app/assets/images/boxroom/fileicons/image.png new file mode 100755 index 0000000..c485c20 Binary files /dev/null and b/app/assets/images/boxroom/fileicons/image.png differ diff --git a/app/assets/images/boxroom/fileicons/java.png b/app/assets/images/boxroom/fileicons/java.png new file mode 100755 index 0000000..d398622 Binary files /dev/null and b/app/assets/images/boxroom/fileicons/java.png differ diff --git a/app/assets/images/boxroom/fileicons/jpeg.png b/app/assets/images/boxroom/fileicons/jpeg.png new file mode 100755 index 0000000..c485c20 Binary files /dev/null and b/app/assets/images/boxroom/fileicons/jpeg.png differ diff --git a/app/assets/images/boxroom/fileicons/jpg.png b/app/assets/images/boxroom/fileicons/jpg.png new file mode 100755 index 0000000..c485c20 Binary files /dev/null and b/app/assets/images/boxroom/fileicons/jpg.png differ diff --git a/app/assets/images/boxroom/fileicons/js.png b/app/assets/images/boxroom/fileicons/js.png new file mode 100755 index 0000000..d398622 Binary files /dev/null and b/app/assets/images/boxroom/fileicons/js.png differ diff --git a/app/assets/images/boxroom/fileicons/mdb.png b/app/assets/images/boxroom/fileicons/mdb.png new file mode 100755 index 0000000..4f08873 Binary files /dev/null and b/app/assets/images/boxroom/fileicons/mdb.png differ diff --git a/app/assets/images/boxroom/fileicons/mdbx.png b/app/assets/images/boxroom/fileicons/mdbx.png new file mode 100755 index 0000000..4f08873 Binary files /dev/null and b/app/assets/images/boxroom/fileicons/mdbx.png differ diff --git a/app/assets/images/boxroom/fileicons/mov.png b/app/assets/images/boxroom/fileicons/mov.png new file mode 100755 index 0000000..c8bd259 Binary files /dev/null and b/app/assets/images/boxroom/fileicons/mov.png differ diff --git a/app/assets/images/boxroom/fileicons/mp3.png b/app/assets/images/boxroom/fileicons/mp3.png new file mode 100755 index 0000000..73ce1ca Binary files /dev/null and b/app/assets/images/boxroom/fileicons/mp3.png differ diff --git a/app/assets/images/boxroom/fileicons/mpg.png b/app/assets/images/boxroom/fileicons/mpg.png new file mode 100755 index 0000000..c8bd259 Binary files /dev/null and b/app/assets/images/boxroom/fileicons/mpg.png differ diff --git a/app/assets/images/boxroom/fileicons/ogg.png b/app/assets/images/boxroom/fileicons/ogg.png new file mode 100755 index 0000000..73ce1ca Binary files /dev/null and b/app/assets/images/boxroom/fileicons/ogg.png differ diff --git a/app/assets/images/boxroom/fileicons/pdf.png b/app/assets/images/boxroom/fileicons/pdf.png new file mode 100755 index 0000000..c68ab66 Binary files /dev/null and b/app/assets/images/boxroom/fileicons/pdf.png differ diff --git a/app/assets/images/boxroom/fileicons/php.png b/app/assets/images/boxroom/fileicons/php.png new file mode 100755 index 0000000..75938d2 Binary files /dev/null and b/app/assets/images/boxroom/fileicons/php.png differ diff --git a/app/assets/images/boxroom/fileicons/pl.png b/app/assets/images/boxroom/fileicons/pl.png new file mode 100755 index 0000000..d398622 Binary files /dev/null and b/app/assets/images/boxroom/fileicons/pl.png differ diff --git a/app/assets/images/boxroom/fileicons/png.png b/app/assets/images/boxroom/fileicons/png.png new file mode 100755 index 0000000..c485c20 Binary files /dev/null and b/app/assets/images/boxroom/fileicons/png.png differ diff --git a/app/assets/images/boxroom/fileicons/ppt.png b/app/assets/images/boxroom/fileicons/ppt.png new file mode 100755 index 0000000..134a007 Binary files /dev/null and b/app/assets/images/boxroom/fileicons/ppt.png differ diff --git a/app/assets/images/boxroom/fileicons/pptx.png b/app/assets/images/boxroom/fileicons/pptx.png new file mode 100755 index 0000000..134a007 Binary files /dev/null and b/app/assets/images/boxroom/fileicons/pptx.png differ diff --git a/app/assets/images/boxroom/fileicons/ps.png b/app/assets/images/boxroom/fileicons/ps.png new file mode 100755 index 0000000..7b8b9b0 Binary files /dev/null and b/app/assets/images/boxroom/fileicons/ps.png differ diff --git a/app/assets/images/boxroom/fileicons/py.png b/app/assets/images/boxroom/fileicons/py.png new file mode 100755 index 0000000..d398622 Binary files /dev/null and b/app/assets/images/boxroom/fileicons/py.png differ diff --git a/app/assets/images/boxroom/fileicons/ram.png b/app/assets/images/boxroom/fileicons/ram.png new file mode 100755 index 0000000..c8bd259 Binary files /dev/null and b/app/assets/images/boxroom/fileicons/ram.png differ diff --git a/app/assets/images/boxroom/fileicons/rar.png b/app/assets/images/boxroom/fileicons/rar.png new file mode 100755 index 0000000..6d6333a Binary files /dev/null and b/app/assets/images/boxroom/fileicons/rar.png differ diff --git a/app/assets/images/boxroom/fileicons/rb.png b/app/assets/images/boxroom/fileicons/rb.png new file mode 100755 index 0000000..7db6ba0 Binary files /dev/null and b/app/assets/images/boxroom/fileicons/rb.png differ diff --git a/app/assets/images/boxroom/fileicons/rm.png b/app/assets/images/boxroom/fileicons/rm.png new file mode 100755 index 0000000..73ce1ca Binary files /dev/null and b/app/assets/images/boxroom/fileicons/rm.png differ diff --git a/app/assets/images/boxroom/fileicons/rtf.png b/app/assets/images/boxroom/fileicons/rtf.png new file mode 100755 index 0000000..ed841a0 Binary files /dev/null and b/app/assets/images/boxroom/fileicons/rtf.png differ diff --git a/app/assets/images/boxroom/fileicons/sql.png b/app/assets/images/boxroom/fileicons/sql.png new file mode 100755 index 0000000..ea232a7 Binary files /dev/null and b/app/assets/images/boxroom/fileicons/sql.png differ diff --git a/app/assets/images/boxroom/fileicons/swf.png b/app/assets/images/boxroom/fileicons/swf.png new file mode 100755 index 0000000..3070f05 Binary files /dev/null and b/app/assets/images/boxroom/fileicons/swf.png differ diff --git a/app/assets/images/boxroom/fileicons/tar.png b/app/assets/images/boxroom/fileicons/tar.png new file mode 100755 index 0000000..6d6333a Binary files /dev/null and b/app/assets/images/boxroom/fileicons/tar.png differ diff --git a/app/assets/images/boxroom/fileicons/tgz.png b/app/assets/images/boxroom/fileicons/tgz.png new file mode 100755 index 0000000..6d6333a Binary files /dev/null and b/app/assets/images/boxroom/fileicons/tgz.png differ diff --git a/app/assets/images/boxroom/fileicons/txt.png b/app/assets/images/boxroom/fileicons/txt.png new file mode 100755 index 0000000..ed841a0 Binary files /dev/null and b/app/assets/images/boxroom/fileicons/txt.png differ diff --git a/app/assets/images/boxroom/fileicons/video.png b/app/assets/images/boxroom/fileicons/video.png new file mode 100755 index 0000000..c8bd259 Binary files /dev/null and b/app/assets/images/boxroom/fileicons/video.png differ diff --git a/app/assets/images/boxroom/fileicons/wav.png b/app/assets/images/boxroom/fileicons/wav.png new file mode 100755 index 0000000..73ce1ca Binary files /dev/null and b/app/assets/images/boxroom/fileicons/wav.png differ diff --git a/app/assets/images/boxroom/fileicons/wma.png b/app/assets/images/boxroom/fileicons/wma.png new file mode 100755 index 0000000..73ce1ca Binary files /dev/null and b/app/assets/images/boxroom/fileicons/wma.png differ diff --git a/app/assets/images/boxroom/fileicons/wmv.png b/app/assets/images/boxroom/fileicons/wmv.png new file mode 100755 index 0000000..c8bd259 Binary files /dev/null and b/app/assets/images/boxroom/fileicons/wmv.png differ diff --git a/app/assets/images/boxroom/fileicons/xls.png b/app/assets/images/boxroom/fileicons/xls.png new file mode 100755 index 0000000..4403681 Binary files /dev/null and b/app/assets/images/boxroom/fileicons/xls.png differ diff --git a/app/assets/images/boxroom/fileicons/xlsx.png b/app/assets/images/boxroom/fileicons/xlsx.png new file mode 100755 index 0000000..4403681 Binary files /dev/null and b/app/assets/images/boxroom/fileicons/xlsx.png differ diff --git a/app/assets/images/boxroom/fileicons/xml.png b/app/assets/images/boxroom/fileicons/xml.png new file mode 100755 index 0000000..b5769e6 Binary files /dev/null and b/app/assets/images/boxroom/fileicons/xml.png differ diff --git a/app/assets/images/boxroom/fileicons/xvid.png b/app/assets/images/boxroom/fileicons/xvid.png new file mode 100755 index 0000000..c8bd259 Binary files /dev/null and b/app/assets/images/boxroom/fileicons/xvid.png differ diff --git a/app/assets/images/boxroom/fileicons/zip.png b/app/assets/images/boxroom/fileicons/zip.png new file mode 100755 index 0000000..6d6333a Binary files /dev/null and b/app/assets/images/boxroom/fileicons/zip.png differ diff --git a/app/assets/images/boxroom/folder.png b/app/assets/images/boxroom/folder.png new file mode 100644 index 0000000..f0c7a97 Binary files /dev/null and b/app/assets/images/boxroom/folder.png differ diff --git a/app/assets/images/boxroom/folder_add.png b/app/assets/images/boxroom/folder_add.png new file mode 100644 index 0000000..1008981 Binary files /dev/null and b/app/assets/images/boxroom/folder_add.png differ diff --git a/app/assets/images/boxroom/group.png b/app/assets/images/boxroom/group.png new file mode 100755 index 0000000..a6aae04 Binary files /dev/null and b/app/assets/images/boxroom/group.png differ diff --git a/app/assets/images/boxroom/group_add.png b/app/assets/images/boxroom/group_add.png new file mode 100644 index 0000000..de1ef7b Binary files /dev/null and b/app/assets/images/boxroom/group_add.png differ diff --git a/app/assets/images/boxroom/group_grey.png b/app/assets/images/boxroom/group_grey.png new file mode 100644 index 0000000..644dc3d Binary files /dev/null and b/app/assets/images/boxroom/group_grey.png differ diff --git a/app/assets/images/boxroom/information.png b/app/assets/images/boxroom/information.png new file mode 100755 index 0000000..5d353a1 Binary files /dev/null and b/app/assets/images/boxroom/information.png differ diff --git a/app/assets/images/boxroom/logo.png b/app/assets/images/boxroom/logo.png new file mode 100644 index 0000000..5ba0687 Binary files /dev/null and b/app/assets/images/boxroom/logo.png differ diff --git a/app/assets/images/boxroom/move.png b/app/assets/images/boxroom/move.png new file mode 100755 index 0000000..d59a9bd Binary files /dev/null and b/app/assets/images/boxroom/move.png differ diff --git a/app/assets/images/boxroom/permissions.png b/app/assets/images/boxroom/permissions.png new file mode 100755 index 0000000..7e47c79 Binary files /dev/null and b/app/assets/images/boxroom/permissions.png differ diff --git a/app/assets/images/boxroom/share.png b/app/assets/images/boxroom/share.png new file mode 100755 index 0000000..e3071ef Binary files /dev/null and b/app/assets/images/boxroom/share.png differ diff --git a/app/assets/images/boxroom/spinner.gif b/app/assets/images/boxroom/spinner.gif new file mode 100755 index 0000000..bdcb518 Binary files /dev/null and b/app/assets/images/boxroom/spinner.gif differ diff --git a/app/assets/images/boxroom/tick.png b/app/assets/images/boxroom/tick.png new file mode 100755 index 0000000..a7d7a96 Binary files /dev/null and b/app/assets/images/boxroom/tick.png differ diff --git a/app/assets/images/boxroom/user.png b/app/assets/images/boxroom/user.png new file mode 100755 index 0000000..274d6b9 Binary files /dev/null and b/app/assets/images/boxroom/user.png differ diff --git a/app/assets/images/boxroom/user_add.png b/app/assets/images/boxroom/user_add.png new file mode 100755 index 0000000..9f6c0f5 Binary files /dev/null and b/app/assets/images/boxroom/user_add.png differ diff --git a/app/assets/javascripts/boxroom/application.js.coffee b/app/assets/javascripts/boxroom/application.js.coffee new file mode 100644 index 0000000..1bad5cd --- /dev/null +++ b/app/assets/javascripts/boxroom/application.js.coffee @@ -0,0 +1,51 @@ +//= require jquery +//= require jquery_ujs +//= require jquery-fileupload/basic +//= require jquery-fileupload/vendor/tmpl +//= require_self +//= require_tree . + +$(window).load -> + fadeout '#notice' + fadeout '#alert' + +jQuery -> + $('.back_link').on 'click', (e) -> + e.preventDefault() + show_element '#files_and_folders' + + $('.permissions_link').on 'click', (e) -> + e.preventDefault() + show_element '#permissions' + + $('.clipboard_link').on 'click', (e) -> + e.preventDefault() + show_element '#clipboard' + + $('.emails_to_share_with').on 'change', (e) -> + update_counter e.target + + $('.emails_to_share_with').on 'keyup', (e) -> + update_counter e.target + +fadeout = (el) -> + $(el).delay(3000).fadeOut('slow') + +show_element = (el) -> + el = '#files_and_folders' if $(el).is(':visible') + + elements = ['#files_and_folders', '#permissions', '#clipboard'] + elements.splice elements.indexOf(el), 1 + hide_elements elements + + $(el).slideDown('slow') + $("#{el}_link").removeClass('folder_menu').addClass('highlight') + +hide_elements = (elements) -> + for element in elements + $(element).slideUp('slow') if $(element).is(':visible') + $("#{element}_link").removeClass('highlight').addClass('folder_menu') + +update_counter = (el) -> + $('#counter').html el.value.length + $('#counter').css 'color', if el.value.length > 255 then '#F00' else '#000' diff --git a/app/assets/javascripts/boxroom/files.js.coffee b/app/assets/javascripts/boxroom/files.js.coffee new file mode 100644 index 0000000..236d074 --- /dev/null +++ b/app/assets/javascripts/boxroom/files.js.coffee @@ -0,0 +1,28 @@ +jQuery -> + $('#new_user_file').fileupload + dataType: 'script' + add: (e, data) -> + $('#user_file_attachment').prop('disabled', true) + file = data.files[0] + folder = $('#target_folder_id').val() + $.getJSON "/file_exists?name=#{encodeURIComponent(file.name)}&folder=#{encodeURIComponent(folder)}", (exists) -> + data.context = $(tmpl("template-upload", file).trim()) + $('#progress').append(data.context) + if exists + data.context.find('.spinner').hide() + data.context.find('.failed').show() + data.context.find('.percentage').hide() + data.context.find('.exists_message').show() + $('#user_file_attachment').prop('disabled', false) + else + data.submit() + progress: (e, data) -> + if data.context + progress = parseInt(data.loaded / data.total * 100) + data.context.find('.percentage').html("#{progress}%") + if data.loaded == data.total + data.context.find('.spinner').hide() + data.context.find('.tick').show() + stop: (e) -> + folder = $('#target_folder_id').val() + window.location.href = "/folders/#{folder}" diff --git a/app/assets/stylesheets/boxroom/application.scss b/app/assets/stylesheets/boxroom/application.scss new file mode 100644 index 0000000..2d49a62 --- /dev/null +++ b/app/assets/stylesheets/boxroom/application.scss @@ -0,0 +1,88 @@ +/* +*= require_self +*= require_tree . +*/ + +html, body { height: 100%; } +body { padding: 0px; margin: 0px; background-color: rgb(225,225,225); } +body, input { font-family: Arial; font-size: 13pt; } +input { padding: 3px; border: 1px solid rgb(210,210,210); } +input[type='button'], input[type='submit'] { background-color: #EEE; padding: 5px; } +input[type='file'] { border: 0; } +textarea { border: 1px solid rgb(210,210,210); width: 700px; padding: 10px; font-family: Arial; font-size: 10pt; } +img { border: 0; } +h1 { font-size: 20pt; text-transform: uppercase; } +h3 { font-size: 13pt; margin-bottom: 0; } +a { color: #BA303A; text-decoration: none; } +a:hover { text-decoration: underline; } +table { border-collapse: collapse; } +th { text-align: left; font-size: 11pt; } +td img { padding: 0; } + +#container { min-height: 100%; position: relative; } +#header { background-color: rgb(0,39,77); color: #FFF; border-bottom: 2px solid rgb(8,58,127); min-height: 70px; } +#menu { background-color: rgb(0,24,49); border-bottom: 4px solid #BA303A; } +#content { position: relative; width: 850px; margin: 10px auto 0 auto; padding: 15px 25px 15px 25px; background-color: #FFF; border-radius: 8px; border-right: 1px solid #CCC; border-bottom: 1px solid #AAA; } +#footer { position: absolute; bottom: 0; width: 100%; background-color: rgb(0,24,49); color: #FFF; border-top: 4px solid #BA303A; } +#footer_spacer { height: 70px; } + +#progress p span.status { margin-left: 3px; } +#progress p img { vertical-align: middle; margin-bottom: 4px; } + +.menu { margin: 0; padding: 10px 15px 7px 15px; color: #FFF; } +.menu a, .footer a { color: #FFF; } +.footer { margin: 0; padding: 15px; text-align: center; } +.footer a { text-decoration: underline; } +.table_header td { font-weight: bold; } +.even td, .odd td, th { padding: 12px 7px 7px 7px; } +.even { background-color: #EEE; } +.odd { background-color: #FFF; } +.text_input { width: 280px; } +.user_welcome { float: right; margin-right: 15px; } +.user_welcome a { color: #FFF; text-decoration: underline; } +.user_groups { margin-right: 200px; display: block; } +.user_groups label { margin-right: 15px; } +.user_name, .user_expiration { min-width: 180px; } +.user_email { min-width: 370px; } +.group_name, .clipboard_item { min-width: 483px; } +.file_name { min-width: 250px; max-width: 400px; overflow: hidden; } +.file_name a, .shared_file a { color: #000; text-decoration: underline; } +.file_size { min-width: 100px; } +.disabled { color: #999; } +.breadcrumb { margin-bottom: 5px; padding: 4px; font-size: 11pt; background-color: #F6F6F6; border: 1px solid #DDD; border-bottom-color: #AAA; border-right-color: #CCC; display: inline-block; } +.nowrap { white-space: nowrap; } +.permission_column { width: 75px; text-align: center; } +.permissions_button, .back { display: inline-block; margin-top: 15px; } +.clipboard_empty { margin-top: 35px; } +.clipboard_info_image { float: left; margin: 3px 15px 15px 0; } +.button_to, .button_to div { display: inline; } +.emails_to_share_with { height: 39px; width: 755px; } +.share_message { height: 80px; width: 755px; } +.shared_file { display: inline-block; min-width: 400px; padding: 15px; background-color: #EEE; } +.shared_file img { margin-right: 8px; } +.share_link_emails { font-size: 11pt; } +.comma_seperated, .optional { position: relative; top: -1px; left: 3px; font-size: 10pt; } +.char_counter { float: right; margin: 5px 75px 0 0; font-size: 10pt; } +.translation .missing, .red { color: #F00; } + +.error, .notice { position: absolute; top: 0; left: 0; width: 100%; text-align: center; } +.error { background-color: rgba(255,0,0,0.8); } +.notice { background-color: rgba(0,165,0,0.7); } + +.error p, .notice p { display: inline-block; font-size: 16pt; color: #FFF; margin: 0; padding: 10px 0 10px 45px; background-repeat: no-repeat; background-position: 0 5px; } +.error p { background-image: url(exclamation.png); } +.notice p { background-image: url(information.png); } + +span.field_with_errors input, span.field_with_errors textarea { background-color: #FDD; } +#errorExplanation { width: 500px; border: 2px solid #c00; padding: 7px 7px 15px 7px; margin: 10px 0 10px 0; background-color: #f0f0f0; } +#errorExplanation p { padding-left: 8px; } +#errorExplanation h2 { text-align: left; font-size: 14pt; font-weight: bold; padding: 5px 5px 5px 15px; margin: -7px; margin-bottom: 7px; background-color: #c00; color: #fff; } +#errorExplanation ul { margin: 0; } +#errorExplanation ul li { list-style: square; } + +.folder_menu, .user_menu, .group_menu { padding: 7px 14px 7px 14px; } +.folder_menu a, .user_menu a, .group_menu a { outline: none; } + +.highlight { display: inline-block; margin: -7px 0 -7px 0; padding-left: 14px; background-color: #BA303A; border-radius: 15px; } +.highlight span { display: inline-block; height: 27px; padding: 7px 14px 0 0; } +.highlight a { text-decoration: none; color: #FFF; outline: none; } diff --git a/app/controllers/boxroom/admins_controller.rb b/app/controllers/boxroom/admins_controller.rb new file mode 100644 index 0000000..a8cb67a --- /dev/null +++ b/app/controllers/boxroom/admins_controller.rb @@ -0,0 +1,28 @@ +module Boxroom + class AdminsController < ApplicationController + skip_before_action :require_admin_in_system, :require_login + before_action :require_no_admin + + def new + @user = User.new + end + + def create + @user = User.new(permitted_params.user) + @user.password_required = true + @user.is_admin = true + + if @user.save + redirect_to new_session_url, :notice => t(:admin_user_created_successfully) + else + render :action => 'new' + end + end + + private + + def require_no_admin + redirect_to new_session_url unless User.no_admin_yet? + end + end +end \ No newline at end of file diff --git a/app/controllers/boxroom/application_controller.rb b/app/controllers/boxroom/application_controller.rb new file mode 100644 index 0000000..3a96328 --- /dev/null +++ b/app/controllers/boxroom/application_controller.rb @@ -0,0 +1,78 @@ +module Boxroom + class ApplicationController < ActionController::Base + protect_from_forgery + + before_action :require_admin_in_system + before_action :require_login + + helper_method :clipboard, :current_user, :signed_in?, :permitted_params + + protected + + def clipboard + session[:clipboard] ||= Clipboard.new + end + + def current_user + @current_user ||= User.find_by_id(session[:user_id]) + end + + def signed_in? + !!current_user + end + + def permitted_params + @permitted_params ||= PermittedParams.new(params, current_user) + end + + def require_admin_in_system + redirect_to new_admin_url if User.no_admin_yet? + end + + def require_admin + redirect_to :root unless current_user.member_of_admins? + end + + def require_login + if current_user.nil? + user = User.find_by_remember_token(cookies[:auth_token]) unless cookies[:auth_token].blank? + + if user.nil? + reset_session + session[:user_id] = nil + session[:return_to] = request.fullpath + redirect_to new_session_url + else + user.refresh_remember_token + session[:user_id] = user.id + cookies[:auth_token] = user.remember_token + end + end + end + + def require_existing_target_folder + @target_folder = get_folder_or_redirect(params[:folder_id]) + end + + def require_create_permission + unless current_user.can_create(@target_folder) + redirect_to @target_folder, :alert => t(:no_permissions_for_this_type, :method => t(:create), :type => t(:this_folder)) + end + end + + %w{read update delete}.each do |method| + define_method "require_#{method}_permission" do + unless (method == 'read' && @folder.is_root?) || current_user.send("can_#{method}", @folder) + redirect_folder = @folder.parent.nil? ? Folder.root : @folder.parent + redirect_to redirect_folder, :alert => t(:no_permissions_for_this_type, :method => t(:create), :type => t(:this_folder)) + end + end + end + + def get_folder_or_redirect(id) + Folder.find(id) + rescue ActiveRecord::RecordNotFound + redirect_to Folder.root, :alert => t(:already_deleted, :type => t(:this_folder)) + end + end +end \ No newline at end of file diff --git a/app/controllers/boxroom/clipboard_controller.rb b/app/controllers/boxroom/clipboard_controller.rb new file mode 100644 index 0000000..03ae974 --- /dev/null +++ b/app/controllers/boxroom/clipboard_controller.rb @@ -0,0 +1,77 @@ +module Boxroom + class ClipboardController < ApplicationController + before_action :require_existing_item, :except => :reset + before_action :require_existing_target_folder, :only => [:copy, :move] + before_action :require_target_is_not_child, :only => :move + before_action :require_create_permission, :only => [:copy, :move] + before_action :require_read_permission, :only => [:create, :copy, :move] + before_action :require_delete_permission, :only => :move + + # @item is set in require_existing_item + def create + clipboard.add(@item) + redirect_to folder_url(params[:folder_id]), :notice => t(:added_to_clipboard) + end + + # @item is set in require_existing_item + def destroy + clipboard.remove(@item) + redirect_to folder_url(params[:folder_id]) + end + + def reset + clipboard.reset + redirect_to folder_url(params[:folder_id]) + end + + def copy + paste :copy + end + + def move + paste :move + end + + private + + # @item is set in require_existing_item + # @target_folder is set in require_existing_target_folder + def paste(action) + @item.send(action, @target_folder) + clipboard.remove(@item) + redirect_to folder_url(params[:folder_id]) + rescue ActiveRecord::RecordInvalid + redirect_to folder_url(params[:folder_id]), :alert => t("could_not_#{action}", :type => t(params[:type])) + end + + def require_existing_item + if params[:type] == 'folder' + @item = @folder = Folder.find(params[:id]) + else + @item = UserFile.find(params[:id]) + @folder = @item.folder + end + rescue ActiveRecord::RecordNotFound + redirect_to folder_url(params[:folder_id]), :alert => t(:already_deleted, :type => t("this_#{params[:type]}")) + end + + def require_target_is_not_child + if params[:type] == 'folder' + if @folder == @target_folder || @folder.parent_of?(@target_folder) + redirect_to folder_url(params[:folder_id]), :alert => t(:cannot_move_to_own_subfolder) + end + end + end + + # Overrides require_#{method}_permission in ApplicationController. + # Check if @folder can be read or deleted and redirects to the + # current folder (identified by params[:folder_id]) if not. + %w{read delete}.each do |method| + define_method "require_#{method}_permission" do + unless current_user.send("can_#{method}", @folder) + redirect_to folder_url(params[:folder_id]), :alert => t(:no_permissions_for_this_type, :method => t(method), :type => t("this_#{params[:type]}")) + end + end + end + end +end \ No newline at end of file diff --git a/app/controllers/boxroom/files_controller.rb b/app/controllers/boxroom/files_controller.rb new file mode 100644 index 0000000..fafb513 --- /dev/null +++ b/app/controllers/boxroom/files_controller.rb @@ -0,0 +1,64 @@ +module Boxroom + class FilesController < ApplicationController + before_action :require_existing_file, :only => [:show, :edit, :update, :destroy] + before_action :require_existing_target_folder, :only => [:new, :create] + + before_action :require_create_permission, :only => [:new, :create] + before_action :require_read_permission, :only => :show + before_action :require_update_permission, :only => [:edit, :update] + before_action :require_delete_permission, :only => :destroy + + # @file and @folder are set in require_existing_file + def show + send_file @file.attachment.path, :filename => @file.attachment_file_name + end + + # @target_folder is set in require_existing_target_folder + def new + @file = @target_folder.user_files.build + end + + # @target_folder is set in require_existing_target_folder + def create + @file = @target_folder.user_files.create(permitted_params.user_file) + render :nothing => true + end + + # @file and @folder are set in require_existing_file + def edit + end + + # @file and @folder are set in require_existing_file + def update + if @file.update_attributes(permitted_params.user_file) + redirect_to edit_file_url(@file), :notice => t(:your_changes_were_saved) + else + render :action => 'edit' + end + end + + # @file and @folder are set in require_existing_file + def destroy + @file.destroy + redirect_to @folder + end + + def exists + @folder = Folder.find(params[:folder]) + + if current_user.can_read(@folder) || current_user.can_write(@folder) + @file = @folder.user_files.build(:attachment_file_name => params[:name].gsub(RESTRICTED_CHARACTERS, '_')) + render :json => !@file.valid? + end + end + + private + + def require_existing_file + @file = UserFile.find(params[:id]) + @folder = @file.folder + rescue ActiveRecord::RecordNotFound + redirect_to Folder.root, :alert => t(:already_deleted, :type => t(:this_file)) + end + end +end \ No newline at end of file diff --git a/app/controllers/boxroom/folders_controller.rb b/app/controllers/boxroom/folders_controller.rb new file mode 100644 index 0000000..7587a3e --- /dev/null +++ b/app/controllers/boxroom/folders_controller.rb @@ -0,0 +1,89 @@ +module Boxroom + class FoldersController < ApplicationController + before_action :require_existing_folder, :only => [:show, :edit, :update, :destroy] + before_action :require_existing_target_folder, :only => [:new, :create] + before_action :require_folder_isnt_root_folder, :only => [:edit, :update, :destroy] + + before_action :require_create_permission, :only => [:new, :create] + before_action :require_read_permission, :only => :show + before_action :require_update_permission, :only => [:edit, :update] + before_action :require_delete_permission, :only => :destroy + + def index + redirect_to Folder.root + end + + # Note: @folder is set in require_existing_folder + def show + end + + # Note: @target_folder is set in require_existing_target_folder + def new + @folder = @target_folder.children.build + end + + # Note: @target_folder is set in require_existing_target_folder + def create + @folder = @target_folder.children.build(permitted_params.folder) + + if @folder.save + redirect_to @target_folder + else + render :action => 'new' + end + end + + # Note: @folder is set in require_existing_folder + def edit + end + + # Note: @folder is set in require_existing_folder + def update + if @folder.update_attributes(permitted_params.folder) + redirect_to edit_folder_url(@folder), :notice => t(:your_changes_were_saved) + else + render :action => 'edit' + end + end + + # Note: @folder is set in require_existing_folder + def destroy + target_folder = @folder.parent + @folder.destroy + redirect_to target_folder + end + + private + + # get_folder_or_redirect is defined in ApplicationController + def require_existing_folder + @folder = get_folder_or_redirect(params[:id]) + end + + def require_folder_isnt_root_folder + if @folder.is_root? + redirect_to Folder.root, :alert => t(:cannot_delete_root_folder) + end + end + + # Overrides require_delete_permission in ApplicationController + def require_delete_permission + unless @folder.is_root? || current_user.can_delete(@folder) + redirect_to @folder.parent, :alert => t(:no_permissions_for_this_type, :method => t(:delete), :type => t(:this_folder)) + else + require_delete_permissions_for(@folder.children) + end + end + + def require_delete_permissions_for(folders) + folders.each do |folder| + unless current_user.can_delete(folder) + redirect_to @folder.parent, :alert => t(:no_delete_permissions_for_subfolder) + else + # Recursive... + require_delete_permissions_for(folder.children) + end + end + end + end +end \ No newline at end of file diff --git a/app/controllers/boxroom/groups_controller.rb b/app/controllers/boxroom/groups_controller.rb new file mode 100644 index 0000000..de30dda --- /dev/null +++ b/app/controllers/boxroom/groups_controller.rb @@ -0,0 +1,58 @@ +module Boxroom + class GroupsController < ApplicationController + before_action :require_admin + before_action :require_existing_group, :only => [:edit, :update, :destroy] + before_action :require_group_isnt_admins_group, :only => [:edit, :update, :destroy] + + def index + @groups = Group.order(:name) + end + + def new + @group = Group.new + end + + def create + @group = Group.new(permitted_params.group) + + if @group.save + redirect_to groups_url + else + render :action => 'new' + end + end + + # Note: @group is set in require_existing_group + def edit + end + + # Note: @group is set in require_existing_group + def update + if @group.update_attributes(permitted_params.group) + redirect_to edit_group_url(@group), :notice => t(:your_changes_were_saved) + else + render :action => 'edit' + end + end + + # Note: @group is set in require_existing_group + def destroy + @group.destroy + redirect_to groups_url + end + + private + + def require_existing_group + @group = Group.find(params[:id]) + rescue ActiveRecord::RecordNotFound + redirect_to groups_url, :alert => t(:group_already_deleted) + end + + def require_group_isnt_admins_group + if @group.admins_group? + redirect_to groups_url, :alert => t(:admins_group_cannot_be_deleted) + end + end + end +end \ No newline at end of file diff --git a/app/controllers/boxroom/permissions_controller.rb b/app/controllers/boxroom/permissions_controller.rb new file mode 100644 index 0000000..720f10e --- /dev/null +++ b/app/controllers/boxroom/permissions_controller.rb @@ -0,0 +1,17 @@ +module Boxroom + class PermissionsController < ApplicationController + before_action :require_admin + + def update_multiple + if params[:permissions] + permissions = Permission.update(params[:permissions].keys, params[:permissions].values) + folder = permissions.first.folder + folder.copy_permissions_to_children(permissions) if params[:recursive] && folder.has_children? + end + + redirect_to :back + rescue ActiveRecord::RecordNotFound # Folder was deleted, so permissions are gone too + redirect_to Folder.root, :alert => t(:already_deleted, :type => t(:this_folder)) + end + end +end \ No newline at end of file diff --git a/app/controllers/boxroom/reset_password_controller.rb b/app/controllers/boxroom/reset_password_controller.rb new file mode 100644 index 0000000..e916077 --- /dev/null +++ b/app/controllers/boxroom/reset_password_controller.rb @@ -0,0 +1,43 @@ +module Boxroom + class ResetPasswordController < ApplicationController + before_action :require_valid_token, :only => [:edit, :update] + skip_before_action :require_login + + def new + end + + def create + user = User.find_by_email(params[:email]) + + unless user.nil? + user.refresh_reset_password_token + UserMailer.reset_password_email(user).deliver_now + end + + redirect_to new_reset_password_url, :notice => t(:instruction_email_sent, :email => params[:email]) + end + + # Note: @user is set in require_valid_token + def edit + end + + # Note: @user is set in require_valid_token + def update + if @user.update_attributes(permitted_params.user.merge({:password_required => true})) + redirect_to new_session_url, :notice => t(:password_reset_successfully) + else + render :action => 'edit' + end + end + + private + + def require_valid_token + @user = User.find_by_reset_password_token(params[:id]) + + if @user.nil? || @user.reset_password_token_expires_at < Time.now + redirect_to new_reset_password_url, :alert => t(:reset_url_expired) + end + end + end +end \ No newline at end of file diff --git a/app/controllers/boxroom/sessions_controller.rb b/app/controllers/boxroom/sessions_controller.rb new file mode 100644 index 0000000..12cbbe9 --- /dev/null +++ b/app/controllers/boxroom/sessions_controller.rb @@ -0,0 +1,46 @@ +module Boxroom + class SessionsController < ApplicationController + skip_before_action :require_login + + def new + end + + def create + user = User.authenticate(params[:username], params[:password]) + + unless user.nil? + if params[:remember_me] == 'true' + user.refresh_remember_token + cookies[:auth_token] = {:value => user.remember_token, :expires => 2.weeks.from_now} + end + + session[:user_id] = user.id + redirect_url = session.delete(:return_to) || folders_url + redirect_to redirect_url, :only_path => true + else + log_failed_sign_in_attempt(Time.now, params[:username], request.remote_ip) + redirect_to new_session_url, :alert => t(:credentials_incorrect) + end + end + + def destroy + current_user.forget_me + cookies.delete :auth_token + reset_session + session[:user_id] = nil + redirect_to new_session_url + end + + private + + def log_failed_sign_in_attempt(date, username, ip) + Rails.logger.error( + "\nFAILED SIGN IN ATTEMPT:\n" + + "=======================\n" + + " Date: #{date}\n" + + " Username: #{username}\n" + + " IP address: #{ip}\n\n" + ) + end + end +end \ No newline at end of file diff --git a/app/controllers/boxroom/share_links_controller.rb b/app/controllers/boxroom/share_links_controller.rb new file mode 100644 index 0000000..71696f4 --- /dev/null +++ b/app/controllers/boxroom/share_links_controller.rb @@ -0,0 +1,65 @@ +module Boxroom + class ShareLinksController < ApplicationController + before_action :require_admin, :only => [:index, :destroy] + before_action :require_existing_file, :except => [:index, :destroy] + before_action :require_existing_share_link, :only => :destroy + before_action :require_read_permission, :only => [:new, :create] + skip_before_action :require_login, :only => :show + + rescue_from ActiveRecord::RecordNotFound, NoMethodError, RuntimeError, :with => :redirect_to_root_or_signin_and_show_alert + + def index + @share_links = ShareLink.active_share_links + end + + # Note: @file is set in require_existing_file + def show + send_file @file.attachment.path, :filename => @file.attachment_file_name unless @file.nil? + end + + # Note: @file is set in require_existing_file + def new + @share_link = @file.share_links.build + end + + # Note: @file and @folder are set in require_existing_file + def create + @share_link = @file.share_links.build(permitted_params.share_link) + @share_link.user = current_user + + if @share_link.save + UserMailer.share_link_email(@share_link).deliver_now + redirect_to @folder, :notice => t(:shared_successfully) + else + render :action => 'new' + end + end + + # Note: @share_link is set in require_existing_share_link + def destroy + @share_link.destroy + redirect_to share_links_url + end + + private + + def require_existing_file + @file = params[:file_id].blank? ? ShareLink.file_for_token(params[:id]) : UserFile.find(params[:file_id]) + @folder = @file.folder + end + + def require_existing_share_link + @share_link = ShareLink.find(params[:id]) + rescue ActiveRecord::RecordNotFound + redirect_to share_links_url, :alert => t(:already_deleted, :type => t(:this_share_link)) + end + + def redirect_to_root_or_signin_and_show_alert + if signed_in? + redirect_to Folder.root, :alert => t(:already_deleted, :type => t(:this_file)) + else + redirect_to signin_url, :alert => t(:already_deleted, :type => t(:this_file)) + end + end + end +end diff --git a/app/controllers/boxroom/signup_controller.rb b/app/controllers/boxroom/signup_controller.rb new file mode 100644 index 0000000..72dc191 --- /dev/null +++ b/app/controllers/boxroom/signup_controller.rb @@ -0,0 +1,29 @@ +module Boxroom + class SignupController < ApplicationController + before_action :require_valid_token, :only => [:edit, :update] + skip_before_action :require_login + + # Note: @user is set in require_valid_token + def edit + end + + # Note: @user is set in require_valid_token + def update + if @user.update_attributes(permitted_params.user.merge({:password_required => true})) + redirect_to new_session_url, :notice => t(:signed_up_successfully) + else + render :action => 'edit' + end + end + + private + + def require_valid_token + @user = User.find_by_signup_token(params[:id]) + + if @user.nil? || @user.signup_token_expires_at < Time.now + redirect_to new_session_url, :alert => t(:sign_url_expired) + end + end + end +end \ No newline at end of file diff --git a/app/controllers/boxroom/users_controller.rb b/app/controllers/boxroom/users_controller.rb new file mode 100644 index 0000000..eab1faa --- /dev/null +++ b/app/controllers/boxroom/users_controller.rb @@ -0,0 +1,73 @@ +module Boxroom + class UsersController < ApplicationController + before_action :require_admin, :except => [:edit, :update] + before_action :require_existing_user, :only => [:edit, :update, :destroy, :extend] + before_action :require_deleted_user_isnt_admin, :only => :destroy + + def index + @users = User.where.not(:name => nil).order('name') + @new_users = User.where(:name => nil).order('email') + end + + def new + @user = User.new + end + + def create + @user = User.new(permitted_params.user) + + if @user.save + UserMailer.signup_email(@user).deliver_now + redirect_to users_url + else + render :action => 'new' + end + end + + # Note: @user is set in require_existing_user + def edit + end + + # Note: @user is set in require_existing_user + def update + if @user.update_attributes(permitted_params.user.merge({:password_required => false})) + redirect_to edit_user_url(@user), :notice => t(:your_changes_were_saved) + else + render :action => 'edit' + end + end + + # Note: @user is set in require_existing_user + def extend + @user.signup_token_expires_at = @user.signup_token_expires_at + 2.weeks + @user.save(:validate => false) + redirect_to users_url + end + + # Note: @user is set in require_existing_user + def destroy + @user.destroy + redirect_to users_url + end + + private + + def require_existing_user + if current_user.member_of_admins? && params[:id] != current_user.id.to_s + @title = t(:edit_user) + @user = User.find(params[:id]) + else + @title = t(:account_settings) + @user = current_user + end + rescue ActiveRecord::RecordNotFound + redirect_to users_url, :alert => t(:user_already_deleted) + end + + def require_deleted_user_isnt_admin + if @user.is_admin + redirect_to users_url, :alert => t(:admin_user_cannot_be_deleted) + end + end + end +end \ No newline at end of file diff --git a/app/helpers/boxroom/application_helper.rb b/app/helpers/boxroom/application_helper.rb new file mode 100644 index 0000000..1eb2a05 --- /dev/null +++ b/app/helpers/boxroom/application_helper.rb @@ -0,0 +1,4 @@ +module Boxroom + module ApplicationHelper + end +end diff --git a/app/helpers/boxroom/folders_helper.rb b/app/helpers/boxroom/folders_helper.rb new file mode 100644 index 0000000..8c22558 --- /dev/null +++ b/app/helpers/boxroom/folders_helper.rb @@ -0,0 +1,17 @@ +module Boxroom + module FoldersHelper + def breadcrumbs(folder, breadcrumbs = '') + breadcrumbs = "#{link_to(folder.parent.name, folder.parent)} » #{breadcrumbs}" + breadcrumbs = breadcrumbs(folder.parent, breadcrumbs) unless folder.parent == Folder.root + breadcrumbs.html_safe + end + + def file_icon(extension) + if extension && FileTest.exists?(Rails.root.join('app', 'assets', 'images', 'fileicons', "#{extension.downcase}.png")) + "fileicons/#{extension.downcase}.png" + else + 'file.png' + end + end + end +end \ No newline at end of file diff --git a/app/jobs/boxroom/application_job.rb b/app/jobs/boxroom/application_job.rb new file mode 100644 index 0000000..4e5aa9c --- /dev/null +++ b/app/jobs/boxroom/application_job.rb @@ -0,0 +1,4 @@ +module Boxroom + class ApplicationJob < ActiveJob::Base + end +end diff --git a/app/mailers/boxroom/application_mailer.rb b/app/mailers/boxroom/application_mailer.rb new file mode 100644 index 0000000..aa23025 --- /dev/null +++ b/app/mailers/boxroom/application_mailer.rb @@ -0,0 +1,6 @@ +module Boxroom + class ApplicationMailer < ActionMailer::Base + default from: 'from@example.com' + layout 'mailer' + end +end diff --git a/app/mailers/boxroom/user_mailer.rb b/app/mailers/boxroom/user_mailer.rb new file mode 100644 index 0000000..1f701ac --- /dev/null +++ b/app/mailers/boxroom/user_mailer.rb @@ -0,0 +1,18 @@ +module Boxroom + class UserMailer < ActionMailer::Base + def signup_email(user) + @user = user + mail(:to => user.email, :subject => t(:signup_email_subject)) + end + + def reset_password_email(user) + @user = user + mail(:to => user.email, :subject => t(:reset_password_email_subject)) + end + + def share_link_email(share_link) + @share_link = share_link + mail(:to => share_link.user.email, :reply_to => share_link.user.email, :bcc => share_link.emails, :subject => t(:share_link_email_subject, :email => share_link.user.email)) + end + end +end \ No newline at end of file diff --git a/app/models/boxroom/application_record.rb b/app/models/boxroom/application_record.rb new file mode 100644 index 0000000..6b43fef --- /dev/null +++ b/app/models/boxroom/application_record.rb @@ -0,0 +1,5 @@ +module Boxroom + class ApplicationRecord < ActiveRecord::Base + self.abstract_class = true + end +end diff --git a/app/models/boxroom/clipboard.rb b/app/models/boxroom/clipboard.rb new file mode 100644 index 0000000..d61fa0d --- /dev/null +++ b/app/models/boxroom/clipboard.rb @@ -0,0 +1,45 @@ +module Boxroom + class Clipboard + def initialize + setup + end + + def folders + Folder.where(:id => @folders) + end + + def files + UserFile.where(:id => @files) + end + + def add(item) + if item.class == Folder + @folders << item.id unless @folders.include?(item.id) + else + @files << item.id unless @files.include?(item.id) + end + end + + def remove(item) + if item.class == Folder + @folders.delete(item.id) + else + @files.delete(item.id) + end + end + + def empty? + (@folders.empty? || folders.empty?) && (@files.empty? || files.empty?) + end + + def reset + setup + end + + private + + def setup + @folders, @files = [], [] + end + end +end diff --git a/app/models/boxroom/folder.rb b/app/models/boxroom/folder.rb new file mode 100644 index 0000000..fc32473 --- /dev/null +++ b/app/models/boxroom/folder.rb @@ -0,0 +1,113 @@ +module Boxroom + class Folder < ActiveRecord::Base + acts_as_tree :order => 'name' + + has_many :user_files, -> {order :attachment_file_name}, :dependent => :destroy + has_many :permissions, :dependent => :destroy + + attr_accessor :is_copied_folder + + validates_uniqueness_of :name, :scope => :parent_id + validates_presence_of :name + + before_save :check_for_parent + after_create :create_permissions, :unless => :is_copied_folder + before_destroy :dont_destroy_root_folder + + def copy(target_folder, originally_copied_folder = nil) + new_folder = self.dup + new_folder.is_copied_folder = true + new_folder.parent = target_folder + new_folder.save! + + originally_copied_folder = new_folder if originally_copied_folder.nil? + + # Copy original folder's permissions + self.permissions.each do |permission| + new_permission = permission.dup + new_permission.folder = new_folder + new_permission.save! + end + + self.user_files.each do |file| + file.copy(new_folder) + end + + # Copy sub-folders recursively + self.children.each do |folder| + folder.copy(new_folder, originally_copied_folder) unless folder == originally_copied_folder + end + + new_folder + end + + def move(target_folder) + unless target_folder == self || self.parent_of?(target_folder) + self.parent = target_folder + save! + else + raise 'You cannot move a folder to its own sub-folder.' + end + end + + def copy_permissions_to_children(permissions_to_copy) + permissions_to_copy.each do |permission| + attributes = permission.attributes.except('id', 'folder_id', 'group_id') + Permission.where(:folder_id => children, :group_id => permission.group_id).update_all(attributes) + end + + # Copy permissions recursively + children.each do |child| + child.copy_permissions_to_children(permissions_to_copy) if child.has_children? + end + end + + def parent_of?(folder) + self.children.each do |child| + if child == folder + return true + else + return child.parent_of?(folder) + end + end + false + end + + def is_root? + parent.nil? && !new_record? + end + + def has_children? + children.count > 0 + end + + def self.root + @root_folder ||= find_by_name_and_parent_id('Root folder', nil) + end + + private + + def check_for_parent + raise 'Folders must have a parent.' if parent.nil? && name != 'Root folder' + end + + def create_permissions + unless is_root? + parent.permissions.each do |permission| + Permission.create! do |p| + p.group = permission.group + p.folder = self + p.can_create = permission.can_create + p.can_read = permission.can_read + p.can_update = permission.can_update + p.can_delete = permission.can_delete + end + end + end + end + + def dont_destroy_root_folder + raise "Can't delete Root folder" if is_root? + end + end +end \ No newline at end of file diff --git a/app/models/boxroom/group.rb b/app/models/boxroom/group.rb new file mode 100644 index 0000000..b3ce6c5 --- /dev/null +++ b/app/models/boxroom/group.rb @@ -0,0 +1,57 @@ +module Boxroom + class Group < ActiveRecord::Base + has_many :permissions, :dependent => :destroy + has_and_belongs_to_many :users + + validates_uniqueness_of :name + validates_presence_of :name + + after_create :create_admin_permissions, :if => :admins_group? + after_create :create_permissions, :unless => :admins_group? + before_destroy :dont_destroy_admins + + def admins_group? + name == 'Admins' + end + + def self.admins_group + where(:name => 'Admins').first + end + + def self.all_except_admins + where.not(:name => 'Admins') + end + + private + + def create_admin_permissions + Folder.find_each do |folder| + Permission.create! do |p| + p.group = self + p.folder = folder + p.can_create = true + p.can_read = true + p.can_update = true + p.can_delete = true + end + end + end + + def create_permissions + Folder.find_each do |folder| + Permission.create! do |p| + p.group = self + p.folder = folder + p.can_create = false + p.can_read = folder.is_root? # New groups can read the root folder + p.can_update = false + p.can_delete = false + end + end + end + + def dont_destroy_admins + raise "Can't delete admins group" if admins_group? + end + end +end \ No newline at end of file diff --git a/app/models/boxroom/permission.rb b/app/models/boxroom/permission.rb new file mode 100644 index 0000000..b02a89c --- /dev/null +++ b/app/models/boxroom/permission.rb @@ -0,0 +1,6 @@ +module Boxroom + class Permission < ActiveRecord::Base + belongs_to :group + belongs_to :folder + end +end \ No newline at end of file diff --git a/app/models/boxroom/permitted_params.rb b/app/models/boxroom/permitted_params.rb new file mode 100644 index 0000000..0643796 --- /dev/null +++ b/app/models/boxroom/permitted_params.rb @@ -0,0 +1,33 @@ +module Boxroom + class PermittedParams < Struct.new(:params, :current_user) + %w{folder group share_link user user_file}.each do |model_name| + define_method model_name do + params.require(model_name.to_sym).permit(*send("#{model_name}_attributes")) + end + end + + def folder_attributes + [:name] + end + + def group_attributes + [:name] + end + + def share_link_attributes + [:emails, :link_expires_at, :message] + end + + def user_attributes + if current_user && current_user.member_of_admins? + [:name, :email, :password, :password_confirmation, {:group_ids => []}] + else + [:name, :email, :password, :password_confirmation] + end + end + + def user_file_attributes + [:attachment, :attachment_file_name] + end + end +end \ No newline at end of file diff --git a/app/models/boxroom/share_link.rb b/app/models/boxroom/share_link.rb new file mode 100644 index 0000000..86c27d5 --- /dev/null +++ b/app/models/boxroom/share_link.rb @@ -0,0 +1,40 @@ +module Boxroom + class ShareLink < ActiveRecord::Base + belongs_to :user + belongs_to :user_file + + validates_presence_of :emails, :link_expires_at + validates_length_of :emails, :maximum => 255 + validate :format_of_emails + + before_save :generate_token + + def self.active_share_links + where('link_expires_at >= ?', DateTime.now).order(:link_expires_at) + end + + def self.file_for_token(token) + share_link = find_by_link_token(token) + + if share_link.link_expires_at < DateTime.now + raise 'This share link expired.' + else + share_link.user_file + end + end + + private + + def format_of_emails + emails.split(/,\s*/).each do |email| + unless email.strip =~ /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/ + errors.add(:emails, I18n.t(:are_invalid_due_to, :email => email)) + end + end + end + + def generate_token + self.link_token = SecureRandom.hex(10) + end + end +end \ No newline at end of file diff --git a/app/models/boxroom/user.rb b/app/models/boxroom/user.rb new file mode 100644 index 0000000..c98bd3a --- /dev/null +++ b/app/models/boxroom/user.rb @@ -0,0 +1,113 @@ +module Boxroom + class User < ActiveRecord::Base + has_and_belongs_to_many :groups + has_many :share_links + + attr_accessor :password_confirmation, :password_required, :dont_clear_reset_password_token + + validates_confirmation_of :password + validates_length_of :password, :in => 6..20, :allow_blank => true + validates_presence_of :password, :if => :password_required + validates_presence_of :name, :unless => :new_record? + validates_presence_of :email + validates_uniqueness_of :name, :unless => :new_record? && :name_is_blank? + validates_uniqueness_of :email + validates_format_of :email, :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/ + + before_create :set_signup_token + before_save :clear_reset_password_token, :unless => :dont_clear_reset_password_token + before_update :clear_signup_token + after_create :create_root_folder_and_admins_group, :if => :is_admin + before_destroy :dont_destroy_admin + + %w{create read update delete}.each do |method| + define_method "can_#{method}" do |folder| + has_permission = false + + Permission.where(:group_id => groups, :folder_id => folder.id).each do |permission| + has_permission = permission.send("can_#{method}") + break if has_permission + end + + has_permission + end + end + + def password + @password + end + + def password=(new_password) + @password = new_password + + unless @password.blank? + self.password_salt = SecureRandom.base64(32) + self.hashed_password = Digest::SHA256.hexdigest(password_salt + password) + end + end + + def member_of_admins? + groups.admins_group.present? + end + + def refresh_reset_password_token + self.reset_password_token = SecureRandom.hex(10) + self.reset_password_token_expires_at = 1.hour.from_now + self.dont_clear_reset_password_token = true + save(:validate => false) + end + + def refresh_remember_token + self.remember_token = SecureRandom.base64(32) + save(:validate => false) + end + + def forget_me + self.remember_token = nil + save(:validate => false) + end + + def name_is_blank? + self.name.blank? + end + + def self.authenticate(name, password) + return nil if name.blank? || password.blank? + user = find_by_name(name) or return nil + hash = Digest::SHA256.hexdigest(user.password_salt + password) + hash == user.hashed_password ? user : nil + end + + def self.no_admin_yet? + find_by_is_admin(true).blank? + end + + private + + def set_signup_token + self.signup_token = SecureRandom.hex(10) + self.signup_token_expires_at = 2.weeks.from_now + end + + def clear_signup_token + unless self.name.blank? + self.signup_token = nil + self.signup_token_expires_at = nil + end + end + + def clear_reset_password_token + self.reset_password_token = nil + self.reset_password_token_expires_at = nil + end + + def create_root_folder_and_admins_group + Folder.create(:name => 'Root folder') + groups << Group.create(:name => 'Admins') + end + + def dont_destroy_admin + raise "Can't delete original admin user" if is_admin + end + end +end diff --git a/app/models/boxroom/user_file.rb b/app/models/boxroom/user_file.rb new file mode 100644 index 0000000..5673a30 --- /dev/null +++ b/app/models/boxroom/user_file.rb @@ -0,0 +1,35 @@ +module Boxroom + class UserFile < ActiveRecord::Base + has_attached_file :attachment, :path => ':rails_root/uploads/:rails_env/:id/:style/:id', :restricted_characters => RESTRICTED_CHARACTERS + do_not_validate_attachment_file_type :attachment + + belongs_to :folder + has_many :share_links, :dependent => :destroy + + validates_attachment_presence :attachment, :message => I18n.t(:blank, :scope => [:activerecord, :errors, :messages]) + validates_presence_of :folder_id + validates_uniqueness_of :attachment_file_name, :scope => 'folder_id', :message => I18n.t(:exists_already, :scope => [:activerecord, :errors, :messages]) + validates_format_of :attachment_file_name, :with => /\A[^\/\\\?\*:|"<>]+\z/, :message => I18n.t(:invalid_characters, :scope => [:activerecord, :errors, :messages]) + + def copy(target_folder) + new_file = self.dup + new_file.folder = target_folder + new_file.save! + + path = "#{Rails.root}/uploads/#{Rails.env}/#{new_file.id}/original" + FileUtils.mkdir_p path + FileUtils.cp_r self.attachment.path, "#{path}/#{new_file.id}" + + new_file + end + + def move(target_folder) + self.folder = target_folder + save! + end + + def extension + File.extname(attachment_file_name)[1..-1] + end + end +end \ No newline at end of file diff --git a/app/views/boxroom/admins/new.html.erb b/app/views/boxroom/admins/new.html.erb new file mode 100644 index 0000000..5da81cf --- /dev/null +++ b/app/views/boxroom/admins/new.html.erb @@ -0,0 +1,28 @@ +<% content_for :title, t(:create_admin) -%> + +

<%= content_for :title %>

+

+ <%= t :no_administrator_yet %> +

+<%= form_for @user, :url => { :action => 'create' } do |f| %> + <%= f.error_messages %> +

+ <%= f.label :name, t(:username) %>:
+ <%= f.text_field :name, { :class => 'text_input' } %> +

+

+ <%= f.label :email %>:
+ <%= f.text_field :email, { :class => 'text_input' } %> +

+

+ <%= label_tag :password %>:
+ <%= f.password_field :password, { :class => 'text_input' } %> +

+

+ <%= label_tag :confirm_password %>:
+ <%= f.password_field :password_confirmation, { :class => 'text_input' } %> +

+

+ <%= f.submit t(:create_admin_account) %> +

+<% end %> diff --git a/app/views/boxroom/clipboard/_clipboard_empty.de.html.erb b/app/views/boxroom/clipboard/_clipboard_empty.de.html.erb new file mode 100644 index 0000000..9c1f7e9 --- /dev/null +++ b/app/views/boxroom/clipboard/_clipboard_empty.de.html.erb @@ -0,0 +1,2 @@ +

Die Zwischenablage ist leer

+Gehen Sie <%= link_to 'zurück', '#', :class => 'back_link' %> und benutzen Sie die Funktion Zwischenablage, um Ordner oder Dateien in die Zwischenablage zu kopieren. diff --git a/app/views/boxroom/clipboard/_clipboard_empty.en.html.erb b/app/views/boxroom/clipboard/_clipboard_empty.en.html.erb new file mode 100644 index 0000000..7bc93b4 --- /dev/null +++ b/app/views/boxroom/clipboard/_clipboard_empty.en.html.erb @@ -0,0 +1,2 @@ +

The clipboard is empty

+Go <%= link_to 'back', '#', :class => 'back_link' %> and use the clipboard button to add files or folders to the clipboard. diff --git a/app/views/boxroom/clipboard/_clipboard_empty.es.html.erb b/app/views/boxroom/clipboard/_clipboard_empty.es.html.erb new file mode 100644 index 0000000..b55e6e1 --- /dev/null +++ b/app/views/boxroom/clipboard/_clipboard_empty.es.html.erb @@ -0,0 +1,2 @@ +

El portapapeles esta vacío

+Volver <%= link_to 'back', '#', :class => 'back_link' %> para usar el boton de portapapeles y agregar archivos o carpetas al portapapeles. diff --git a/app/views/boxroom/clipboard/_clipboard_empty.fr.html.erb b/app/views/boxroom/clipboard/_clipboard_empty.fr.html.erb new file mode 100644 index 0000000..725bb06 --- /dev/null +++ b/app/views/boxroom/clipboard/_clipboard_empty.fr.html.erb @@ -0,0 +1,2 @@ +

Le presse-papier est vide !

+Revenir <%= link_to 'en arrière', '#', :class => 'back_link' %> et utilisez le bouton "presse-papier" pour y ajouter des fichiers ou dossiers. diff --git a/app/views/boxroom/clipboard/_clipboard_empty.it.html.erb b/app/views/boxroom/clipboard/_clipboard_empty.it.html.erb new file mode 100644 index 0000000..90a8da3 --- /dev/null +++ b/app/views/boxroom/clipboard/_clipboard_empty.it.html.erb @@ -0,0 +1,2 @@ +

Nessun file presente negli appunti

+Vai <%= link_to 'indietro', '#', :class => 'back_link' %> e usa il pulsante appunti per aggiungere file o cartelle agli appunti. diff --git a/app/views/boxroom/clipboard/_clipboard_empty.nl.html.erb b/app/views/boxroom/clipboard/_clipboard_empty.nl.html.erb new file mode 100644 index 0000000..422bda9 --- /dev/null +++ b/app/views/boxroom/clipboard/_clipboard_empty.nl.html.erb @@ -0,0 +1,2 @@ +

Het klembord is leeg

+Ga <%= link_to 'terug', '#', :class => 'back_link' %> en gebruik de klembord knop om bestanden en mappen toe te voegen aan het klembord. diff --git a/app/views/boxroom/clipboard/_clipboard_empty.zh-CN.html.erb b/app/views/boxroom/clipboard/_clipboard_empty.zh-CN.html.erb new file mode 100644 index 0000000..a6abd5b --- /dev/null +++ b/app/views/boxroom/clipboard/_clipboard_empty.zh-CN.html.erb @@ -0,0 +1,2 @@ +

剪贴板是空的

+<%= link_to '回去', '#', :class => 'back_link' %>用剪贴板按钮将文件或文件夹加到剪贴板。 diff --git a/app/views/boxroom/clipboard/_show.html.erb b/app/views/boxroom/clipboard/_show.html.erb new file mode 100644 index 0000000..51abec8 --- /dev/null +++ b/app/views/boxroom/clipboard/_show.html.erb @@ -0,0 +1,70 @@ +<% if clipboard.empty? -%> +

+ <%= image_tag('boxroom/information.png', :alt => 'Notice', :class => 'clipboard_info_image') %> + <%= render 'boxroom/clipboard/clipboard_empty' %> +

+<% else -%> + + + + + + + <% reset_cycle -%> + <% clipboard.folders.each do |item| -%> + + + + + + <% end -%> + <% clipboard.files.each do |item| -%> + + + + + + <% end -%> +
<%= t :name %>
<%= image_tag('boxroom/folder.png') %><%= item.name %> + <% if current_user.can_create(@folder) -%> + <%= link_to image_tag('boxroom/copy.png', :alt => t(:copy)), + { :controller => :clipboard, :action => :copy, :id => item.id, :type => 'folder', :folder_id => @folder, :authenticity_token => form_authenticity_token }, + :method => :post, :title => t(:copy_folder) + %>  + <% end -%> + <% if current_user.can_create(@folder) && current_user.can_delete(item) -%> + <%= link_to image_tag('boxroom/move.png', :alt => t(:move)), + { :controller => :clipboard, :action => :move, :id => item.id, :type => 'folder', :folder_id => @folder, :authenticity_token => form_authenticity_token }, + :method => :post, :title => t(:move_folder), :data => { :confirm => t(:are_you_sure) } + %>  + <% end -%> + <%= link_to image_tag('boxroom/delete.png', :alt => t(:delete_item)), + { :controller => :clipboard, :action => :destroy, :id => item.id, :type => 'folder', :folder_id => @folder, :authenticity_token => form_authenticity_token }, + :method => :delete, :title => t(:remove_from_clipboard) + %> +
<%= image_tag(file_icon(item.extension)) %><%= item.attachment_file_name %> + <% if current_user.can_create(@folder) -%> + <%= link_to image_tag('boxroom/copy.png', :alt => t(:copy)), + { :controller => :clipboard, :action => :copy, :id => item.id, :type => 'file', :folder_id => @folder, :authenticity_token => form_authenticity_token }, + :method => :post, :title => t(:copy_file) + %>  + <% end -%> + <% if current_user.can_create(@folder) && current_user.can_delete(item.folder) -%> + <%= link_to image_tag('boxroom/move.png', :alt => t(:move)), + { :controller => :clipboard, :action => :move, :id => item.id, :type => 'file', :folder_id => @folder, :authenticity_token => form_authenticity_token }, + :method => :post, :title => t(:move_file), :data => { :confirm => t(:are_you_sure) } + %>  + <% end -%> + <%= link_to image_tag('boxroom/delete.png', :alt => t(:delete_item)), + { :controller => :clipboard, :action => :destroy, :id => item.id, :type => 'file', :folder_id => @folder, :authenticity_token => form_authenticity_token }, + :method => :delete, :title => t(:remove_from_clipboard) + %> +
+

+ <%= button_to t(:clear_clipboard), + { :controller => :clipboard, :action => :reset, :folder_id => @folder, :authenticity_token => form_authenticity_token }, :method => :put + %> +   —   + <%= link_to t(:back), '#', :class => 'back_link' %> +

+<% end -%> diff --git a/app/views/boxroom/files/edit.html.erb b/app/views/boxroom/files/edit.html.erb new file mode 100644 index 0000000..895c6e9 --- /dev/null +++ b/app/views/boxroom/files/edit.html.erb @@ -0,0 +1,14 @@ +<% content_for :title, t(:rename_file) -%> + +

<%= content_for :title %>

+<%= form_for @file, :url => { :action => 'update' } do |f| %> + <%= f.error_messages %> +

+ <%= f.label :name %>:
+ <%= f.text_field :attachment_file_name %> +

+

+ <%= f.submit t(:save) %>   —   + <%= link_to t(:back), @folder %> +

+<% end %> diff --git a/app/views/boxroom/files/new.html.erb b/app/views/boxroom/files/new.html.erb new file mode 100644 index 0000000..befd99c --- /dev/null +++ b/app/views/boxroom/files/new.html.erb @@ -0,0 +1,25 @@ +<% content_for :title, t(:upload_file) -%> + +

<%= content_for :title %>

+<%= form_for [@target_folder, @file], :url => { :action => 'create' } do |f| %> +

+ <%= hidden_field_tag :target_folder_id, @target_folder.id %> + <%= file_field_tag :attachment, :multiple => true, :name => 'user_file[attachment]' %> +

+
+
+

+ <%= link_to t(:back), @target_folder %> +

+<% end %> + + diff --git a/app/views/boxroom/folders/_form.html.erb b/app/views/boxroom/folders/_form.html.erb new file mode 100644 index 0000000..30b2d2d --- /dev/null +++ b/app/views/boxroom/folders/_form.html.erb @@ -0,0 +1,9 @@ +<%= f.error_messages %> +

+ <%= f.label :name %>:
+ <%= f.text_field :name, { :class => 'text_input' } %> +

+

+ <%= f.submit t(:save) %>   —   + <%= link_to t(:back), @folder.parent %> +

diff --git a/app/views/boxroom/folders/edit.html.erb b/app/views/boxroom/folders/edit.html.erb new file mode 100644 index 0000000..91e9df7 --- /dev/null +++ b/app/views/boxroom/folders/edit.html.erb @@ -0,0 +1,6 @@ +<% content_for :title, t(:rename_folder) -%> + +

<%= content_for :title %>

+<%= form_for @folder do |f| %> + <%= render :partial => 'form', :locals => { :f => f } %> +<% end %> diff --git a/app/views/boxroom/folders/new.html.erb b/app/views/boxroom/folders/new.html.erb new file mode 100644 index 0000000..52693b8 --- /dev/null +++ b/app/views/boxroom/folders/new.html.erb @@ -0,0 +1,6 @@ +<% content_for :title, t(:new_folder) -%> + +

<%= content_for :title %>

+<%= form_for [@target_folder, @folder] do |f| %> + <%= render :partial => 'form', :locals => { :f => f } %> +<% end %> diff --git a/app/views/boxroom/folders/show.html.erb b/app/views/boxroom/folders/show.html.erb new file mode 100644 index 0000000..f803655 --- /dev/null +++ b/app/views/boxroom/folders/show.html.erb @@ -0,0 +1,92 @@ +<% content_for :title, @folder.name -%> + +

<%= content_for :title %>

+<% unless @folder.is_root? -%> +

+ <%= breadcrumbs(@folder) %> + <%= @folder.name %> +

+<% end -%> +

+<% if current_user.can_create(@folder) -%> + <%= image_tag('boxroom/folder_add.png', :alt => t(:create_a_new_folder)) %> <%= link_to t(:create_a_new_folder), new_folder_folder_path(@folder) %> + <%= image_tag('boxroom/file_add.png', :alt => t(:upload_a_file)) %> <%= link_to t(:upload_a_file), new_folder_file_path(@folder) %> +<% end -%> +<% if current_user.member_of_admins? -%> + <%= image_tag('boxroom/permissions.png', :alt => t(:permissions)) %> <%= link_to t(:permissions), '#', :class => 'permissions_link' %> +<% end -%> + <%= image_tag('boxroom/clipboard.png', :alt => t(:clipboard)) %> <%= link_to t(:clipboard), '#', :class => 'clipboard_link' %> +

+
+ + + + + + + + + <% unless @folder.is_root? -%> + + + + + + + + <% end -%> + <% @folder.children.each do |folder| -%> + <% if current_user.can_read(folder) -%> + + + + + + + + <% end -%> + <% end -%> + <% @folder.user_files.each do |file| -%> + <% if current_user.can_read(@folder) -%> + + + + + + + + <% end -%> + <% end -%> +
<%= t :name %><%= t :size %><%= t :date_modified %>
<%= image_tag('boxroom/folder.png') %>↑ <%= link_to t(:up), @folder.parent, :title => @folder.parent.name %>----
<%= image_tag('boxroom/folder.png') %><%= link_to folder.name, folder %>--<%= l folder.updated_at, :format => :short %> + <% if current_user.can_update(folder) -%> + <%= link_to image_tag('boxroom/edit.png', :alt => t(:edit)), edit_folder_path(folder), :title => t(:edit) %>  + <% end -%> + <% if current_user.can_delete(folder) -%> + <%= link_to image_tag('boxroom/delete.png', :alt => t(:delete_item)), folder, :method => :delete, :data => { :confirm => t(:are_you_sure) }, :title => t(:delete_item) %>  + <% end -%> + <%= link_to image_tag('boxroom/clipboard_add.png', :alt => t(:add_to_clipboard)), + { :controller => :clipboard, :action => :create, :id => folder.id, :type => 'folder', :folder_id => @folder, :authenticity_token => form_authenticity_token }, + :method => :post, :title => t(:add_to_clipboard) + %> +
<%= image_tag(file_icon(file.extension)) %><%= link_to file.attachment_file_name, file_path(file), :title => "#{t(:download)} #{file.attachment_file_name}" %><%= number_to_human_size(file.attachment_file_size, :locale => I18n.locale) %><%= l file.updated_at, :format => :short %> + <% if current_user.can_update(file.folder) -%> + <%= link_to image_tag('boxroom/edit.png', :alt => t(:edit)), edit_file_path(file), :title => t(:edit) %>  + <% end -%> + <% if current_user.can_delete(file.folder) -%> + <%= link_to image_tag('boxroom/delete.png', :alt => t(:delete_item)), file_path(file), :method => :delete, :data => { :confirm => t(:are_you_sure) }, :title => t(:delete_item) %>  + <% end -%> + <%= link_to image_tag('boxroom/clipboard_add.png', :alt => t(:add_to_clipboard)), + { :controller => :clipboard, :action => :create, :id => file.id, :type => 'file', :folder_id => @folder, :authenticity_token => form_authenticity_token }, + :method => :post, :title => t(:add_to_clipboard) + %>  + <%= link_to image_tag('boxroom/share.png', :alt => t(:share)), new_file_share_link_path(file), :title => t(:share) %> +
+
+<% if current_user.member_of_admins? -%> + +<% end -%> + diff --git a/app/views/boxroom/groups/_form.html.erb b/app/views/boxroom/groups/_form.html.erb new file mode 100644 index 0000000..877f415 --- /dev/null +++ b/app/views/boxroom/groups/_form.html.erb @@ -0,0 +1,11 @@ +<%= form_for @group do |f| %> + <%= f.error_messages %> +

+ <%= f.label :name %>:
+ <%= f.text_field :name, { :class => 'text_input' } %> +

+

+ <%= f.submit t(:save) %>   —   + <%= link_to t(:back), groups_url %> +

+<% end %> diff --git a/app/views/boxroom/groups/edit.html.erb b/app/views/boxroom/groups/edit.html.erb new file mode 100644 index 0000000..9ac3dd2 --- /dev/null +++ b/app/views/boxroom/groups/edit.html.erb @@ -0,0 +1,4 @@ +<% content_for :title, t(:rename_group) -%> + +

<%= content_for :title %>

+<%= render 'form' %> diff --git a/app/views/boxroom/groups/index.html.erb b/app/views/boxroom/groups/index.html.erb new file mode 100644 index 0000000..cf21f53 --- /dev/null +++ b/app/views/boxroom/groups/index.html.erb @@ -0,0 +1,29 @@ +<% content_for :title, t(:groups) -%> + +

<%= content_for :title %>

+

+ <%= image_tag('boxroom/group_add.png', :alt => t(:create_a_new_group)) %> <%= link_to t(:create_a_new_group), new_group_path %> +

+ + + + + + +<% @groups.each do |group| -%> + + <% if group.admins_group? -%> + + + + <% else -%> + + + + <% end -%> + +<% end -%> +
<%= t :name %>
<%= image_tag('boxroom/group_grey.png') %><%= group.name %><%= image_tag('boxroom/group.png') %><%= group.name %> + <%= link_to image_tag('boxroom/edit.png', :alt => t(:edit)), edit_group_path(group), :title => t(:edit) %>  + <%= link_to image_tag('boxroom/delete.png', :alt => t(:delete_item)), group_path(group), :method => :delete, :data => { :confirm => t(:are_you_sure) }, :title => t(:delete_item) %> +
diff --git a/app/views/boxroom/groups/new.html.erb b/app/views/boxroom/groups/new.html.erb new file mode 100644 index 0000000..72f78dd --- /dev/null +++ b/app/views/boxroom/groups/new.html.erb @@ -0,0 +1,4 @@ +<% content_for :title, t(:new_group) -%> + +

<%= content_for :title %>

+<%= render 'form' %> diff --git a/app/views/boxroom/permissions/_form.html.erb b/app/views/boxroom/permissions/_form.html.erb new file mode 100644 index 0000000..28990ca --- /dev/null +++ b/app/views/boxroom/permissions/_form.html.erb @@ -0,0 +1,41 @@ +<%= form_tag update_multiple_permissions_path do %> + <%= hidden_field_tag '_method', 'put' %> + + + + + + + + + + <% reset_cycle -%> + <% @folder.permissions.each do |permission| -%> + <%= fields_for "permissions[]", permission do |f| %> + + <% if permission.group.admins_group? -%> + + + + + + + <% else -%> + + + + + + + <% end -%> + + <% end -%> + <% end -%> +
<%= t :create_permission %><%= t :read_permission %><%= t :update_permission %><%= t :delete_permission %>
<%= image_tag('boxroom/group_grey.png') %><%= permission.group.name %><%= image_tag('boxroom/group.png') %><%= permission.group.name %><%= f.check_box :can_create %><%= f.check_box :can_read %><%= f.check_box :can_update %><%= f.check_box :can_delete %>
+

+ <%= submit_tag t(:save) %> + <%= check_box_tag :recursive, true %> <%= t :apply_changes_to_subfolders %> +   —   + <%= link_to t(:back), '#', :class => 'back_link' %> +

+<% end -%> diff --git a/app/views/boxroom/reset_password/_message.de.html.erb b/app/views/boxroom/reset_password/_message.de.html.erb new file mode 100644 index 0000000..b6d4bcf --- /dev/null +++ b/app/views/boxroom/reset_password/_message.de.html.erb @@ -0,0 +1,2 @@ +Geben Sie ihre E-Mail Adresse ein um eine Anleitung zur
+Rücksetzung Ihres Kennworts zu erhalten. diff --git a/app/views/boxroom/reset_password/_message.en.html.erb b/app/views/boxroom/reset_password/_message.en.html.erb new file mode 100644 index 0000000..6fb6b83 --- /dev/null +++ b/app/views/boxroom/reset_password/_message.en.html.erb @@ -0,0 +1,2 @@ +Submit your email address and we will send you an email
+with instructions on how to reset your password. diff --git a/app/views/boxroom/reset_password/_message.es.html.erb b/app/views/boxroom/reset_password/_message.es.html.erb new file mode 100644 index 0000000..6c2bf6f --- /dev/null +++ b/app/views/boxroom/reset_password/_message.es.html.erb @@ -0,0 +1,2 @@ +Ingrese su cuenta de correo donde recibirá un correo
+con instrucciones de como reiniciar sus credenciales. diff --git a/app/views/boxroom/reset_password/_message.fr.html.erb b/app/views/boxroom/reset_password/_message.fr.html.erb new file mode 100644 index 0000000..532aa81 --- /dev/null +++ b/app/views/boxroom/reset_password/_message.fr.html.erb @@ -0,0 +1,2 @@ +Saisissez votre adresse email et vous recevrez un message
+contentant les instructions pour réinitialiser votre mot de passe. \ No newline at end of file diff --git a/app/views/boxroom/reset_password/_message.it.html.erb b/app/views/boxroom/reset_password/_message.it.html.erb new file mode 100644 index 0000000..25214a3 --- /dev/null +++ b/app/views/boxroom/reset_password/_message.it.html.erb @@ -0,0 +1,2 @@ +Inserisci il tuo indirizzo email e riceverai una email
+con le istruzioni su come reimpostare la password. diff --git a/app/views/boxroom/reset_password/_message.nl.html.erb b/app/views/boxroom/reset_password/_message.nl.html.erb new file mode 100644 index 0000000..58bb75f --- /dev/null +++ b/app/views/boxroom/reset_password/_message.nl.html.erb @@ -0,0 +1,2 @@ +Vul uw e-mailadres in en we zullen u een e-mail toesturen
+met instructies om uw wachtwoord te resetten. diff --git a/app/views/boxroom/reset_password/_message.zh-CN.html.erb b/app/views/boxroom/reset_password/_message.zh-CN.html.erb new file mode 100644 index 0000000..f62fbf6 --- /dev/null +++ b/app/views/boxroom/reset_password/_message.zh-CN.html.erb @@ -0,0 +1,2 @@ +请提供您的电子邮箱地址,
+我们将给您发邮件告诉您如何重设密码。 diff --git a/app/views/boxroom/reset_password/edit.html.erb b/app/views/boxroom/reset_password/edit.html.erb new file mode 100644 index 0000000..2bf20ec --- /dev/null +++ b/app/views/boxroom/reset_password/edit.html.erb @@ -0,0 +1,18 @@ +<% content_for :title, t(:reset_password) -%> + +

<%= content_for :title %>

+<%= form_for @user, :url => { :action => 'update' } do |f| %> + <%= f.error_messages %> +

+ <%= label_tag :password, t(:password) %>:
+ <%= f.password_field :password, { :class => 'text_input' } %> +

+

+ <%= label_tag :confirm_password, t(:confirm_password) %>:
+ <%= f.password_field :password_confirmation, { :class => 'text_input' } %> +

+

+ <%= f.submit t(:reset_password) %>   —   + <%= link_to t(:back), new_session_path %> +

+<% end %> diff --git a/app/views/boxroom/reset_password/new.html.erb b/app/views/boxroom/reset_password/new.html.erb new file mode 100644 index 0000000..649a069 --- /dev/null +++ b/app/views/boxroom/reset_password/new.html.erb @@ -0,0 +1,16 @@ +<% content_for :title, t(:reset_password) -%> + +

<%= content_for :title %>

+

+ <%= render 'message' %> +

+<%= form_tag(reset_password_index_path) do %> +

+ <%= label_tag :email, t(:email) %>:
+ <%= text_field_tag :email, nil, :class => 'text_input' %> +

+

+ <%= submit_tag t(:send_email) %>   —   + <%= link_to t(:back), new_session_path %> +

+<% end %> diff --git a/app/views/boxroom/sessions/new.html.erb b/app/views/boxroom/sessions/new.html.erb new file mode 100644 index 0000000..41e5c98 --- /dev/null +++ b/app/views/boxroom/sessions/new.html.erb @@ -0,0 +1,21 @@ +<% content_for :title, t(:sign_in) -%> + +

<%= content_for :title %>

+<%= form_tag(sessions_path) do %> +

+ <%= label_tag :username, t(:username) %>:
+ <%= text_field_tag :username, nil, :class => 'text_input' %> +

+

+ <%= label_tag :password, t(:password) %>:
+ <%= password_field_tag :password, nil, :class => 'text_input' %> +

+

+ <%= check_box_tag :remember_me, 'true' %> + <%= label_tag :remember_me, t(:remember_me) %> +

+

+ <%= submit_tag t(:sign_in) %>   —   + <%= link_to t(:reset_password), new_reset_password_path %> +

+<% end %> diff --git a/app/views/boxroom/share_links/index.html.erb b/app/views/boxroom/share_links/index.html.erb new file mode 100644 index 0000000..ea0187a --- /dev/null +++ b/app/views/boxroom/share_links/index.html.erb @@ -0,0 +1,24 @@ +<% content_for :title, t(:shared_files) -%> + +

<%= content_for :title %>

+ + + + + + + + + + +<% @share_links.each do |share_link| -%> + + + + + + + + +<% end -%> +
<%= t('activerecord.models.user_file') %><%= t(:shared_by) %><%= t('activerecord.attributes.share_link.emails') %><%= t('activerecord.attributes.share_link.expires_at') %>
<%= image_tag file_icon(share_link.user_file.extension) %><%= link_to truncate(share_link.user_file.attachment_file_name, :length => 24), share_link.user_file.folder, :title => "#{share_link.user_file.attachment_file_name} (#{share_link.user_file.folder.name})" %><%= share_link.user.name %><%= l share_link.link_expires_at, :format => :very_short %><%= link_to image_tag('boxroom/delete.png', :alt => t(:delete_item)), share_link_path(share_link), :method => :delete, :data => { :confirm => t(:are_you_sure) }, :title => t(:unshare) %>
diff --git a/app/views/boxroom/share_links/new.html.erb b/app/views/boxroom/share_links/new.html.erb new file mode 100644 index 0000000..6644f4b --- /dev/null +++ b/app/views/boxroom/share_links/new.html.erb @@ -0,0 +1,48 @@ +<% content_for :title, t(:share_file) -%> + +

<%= content_for :title %>

+<%= form_for [@file, @share_link], :url => { :action => 'create' } do |f| %> + <%= f.error_messages :header_message => t(:share_link_could_not_be_sent) %> +

+ <%= t :you_are_about_to_share_the_following_file %>:
+ + <%= image_tag(file_icon(@file.extension)) %> + <%= link_to @file.attachment_file_name, @folder %> + +

+

+ <%= f.label :emails, t(:emails_to_share_with) %>: + (<%= t :comma_seperated %>)
+ <%= f.text_area :emails, :class => 'emails_to_share_with' %>
+ + <%= t :number_of_charachters %>: + + <%= @share_link.emails.nil? ? 0 : @share_link.emails.length %> + + / 255 + +

+

+ <%= f.label :message, t(:shared_message) %>: (<%= t :optional %>)
+ <%= f.text_area :message, :class => 'share_message' %> +

+

+ <%= f.label t(:link_expires) %>:
+ <%= f.select :link_expires_at, options_for_select([ + [t(:tomorrow), 1.day.from_now.end_of_day], + [t(:three_days_from_now), 3.day.from_now.end_of_day], + [t(:one_week_from_now), 1.week.from_now.end_of_day], + [t(:ten_days_from_now), 10.days.from_now.end_of_day], + [t(:two_weeks_from_now), 2.weeks.from_now.end_of_day], + [t(:three_weeks_from_now), 3.weeks.from_now.end_of_day], + [t(:one_month_from_now), 1.month.from_now.end_of_day], + [t(:two_months_from_now), 2.months.from_now.end_of_day], + [t(:three_months_from_now), 3.months.from_now.end_of_day], + [t(:half_year_from_now), 6.months.from_now.end_of_day] + ], 2.weeks.from_now.end_of_day) %> +

+

+ <%= f.submit t(:share) %>   —   + <%= link_to t(:back), @folder %> +

+<% end %> diff --git a/app/views/boxroom/shared/_footer.html.erb b/app/views/boxroom/shared/_footer.html.erb new file mode 100644 index 0000000..b0b0241 --- /dev/null +++ b/app/views/boxroom/shared/_footer.html.erb @@ -0,0 +1,5 @@ + diff --git a/app/views/boxroom/shared/_header.html.erb b/app/views/boxroom/shared/_header.html.erb new file mode 100644 index 0000000..16da834 --- /dev/null +++ b/app/views/boxroom/shared/_header.html.erb @@ -0,0 +1,11 @@ + diff --git a/app/views/boxroom/shared/_menu.html.erb b/app/views/boxroom/shared/_menu.html.erb new file mode 100644 index 0000000..dda195e --- /dev/null +++ b/app/views/boxroom/shared/_menu.html.erb @@ -0,0 +1,13 @@ + diff --git a/app/views/boxroom/signup/edit.html.erb b/app/views/boxroom/signup/edit.html.erb new file mode 100644 index 0000000..03408c5 --- /dev/null +++ b/app/views/boxroom/signup/edit.html.erb @@ -0,0 +1,26 @@ +<% content_for :title, t(:sign_up) -%> + +

<%= content_for :title %>

+<%= form_for @user, :url => { :action => 'update' } do |f| %> + <%= f.error_messages %> +

+ <%= f.label :name %>:
+ <%= f.text_field :name, { :class => 'text_input' } %> +

+

+ <%= f.label :email %>:
+ <%= f.text_field :email, { :class => 'text_input' } %> +

+

+ <%= f.label :password %>:
+ <%= f.password_field :password, { :class => 'text_input' } %> +

+

+ <%= label_tag t(:confirm_password) %>:
+ <%= f.password_field :password_confirmation, { :class => 'text_input' } %> +

+

+ <%= f.submit t(:sign_up) %>   —   + <%= link_to t(:back), new_session_path %> +

+<% end %> diff --git a/app/views/boxroom/user_mailer/reset_password_email.de.text.erb b/app/views/boxroom/user_mailer/reset_password_email.de.text.erb new file mode 100644 index 0000000..fea58f9 --- /dev/null +++ b/app/views/boxroom/user_mailer/reset_password_email.de.text.erb @@ -0,0 +1,18 @@ +Sehr geehrter Nutzer, + +Über die folgende URL können Sie ein neues Kennwort für Ihr Konto erstellen: + + <%= edit_reset_password_url(@user.reset_password_token) %> + +Zur Erinnerung hier nochmals Ihre Anmeldedaten: + + Benutzername: <%= @user.name %> + E-Mail: <%= @user.email %> + +Sollten Sie keine Anfrage zum Zurücksetzen Ihres Kennworts geschickt haben, +ignorieren Sie diese Nachricht. +Ihr altes Kennwort ist weiterhin gültig. + +-- +Boxroom +http://boxroomapp.com/ diff --git a/app/views/boxroom/user_mailer/reset_password_email.en.text.erb b/app/views/boxroom/user_mailer/reset_password_email.en.text.erb new file mode 100644 index 0000000..42c7f35 --- /dev/null +++ b/app/views/boxroom/user_mailer/reset_password_email.en.text.erb @@ -0,0 +1,17 @@ +Dear user, + +Please use the following URL to reset your Boxroom password: + + <%= edit_reset_password_url(@user.reset_password_token) %> + +Just as a reminder, your account info: + + Username: <%= @user.name %> + Email: <%= @user.email %> + +If you did not submit a request to reset your password, please ignore this email. +Your current password is still valid. + +-- +Boxroom +http://boxroomapp.com/ diff --git a/app/views/boxroom/user_mailer/reset_password_email.es.text.erb b/app/views/boxroom/user_mailer/reset_password_email.es.text.erb new file mode 100644 index 0000000..150d808 --- /dev/null +++ b/app/views/boxroom/user_mailer/reset_password_email.es.text.erb @@ -0,0 +1,17 @@ +Estiamdo usuario, + +Use la siguiente URL para reiniciar sus credenciales de Boxroom: + + <%= edit_reset_password_url(@user.reset_password_token) %> + +Información de su cuenta: + + Usuario: <%= @user.name %> + Correo: <%= @user.email %> + +Si usted no solicitó reiniciar sus credenciales, por favor ignore este correo. +Sus credenciales seguirán siendo validas. + +-- +Boxroom +http://boxroomapp.com/ diff --git a/app/views/boxroom/user_mailer/reset_password_email.fr.text.erb b/app/views/boxroom/user_mailer/reset_password_email.fr.text.erb new file mode 100644 index 0000000..296d357 --- /dev/null +++ b/app/views/boxroom/user_mailer/reset_password_email.fr.text.erb @@ -0,0 +1,17 @@ +Cher utilisateur, + +Veuillez cliquer le lien ci-dessous pour réinitialiser votre mot de passe Boxroom: + + <%= edit_reset_password_url(@user.reset_password_token) %> + +A titre d'information, vos informations utilisateur: + + Nom d'utilisateur: <%= @user.name %> + Email: <%= @user.email %> + +Si vous n'avez pas demandé à réinitialiser votre mot de passe, ignorez simplement ce message. +Votre mot de passe actuel reste inchangé. + +-- +Boxroom +http://boxroomapp.com/ diff --git a/app/views/boxroom/user_mailer/reset_password_email.it.text.erb b/app/views/boxroom/user_mailer/reset_password_email.it.text.erb new file mode 100644 index 0000000..a22edd5 --- /dev/null +++ b/app/views/boxroom/user_mailer/reset_password_email.it.text.erb @@ -0,0 +1,17 @@ +Gentile utente, + +La preghiamo di utilizzare il seguente URL per reimpostare la sua password su BoxRoom: + + <%= edit_reset_password_url(@user.reset_password_token) %> + +Le ricordiamo i dettagli dell'account: + + Username: <%= @user.name %> + Email: <%= @user.email %> + +Se non ha inoltrato la richiesta per reimpostare la password, può ignorare questa email. +La password corrente continuerà ad essere valida. + +-- +Boxroom +http://boxroomapp.com/ diff --git a/app/views/boxroom/user_mailer/reset_password_email.nl.text.erb b/app/views/boxroom/user_mailer/reset_password_email.nl.text.erb new file mode 100644 index 0000000..2003859 --- /dev/null +++ b/app/views/boxroom/user_mailer/reset_password_email.nl.text.erb @@ -0,0 +1,17 @@ +Geachte gebruiker, + +Gebruik onderstaande URL om uw wachtwoord te resetten: + + <%= edit_reset_password_url(@user.reset_password_token) %> + +Ter herinnering, uw account informatie is: + + Gebruikersnaam: <%= @user.name %> + E-mail: <%= @user.email %> + +Als u geen aanvraag heeft gedaan voor het resetten van uw wachtwoord kunt u deze e-mail negeren. +Uw huidige wachtwoord is nog steeds geldig. + +-- +Boxroom +http://boxroomapp.com/ diff --git a/app/views/boxroom/user_mailer/reset_password_email.zh-CN.text.erb b/app/views/boxroom/user_mailer/reset_password_email.zh-CN.text.erb new file mode 100644 index 0000000..911d82d --- /dev/null +++ b/app/views/boxroom/user_mailer/reset_password_email.zh-CN.text.erb @@ -0,0 +1,16 @@ +亲爱的用户: + +请用下面的网址重设您的Boxroom密码: + + <%= edit_reset_password_url(@user.reset_password_token) %> + +提醒一下,您的户头情况: + + 用户名: <%= @user.name %> + 邮箱: <%= @user.email %> + +如果您不曾提交要求重设密码,请忽略这封信。您当前的密码仍然有效。 + +-- +Boxroom +http://boxroomapp.com/ diff --git a/app/views/boxroom/user_mailer/share_link_email.de.text.erb b/app/views/boxroom/user_mailer/share_link_email.de.text.erb new file mode 100644 index 0000000..2eca673 --- /dev/null +++ b/app/views/boxroom/user_mailer/share_link_email.de.text.erb @@ -0,0 +1,20 @@ +Sehr geehrter Empfänger, + +<%= @share_link.user.email %> hat Ihnen eine Datei freigegeben: + + <%= @share_link.user_file.attachment_file_name %> (<%= number_to_human_size(@share_link.user_file.attachment_file_size, :locale => I18n.locale) %>) + +Benutzen Sie die folgende Adresse, um die Datei herunterzuladen: + + <%= share_link_url(:id => @share_link.link_token) %> + +Diese URL wird am <%= l @share_link.link_expires_at, :format => :long %> ablaufen. + +<% unless @share_link.message.blank? -%> +=== <%= t(:shared_message) %>: === +<%= strip_tags(@share_link.message) %> +<% end -%> + +-- +Boxroom +http://boxroomapp.com/ diff --git a/app/views/boxroom/user_mailer/share_link_email.en.text.erb b/app/views/boxroom/user_mailer/share_link_email.en.text.erb new file mode 100644 index 0000000..1223d9b --- /dev/null +++ b/app/views/boxroom/user_mailer/share_link_email.en.text.erb @@ -0,0 +1,20 @@ +Dear recipient, + +<%= @share_link.user.email %> has shared a file with you: + + <%= @share_link.user_file.attachment_file_name %> (<%= number_to_human_size(@share_link.user_file.attachment_file_size, :locale => I18n.locale) %>) + +Use the following URL to download your file: + + <%= share_link_url(:id => @share_link.link_token) %> + +The URL above will expire at <%= l @share_link.link_expires_at, :format => :time_only %> on <%= l @share_link.link_expires_at, :format => :date_only %>. + +<% unless @share_link.message.blank? -%> +=== <%= t(:shared_message) %>: === +<%= strip_tags(@share_link.message) %> +<% end -%> + +-- +Boxroom +http://boxroomapp.com/ diff --git a/app/views/boxroom/user_mailer/share_link_email.es.text.erb b/app/views/boxroom/user_mailer/share_link_email.es.text.erb new file mode 100644 index 0000000..e13eb18 --- /dev/null +++ b/app/views/boxroom/user_mailer/share_link_email.es.text.erb @@ -0,0 +1,20 @@ +Estimado, + +<%= @share_link.user.email %> ha compartido un archivo con usted: + + <%= @share_link.user_file.attachment_file_name %> (<%= number_to_human_size(@share_link.user_file.attachment_file_size, :locale => I18n.locale) %>) + +Use la siguiente URL para descargar su archivo: + + <%= share_link_url(:id => @share_link.link_token) %> + +La URL expirará a las <%= l @share_link.link_expires_at, :format => :time_only %> del <%= l @share_link.link_expires_at, :format => :date_only %>. + +<% unless @share_link.message.blank? -%> +=== <%= t(:shared_message) %>: === +<%= strip_tags(@share_link.message) %> +<% end -%> + +-- +Boxroom +http://boxroomapp.com/ diff --git a/app/views/boxroom/user_mailer/share_link_email.fr.text.erb b/app/views/boxroom/user_mailer/share_link_email.fr.text.erb new file mode 100644 index 0000000..9b88fa1 --- /dev/null +++ b/app/views/boxroom/user_mailer/share_link_email.fr.text.erb @@ -0,0 +1,20 @@ +Cher destinataire, + +<%= @share_link.user.email %> a partagé un fichier avec vous: + + <%= @share_link.user_file.attachment_file_name %> (<%= number_to_human_size(@share_link.user_file.attachment_file_size, :locale => I18n.locale) %>) + +Utilisez le lien suivant pour télécharger le fichier: + + <%= share_link_url(:id => @share_link.link_token) %> + +Le lien ci-dessus expirera à <%= l @share_link.link_expires_at, :format => :time_only %> le <%= l @share_link.link_expires_at, :format => :date_only %>. + +<% unless @share_link.message.blank? -%> +=== <%= t(:shared_message) %>: === +<%= strip_tags(@share_link.message) %> +<% end -%> + +-- +Boxroom +http://boxroomapp.com/ diff --git a/app/views/boxroom/user_mailer/share_link_email.it.text.erb b/app/views/boxroom/user_mailer/share_link_email.it.text.erb new file mode 100644 index 0000000..0373042 --- /dev/null +++ b/app/views/boxroom/user_mailer/share_link_email.it.text.erb @@ -0,0 +1,20 @@ +Gentile utente, + +<%= @share_link.user.email %> ha condiviso un file con te: + + <%= @share_link.user_file.attachment_file_name %> (<%= number_to_human_size(@share_link.user_file.attachment_file_size, :locale => I18n.locale) %>) + +Clicca sul seguente URL per scaricare il file: + + <%= share_link_url(:id => @share_link.link_token) %> + +L'URL indicato sopra scadrà <%= l @share_link.link_expires_at, :format => :long %>. + +<% unless @share_link.message.blank? -%> +=== <%= t(:shared_message) %>: === +<%= strip_tags(@share_link.message) %> +<% end -%> + +-- +Boxroom +http://boxroomapp.com/ diff --git a/app/views/boxroom/user_mailer/share_link_email.nl.text.erb b/app/views/boxroom/user_mailer/share_link_email.nl.text.erb new file mode 100644 index 0000000..942221f --- /dev/null +++ b/app/views/boxroom/user_mailer/share_link_email.nl.text.erb @@ -0,0 +1,20 @@ +Geachte ontvanger, + +<%= @share_link.user.email %> heeft een bestand met u gedeeld: + + <%= @share_link.user_file.attachment_file_name %> (<%= number_to_human_size(@share_link.user_file.attachment_file_size, :locale => I18n.locale) %>) + +Gebruik onderstaande URL om het bestand te downloaden: + + <%= share_link_url(:id => @share_link.link_token) %> + +De vervaldatum van bovenstaande URL is <%= l @share_link.link_expires_at, :format => :long %>. + +<% unless @share_link.message.blank? -%> +=== <%= t(:shared_message) %>: === +<%= strip_tags(@share_link.message) %> +<% end -%> + +-- +Boxroom +http://boxroomapp.com/ diff --git a/app/views/boxroom/user_mailer/share_link_email.zh-CN.text.erb b/app/views/boxroom/user_mailer/share_link_email.zh-CN.text.erb new file mode 100644 index 0000000..84e8728 --- /dev/null +++ b/app/views/boxroom/user_mailer/share_link_email.zh-CN.text.erb @@ -0,0 +1,20 @@ +亲爱的收件人: + +<%= @share_link.user.email %> 与您共享了一个文件: + + <%= @share_link.user_file.attachment_file_name %> (<%= number_to_human_size(@share_link.user_file.attachment_file_size, :locale => I18n.locale) %>) + +请用下面的链接下载文件: + + <%= share_link_url(:id => @share_link.link_token) %> + +此链接会在<%= l @share_link.link_expires_at, :format => :time_only %>,<%= l @share_link.link_expires_at, :format => :date_only %>失效。 + +<% unless @share_link.message.blank? -%> +=== <%= t(:shared_message) %>: === +<%= strip_tags(@share_link.message) %> +<% end -%> + +-- +Boxroom +http://boxroomapp.com/ diff --git a/app/views/boxroom/user_mailer/signup_email.de.text.erb b/app/views/boxroom/user_mailer/signup_email.de.text.erb new file mode 100644 index 0000000..2e1bf07 --- /dev/null +++ b/app/views/boxroom/user_mailer/signup_email.de.text.erb @@ -0,0 +1,9 @@ +Dear recipient, + +This is an invitation to sign up for Boxroom. Please use the following URL to sign up: + + <%= edit_signup_url(@user.signup_token) %> + +-- +Boxroom +http://boxroomapp.com/ diff --git a/app/views/boxroom/user_mailer/signup_email.en.text.erb b/app/views/boxroom/user_mailer/signup_email.en.text.erb new file mode 100644 index 0000000..2e1bf07 --- /dev/null +++ b/app/views/boxroom/user_mailer/signup_email.en.text.erb @@ -0,0 +1,9 @@ +Dear recipient, + +This is an invitation to sign up for Boxroom. Please use the following URL to sign up: + + <%= edit_signup_url(@user.signup_token) %> + +-- +Boxroom +http://boxroomapp.com/ diff --git a/app/views/boxroom/user_mailer/signup_email.es.text.erb b/app/views/boxroom/user_mailer/signup_email.es.text.erb new file mode 100644 index 0000000..1f4c701 --- /dev/null +++ b/app/views/boxroom/user_mailer/signup_email.es.text.erb @@ -0,0 +1,9 @@ +Estimado, + +Esta es una invitacion para activar su cuenta Boxroom. Por favor use la siguiente URL: + + <%= edit_signup_url(@user.signup_token) %> + +-- +Boxroom +http://boxroomapp.com/ diff --git a/app/views/boxroom/user_mailer/signup_email.fr.text.erb b/app/views/boxroom/user_mailer/signup_email.fr.text.erb new file mode 100644 index 0000000..eb2bedf --- /dev/null +++ b/app/views/boxroom/user_mailer/signup_email.fr.text.erb @@ -0,0 +1,9 @@ +Cher destinataire, + +Ceci est un mail d'invitation à Boxroom. Pour vous inscrire, veuillez utiliser le lien ci-dessous: + + <%= edit_signup_url(@user.signup_token) %> + +-- +Boxroom +http://boxroomapp.com/ diff --git a/app/views/boxroom/user_mailer/signup_email.it.text.erb b/app/views/boxroom/user_mailer/signup_email.it.text.erb new file mode 100644 index 0000000..2e1bf07 --- /dev/null +++ b/app/views/boxroom/user_mailer/signup_email.it.text.erb @@ -0,0 +1,9 @@ +Dear recipient, + +This is an invitation to sign up for Boxroom. Please use the following URL to sign up: + + <%= edit_signup_url(@user.signup_token) %> + +-- +Boxroom +http://boxroomapp.com/ diff --git a/app/views/boxroom/user_mailer/signup_email.nl.text.erb b/app/views/boxroom/user_mailer/signup_email.nl.text.erb new file mode 100644 index 0000000..3f5f9d9 --- /dev/null +++ b/app/views/boxroom/user_mailer/signup_email.nl.text.erb @@ -0,0 +1,10 @@ +Geachte ontvanger, + +Dit is een uitnodiging om u aan te melden voor Boxroom. +Gebruik onderstaande URL om uw account aan te maken: + + <%= edit_signup_url(@user.signup_token) %> + +-- +Boxroom +http://boxroomapp.com/ diff --git a/app/views/boxroom/user_mailer/signup_email.zh-CN.text.erb b/app/views/boxroom/user_mailer/signup_email.zh-CN.text.erb new file mode 100644 index 0000000..151e25a --- /dev/null +++ b/app/views/boxroom/user_mailer/signup_email.zh-CN.text.erb @@ -0,0 +1,8 @@ +亲爱的收件人, + +此信邀请你注册Boxroom。请用下面的网址注册: + + <%= edit_signup_url(@user.signup_token) %> +-- +Boxroom +http://boxroomapp.com/ diff --git a/app/views/boxroom/users/_form.html.erb b/app/views/boxroom/users/_form.html.erb new file mode 100644 index 0000000..e71281f --- /dev/null +++ b/app/views/boxroom/users/_form.html.erb @@ -0,0 +1,46 @@ +<%= form_for @user do |f| %> + <%= f.error_messages %> + <% unless @user.new_record? -%> +

+ <%= f.label :name %>:
+ <%= f.text_field :name, { :class => 'text_input' } %> +

+ <% end -%> +

+ <%= f.label :email %>:
+ <%= f.text_field :email, { :class => 'text_input' } %> +

+ <% unless @user.new_record? -%> +

+ <%= f.label :password %>:
+ <%= f.password_field :password, { :class => 'text_input' } %> +

+

+ <%= label_tag t(:confirm_password) %>:
+ <%= f.password_field :password_confirmation, { :class => 'text_input' } %> +

+ <% end -%> + <% if signed_in? && current_user.member_of_admins? -%> +

+ <%= t :member_of_these_groups %>: + + <% if @user.is_admin -%> + + <%= hidden_field_tag 'user[group_ids][]', Group.admins_group.id %> + + + <%= f.collection_check_boxes :group_ids, Group.all_except_admins, :id, :name %> + <% else -%> + <%= f.collection_check_boxes :group_ids, Group.all, :id, :name %> + <% end -%> + +

+ <% end -%> +

+ <%= f.submit t(:save) %> + <% if @user != current_user -%> +   —   + <%= link_to t(:back), users_url %> + <% end -%> +

+<% end %> diff --git a/app/views/boxroom/users/edit.html.erb b/app/views/boxroom/users/edit.html.erb new file mode 100644 index 0000000..c9f9b5b --- /dev/null +++ b/app/views/boxroom/users/edit.html.erb @@ -0,0 +1,4 @@ +<% content_for :title, @title -%> + +

<%= content_for :title %>

+<%= render 'form' %> diff --git a/app/views/boxroom/users/index.html.erb b/app/views/boxroom/users/index.html.erb new file mode 100644 index 0000000..0d15d89 --- /dev/null +++ b/app/views/boxroom/users/index.html.erb @@ -0,0 +1,60 @@ +<% content_for :title, t(:users) -%> + +

<%= content_for :title %>

+

+ <%= image_tag('boxroom/user_add.png', :alt => t(:create_a_new_user)) %> <%= link_to t(:create_a_new_user), new_user_path %> +

+ +

<%= t :active_users %>

+ + + + + + + +<% @users.each do |user| -%> + + + + + + +<% end -%> +
<%= t :name %><%= t :email %>
<%= image_tag('boxroom/user.png') %><%= user.name %><%= user.email %> + <%= link_to image_tag('boxroom/edit.png', :alt => t(:edit)), edit_user_path(user), :title => t(:edit) %>  + <% unless user.is_admin -%> + <%= link_to image_tag('boxroom/delete.png', :alt => t(:delete_item)), user_path(user), :method => :delete, :data => { :confirm => t(:are_you_sure) }, :title => t(:delete_item) %> + <% end -%> +
+ +<% unless @new_users.blank? -%> +

<%= t :invited_users %>

+ + + + + + + +<% @new_users.each do |user| -%> + + + + + + +<% end -%> +
<%= t :email %><%= t :expiration_date %>
<%= image_tag('boxroom/user.png') %><%= user.email %> + <% if user.signup_token_expires_at > Time.now -%> + <%= l user.signup_token_expires_at, :format => :very_short %> + <% else -%> + <%= l user.signup_token_expires_at, :format => :very_short %> + <% end -%> + + <%= link_to image_tag('boxroom/extend.png', :alt => t(:extend_expiration_date)), extend_user_path(user), :method => :put, :title => t(:extend_expiration_date) %>  + <% unless user.is_admin -%> + <%= link_to image_tag('boxroom/delete.png', :alt => t(:delete_item)), user_path(user), :method => :delete, :data => { :confirm => t(:are_you_sure) }, :title => t(:delete_item) %> + <% end -%> +
+<% end -%> diff --git a/app/views/boxroom/users/new.html.erb b/app/views/boxroom/users/new.html.erb new file mode 100644 index 0000000..41d442f --- /dev/null +++ b/app/views/boxroom/users/new.html.erb @@ -0,0 +1,4 @@ +<% content_for :title, t(:new_user) -%> + +

<%= content_for :title %>

+<%= render 'form' %> diff --git a/app/views/layouts/boxroom/application.html.erb b/app/views/layouts/boxroom/application.html.erb new file mode 100644 index 0000000..1374a37 --- /dev/null +++ b/app/views/layouts/boxroom/application.html.erb @@ -0,0 +1,39 @@ + + + +<% if content_for? :title -%> + <%= Boxroom.configuration.site_name %> | <%= content_for :title %> +<% else -%> + <%= Boxroom.configuration.site_name %> +<% end -%> + <%= stylesheet_link_tag 'boxroom/application' %> + <%= javascript_include_tag 'boxroom/application' %> + <%= csrf_meta_tag %> + + + +
+ <% if flash[:notice] -%> +
+

+ <%= flash[:notice] %> +

+
+ <% end -%> + <% if flash[:alert] -%> +
+

+ <%= flash[:alert] %> +

+
+ <% end -%> + <%= render 'boxroom/shared/header' %> + <%= render 'boxroom/shared/menu' %> +
+ <%= yield %> +
+ + <%= render 'boxroom/shared/footer' %> +
+ + diff --git a/bin/rails b/bin/rails new file mode 100755 index 0000000..d6b505d --- /dev/null +++ b/bin/rails @@ -0,0 +1,14 @@ +#!/usr/bin/env ruby +# This command will automatically be run when you run "rails" with Rails gems +# installed from the root of your application. + +ENGINE_ROOT = File.expand_path('../..', __FILE__) +ENGINE_PATH = File.expand_path('../../lib/boxroom/engine', __FILE__) +APP_PATH = File.expand_path('../../test/dummy/config/application', __FILE__) + +# Set up gems listed in the Gemfile. +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) +require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE']) + +require 'rails/all' +require 'rails/engine/commands' diff --git a/boxroom.gemspec b/boxroom.gemspec new file mode 100644 index 0000000..4ce4535 --- /dev/null +++ b/boxroom.gemspec @@ -0,0 +1,26 @@ +$:.push File.expand_path("../lib", __FILE__) + +# Maintain your gem's version: +require "boxroom/version" + +# Describe your gem and declare its dependencies: +Gem::Specification.new do |s| + s.name = "boxroom" + s.version = Boxroom::VERSION + s.authors = ["Serge Koba"] + s.email = ["s.koba@mobidev.biz"] + s.homepage = "" + s.summary = "File manager engine" + s.description = "File manager engine" + s.license = "MIT" + + s.files = Dir["{app,config,db,lib}/**/*", "MIT-LICENSE", "Rakefile", "README.md"] + + s.add_dependency 'rails', "~> 5.0.2" + s.add_dependency 'dynamic_form' + s.add_dependency 'acts_as_tree' + s.add_dependency 'paperclip' + s.add_dependency 'jquery-fileupload-rails' + + s.add_development_dependency "sqlite3" +end diff --git a/config/locales/de.yml b/config/locales/de.yml new file mode 100644 index 0000000..fb45a14 --- /dev/null +++ b/config/locales/de.yml @@ -0,0 +1,412 @@ +# German translations for Boxroom +# Original Rails translation by Clemens Kofler (clemens@railway.at) +# and Alexander Dreher - http://github.com/alexdreher - Rails 3 update +# +# see: https://github.com/svenfuchs/rails-i18n/blob/master/rails/locale/de.yml + +de: + date: + formats: + default: "%d.%m.%Y" + short: "%e. %b" + long: "%e. %B %Y" + only_day: "%e" + + day_names: [Sonntag, Montag, Dienstag, Mittwoch, Donnerstag, Freitag, Samstag] + abbr_day_names: [So, Mo, Di, Mi, Do, Fr, Sa] + month_names: [~, Januar, Februar, März, April, Mai, Juni, Juli, August, September, Oktober, November, Dezember] + abbr_month_names: [~, Jan, Feb, Mär, Apr, Mai, Jun, Jul, Aug, Sep, Okt, Nov, Dez] + order: + - :day + - :month + - :year + + time: + formats: + default: "%A, %d. %B %Y, %H:%M Uhr" + short: "%d. %B %Y, %H:%M Uhr" + very_short: "%d. %B %Y" + long: "%A, %d. %B %Y, %H:%M Uhr" + time: "%H:%M" + + am: "vormittags" + pm: "nachmittags" + + datetime: + distance_in_words: + half_a_minute: 'eine halbe Minute' + less_than_x_seconds: + one: 'weniger als eine Sekunde' + other: 'weniger als %{count} Sekunden' + x_seconds: + one: 'eine Sekunde' + other: '%{count} Sekunden' + less_than_x_minutes: + one: 'weniger als eine Minute' + other: 'weniger als %{count} Minuten' + x_minutes: + one: 'eine Minute' + other: '%{count} Minuten' + about_x_hours: + one: 'etwa eine Stunde' + other: 'etwa %{count} Stunden' + x_days: + one: 'ein Tag' + other: '%{count} Tage' + about_x_months: + one: 'etwa ein Monat' + other: 'etwa %{count} Monate' + x_months: + one: 'ein Monat' + other: '%{count} Monate' + almost_x_years: + one: 'fast ein Jahr' + other: 'fast %{count} Jahre' + about_x_years: + one: 'etwa ein Jahr' + other: 'etwa %{count} Jahre' + over_x_years: + one: 'mehr als ein Jahr' + other: 'mehr als %{count} Jahre' + prompts: + second: "Sekunden" + minute: "Minuten" + hour: "Stunden" + day: "Tag" + month: "Monat" + year: "Jahr" + + number: + format: + precision: 2 + separator: ',' + delimiter: '.' + significant: false + strip_insignificant_zeros: false + currency: + format: + unit: '€' + format: '%n%u' + separator: "," + delimiter: "" + precision: 2 + significant: false + strip_insignificant_zeros: false + percentage: + format: + delimiter: "" + precision: + format: + delimiter: "" + human: + format: + delimiter: "" + precision: 1 + significant: true + strip_insignificant_zeros: true + storage_units: + # Storage units output formatting. + # %u is the storage unit, %n is the number (default: 2 MB) + format: "%n %u" + units: + byte: + one: "Byte" + other: "Bytes" + kb: "KB" + mb: "MB" + gb: "GB" + tb: "TB" + decimal_units: + format: "%n %u" + units: + unit: "" + thousand: Tausend + million: Millionen + billion: + one: Milliarde + others: Milliarden + trillion: Billionen + quadrillion: + one: Billiarde + others: Billiarden + + support: + array: + words_connector: ", " + two_words_connector: " und " + last_word_connector: " und " + select: + prompt: "Bitte wählen:" + + activemodel: + errors: + template: + header: + one: "Konnte %{model} nicht speichern: ein Fehler." + other: "Konnte %{model} nicht speichern: %{count} Fehler." + body: "Bitte überprüfen Sie die folgenden Felder:" + helpers: + select: + prompt: "Bitte wählen" + + submit: + create: '%{model} erstellen' + update: '%{model} aktualisieren' + submit: '%{model} speichern' + + errors: + format: "%{attribute} %{message}" + + messages: &errors_messages + inclusion: "ist kein gültiger Wert" + exclusion: "ist nicht verfügbar" + invalid: "ist nicht gültig" + confirmation: "stimmt nicht" + accepted: "muss akzeptiert werden" + empty: "muss ausgefüllt werden" + blank: "muss ausgefüllt werden" + too_long: "ist zu lang (nicht mehr als %{count} Zeichen)" + too_short: "ist zu kurz (nicht weniger als %{count} Zeichen)" + wrong_length: "hat die falsche Länge (muss genau %{count} Zeichen haben)" + not_a_number: "ist keine Zahl" + greater_than: "muss größer als %{count} sein" + greater_than_or_equal_to: "muss größer oder gleich %{count} sein" + equal_to: "muss genau %{count} sein" + less_than: "muss kleiner als %{count} sein" + less_than_or_equal_to: "muss kleiner oder gleich %{count} sein" + odd: "muss ungerade sein" + even: "muss gerade sein" + not_an_integer: "muss ganzzahlig sein" + + activerecord: + errors: + template: + header: + one: "Konnte %{model} nicht speichern: ein Fehler." + other: "Konnte %{model} nicht speichern: %{count} Fehler." + body: "Bitte überprüfen Sie die folgenden Felder:" + + messages: + taken: "ist bereits vergeben" + record_invalid: "Gültigkeitsprüfung ist fehlgeschlagen: %{errors}" + <<: *errors_messages + + full_messages: + format: "%{attribute} %{message}" + + models: + clipboard: Zwischenablage + folder: Ordner + group: Gruppe + permission: Berechtigung + share_link: Share link + user: Benutzer + user_file: Datei + + attributes: + folder: + name: Name + group: + name: Name + share_link: + emails: E-Mail Adressen + expires_at: Läuft ab am + user: + email: E-Mail + name: Name + password: Kennwort + user_file: + name: Name + attachment_file_name: Datei + + # APPLICATION SPECIFIC + + # general + back: Zurück + save: Speichern + name: Name + email: E-Mail + submit: Senden + + your_changes_were_saved: Ihre Einstellungen wurden erfolgreich gespeichert. + already_deleted: "Jemand hat %{type} bereits gelöscht. Die Aktion wurde abgebrochen." + + # admins/new + create_admin: Administrator-Zugang erstellen + no_administrator_yet: Es gibt noch keinen Administrator-Zugang zu Boxroom. Hier können Sie einen anlegen. + create_admin_account: Konto erstellen + admin_user_created_successfully: Das Konto wurde erfolgreich erstellt. Sie können sich nun einloggen. + + # clipboard/_show + folder: Ordner + file: Datei + this_folder: dieser Ordner + this_file: diese Datei + copy: Kopieren + copy_folder: Ordner kopieren + copy_file: Datei kopieren + move: Verschieben + move_folder: Ordner verschieben + move_file: Datei verschieben + are_you_sure: Sind Sie sicher? + delete_item: Löschen + remove_from_clipboard: Aus der Zwischenablage entfernen + clear_clipboard: Zwischenablage leeren + + # files/edit + rename_file: Datei umbenennen + + # files/new + select_file: Datei wählen + upload_file: Dateien hochladen + upload: Hochladen + exists_already: bereits vorhanden + + #folders/edit + rename_folder: Ordner umbenennen + + #folders/new + new_folder: Neuen Ordner anlegen + + #folders/show + create_a_new_folder: Neuer Ordner + upload_a_file: Dateien hochladen + permissions: Berechtigungen + clipboard: Zwischenablage + size: Größe + date_modified: Letzte Änderung + up: nach oben + edit: Bearbeiten + add_to_clipboard: Zur Zwischenablage hinzufügen + download: Herunterladen + share: Freigeben + + #groups/edit + rename_group: Gruppe umbenennen + + #groups/index + groups: Gruppen + create_a_new_group: Neue Gruppe anlegen + + #groups/new + new_group: Neue Gruppe anlegen + + #permissions/form + create_permission: Erstellen + read_permission: Lesen + update_permission: Aktualisieren + delete_permission: Löschen + apply_changes_to_subfolders: Änderungen auf Unterordner anwenden + + create: Erstellen + read: Lesen + update: Aktualisieren + delete: Löschen + + #reset_password/edit + password: Kennwort + reset_password: Kennwort zurücksetzen + send_email: Absenden + + #signup/edit + sign_up: Sign up + + #sessions + username: Benutzername + remember_me: Angemeldet bleiben + sign_in: Anmelden + + #share_links/index + shared_by: Freigabe von + unshare: Freigabe aufheben + + #share_links/new + this_share_link: Dieser Freigabe-Link + share_file: Datei freigeben + you_are_about_to_share_the_following_file: Sie möchten die folgende Datei freigeben + emails_to_share_with: 'E-Mail Adressen, für welche die Datei freigegeben werden soll' + comma_seperated: Komma-separiert + number_of_charachters: Anzahl d. Zeichen + link_expires: Ablaufdatum + tomorrow: Morgen + three_days_from_now: In drei Tagen + one_week_from_now: In einer Woche + ten_days_from_now: In zehn Tagen + two_weeks_from_now: In zwei Wochen + three_weeks_from_now: In drei Wochen + one_month_from_now: In einem Monat + two_months_from_now: In zwei Monaten + three_months_from_now: In drei Monaten + half_year_from_now: In einem halben Jahr + download_link_could_not_be_sent: Die Download-URL konnte nicht versendet werden. + are_invalid_due_to: "Die Adresse %{email} ist ungültig." + shared_successfully: Die Datei wurde erfolgreich freigegeben. + shared_message: Nachricht + optional: Nicht erforderlich + + #shared/_header + hello: Hallo + settings: Einstellungen + sign_out: Abmelden + + #shared/_menu + folders: Ordner + users: Benutzer + shared_files: Freigegebene Dateien + + #users/_form + member_of_these_groups: Mitglied in diesen Gruppen + confirm_password: Kennwort bestätigen + + #users/index + create_a_new_user: Neuen Benutzer anlegen + active_users: Active users + invited_users: Invited users + expiration_date: Expiration date + extend_expiration_date: Extend expiration date + + #users/new + new_user: Neuen Benutzer anlegen + + #admins/controller + admin_user_created_sucessfully: Der Administrator-Zugang wurde erfolgreich angelegt. Sie können sich nun anmelden. + + #application_controller + no_permissions_for_this_type: "Sie haben keine Berechtigung um %{type} zu %{method}." + + # clipboard_controller + added_to_clipboard: Erfolgreich zur Zwischenablage hinzugefügt. + could_not_copy: "Kopieren fehlgeschlagen. Ein %{type} dieses Namens existiert bereits." + could_not_move: "Verschieben fehlgeschlagen. Ein %{type} dieses Namens existiert bereits." + cannot_move_to_own_subfolder: Sie können einen Ordner nicht in einen seiner Unterordner verschieben. + + # folders_controller + cannot_delete_root_folder: Das Haupt-Verzeichnis kann nicht gelöscht oder umbenannt werden. + no_delete_permissions_for_subfolder: "Sie haben keine Berechtigung, einen der Unterordner zu löschen." + + # groups_controller + group_already_deleted: Jemand hat diese Gruppe bereits gelöscht. Die Aktion wurde abgebrochen. + admins_group_cannot_be_deleted: Die Administrator-Gruppe kann nicht gelöscht werden. + + # reset_password_controller + instruction_email_sent: E-Mail erfolgreich verschickt. Bitte prüfen Sie Ihren Posteingang. + password_reset_successfully: Ihr Kennwort wurde erfolgreich zurückgesetzt. Sie können sich nun anmelden. + reset_url_expired: Die URL zum Rücksetzen des Kennworts ist leider abgelaufen. Bitte probieren Sie es nochmals. + + # signup_controller + signed_up_successfully: Account created successfully. You can now sign in. + sign_url_expired: The URL for signing up expired. Please contact the administrator. + + # sessions_controller + credentials_incorrect: Benutzername und/oder Kennwort falsch. Bitte probieren Sie es nochmals. + + # users_controller + user_already_deleted: Jemand hat diesen Benutzer bereits gelöscht. Die Aktion wurde abgebrochen. + admin_user_cannot_be_deleted: Der Administrator-Zugang kann nicht gelöscht werden. + edit_user: Benutzer bearbeiten + account_settings: Kontoeinstellungen + + # mailers/user_mailer + signup_email_subject: '[Boxroom] Sign up invitation' + reset_password_email_subject: '[Boxroom] Anleitung zum Ändern Ihres Kennworts' + share_link_email_subject: '[Boxroom] %{email} möchte Ihnen eine Datei freigeben' diff --git a/config/locales/en.yml b/config/locales/en.yml new file mode 100644 index 0000000..a2a81e6 --- /dev/null +++ b/config/locales/en.yml @@ -0,0 +1,405 @@ +# US English translations for Ruby on Rails +# +# Use this as the base for the locale file of your language. +# see: https://github.com/svenfuchs/rails-i18n/blob/master/rails/locale/en-US.yml + +"en": + date: + formats: + default: "%Y-%m-%d" + short: "%b %d" + long: "%B %d, %Y" + + day_names: [Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday] + abbr_day_names: [Sun, Mon, Tue, Wed, Thu, Fri, Sat] + + month_names: [~, January, February, March, April, May, June, July, August, September, October, November, December] + abbr_month_names: [~, Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec] + order: + - :year + - :month + - :day + + time: + formats: + default: "%a, %d %b %Y %H:%M:%S %z" + short: "%d %b %Y %H:%M" + very_short: "%d %b %Y" + long: "%B %d, %Y %H:%M" + date_only: "%B %d, %Y" + time_only: "%H:%M" + am: "am" + pm: "pm" + + support: + array: + words_connector: ", " + two_words_connector: " and " + last_word_connector: ", and " + + select: + prompt: "Please select" + + number: + format: + separator: "." + delimiter: "," + precision: 3 + significant: false + strip_insignificant_zeros: false + + currency: + format: + format: "%u%n" + unit: "$" + separator: "." + delimiter: "," + precision: 2 + significant: false + strip_insignificant_zeros: false + + percentage: + format: + delimiter: "" + + precision: + format: + delimiter: "" + + human: + format: + delimiter: "" + precision: 3 + significant: true + strip_insignificant_zeros: true + storage_units: + format: "%n %u" + units: + byte: + one: "Byte" + other: "Bytes" + kb: "KB" + mb: "MB" + gb: "GB" + tb: "TB" + decimal_units: + format: "%n %u" + units: + unit: "" + thousand: Thousand + million: Million + billion: Billion + trillion: Trillion + quadrillion: Quadrillion + + datetime: + distance_in_words: + half_a_minute: "half a minute" + less_than_x_seconds: + one: "less than 1 second" + other: "less than %{count} seconds" + x_seconds: + one: "1 second" + other: "%{count} seconds" + less_than_x_minutes: + one: "less than a minute" + other: "less than %{count} minutes" + x_minutes: + one: "1 minute" + other: "%{count} minutes" + about_x_hours: + one: "about 1 hour" + other: "about %{count} hours" + x_days: + one: "1 day" + other: "%{count} days" + about_x_months: + one: "about 1 month" + other: "about %{count} months" + x_months: + one: "1 month" + other: "%{count} months" + about_x_years: + one: "about 1 year" + other: "about %{count} years" + over_x_years: + one: "over 1 year" + other: "over %{count} years" + almost_x_years: + one: "almost 1 year" + other: "almost %{count} years" + prompts: + year: "Year" + month: "Month" + day: "Day" + hour: "Hour" + minute: "Minute" + second: "Seconds" + + helpers: + select: + prompt: "Please select" + + submit: + create: 'Create %{model}' + update: 'Update %{model}' + submit: 'Save %{model}' + + errors: + format: "%{attribute} %{message}" + + messages: &errors_messages + inclusion: "is not included in the list" + exclusion: "is reserved" + invalid: "is invalid" + confirmation: "doesn't match" + accepted: "must be accepted" + empty: "can't be empty" + blank: "can't be blank" + exists_already: 'exists already' + too_long: "is too long (maximum is %{count} characters)" + too_short: "is too short (minimum is %{count} characters)" + wrong_length: "is the wrong length (should be %{count} characters)" + not_a_number: "is not a number" + not_an_integer: "must be an integer" + greater_than: "must be greater than %{count}" + greater_than_or_equal_to: "must be greater than or equal to %{count}" + equal_to: "must be equal to %{count}" + less_than: "must be less than %{count}" + less_than_or_equal_to: "must be less than or equal to %{count}" + odd: "must be odd" + even: "must be even" + invalid_characters: 'cannot contain any of these characters: < > : " / \ | ? *' + + activerecord: + errors: + template: + header: + one: "1 error prohibited this %{model} from being saved" + other: "%{count} errors prohibited this %{model} from being saved" + body: "There were problems with the following fields:" + + messages: + taken: "has already been taken" + record_invalid: "Validation failed: %{errors}" + <<: *errors_messages + + full_messages: + format: "%{attribute} %{message}" + + models: + clipboard: Clipboard + folder: Folder + group: Group + permission: Permission + share_link: Share link + user: User + user_file: File + + attributes: + folder: + name: Name + group: + name: Name + share_link: + emails: Email addresses + expires_at: Expires + user: + email: Email + name: Name + password: Password + user_file: + name: Name + attachment_file_name: File + + # APPLICATION SPECIFIC + + # general + back: Back + save: Save + name: Name + email: Email + submit: Submit + + your_changes_were_saved: Your changes were saved successfully. + already_deleted: "Sorry, but this %{type} was deleted already." + + # admins/new + create_admin: Create admin + no_administrator_yet: Boxroom does not have an administrator yet. Create one here. + create_admin_account: Create admin account + admin_user_created_successfully: The admin user was created successfully. You can now sign in. + + # clipboard/_show + folder: folder + file: file + this_folder: this folder + this_file: this file + copy: Copy + copy_folder: Copy folder + copy_file: Copy file + move: Move + move_folder: Move folder + move_file: Move file + are_you_sure: Are you sure? + delete_item: Delete + remove_from_clipboard: Remove from clipboard + clear_clipboard: Clear clipboard + + # files/edit + rename_file: Rename file + + # files/new + select_file: Select file + upload_file: Upload files + upload: Upload + exists_already: exists already + + #folders/edit + rename_folder: Rename folder + + #folders/new + new_folder: New folder + + #folders/show + create_a_new_folder: Create a new folder + upload_a_file: Upload files + permissions: Permissions + clipboard: Clipboard + size: Size + date_modified: Date modified + up: up + edit: Edit + add_to_clipboard: Add to clipboard + download: Download + share: Share + + #groups/edit + rename_group: Rename group + + #groups/index + groups: Groups + create_a_new_group: Create a new group + + #groups/new + new_group: New group + + #permissions/form + create_permission: Create + read_permission: Read + update_permission: Update + delete_permission: Delete + apply_changes_to_subfolders: Apply changes to subfolders + + create: create + read: read + update: update + delete: delete + + #reset_password/edit + password: Password + reset_password: Reset password + send_email: Send + + #signup/edit + sign_up: Sign up + + #sessions + username: Username + remember_me: Remember me + sign_in: Sign in + + #share_links/index + shared_by: Shared by + unshare: Unshare + + #share_links/new + this_share_link: this share link + share_file: Share file + you_are_about_to_share_the_following_file: You are about to share the following file + emails_to_share_with: Email addresses of the people you wish to share this file with + comma_seperated: Comma seperated + number_of_charachters: Number of characters + link_expires: Expires + tomorrow: Tomorrow + three_days_from_now: Three days from now + one_week_from_now: A week from now + ten_days_from_now: Ten days from now + two_weeks_from_now: Two weeks from now + three_weeks_from_now: Three weeks from now + one_month_from_now: A month from now + two_months_from_now: Two months from now + three_months_from_now: Three months from now + half_year_from_now: A half year from now + share_link_could_not_be_sent: The download link could not be sent + are_invalid_due_to: "is invalid due to %{email}" + shared_successfully: The file was shared successfully. + shared_message: Message + optional: Optional + + #shared/_header + hello: Hello + settings: Settings + sign_out: Sign out + + #shared/_menu + folders: Folders + users: Users + shared_files: Shared files + + #users/_form + member_of_these_groups: Member of these groups + confirm_password: Confirm password + + #users/index + create_a_new_user: Create a new user + active_users: Active users + invited_users: Invited users + expiration_date: Expiration date + extend_expiration_date: Extend expiration date + + #users/new + new_user: New user + + #admins/controller + admin_user_created_sucessfully: The admin user was created successfully. You can now sign in. + + #application_controller + no_permissions_for_this_type: "You don't have %{method} permissions for %{type}." + + # clipboard_controller + added_to_clipboard: Successfully added to clipboard. + could_not_copy: "Couldn't copy. A %{type} with the same name exists already." + could_not_move: "Couldn't move. A %{type} with the same name exists already." + cannot_move_to_own_subfolder: You cannot move a folder to its own sub-folder. + + # folders_controller + cannot_delete_root_folder: The root folder cannot be deleted or renamed. + no_delete_permissions_for_subfolder: You don't have delete permissions for one of the subfolders. + + # groups_controller + group_already_deleted: Someone else deleted this group. Your action was cancelled. + admins_group_cannot_be_deleted: The admins group cannot be deleted or renamed. + + # reset_password_controller + instruction_email_sent: "An email with instructions was sent if '%{email}' exists in our system." + password_reset_successfully: Your password was reset successfully. You can now sign in. + reset_url_expired: The URL for resetting your password expired. Please try again. + + # signup_controller + signed_up_successfully: Account created successfully. You can now sign in. + sign_url_expired: The URL for signing up expired. Please contact the administrator. + + # sessions_controller + credentials_incorrect: Username and/or password were incorrect. Try again. + + # users_controller + user_already_deleted: Someone else deleted the user. Your action was cancelled. + admin_user_cannot_be_deleted: The admin user cannot be deleted. + edit_user: Edit user + account_settings: Account settings + + # mailers/user_mailer + signup_email_subject: '[Boxroom] Sign up invitation' + reset_password_email_subject: '[Boxroom] Password reset instructions' + share_link_email_subject: '[Boxroom] %{email} shared a file with you' diff --git a/config/locales/es.yml b/config/locales/es.yml new file mode 100644 index 0000000..46640ab --- /dev/null +++ b/config/locales/es.yml @@ -0,0 +1,401 @@ +# ES Spanish translations for Boxroom +# + + +"es": + date: + formats: + default: "%d-%m-%Y" + short: "%b %d" + long: "%B %d, %Y" + + day_names: [Domingo, Lunes, Martes, Miércoles, Jueves, Viernes, Sábado] + abbr_day_names: [Dom, Lun, Mar, Mie, Jue, Vie, Sab] + + month_names: [~, Enero, Febrero, Marzo, Abril, Mayo, Junio, Julio, Agosto, Septiembre, Octubre, Noviembre, Diciembre] + abbr_month_names: [~, Ene, Feb, Mar, Abr, May, Jun, Jul, Ago, Sep, Oct, Nov, Dic] + order: + - :day + - :month + - :year + + time: + formats: + default: "%a, %d %b %Y %H:%M:%S %z" + short: "%d %b %Y %H:%M" + very_short: "%d %b %Y" + long: "%B %d, %Y %H:%M" + date_only: "%d de %B del %Y" + time_only: "%H:%M" + am: "am" + pm: "pm" + + support: + array: + words_connector: ", " + two_words_connector: " y " + last_word_connector: ", y " + + select: + prompt: "Seleccione" + + number: + format: + separator: "." + delimiter: "," + precision: 3 + significant: false + strip_insignificant_zeros: false + + currency: + format: + format: "%u%n" + unit: "$" + separator: "." + delimiter: "," + precision: 2 + significant: false + strip_insignificant_zeros: false + + percentage: + format: + delimiter: "" + + precision: + format: + delimiter: "" + + human: + format: + delimiter: "" + precision: 3 + significant: true + strip_insignificant_zeros: true + storage_units: + format: "%n %u" + units: + byte: + one: "Byte" + other: "Bytes" + kb: "KB" + mb: "MB" + gb: "GB" + tb: "TB" + decimal_units: + format: "%n %u" + units: + unit: "" + thousand: Ciento + million: Millon + billion: Billon + trillion: Trillon + quadrillion: Cuadrillon + + datetime: + distance_in_words: + half_a_minute: "minuto y medio" + less_than_x_seconds: + one: "menos de 1 segundo" + other: "menos de %{count} segundos" + x_seconds: + one: "1 segundo" + other: "%{count} segundos" + less_than_x_minutes: + one: "menos de un minuto" + other: "menos de %{count} minutos" + x_minutes: + one: "1 minuto" + other: "%{count} minutos" + about_x_hours: + one: "alrededor de 1 hora" + other: "alrededor de %{count} horas" + x_days: + one: "1 día" + other: "%{count} días" + about_x_months: + one: "alrededor de 1 mes" + other: "alrededor de %{count} meses" + x_months: + one: "1 mes" + other: "%{count} meses" + about_x_years: + one: "alrededor de 1 año" + other: "alrededor de %{count} años" + over_x_years: + one: "mas de 1 año" + other: "mas de %{count} años" + almost_x_years: + one: "casi 1 año" + other: "casi %{count} años" + prompts: + year: "Año" + month: "Mes" + day: "Día" + hour: "Hora" + minute: "Minuto" + second: "Segundos" + + helpers: + select: + prompt: "Seleccione" + + submit: + create: 'Crear %{model}' + update: 'Actualizar %{model}' + submit: 'Guardar %{model}' + + errors: + format: "%{attribute} %{message}" + + messages: &errors_messages + inclusion: "no está incluido en la lista" + exclusion: "es reservado" + invalid: "es inválido" + confirmation: "no concuerda" + accepted: "debe ser aceptado" + empty: "no puede estar vacío" + blank: "no puede estar vacío" + exists_already: 'ya existe' + too_long: "demaciado largo (maximo %{count} caracteres)" + too_short: "demaciado corto (minimo is %{count} caracteres)" + wrong_length: "longitud incorrecta (debe ser %{count} caracteres)" + not_a_number: "no es un número" + not_an_integer: "debe ser un entero" + greater_than: "debe ser mayor que %{count}" + greater_than_or_equal_to: "debe ser mayor o igual que %{count}" + equal_to: "debe ser igual a %{count}" + less_than: "debe ser menor que %{count}" + less_than_or_equal_to: "debe ser menor o igual que %{count}" + odd: "debe ser impar" + even: "debe ser par" + invalid_characters: 'no puede tener los caracteres: < > : " / \ | ? *' + + activerecord: + errors: + template: + header: + one: "1 error impidió guardar %{model}" + other: "%{count} errores impidió guardar %{model}" + body: "Los siguientes campos tienen un problema:" + + messages: + taken: "ya está en uso" + record_invalid: "Validación: %{errors}" + <<: *errors_messages + + full_messages: + format: "%{attribute} %{message}" + + models: + clipboard: Portapaleles + folder: Carpeta + group: Grupo + permission: Permisos + share_link: Compartir + user: Usuario + user_file: Archivo + + attributes: + folder: + name: Nombre + group: + name: Nombre + share_link: + emails: Correo electrónico + expires_at: Expira + user: + email: Correo + name: Usuario (sin espacios) + password: Clave + user_file: + name: Nombre + attachment_file_name: Archivo + + # APPLICATION SPECIFIC + + # general + back: Atrás + save: Guardar + name: Nombre + email: Correo + submit: Enviar + + your_changes_were_saved: Los cambios fueron guardados correctamente. + already_deleted: "%{type} ya fue borrado." + + # admins/new + create_admin: Crear admin + no_administrator_yet: El Sistema de Gestion de Archivos no tiene un administrador. Crear uno. + create_admin_account: Crear admin + admin_user_created_successfully: El administrador fue creado. Iniciar sesión. + + # clipboard/_show + folder: carpeta + file: archivo + this_folder: esta carpeta + this_file: este archivo + copy: Copiar + copy_folder: Copiar carpeta + copy_file: Copiar archivo + move: Mover + move_folder: Mover carpeta + move_file: Mover archivo + are_you_sure: Está seguro? + delete_item: Borrar + remove_from_clipboard: Borrar desde el portapepeles + clear_clipboard: Limpiar portpapeles + + # files/edit + rename_file: Renombrar archivo + + # files/new + select_file: Seleccionar archivp + upload_file: Subir archivos + upload: Subir + exists_already: ya existe + + #folders/edit + rename_folder: Renombrar Carpeta + + #folders/new + new_folder: Nueva Carpeta + + #folders/show + create_a_new_folder: Crear nueva carpeta + upload_a_file: Subir Archivos + permissions: Permisos + clipboard: Portapapeles + size: KB/MB + date_modified: Fecha modificación + up: subir + edit: Editar + add_to_clipboard: Agregar al portapapeles + download: Descargar + share: Compartir + + #groups/edit + rename_group: Renombrar grupo + + #groups/index + groups: Grupos + create_a_new_group: Crear grupo + + #groups/new + new_group: Nuevo grupo + + #permissions/form + create_permission: Crear + read_permission: Leer + update_permission: Actualizar + delete_permission: Borrar + apply_changes_to_subfolders: Aplicar cabios a las subcarpetas + + create: crear + read: leer + update: actualizar + delete: borrar + + #reset_password/edit + password: Clave + reset_password: Cambiar clave + send_email: Enviar + + #signup/edit + sign_up: Iniciar sesión + + #sessions + username: Usuario + remember_me: Recordarme + sign_in: Iniciar sesión + + #share_links/index + unshare: Descompartir + + #share_links/new + this_share_link: este enlace + share_file: Compartir archivo + you_are_about_to_share_the_following_file: Compartiendo el archivo + emails_to_share_with: Correos electrónicos a enviar el enlace + comma_seperated: Separados por comas + number_of_charachters: Número de caracteres + link_expires: Expira + tomorrow: Mañana + three_days_from_now: En 3 días + one_week_from_now: En 1 semana + ten_days_from_now: En 10 días + two_weeks_from_now: En 2 semanas + three_weeks_from_now: En 3 semanas + one_month_from_now: En 1 mes + two_months_from_now: En 2 meses + three_months_from_now: En 3 meses + half_year_from_now: En 6 meses + share_link_could_not_be_sent: El enclace no se pudo enviar + are_invalid_due_to: "%{email} es inválido" + shared_successfully: El archivo fue compartido. + + #shared/_header + hello: Usuario + settings: Configuraciones + sign_out: Desconectarse + + #shared/_menu + folders: Carpetas + users: Usuarios + shared_files: Compartir Archivos + + #users/_form + member_of_these_groups: Miembro de estos grupos + confirm_password: Confirmar clave + + #users/index + create_a_new_user: Crear usuario + active_users: Usuarios Activos + invited_users: Invitados + expiration_date: Fecha de Expiración + extend_expiration_date: Extender fecha de expiración + + #users/new + new_user: Nuevo usuario + + #admins/controller + admin_user_created_sucessfully: El administrador ha sido creado. + + #application_controller + no_permissions_for_this_type: "No tiene permisos en %{method} para %{type}." + + # clipboard_controller + added_to_clipboard: Agregado al portapapeles. + could_not_copy: "No se pudo copiar. Ya existe un %{type} con el mismo nombre." + could_not_move: "No se pudo mover. Ya existe un %{type} con el mismo nombre." + cannot_move_to_own_subfolder: No se puede mover una carpeta en la subcarpeta. + + # folders_controller + cannot_delete_root_folder: La carpeta raíz no se puede borrar o renombrar. + no_delete_permissions_for_subfolder: No tiene permisos para esta subcarpeta. + + # groups_controller + group_already_deleted: Este grupo fue borrado. + admins_group_cannot_be_deleted: El grupo admins no se puede borrar o renombrar. + + # reset_password_controller + instruction_email_sent: "Un correo fue enviado con las instrucciones a '%{email}'." + password_reset_successfully: La clave fue cambiada. + reset_url_expired: El enlace para cambiar la clave ha expirado, contacte al administrador. + + # signup_controller + signed_up_successfully: Cuenta creada. + sign_url_expired: El enlace para iniciar sesión expiró, contacte al administrador. + + # sessions_controller + credentials_incorrect: Usuario y/o clave incorrecta. + + # users_controller + user_already_deleted: Usuario borrado. + admin_user_cannot_be_deleted: El administrador no puede borrarse. + edit_user: Editar usuario + account_settings: Configuración de cuenta + + # mailers/user_mailer + signup_email_subject: 'Invitación al Sistema de Gestión de Archivos' + reset_password_email_subject: 'Gestión de Archivos: cambio de claves' + share_link_email_subject: 'Gestión de Archivos: se le ha compartido un enlace' diff --git a/config/locales/fr.yml b/config/locales/fr.yml new file mode 100644 index 0000000..9c56dc3 --- /dev/null +++ b/config/locales/fr.yml @@ -0,0 +1,401 @@ +# US English translations for Ruby on Rails +# +# Use this as the base for the locale file of your language. +# see: https://github.com/svenfuchs/rails-i18n/blob/master/rails/locale/en-US.yml + +"fr": + date: + abbr_day_names: + - dim + - lun + - mar + - mer + - jeu + - ven + - sam + abbr_month_names: + - + - jan. + - fév. + - mar. + - avr. + - mai + - juin + - juil. + - août + - sept. + - oct. + - nov. + - déc. + day_names: + - dimanche + - lundi + - mardi + - mercredi + - jeudi + - vendredi + - samedi + formats: + default: ! '%d/%m/%Y' + long: ! '%e %B %Y' + short: ! '%e %b' + month_names: + - + - janvier + - février + - mars + - avril + - mai + - juin + - juillet + - août + - septembre + - octobre + - novembre + - décembre + order: + - :day + - :month + - :year + datetime: + distance_in_words: + about_x_hours: + one: environ %{count} heure + other: environ %{count} heures + about_x_months: + one: environ %{count} mois + other: environ %{count} mois + about_x_years: + one: environ %{count} an + other: environ %{count} ans + almost_x_years: + one: presque %{count} an + other: presque %{count} ans + half_a_minute: une demi-minute + less_than_x_minutes: + one: moins de %{count} minute + other: moins de %{count} minutes + zero: moins d'une minute + less_than_x_seconds: + one: moins de %{count} seconde + other: moins de %{count} secondes + zero: moins d'une seconde + over_x_years: + one: plus de %{count} an + other: plus de %{count} ans + x_days: + one: ! '%{count} jour' + other: ! '%{count} jours' + x_minutes: + one: ! '%{count} minute' + other: ! '%{count} minutes' + x_months: + one: ! '%{count} mois' + other: ! '%{count} mois' + x_seconds: + one: ! '%{count} seconde' + other: ! '%{count} secondes' + prompts: + day: Jour + hour: Heure + minute: Minute + month: Mois + second: Seconde + year: Année + activerecord: + errors: + format: Le %{attribute} %{message} + messages: + accepted: doit être accepté(e) + blank: doit être rempli(e) + confirmation: ne concorde pas + empty: doit être rempli(e) + equal_to: doit être égal à %{count} + even: doit être pair + exclusion: n'est pas disponible + greater_than: doit être supérieur à %{count} + greater_than_or_equal_to: doit être supérieur ou égal à %{count} + inclusion: n'est pas inclus(e) dans la liste + invalid: n'est pas valide + less_than: doit être inférieur à %{count} + less_than_or_equal_to: doit être inférieur ou égal à %{count} + not_a_number: n'est pas un nombre + not_an_integer: doit être un nombre entier + odd: doit être impair + record_invalid: ! 'La validation a échoué : %{errors}' + taken: n'est pas disponible + too_long: + one: est trop long (pas plus de %{count} caractère) + other: est trop long (pas plus de %{count} caractères) + too_short: + one: est trop court (au moins %{count} caractère) + other: est trop court (au moins %{count} caractères) + wrong_length: + one: ne fait pas la bonne longueur (doit comporter %{count} caractère) + other: ne fait pas la bonne longueur (doit comporter %{count} caractères) + template: + body: ! 'Veuillez vérifier les champs suivants : ' + header: + one: ! 'Impossible d''enregistrer ce(tte) %{model} : %{count} erreur' + other: ! 'Impossible d''enregistrer ce(tte) %{model} : %{count} erreurs' + helpers: + select: + prompt: Veuillez sélectionner + submit: + create: Créer un(e) %{model} + submit: Enregistrer ce(tte) %{model} + update: Modifier ce(tte) %{model} + number: + currency: + format: + delimiter: ! ' ' + format: ! '%n %u' + precision: 2 + separator: ! ',' + significant: false + strip_insignificant_zeros: false + unit: € + format: + delimiter: ! ' ' + precision: 3 + separator: ! ',' + significant: false + strip_insignificant_zeros: false + human: + decimal_units: + format: ! '%n %u' + units: + billion: milliard + million: million + quadrillion: million de milliards + thousand: millier + trillion: billion + unit: '' + format: + delimiter: '' + precision: 2 + significant: true + strip_insignificant_zeros: true + storage_units: + format: ! '%n %u' + units: + byte: + one: octet + other: octets + gb: Go + kb: ko + mb: Mo + tb: To + percentage: + format: + delimiter: '' + precision: + format: + delimiter: '' + support: + array: + last_word_connector: ! ' et ' + two_words_connector: ! ' et ' + words_connector: ! ', ' + time: + am: am + formats: + default: ! '%d %B %Y %H:%M:%S' + long: ! '%A %d %B %Y %H:%M' + short: ! '%d %b %H:%M' + very_short: "%d %b %Y" + date_only: "%B %d, %Y" + time_only: "%H:%M" + pm: pm + + # APPLICATION SPECIFIC + + # general + back: Retour + save: Sauvegarder + name: Nom + email: Email + submit: Valider + + your_changes_were_saved: Vos modifications ont été sauvegardées. + already_deleted: "Désolé mais ce %{type} a déjà été supprimé." + + # admins/new + create_admin: Créer un admin + no_administrator_yet: Boxroom n'a pas encore d'admin. Créez-en un ici. + create_admin_account: Créer un compte admin + admin_user_created_successfully: "L'admin est maintenant créé, vous pouvez vous connecter" + + # clipboard/_show + folder: dossier + file: fichier + this_folder: ce dossier + this_file: ce fichier + copy: Copier + copy_folder: Copier dossier + copy_file: Copier fichier + move: Déplacer + move_folder: Déplacer dossier + move_file: Déplacer fichier + are_you_sure: Etes-vous sûr? + delete_item: supprimer + remove_from_clipboard: Supprimer du presse-papier + clear_clipboard: Vider le presse-papier + + # files/edit + rename_file: Renommer fichier + + # files/new + select_file: Choisir un fichier + upload_file: Déposer des fichiers + upload: Déposer + exists_already: existe déjà + + #folders/edit + rename_folder: Renommer dossier + + #folders/new + new_folder: Nouveau dossier + + #folders/show + create_a_new_folder: Créer un nouveau dossier + upload_a_file: Déposer un fichier + permissions: Permissions + clipboard: Presse-papier + size: Taille + date_modified: Date de modification + up: haut + edit: Modifier + add_to_clipboard: Ajouter au presse-papier + download: Télécharger + share: Partager + + #groups/edit + rename_group: Renommer groupe + + #groups/index + groups: Groupes + create_a_new_group: Créer un nouveau groupe + + #groups/new + new_group: Nouveau groupe + + #permissions/form + create_permission: Créer + read_permission: Lire + update_permission: Modifier + delete_permission: Supprimer + apply_changes_to_subfolders: Appliquer les changements aux sous-dossiers + + create: créer + read: lire + update: Modifier + delete: Supprimer + + #reset_password/edit + password: Mot de passe + reset_password: Réinitialiser le mot de passe + send_email: Envoyer + + #signup/edit + sign_up: Inscription + + #sessions + username: Nom d'utilisateur + remember_me: Se souvenir de moi + sign_in: Identification + + #share_links/index + shared_by: Partage par + unshare: Annuler le partage + + #share_links/new + this_share_link: ce lien de partage + share_file: Partager le fichier + you_are_about_to_share_the_following_file: Vous êtes sur le point de partager le fichier suivant + emails_to_share_with: Adresses email des personnes avec qui vous souhaitez partager + comma_seperated: Séparés par une virgule + number_of_charachters: Nombre de caractères + link_expires: Expiration + tomorrow: Demain + three_days_from_now: Dans 3 jours + one_week_from_now: Dans une semaine + ten_days_from_now: Dans 10 jours + two_weeks_from_now: Dans 2 semaines + three_weeks_from_now: Dans 3 semaines + one_month_from_now: Dans un mois + two_months_from_now: Dans 2 mois + three_months_from_now: Dans 3 mois + half_year_from_now: Dans 6 mois + share_link_could_not_be_sent: Le lien n'a pu être envoyé + are_invalid_due_to: "est invalide à cause de %{email}" + shared_successfully: Le fichier a bien été partagé. + shared_message: Message + optional: Optionnel + + #shared/_header + hello: Bonjour + settings: Réglages + sign_out: Déconnexion + + #shared/_menu + folders: Dossiers + users: Fichiers + shared_files: Fichiers partagés + + #users/_form + member_of_these_groups: Membre de ces groupes + confirm_password: Confirmer le mot de passe + + #users/index + create_a_new_user: Créer un nouvel utilisateur + active_users: Utilisateurs actifs + invited_users: Utilisateurs invités + expiration_date: Date d'expiration + extend_expiration_date: Prolonger la durée de validité + + #users/new + new_user: Nouvel utilisateur + + #admins/controller + admin_user_created_sucessfully: "L'admin est maintenant créé, vous pouvez vous connecter" + + #application_controller + no_permissions_for_this_type: "Vous n'avez pas la permission de %{method} %{type}." + + # clipboard_controller + added_to_clipboard: Ajouté au presse-papier. + could_not_copy: "Copie impossible. Un %{type} du même nom existe déjà." + could_not_move: "Déplacement impossible. A %{type} du même nom existe déjà." + cannot_move_to_own_subfolder: Vous ne pouvez pas déplacer un dossier dans un de ses sous-dossiers. + + # folders_controller + cannot_delete_root_folder: Le dossier racine ne peut pas être supprimé. + no_delete_permissions_for_subfolder: Vous n'avez pas les permissions pour un ou plusieurs sous-dossiers. + + # groups_controller + group_already_deleted: Quelqu'un d'autre a déjà supprimé ce groupe. Action annulée + admins_group_cannot_be_deleted: Le groupe admins ne peut être supprimé ni renommé. + + # reset_password_controller + instruction_email_sent: "Se '%{email}' est présent dans le système, vous allez recevoir un message avec les instructions." + password_reset_successfully: Mot de passe réinitialisé, vous pouvez maintenant vous connecter. + reset_url_expired: L'URL de réinitialisation a expiré, veuillez réessayer à nouveau. + + # signup_controller + signed_up_successfully: "Votre compte est maintenant créé, vous pouvez vous connecter" + sign_url_expired: "L'URL de confirmation a expiré, veuillez contacter l'administrateur." + + # sessions_controller + credentials_incorrect: Nom d'utilisateur ou mot de passe incorrect. Veuillez réessayer. + + # users_controller + user_already_deleted: Quelqu'un d'autre a déjà supprimé l'utilisateur. + admin_user_cannot_be_deleted: L'admin ne peut être supprimé + edit_user: Modifier utilisateur + account_settings: Profil + + # mailers/user_mailer + signup_email_subject: '[Boxroom] Invitiation à créer un compte' + reset_password_email_subject: '[Boxroom] Instructions de réinitialisation mot de passe' + share_link_email_subject: "[Boxroom] %{email} a partagé un fichier avec vous" diff --git a/config/locales/it.yml b/config/locales/it.yml new file mode 100644 index 0000000..cd14739 --- /dev/null +++ b/config/locales/it.yml @@ -0,0 +1,412 @@ +# IT Italian translations for Ruby on Rails +# Author Jessica Marcon +# Use this as the base for the locale file of your language. +# see: https://github.com/svenfuchs/rails-i18n/blob/master/rails/locale/en-US.yml + + +"it": + date: + formats: + default: "%d/%m/%Y" + short: "%d %b" + long: "%d %B %Y" + + day_names: [Domenica, Lunedì, Martedì, Mercoledì, Giovedì, Venerdì, Sabato] + abbr_day_names: [Dom, Lun, Mar, Mer, Gio, Ven, Sab] + + month_names: [~, Gennaio, Febbraio, Marzo, Aprile, Maggio, Giugno, Luglio, Agosto, Settembre, Ottobre, Novembre, Dicembre] + abbr_month_names: [~, Gen, Feb, Mar, Apr, Mag, Giu, Lug, Ago, Set, Ott, Nov, Dic] + order: + - :day + - :month + - :year + + time: + formats: + default: "%a %d %b %Y, %H:%M %:z" + short: "%d %b %Y %H:%M" + very_short: "%d %b %Y" + long: "%d %B %Y, %H:%M" + am: "am" + pm: "pm" + + support: + array: + words_connector: ", " + two_words_connector: " e " + last_word_connector: ", e " + + select: + prompt: "Seleziona" + + number: + format: + precision: 2 + separator: "," + delimiter: "." + significant: false + strip_insignificant_zeros: false + + currency: + format: + unit: "€" + format: "%u%n" + separator: "," + delimiter: "." + precision: 2 + significant: false + strip_insignificant_zeros: false + + percentage: + format: + delimiter: "" + + precision: + format: + delimiter: "" + + human: + format: + delimiter: "" + precision: 3 + significant: true + strip_insignificant_zeros: true + storage_units: + format: "%n %u" + units: + byte: + one: "Byte" + other: "Bytes" + kb: "KB" + mb: "MB" + gb: "GB" + tb: "TB" + decimal_units: + format: "%n %u" + units: + unit: "" + thousand: "Mille" + million: + one: "Milione" + others: "Milioni" + billion: + one: "Miliardo" + others: "Miliardi" + trillion: + one: "Trilione" + others: "Trilioni" + quadrillion: + one: "Quadrilione" + others: "Quadrilioni" + + datetime: + distance_in_words: + half_a_minute: "mezzo minuto" + less_than_x_seconds: + one: "meno di 1 secondo" + other: "meno di %{count} secondi" + x_seconds: + one: "1 secondo" + other: "%{count} secondi" + less_than_x_minutes: + one: "meno di un minuto" + other: "meno di %{count} minuti" + x_minutes: + one: "1 minuto" + other: "%{count} minuti" + about_x_hours: + one: "circa un'ora" + other: "circa %{count} ore" + x_days: + one: "1 giorno" + other: "%{count} giorni" + about_x_months: + one: "circa 1 mese" + other: "circa %{count} mesi" + x_months: + one: "1 mese" + other: "%{count} mese" + about_x_years: + one: "circa 1 anno" + other: "circa %{count} anni" + over_x_years: + one: "oltre 1 anno" + other: "oltre %{count} anni" + almost_x_years: + one: "quasi 1 anno" + other: "quasi %{count} anni" + prompts: + year: "Anno" + month: "Mese" + day: "Giorno" + hour: "Ora" + minute: "Minuto" + second: "Secondi" + + helpers: + select: + prompt: "Seleziona" + + submit: + create: 'Crea %{model}' + update: 'Carica %{model}' + submit: 'Salva %{model}' + + errors: + format: "%{attribute} %{message}" + + messages: &errors_messages + inclusion: "non è incluso nella lista" + exclusion: "è riservato" + invalid: "non è valido" + confirmation: "non corrisponde" + accepted: "dev'essere accettato" + empty: "non può essere vuoto" + blank: "non può essere vuoto" + exists_already: 'esiste già' + too_long: "è troppo lungo (massimo %{count} caratteri)" + too_short: "è troppo corto (minimo %{count} caratteri)" + wrong_length: "la lunghezza è sbagliata (dovrebbe essere di %{count} caratteri)" + not_a_number: "non è un numero" + not_an_integer: "deve essere un numero intero" + greater_than: "deve essere maggiore di %{count}" + greater_than_or_equal_to: "deve essere maggiore o uguale a %{count}" + equal_to: "deve essere uguale a %{count}" + less_than: "deve essere inferiore a %{count}" + less_than_or_equal_to: "deve essere inferiore o uguale a %{count}" + odd: "deve essere dispari" + even: "deve essere ancora" + invalid_characters: 'non può contenere questo tipo di carattere: < > : " / \ | ? *' + + activerecord: + errors: + template: + header: + one: "1 errore ha impedito a %{model} di essere salvato" + other: "%{count} errori hanno impedito a %{model} di essere salvato" + body: "Sono stati rilevati dei problemi con questi campi:" + + messages: + taken: "è già in uso" + record_invalid: "Validation failed: %{errors}" + <<: *errors_messages + + full_messages: + format: "%{attribute} %{message}" + + models: + clipboard: Appunti + folder: Cartella + group: Gruppo + permission: Permessi + share_link: Condividi link + user: Utente + user_file: File + + attributes: + folder: + name: Nome + group: + name: Nome + share_link: + emails: Indirizzo Email + expires_at: Scade + user: + email: Email + name: Nome + password: Password + user_file: + name: Nome + attachment_file_name: File + + # APPLICATION SPECIFIC + + # general + back: Indietro + save: Salva + name: Nome + email: Email + submit: Invia + + your_changes_were_saved: Le tue modifiche sono state salvate con successo. + already_deleted: "Qualcuno ha cancellato %{type}. Azione non valida." + + # admins/new + create_admin: Crea amministratore + no_administrator_yet: "Boxroom non ha ancora un amministratore: aggiungilo ora." + create_admin_account: Crea account amministratore + admin_user_created_successfully: "L'utente amministratore è stato aggiunto con successo! Ora puoi accedere." + + # clipboard/_show + folder: cartella + file: file + this_folder: questa cartella + this_file: questo file + copy: Copia + copy_folder: Copia cartella + copy_file: Copia file + move: Sposta + move_folder: Sposta cartella + move_file: Sposta file + are_you_sure: Sei sicuro? + delete_item: Elimina + remove_from_clipboard: Elimina dagli appunti + clear_clipboard: Cancella appunti + + # files/edit + rename_file: Rinomina file + + # files/new + select_file: Seleziona file + upload_file: Carica file + upload: Carica + exists_already: esiste già + + #folders/edit + rename_folder: Rinomina cartella + + #folders/new + new_folder: Nuova cartella + + #folders/show + create_a_new_folder: Crea una nuova cartella + upload_a_file: Carica file + permissions: Permessi + clipboard: Appunti + size: Dimensione + date_modified: Data modifica + up: up + edit: Modifica + add_to_clipboard: Copia negli appunti + download: Scarica + share: Condividi + + #groups/edit + rename_group: Rinomina gruppo + + #groups/index + groups: Gruppi + create_a_new_group: Aggiungi un nuovo gruppo + + #groups/new + new_group: Nuovo gruppo + + #permissions/form + create_permission: Crea + read_permission: Lettura + update_permission: Modifica + delete_permission: Elimina + apply_changes_to_subfolders: Applica modifiche alle sottocartelle + + create: crea + read: lettura + update: modifica + delete: elimina + + #reset_password/edit + password: Password + reset_password: Modifica password + send_email: Invia + + #signup/edit + sign_up: Sign up + + #sessions + username: Username + remember_me: Ricordami + sign_in: Accedi + + #share_links/index + shared_by: Condiviso da + unshare: Annulla la condivisione + + #share_links/new + this_share_link: this share link + share_file: Condividi file + you_are_about_to_share_the_following_file: Stai per condividere il seguente file + emails_to_share_with: Inserisci gli indirizzi email con i quali vuoi condividere il file + comma_seperated: Separati da una virgola + number_of_charachters: Numero di caratteri + link_expires: Scadenza + tomorrow: Domani + three_days_from_now: Tre giorni da adesso + one_week_from_now: Una settimana da adesso + ten_days_from_now: Dieci giorni da adesso + two_weeks_from_now: Due settimane da adesso + three_weeks_from_now: Tre settimane da adesso + one_month_from_now: Un mese da adesso + two_months_from_now: Due mesi da adesso + three_months_from_now: Tre mesi da adesso + half_year_from_now: Sei mesi da adesso + share_link_could_not_be_sent: Il link per il download non è stato inviato + are_invalid_due_to: " %{email} non è valido" + shared_successfully: Il file è stato condiviso con successo. + shared_message: Messaggio + optional: Opzionale + + #shared/_header + hello: Salve + settings: Impostazioni + sign_out: Esci + + #shared/_menu + folders: Cartelle + users: Utenti + shared_files: Condivisione file + + #users/_form + member_of_these_groups: Membro di questi gruppi + confirm_password: Conferma password + + #users/index + create_a_new_user: Aggiungi un nuovo utente + active_users: Active users + invited_users: Invited users + expiration_date: Expiration date + extend_expiration_date: Extend expiration date + + #users/new + new_user: Nuovo utente + + #admins/controller + admin_user_created_sucessfully: "L'utente amministratore è stato aggiunto con successo! Ora puoi accedere." + + #application_controller + no_permissions_for_this_type: "Non hai %{method} i permessi per %{type}." + + # clipboard_controller + added_to_clipboard: Aggiunto con successo negli appunti. + could_not_copy: "Non puoi copiare. Il %{type} con lo stesso nome esiste già." + could_not_move: "Non puoi spostare. Il %{type} con lo stesso nome esiste già." + cannot_move_to_own_subfolder: Non puoi spostare la cartella nella propria sottocartella. + + # folders_controller + cannot_delete_root_folder: La cartella principale non può essere cancellata o rinominata. + no_delete_permissions_for_subfolder: "Non hai il permesso di cancellare una sottocartella." + + # groups_controller + group_already_deleted: Qualcuno ha cancellato questo gruppo. Azione non valida. + admins_group_cannot_be_deleted: Il gruppo amministratore non può essere cancellato o rinominato. + + # reset_password_controller + instruction_email_sent: "L'email con le istruzioni è stata inviata. Controlla la tua email." + password_reset_successfully: La password è stata modificata con successo. Ora puoi accedere. + reset_url_expired: Il link per cambiare la password è scaduto. Riprova. + + # signup_controller + signed_up_successfully: Account created successfully. You can now sign in. + sign_url_expired: The URL for signing up expired. Please contact the administrator. + + # sessions_controller + credentials_incorrect: "Username e/o password errati. Riprova." + + # users_controller + user_already_deleted: "Qualcuno ha cancellato l'utente. Azione non valida." + admin_user_cannot_be_deleted: "L'utente amministratore non può essere cancellato." + edit_user: Inserisci utente + account_settings: Impostazioni account + + # mailers/user_mailer + signup_email_subject: '[Boxroom] Sign up invitation' + share_link_email_subject: '[Boxroom] %{email} ha condiviso un file con te' + reset_password_email_subject: '[Boxroom] Istruzioni per modificare la password' diff --git a/config/locales/nl.yml b/config/locales/nl.yml new file mode 100644 index 0000000..2a6093d --- /dev/null +++ b/config/locales/nl.yml @@ -0,0 +1,406 @@ +# Dutch translations for Ruby on Rails, based on US English template +# Original version by Ariejan de Vroom +# - Sponsored by Kabisa ICT - http://kabisa.nl +# Rails 3 update by Floris Huetink (github: florish) + +nl: + date: + formats: + default: "%d/%m/%Y" + short: "%e %b" + long: "%e %B %Y" + only_day: "%e" + + day_names: [zondag, maandag, dinsdag, woensdag, donderdag, vrijdag, zaterdag] + abbr_day_names: [zon, maa, din, woe, don, vri, zat] + + month_names: [~, januari, februari, maart, april, mei, juni, juli, augustus, september, oktober, november, december] + abbr_month_names: [~, jan, feb, mar, apr, mei, jun, jul, aug, sep, okt, nov, dec] + order: + - :day + - :month + - :year + + time: + formats: + default: "%a %d %b %Y %H:%M:%S %Z" + short: "%d %b %Y %H:%M" + very_short: "%d %b %Y" + long: "%d %B %Y %H:%M" + time: "%H:%M" + only_second: "%S" + am: "'s ochtends" + pm: "'s middags" + + support: + array: + words_connector: ", " + two_words_connector: " en " + last_word_connector: " en " + + select: + prompt: "Selecteer" + + number: + format: + separator: "," + delimiter: "." + precision: 2 + significant: false + strip_insignificant_zeros: false + + currency: + format: + format: "%u%n" + unit: "€" + separator: "," + delimiter: "." + precision: 2 + significant: false + strip_insignificant_zeros: false + + percentage: + format: + delimiter: "" + + precision: + format: + delimiter: "" + + human: + format: + delimiter: "" + precision: 3 + significant: true + strip_insignificant_zeros: true + storage_units: + format: "%n %u" + units: + byte: + one: "Byte" + other: "Bytes" + kb: "KB" + mb: "MB" + gb: "GB" + tb: "TB" + decimal_units: + format: "%n %u" + units: + unit: "" + thousand: "duizend" + million: "miljoen" + billion: "miljard" + trillion: "biljoen" + quadrillion: "biljard" + + datetime: + distance_in_words: + half_a_minute: "een halve minuut" + less_than_x_seconds: + one: "minder dan \xC3\xA9\xC3\xA9n seconde" + other: "minder dan %{count} seconden" + x_seconds: + one: "1 seconde" + other: "%{count} seconden" + less_than_x_minutes: + one: "minder dan \xC3\xA9\xC3\xA9n minuut" + other: "minder dan %{count} minuten" + x_minutes: + one: "1 minuut" + other: "%{count} minuten" + about_x_hours: + one: "ongeveer \xC3\xA9\xC3\xA9n uur" + other: "ongeveer %{count} uur" + x_days: + one: "1 dag" + other: "%{count} dagen" + about_x_months: + one: "ongeveer \xC3\xA9\xC3\xA9n maand" + other: "ongeveer %{count} maanden" + x_months: + one: "1 maand" + other: "%{count} maanden" + about_x_years: + one: "ongeveer \xC3\xA9\xC3\xA9n jaar" + other: "ongeveer %{count} jaar" + over_x_years: + one: "meer dan \xC3\xA9\xC3\xA9n jaar" + other: "meer dan %{count} jaar" + almost_x_years: + one: "bijna \xC3\xA9\xC3\xA9n jaar" + other: "bijna %{count} jaar" + prompts: + year: "jaar" + month: "maand" + day: "dag" + hour: "uur" + minute: "minuut" + second: "seconde" + + helpers: + select: + prompt: "Selecteer" + + submit: + create: '%{model} toevoegen' + update: '%{model} opslaan' + submit: '%{model} opslaan' + + errors: + format: "%{attribute} %{message}" + + messages: &errors_messages + inclusion: "is niet in de lijst opgenomen" + exclusion: "is niet beschikbaar" + invalid: "is ongeldig" + confirmation: "klopt niet" + accepted: "moet worden geaccepteerd" + empty: " mag niet leeg zijn" + blank: "mag niet leeg zijn" + exists_already: 'bestaat al' + too_long: "is te lang (maximaal %{count} tekens)" + too_short: "is te kort (minimaal %{count} tekens)" + wrong_length: "heeft onjuiste lengte (moet %{count} tekens lang zijn)" + not_a_number: "is geen getal" + not_an_integer: "moet een geheel getal zijn" + greater_than: "moet groter zijn dan %{count}" + greater_than_or_equal_to: "moet groter dan of gelijk zijn aan %{count}" + equal_to: "moet gelijk zijn aan %{count}" + less_than: "moet minder zijn dan %{count}" + less_than_or_equal_to: "moet minder dan of gelijk zijn aan %{count}" + odd: "moet oneven zijn" + even: "moet even zijn" + invalid_characters: 'mag geen van deze tekens bevatten: < > : " / \ | ? *' + + activerecord: + errors: + template: + header: + one: "1 fout gevonden: %{model} niet opgeslagen" + other: "%{count} fouten gevonden: %{model} niet opgeslagen" + body: "Controleer de volgende velden:" + + messages: + taken: "is al in gebruik" + record_invalid: "Validatie mislukt: %{errors}" + <<: *errors_messages + + full_messages: + format: "%{attribute} %{message}" + + models: + clipboard: Klembord + folder: Map + group: Groep + permission: Bevoegdheid + share_link: Gedeelde link + user: Gebruiker + user_file: Bestand + + attributes: + folder: + name: Naam + group: + name: Naam + share_link: + emails: E-mailadressen + expires_at: Vervaldatum + user: + email: E-mail + name: Naam + password: Wachtwoord + user_file: + name: Naam + attachment_file_name: Bestand + + # APPLICATION SPECIFIC + + # general + back: Terug + save: Opslaan + name: Naam + email: E-mail + submit: Opslaan + + your_changes_were_saved: Uw wijzigingen zijn opgeslagen. + already_deleted: "Iemand heeft %{type} reeds verwijderd." + + # admins/new + create_admin: Admin aanmaken + no_administrator_yet: Boxroom heeft nog geen administrator. Deze kunt u nu aanmaken. + create_admin_account: Admin gebruiker aanmaken + admin_user_created_successfully: De admin gebruiker is aangemaakt. U kunt nu inloggen. + + # clipboard/_show + folder: map + file: bestand + this_folder: deze map + this_file: dit bestand + copy: Kopieer + copy_folder: Map kopiëren + copy_file: Bestand kopiëren + move: Verplaatsen + move_folder: Map verplaatsen + move_file: Bestand verplaatsen + are_you_sure: Weet u het zeker? + delete_item: Verwijderen + remove_from_clipboard: Verwijder van klembord + clear_clipboard: Klembord legen + + # files/edit + rename_file: Bestandsnaam wijzigen + + # files/new + select_file: Selecteer bestand + upload_file: Bestanden uploaden + upload: Uploaden + exists_already: bestaat al + + #folders/edit + rename_folder: Mapnaam wijzigen + + #folders/new + new_folder: Nieuwe map + + #folders/show + create_a_new_folder: Nieuwe map aanmaken + upload_a_file: Bestanden uploaden + permissions: Bevoegdheden + clipboard: Klembord + size: Grootte + date_modified: Datum gewijzigd + up: omhoog + edit: Wijzigen + add_to_clipboard: Op klembord plaatsen + download: Download + share: Delen + + #groups/edit + rename_group: Groepnaam wijzigen + + #groups/index + groups: Groepen + create_a_new_group: Nieuwe groep aanmaken + + #groups/new + new_group: Nieuwe groep + + #permissions/form + create_permission: Aanmaken + read_permission: Lezen + update_permission: Wijzigen + delete_permission: Verwijderen + apply_changes_to_subfolders: Toepassen op submappen + + create: aanmaak + read: lees + update: wijzig + delete: verwijder + + #reset_password/edit + password: Wachtwoord + reset_password: Wachtwoord resetten + send_email: Verzenden + + #signup/edit + sign_up: Aanmelden + + #sessions + username: Gebruikersnaam + remember_me: Onthoud mij + sign_in: Inloggen + + #share_links/index + shared_by: Gedeeld door + unshare: Delen ongedaan maken + + #share_links/new + this_share_link: this share link + share_file: Bestand delen + you_are_about_to_share_the_following_file: U staat op het punt het volgende bestand te delen + emails_to_share_with: E-mailadressen van de mensen waarmee u dit bestand wilt delen + comma_seperated: Gescheiden door komma's + number_of_charachters: Aantal tekens + link_expires: Vervaldatum + tomorrow: Morgen + three_days_from_now: Over drie dagen + one_week_from_now: Over een week + ten_days_from_now: Over tien dagen + two_weeks_from_now: Over twee weken + three_weeks_from_now: Over drie weken + one_month_from_now: Over een maand + two_months_from_now: Over twee maanden + three_months_from_now: Over drie maanden + half_year_from_now: Over een half jaar + share_link_could_not_be_sent: De download link kon niet verstuurd worden + are_invalid_due_to: "is ongeldig vanwege %{email}" + shared_successfully: De download link is verstuurd. + shared_message: Bericht + optional: Niet verplicht + + #shared/_header + hello: Hallo + settings: Instellingen + sign_out: Uitloggen + + #shared/_menu + folders: Mappen + users: Gebruikers + shared_files: Gedeelde bestanden + + #users/_form + member_of_these_groups: Lid van deze groepen + confirm_password: Bevestig wachtwoord + + #users/index + create_a_new_user: Nieuwe gebruiker aanmaken + active_users: Actieve gebruikers + invited_users: Uitgenodigde gebruikers + expiration_date: Vervaldatum + extend_expiration_date: Vervaldatum uitstellen + + #users/new + new_user: Nieuwe gebruiker + + #admins/controller + admin_user_created_sucessfully: De admin gebruiker is aangemaakt. U kunt nu inloggen. + + #application_controller + no_permissions_for_this_type: "U heeft geen %{method} bevoegdheden voor %{type}." + + # clipboard_controller + added_to_clipboard: Succesvol toegevoegd aan klembord. + could_not_copy: "Kopiëren mislukt. Een %{type} met dezelfde naam bestaat al." + could_not_move: "Verplaatsen mislukt. Een %{type} met dezelfde naam bestaat al." + cannot_move_to_own_subfolder: U kunt een map niet verplaatsen naar zijn eigen submap. + + # folders_controller + cannot_delete_root_folder: Root folder kan niet verwijderd of gewijzigd worden. + no_delete_permissions_for_subfolder: U heeft geen bevoegdheden om één van de submappen te verwijderen. + + # groups_controller + group_already_deleted: Iemand anders heeft deze groep verwijderd. De actie is afgebroken. + admins_group_cannot_be_deleted: De admin groep kan niet verwijderd of gewijzigd worden. + + # reset_password_controller + instruction_email_sent: "Een e-mail met instructies is verzonden als '%{email}' aanwezig is in ons systeem." + password_reset_successfully: Uw wachtwoord is gereset. U kunt nu inloggen. + reset_url_expired: De URL om uw wachtwoord te resetten is ongeldig. Probeer het nogmaals. + + # signup_controller + signed_up_successfully: Account aangemaakt. U kunt nu inloggen. + sign_url_expired: The URL om aan te melden is ongeldig. Neem contact op met de administrator. + + # sessions_controller + credentials_incorrect: Gebruikersnaam en/of wachtwoord was incorrect. Probeer het nogmaals. + + # users_controller + user_already_deleted: Iemand anders heeft deze gebruiker verwijderd. De actie is afgebroken. + admin_user_cannot_be_deleted: De admin gebruiker kan niet verwijderd worden. + edit_user: Gebruiker wijzigen + account_settings: Mijn instellingen + + # mailers/user_mailer + signup_email_subject: '[Boxroom] Uitnodiging om aan te melden' + reset_password_email_subject: '[Boxroom] Instructies om uw wachtwoord te resetten' + share_link_email_subject: '[Boxroom] %{email} heeft een bestand met u gedeeld' diff --git a/config/locales/zh-CN.yml b/config/locales/zh-CN.yml new file mode 100644 index 0000000..fabde23 --- /dev/null +++ b/config/locales/zh-CN.yml @@ -0,0 +1,404 @@ +# Simplified Chinese translations + +# The base of this locale file is https://github.com/svenfuchs/rails-i18n/blob/master/rails/locale/zh-CN.yml + +"zh-CN": + date: + formats: + default: "%Y-%m-%d" + short: "%b%d日" + long: "%Y年%b%d日" + + day_names: [星期天, 星期一, 星期二, 星期三, 星期四, 星期五, 星期六] + abbr_day_names: [周日, 周一, 周二, 周三, 周四, 周五, 周六] + + month_names: [~, 1月, 2月, 3月, 4月, 5月, 6月, 7月, 8月, 9月, 10月, 11月, 12月] + abbr_month_names: [~, 1月, 2月, 3月, 4月, 5月, 6月, 7月, 8月, 9月, 10月, 11月, 12月] + order: + - :year + - :month + - :day + + time: + formats: + default: "%a, %Y年%B%d日 %H:%M:%S %z" + short: "%Y年%B%d日 %H:%M" + very_short: "%Y年%B%d日" + long: "%Y年%B%d日 %H:%M" + date_only: "%Y年%B%d日" + time_only: "%H:%M" + am: 上午 + pm: 下午 + + support: + array: + words_connector: "," + two_words_connector: "和" + last_word_connector: ",和" + + select: + prompt: "请选择" + + number: + format: + separator: "." + delimiter: "," + precision: 3 + significant: false + strip_insignificant_zeros: false + + currency: + format: + format: "%u%n" + unit: "¥" + separator: "." + delimiter: "," + precision: 2 + significant: false + strip_insignificant_zeros: false + + percentage: + format: + delimiter: "" + + precision: + format: + delimiter: "" + + human: + format: + delimiter: "" + precision: 3 + significant: true + strip_insignificant_zeros: true + storage_units: + format: "%n %u" + units: + byte: + one: "字节" + other: "字节" + kb: "KB" + mb: "MB" + gb: "GB" + tb: "TB" + decimal_units: + format: "%n %u" + units: + unit: "" + thousand: 千 + million: 百万 + billion: 十亿 + trillion: 万亿 + quadrillion: 千万亿 + + datetime: + distance_in_words: + half_a_minute: "半分钟" + less_than_x_seconds: + one: "不到1秒" + other: "不到%{count}秒" + x_seconds: + one: "1秒" + other: "%{count}秒" + less_than_x_minutes: + one: "不到1分钟" + other: "不到%{count}分钟" + x_minutes: + one: "1分钟" + other: "%{count}分钟" + about_x_hours: + one: "大约1小时" + other: "大约%{count}小时" + x_days: + one: "1天" + other: "%{count}天" + about_x_months: + one: "大约1月" + other: "大约%{count}月" + x_months: + one: "1月" + other: "%{count}月" + about_x_years: + one: "大约1年" + other: "大约%{count}年" + over_x_years: + one: "1年多" + other: "%{count}年多" + almost_x_years: + one: "大约1年" + other: "大约%{count}年" + prompts: + year: "年" + month: "月" + day: "日" + hour: "时" + minute: "分" + second: "秒" + + helpers: + select: + prompt: "请选择" + + submit: + create: '新建%{model}' + update: '更新%{model}' + submit: '提交%{model}' + + errors: + format: "%{attribute} %{message}" + + messages: &errors_messages + inclusion: "不包含于列表中" + exclusion: "是保留关键字" + invalid: "是无效的" + confirmation: "不一致" + accepted: "必须同意" + empty: "不能为空" + blank: "不能为空" + exists_already: '已经存在' + too_long: "太长(最多%{count}字节)" + too_short: "太短(至少%{count}字节)" + wrong_length: "长度不对(应该是%{count}字节)" + not_a_number: "不是数字" + not_an_integer: "必须是整数" + greater_than: "必须大于%{count}" + greater_than_or_equal_to: "必须大于或等于%{count}" + equal_to: "必须等于%{count}" + less_than: "必须小于%{count}" + less_than_or_equal_to: "必须小于或等于%{count}" + odd: "必须是单数" + even: "必须是双数" + invalid_characters: '不能包括这些字符: < > : " / \ | ? *' + + activerecord: + errors: + template: + header: + one: "有1个错误导致%{model}无法被保存" + other: "有%{count}个错误发生导致%{model}无法被保存" + body: "如下字段出现错误" + + messages: + taken: "已经被使用" + record_invalid: "验证失败: %{errors}" + <<: *errors_messages + + full_messages: + format: "%{attribute} %{message}" + + models: + clipboard: 剪贴板 + folder: 文件夹 + group: 群组 + permission: 权限 + share_link: 共享链接 + user: 用户 + user_file: 文件 + + attributes: + folder: + name: 名称 + group: + name: 名称 + share_link: + emails: 邮箱 + expires_at: 失效期 + user: + email: 邮箱 + name: 用户名 + password: 密码 + user_file: + name: 文件名 + attachment_file_name: 文件 + + # APPLICATION SPECIFIC + + # general + back: 返回 + save: 保存 + name: 名字 + email: 邮箱 + submit: 提交 + + your_changes_were_saved: "你的修改已保存" + already_deleted: "对不起, 但是%{type}已被删掉了." + + # admins/new + create_admin: 新增管理员 + no_administrator_yet: Boxroom还没有管理员。请在此新增一个。 + create_admin_account: 新增管理员户头 + admin_user_created_successfully: 管理员户头已添加成功。您可以登录了。 + + # clipboard/_show + folder: 文件夹 + file: 文件 + this_folder: 此文件夹 + this_file: 此文件 + copy: 拷贝 + copy_folder: 拷贝文件夹 + copy_file: 拷贝文件 + move: 移动 + move_folder: 移动文件夹 + move_file: 移动文件 + are_you_sure: 您确定? + delete_item: 删除 + remove_from_clipboard: 从剪贴板删除 + clear_clipboard: 清空剪贴板 + + # files/edit + rename_file: 重新命名文件 + + # files/new + select_file: 选择文件 + upload_file: 上传文件 + upload: 上传 + exists_already: 已存在 + + #folders/edit + rename_folder: 重新命名文件夹 + + #folders/new + new_folder: 新文件夹 + + #folders/show + create_a_new_folder: 新增新文件夹 + upload_a_file: 上传文件 + permissions: 权限 + clipboard: 剪贴板 + size: 大小 + date_modified: 修改日期 + up: 上一层 + edit: 编辑 + add_to_clipboard: 加到剪贴板 + download: 下载 + share: 共享 + + #groups/edit + rename_group: 群组重新命名 + + #groups/index + groups: 群组 + create_a_new_group: 新增群组 + + #groups/new + new_group: 新群组 + + #permissions/form + create_permission: 新增 + read_permission: 可读 + update_permission: 可写 + delete_permission: 删除 + apply_changes_to_subfolders: 应用到所有子文件夹 + + create: 新增 + read: 读 + update: 写 + delete: 删除 + + #reset_password/edit + password: 密码 + reset_password: 重设密码 + send_email: 发送 + + #signup/edit + sign_up: 注册 + + #sessions + username: 用户名 + remember_me: 记住我 + sign_in: 登录 + + #share_links/index + shared_by: 共享人 + unshare: 撤销共享 + + #share_links/new + this_share_link: 这个共享链接 + share_file: 共享文件 + you_are_about_to_share_the_following_file: 您就要共享以下文件 + emails_to_share_with: 您想与之共享文件的人的邮箱地址 + comma_seperated: 由逗号分隔的 + number_of_charachters: 字数 + link_expires: 过期 + tomorrow: 明天 + three_days_from_now: 三天后 + one_week_from_now: 一星期后 + ten_days_from_now: 两天后 + two_weeks_from_now: 两星期后 + three_weeks_from_now: 三个星期后 + one_month_from_now: 一个月后 + two_months_from_now: 两个月后 + three_months_from_now: 三个月后 + half_year_from_now: 半年后 + share_link_could_not_be_sent: 不能发送出下载链接 + are_invalid_due_to: "因%{email}而无效" + shared_successfully: 成功共享文件 + shared_message: 消息 + optional: 可选 + + #shared/_header + hello: 您好 + settings: 设置 + sign_out: 退出 + + #shared/_menu + folders: 文件夹 + users: 用户 + shared_files: 共享的文件 + + #users/_form + member_of_these_groups: 属于群组 + confirm_password: 确认密码 + + #users/index + create_a_new_user: 新增用户 + active_users: 已激活的用户 + invited_users: 已邀请的用户 + expiration_date: 失效期 + extend_expiration_date: 推迟失效期 + + #users/new + new_user: 新用户 + + #admins/controller + admin_user_created_sucessfully: 管理员用户已添加好。可以登录了。 + + #application_controller + no_permissions_for_this_type: "您没有对%{type}的%{method}权限." + + # clipboard_controller + added_to_clipboard: 已成功添加到剪贴板。 + could_not_copy: "不能拷贝。同样名字的%{type}已存在。" + could_not_move: "不能移动。同样名字的%{type}已存在。" + cannot_move_to_own_subfolder: 您不能把文件夹放到其子文件夹里。 + + # folders_controller + cannot_delete_root_folder: 根文件夹不能删除或重新命名。 + no_delete_permissions_for_subfolder: 您没有删除其中某个子文件夹的权限。 + + # groups_controller + group_already_deleted: 有人已删掉此群组。您的操作已被撤销。 + admins_group_cannot_be_deleted: 管理员群组不能被删掉。 + + # reset_password_controller + instruction_email_sent: "如果'%{email}'在本系统中,我们会发出邮件告诉您如何重设密码。" + password_reset_successfully: 您的密码已成功重设。您可以登录了。 + reset_url_expired: 这个重设密码的网址已失效。请重试。 + + # signup_controller + signed_up_successfully: 户头注册成功。您可以登录了。 + sign_url_expired: 这个注册户头的网址已失效。请联系管理员。 + + # sessions_controller + credentials_incorrect: 用户名或密码不正确。请重试。 + + # users_controller + user_already_deleted: 有人已删掉此用户。您的操作已被撤销。 + admin_user_cannot_be_deleted: 此管理员不能被删除。 + edit_user: 编辑用户 + account_settings: 用户设置 + + # mailers/user_mailer + signup_email_subject: '[Boxroom] 注册邀请' + reset_password_email_subject: '[Boxroom] 重设密码的步骤' + share_link_email_subject: '[Boxroom] %{email}与您共享了文件' diff --git a/config/routes.rb b/config/routes.rb new file mode 100644 index 0000000..41723ea --- /dev/null +++ b/config/routes.rb @@ -0,0 +1,43 @@ +Boxroom::Engine.routes.draw do + get '/file_exists', :to => 'files#exists' + get '/signin', :to => 'sessions#new', :as => 'signin' + delete '/signout', :to => 'sessions#destroy' + + # Resources + resources :admins, :only => [:new, :create] + resources :sessions, :only => [:new, :create, :destroy] + resources :reset_password, :except => [:index, :show, :destroy] + resources :signup, :only => [:edit, :update] + resources :groups, :except => :show + resources :files, :except => [:index, :new, :create] + resources :share_links, :only => [:index, :show, :destroy] + + resources :users, :except => :show do + put :extend, :on => :member + end + + resources :clipboard, :only => [:create, :destroy] do + post :copy, :on => :member + post :move, :on => :member + put :reset, :on => :member + end + + # Update a collection of permissions + resources :permissions, :only => :update_multiple do + put :update_multiple, :on => :collection + end + + # Nested resources + resources :folders, :shallow => true, :except => [:new, :create] do + resources :folders, :only => [:new, :create] + resources :files, :only => [:new, :create] + end + + resources :files, :shallow => :true, :only => :show do + resources :share_links, :only => [:new, :create] + end + + # You can have the root of your site routed with "root" + # just remember to delete public/index.html. + root :to => "folders#index" +end diff --git a/db/migrate/20100930062939_create_users.rb b/db/migrate/20100930062939_create_users.rb new file mode 100644 index 0000000..aec191a --- /dev/null +++ b/db/migrate/20100930062939_create_users.rb @@ -0,0 +1,20 @@ +class CreateUsers < ActiveRecord::Migration + def self.up + create_table :boxroom_users do |t| + t.string :name + t.string :email + t.string :hashed_password + t.string :password_salt + t.string :is_admin + t.string :access_key + t.string :remember_token + t.string :reset_password_token + t.datetime :reset_password_token_expires_at + t.timestamps + end + end + + def self.down + drop_table :boxroom_users + end +end diff --git a/db/migrate/20100930091426_create_folders.rb b/db/migrate/20100930091426_create_folders.rb new file mode 100644 index 0000000..19490b4 --- /dev/null +++ b/db/migrate/20100930091426_create_folders.rb @@ -0,0 +1,14 @@ +class CreateFolders < ActiveRecord::Migration + def self.up + create_table :boxroom_folders do |t| + t.string :name + t.references :user + t.references :parent + t.timestamps + end + end + + def self.down + drop_table :boxroom_folders + end +end diff --git a/db/migrate/20100930091451_create_groups.rb b/db/migrate/20100930091451_create_groups.rb new file mode 100644 index 0000000..3200872 --- /dev/null +++ b/db/migrate/20100930091451_create_groups.rb @@ -0,0 +1,12 @@ +class CreateGroups < ActiveRecord::Migration + def self.up + create_table :boxroom_groups do |t| + t.string :name + t.timestamps + end + end + + def self.down + drop_table :boxroom_groups + end +end diff --git a/db/migrate/20101002122244_create_user_files.rb b/db/migrate/20101002122244_create_user_files.rb new file mode 100644 index 0000000..9740141 --- /dev/null +++ b/db/migrate/20101002122244_create_user_files.rb @@ -0,0 +1,17 @@ +class CreateUserFiles < ActiveRecord::Migration + def self.up + create_table :boxroom_user_files do |t| + t.string :attachment_file_name + t.string :attachment_content_type + t.integer :attachment_file_size + t.datetime :attachment_updated_at + t.references :folder + t.references :user + t.timestamps + end + end + + def self.down + drop_table :boxroom_user_files + end +end diff --git a/db/migrate/20101005071402_create_permissions.rb b/db/migrate/20101005071402_create_permissions.rb new file mode 100644 index 0000000..615d0e5 --- /dev/null +++ b/db/migrate/20101005071402_create_permissions.rb @@ -0,0 +1,16 @@ +class CreatePermissions < ActiveRecord::Migration + def self.up + create_table :boxroom_permissions do |t| + t.references :folder + t.references :group + t.boolean :can_create + t.boolean :can_read + t.boolean :can_update + t.boolean :can_delete + end + end + + def self.down + drop_table :boxroom_permissions + end +end diff --git a/db/migrate/20101005071508_create_groups_users.rb b/db/migrate/20101005071508_create_groups_users.rb new file mode 100644 index 0000000..cc1839f --- /dev/null +++ b/db/migrate/20101005071508_create_groups_users.rb @@ -0,0 +1,12 @@ +class CreateGroupsUsers < ActiveRecord::Migration + def self.up + create_table :boxroom_groups_users, :id => false do |t| + t.references :group + t.references :user + end + end + + def self.down + drop_table :boxroom_groups_users + end +end diff --git a/db/migrate/20110106045148_drop_column_user_id_from_folders.rb b/db/migrate/20110106045148_drop_column_user_id_from_folders.rb new file mode 100644 index 0000000..6c50a73 --- /dev/null +++ b/db/migrate/20110106045148_drop_column_user_id_from_folders.rb @@ -0,0 +1,9 @@ +class DropColumnUserIdFromFolders < ActiveRecord::Migration + def self.up + remove_column :boxroom_folders, :user_id + end + + def self.down + add_column :boxroom_folders, :user_id, :integer + end +end diff --git a/db/migrate/20110106045414_drop_column_user_id_from_user_files.rb b/db/migrate/20110106045414_drop_column_user_id_from_user_files.rb new file mode 100644 index 0000000..ae392f7 --- /dev/null +++ b/db/migrate/20110106045414_drop_column_user_id_from_user_files.rb @@ -0,0 +1,9 @@ +class DropColumnUserIdFromUserFiles < ActiveRecord::Migration + def self.up + remove_column :boxroom_user_files, :user_id + end + + def self.down + add_column :boxroom_user_files, :user_id, :integer + end +end diff --git a/db/migrate/20110529123402_drop_column_access_key_from_users.rb b/db/migrate/20110529123402_drop_column_access_key_from_users.rb new file mode 100644 index 0000000..37b5fcb --- /dev/null +++ b/db/migrate/20110529123402_drop_column_access_key_from_users.rb @@ -0,0 +1,9 @@ +class DropColumnAccessKeyFromUsers < ActiveRecord::Migration + def self.up + remove_column :boxroom_users, :access_key + end + + def self.down + add_column :boxroom_users, :access_key, :string + end +end diff --git a/db/migrate/20110616215033_create_share_links.rb b/db/migrate/20110616215033_create_share_links.rb new file mode 100644 index 0000000..70a7c60 --- /dev/null +++ b/db/migrate/20110616215033_create_share_links.rb @@ -0,0 +1,15 @@ +class CreateShareLinks < ActiveRecord::Migration + def self.up + create_table :boxroom_share_links do |t| + t.string :emails + t.string :link_token + t.datetime :link_expires_at + t.references :user_file + t.timestamps + end + end + + def self.down + drop_table :boxroom_share_links + end +end diff --git a/db/migrate/20120411075110_add_column_signup_token_to_users.rb b/db/migrate/20120411075110_add_column_signup_token_to_users.rb new file mode 100644 index 0000000..b57069e --- /dev/null +++ b/db/migrate/20120411075110_add_column_signup_token_to_users.rb @@ -0,0 +1,8 @@ +class AddColumnSignupTokenToUsers < ActiveRecord::Migration + def change + change_table :boxroom_users do |t| + t.string :signup_token + t.index :signup_token + end + end +end diff --git a/db/migrate/20120411081345_add_column_signup_token_expires_at_to_users.rb b/db/migrate/20120411081345_add_column_signup_token_expires_at_to_users.rb new file mode 100644 index 0000000..278b561 --- /dev/null +++ b/db/migrate/20120411081345_add_column_signup_token_expires_at_to_users.rb @@ -0,0 +1,7 @@ +class AddColumnSignupTokenExpiresAtToUsers < ActiveRecord::Migration + def change + change_table :boxroom_users do |t| + t.datetime :signup_token_expires_at + end + end +end diff --git a/db/migrate/20130307082111_alter_column_type_is_admin_from_users.rb b/db/migrate/20130307082111_alter_column_type_is_admin_from_users.rb new file mode 100644 index 0000000..786190a --- /dev/null +++ b/db/migrate/20130307082111_alter_column_type_is_admin_from_users.rb @@ -0,0 +1,9 @@ +class AlterColumnTypeIsAdminFromUsers < ActiveRecord::Migration + def self.up + change_column :boxroom_users, :is_admin, :boolean + end + + def self.down + change_column :boxroom_users, :is_admin, :string + end +end diff --git a/db/migrate/20130626210927_add_columns_message_user_id_to_share_links.rb b/db/migrate/20130626210927_add_columns_message_user_id_to_share_links.rb new file mode 100644 index 0000000..961fd83 --- /dev/null +++ b/db/migrate/20130626210927_add_columns_message_user_id_to_share_links.rb @@ -0,0 +1,6 @@ +class AddColumnsMessageUserIdToShareLinks < ActiveRecord::Migration + def change + add_column :boxroom_share_links, :message, :text + add_column :boxroom_share_links, :user_id, :integer + end +end diff --git a/db/migrate/20130628082245_populate_user_id_in_share_links.rb b/db/migrate/20130628082245_populate_user_id_in_share_links.rb new file mode 100644 index 0000000..ab9b2b6 --- /dev/null +++ b/db/migrate/20130628082245_populate_user_id_in_share_links.rb @@ -0,0 +1,9 @@ +class PopulateUserIdInShareLinks < ActiveRecord::Migration + def change + active_users = Boxroom::User.where.not(:name => nil) + + if active_users.any? && Boxroom::ShareLink.any? + Boxroom::ShareLink.where(:user_id => nil).update_all(:user_id => active_users.first.id) + end + end +end diff --git a/lib/boxroom.rb b/lib/boxroom.rb new file mode 100644 index 0000000..2defb53 --- /dev/null +++ b/lib/boxroom.rb @@ -0,0 +1,24 @@ +require "boxroom/engine" +require "dynamic_form" +require 'jquery-fileupload-rails' +require 'acts_as_tree' +require 'paperclip' +require 'boxroom/configuration' + +module Boxroom + class << self + attr_writer :configuration + + def configuration + @configuration ||= Configuration.new + end + + def reset + @configuration = Configuration.new + end + + def configure + yield(configuration) + end + end +end diff --git a/lib/boxroom/configuration.rb b/lib/boxroom/configuration.rb new file mode 100644 index 0000000..f78fa9d --- /dev/null +++ b/lib/boxroom/configuration.rb @@ -0,0 +1,10 @@ +module Boxroom + class Configuration + attr_accessor :site_name, :logo + + def initialize + @site_name = 'Boxroom' + @logo = 'boxroom/logo.png' + end + end +end \ No newline at end of file diff --git a/lib/boxroom/engine.rb b/lib/boxroom/engine.rb new file mode 100644 index 0000000..0da685c --- /dev/null +++ b/lib/boxroom/engine.rb @@ -0,0 +1,9 @@ +module Boxroom + class Engine < ::Rails::Engine + isolate_namespace Boxroom + + initializer 'boxroom.assets.precompile' do |app| + app.config.assets.precompile += %w( boxroom/*.png ) + end + end +end diff --git a/lib/boxroom/version.rb b/lib/boxroom/version.rb new file mode 100644 index 0000000..afe6d69 --- /dev/null +++ b/lib/boxroom/version.rb @@ -0,0 +1,3 @@ +module Boxroom + VERSION = '0.1.0' +end diff --git a/lib/tasks/boxroom_tasks.rake b/lib/tasks/boxroom_tasks.rake new file mode 100644 index 0000000..5ae3d0b --- /dev/null +++ b/lib/tasks/boxroom_tasks.rake @@ -0,0 +1,4 @@ +# desc "Explaining what the task does" +# task :boxroom do +# # Task goes here +# end diff --git a/test/boxroom_test.rb b/test/boxroom_test.rb new file mode 100644 index 0000000..6ebfeba --- /dev/null +++ b/test/boxroom_test.rb @@ -0,0 +1,7 @@ +require 'test_helper' + +class Boxroom::Test < ActiveSupport::TestCase + test "truth" do + assert_kind_of Module, Boxroom + end +end diff --git a/test/dummy/Rakefile b/test/dummy/Rakefile new file mode 100644 index 0000000..e85f913 --- /dev/null +++ b/test/dummy/Rakefile @@ -0,0 +1,6 @@ +# 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_relative 'config/application' + +Rails.application.load_tasks diff --git a/test/dummy/app/assets/config/manifest.js b/test/dummy/app/assets/config/manifest.js new file mode 100644 index 0000000..2882d66 --- /dev/null +++ b/test/dummy/app/assets/config/manifest.js @@ -0,0 +1,5 @@ + +//= link_tree ../images +//= link_directory ../javascripts .js +//= link_directory ../stylesheets .css +//= link boxroom_manifest.js diff --git a/test/dummy/app/assets/images/.keep b/test/dummy/app/assets/images/.keep new file mode 100644 index 0000000..e69de29 diff --git a/test/dummy/app/assets/javascripts/application.js b/test/dummy/app/assets/javascripts/application.js new file mode 100644 index 0000000..e54c646 --- /dev/null +++ b/test/dummy/app/assets/javascripts/application.js @@ -0,0 +1,13 @@ +// This is a manifest file that'll be compiled into application.js, which will include all the files +// listed below. +// +// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts, +// or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path. +// +// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the +// compiled file. JavaScript code in this file should be added after the last require_* statement. +// +// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details +// about supported directives. +// +//= require_tree . diff --git a/test/dummy/app/assets/javascripts/cable.js b/test/dummy/app/assets/javascripts/cable.js new file mode 100644 index 0000000..739aa5f --- /dev/null +++ b/test/dummy/app/assets/javascripts/cable.js @@ -0,0 +1,13 @@ +// Action Cable provides the framework to deal with WebSockets in Rails. +// You can generate new channels where WebSocket features live using the `rails generate channel` command. +// +//= require action_cable +//= require_self +//= require_tree ./channels + +(function() { + this.App || (this.App = {}); + + App.cable = ActionCable.createConsumer(); + +}).call(this); diff --git a/test/dummy/app/assets/javascripts/channels/.keep b/test/dummy/app/assets/javascripts/channels/.keep new file mode 100644 index 0000000..e69de29 diff --git a/test/dummy/app/assets/stylesheets/application.css b/test/dummy/app/assets/stylesheets/application.css new file mode 100644 index 0000000..0ebd7fe --- /dev/null +++ b/test/dummy/app/assets/stylesheets/application.css @@ -0,0 +1,15 @@ +/* + * This is a manifest file that'll be compiled into application.css, which will include all the files + * listed below. + * + * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets, + * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path. + * + * You're free to add application-wide styles to this file and they'll appear at the bottom of the + * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS + * files in this directory. Styles in this file should be added after the last require_* statement. + * It is generally better to create a new file per style scope. + * + *= require_tree . + *= require_self + */ diff --git a/test/dummy/app/channels/application_cable/channel.rb b/test/dummy/app/channels/application_cable/channel.rb new file mode 100644 index 0000000..d672697 --- /dev/null +++ b/test/dummy/app/channels/application_cable/channel.rb @@ -0,0 +1,4 @@ +module ApplicationCable + class Channel < ActionCable::Channel::Base + end +end diff --git a/test/dummy/app/channels/application_cable/connection.rb b/test/dummy/app/channels/application_cable/connection.rb new file mode 100644 index 0000000..0ff5442 --- /dev/null +++ b/test/dummy/app/channels/application_cable/connection.rb @@ -0,0 +1,4 @@ +module ApplicationCable + class Connection < ActionCable::Connection::Base + end +end diff --git a/test/dummy/app/controllers/application_controller.rb b/test/dummy/app/controllers/application_controller.rb new file mode 100644 index 0000000..1c07694 --- /dev/null +++ b/test/dummy/app/controllers/application_controller.rb @@ -0,0 +1,3 @@ +class ApplicationController < ActionController::Base + protect_from_forgery with: :exception +end diff --git a/test/dummy/app/controllers/concerns/.keep b/test/dummy/app/controllers/concerns/.keep new file mode 100644 index 0000000..e69de29 diff --git a/test/dummy/app/helpers/application_helper.rb b/test/dummy/app/helpers/application_helper.rb new file mode 100644 index 0000000..de6be79 --- /dev/null +++ b/test/dummy/app/helpers/application_helper.rb @@ -0,0 +1,2 @@ +module ApplicationHelper +end diff --git a/test/dummy/app/jobs/application_job.rb b/test/dummy/app/jobs/application_job.rb new file mode 100644 index 0000000..a009ace --- /dev/null +++ b/test/dummy/app/jobs/application_job.rb @@ -0,0 +1,2 @@ +class ApplicationJob < ActiveJob::Base +end diff --git a/test/dummy/app/mailers/application_mailer.rb b/test/dummy/app/mailers/application_mailer.rb new file mode 100644 index 0000000..286b223 --- /dev/null +++ b/test/dummy/app/mailers/application_mailer.rb @@ -0,0 +1,4 @@ +class ApplicationMailer < ActionMailer::Base + default from: 'from@example.com' + layout 'mailer' +end diff --git a/test/dummy/app/models/application_record.rb b/test/dummy/app/models/application_record.rb new file mode 100644 index 0000000..10a4cba --- /dev/null +++ b/test/dummy/app/models/application_record.rb @@ -0,0 +1,3 @@ +class ApplicationRecord < ActiveRecord::Base + self.abstract_class = true +end diff --git a/test/dummy/app/models/concerns/.keep b/test/dummy/app/models/concerns/.keep new file mode 100644 index 0000000..e69de29 diff --git a/test/dummy/app/views/layouts/application.html.erb b/test/dummy/app/views/layouts/application.html.erb new file mode 100644 index 0000000..a6eb017 --- /dev/null +++ b/test/dummy/app/views/layouts/application.html.erb @@ -0,0 +1,14 @@ + + + + Dummy + <%= csrf_meta_tags %> + + <%= stylesheet_link_tag 'application', media: 'all' %> + <%= javascript_include_tag 'application' %> + + + + <%= yield %> + + diff --git a/test/dummy/app/views/layouts/mailer.html.erb b/test/dummy/app/views/layouts/mailer.html.erb new file mode 100644 index 0000000..cbd34d2 --- /dev/null +++ b/test/dummy/app/views/layouts/mailer.html.erb @@ -0,0 +1,13 @@ + + + + + + + + + <%= yield %> + + diff --git a/test/dummy/app/views/layouts/mailer.text.erb b/test/dummy/app/views/layouts/mailer.text.erb new file mode 100644 index 0000000..37f0bdd --- /dev/null +++ b/test/dummy/app/views/layouts/mailer.text.erb @@ -0,0 +1 @@ +<%= yield %> diff --git a/test/dummy/bin/bundle b/test/dummy/bin/bundle new file mode 100755 index 0000000..66e9889 --- /dev/null +++ b/test/dummy/bin/bundle @@ -0,0 +1,3 @@ +#!/usr/bin/env ruby +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) +load Gem.bin_path('bundler', 'bundle') diff --git a/test/dummy/bin/rails b/test/dummy/bin/rails new file mode 100755 index 0000000..0739660 --- /dev/null +++ b/test/dummy/bin/rails @@ -0,0 +1,4 @@ +#!/usr/bin/env ruby +APP_PATH = File.expand_path('../config/application', __dir__) +require_relative '../config/boot' +require 'rails/commands' diff --git a/test/dummy/bin/rake b/test/dummy/bin/rake new file mode 100755 index 0000000..1724048 --- /dev/null +++ b/test/dummy/bin/rake @@ -0,0 +1,4 @@ +#!/usr/bin/env ruby +require_relative '../config/boot' +require 'rake' +Rake.application.run diff --git a/test/dummy/bin/setup b/test/dummy/bin/setup new file mode 100755 index 0000000..78c4e86 --- /dev/null +++ b/test/dummy/bin/setup @@ -0,0 +1,38 @@ +#!/usr/bin/env ruby +require 'pathname' +require 'fileutils' +include FileUtils + +# path to your application root. +APP_ROOT = Pathname.new File.expand_path('../../', __FILE__) + +def system!(*args) + system(*args) || abort("\n== Command #{args} failed ==") +end + +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') || system!('bundle install') + + # Install JavaScript dependencies if using Yarn + # system('bin/yarn') + + + # puts "\n== Copying sample files ==" + # unless File.exist?('config/database.yml') + # cp 'config/database.yml.sample', 'config/database.yml' + # end + + puts "\n== Preparing database ==" + system! 'bin/rails db:setup' + + puts "\n== Removing old logs and tempfiles ==" + system! 'bin/rails log:clear tmp:clear' + + puts "\n== Restarting application server ==" + system! 'bin/rails restart' +end diff --git a/test/dummy/bin/update b/test/dummy/bin/update new file mode 100755 index 0000000..a8e4462 --- /dev/null +++ b/test/dummy/bin/update @@ -0,0 +1,29 @@ +#!/usr/bin/env ruby +require 'pathname' +require 'fileutils' +include FileUtils + +# path to your application root. +APP_ROOT = Pathname.new File.expand_path('../../', __FILE__) + +def system!(*args) + system(*args) || abort("\n== Command #{args} failed ==") +end + +chdir APP_ROOT do + # This script is a way to update your development environment automatically. + # Add necessary update steps to this file. + + puts '== Installing dependencies ==' + system! 'gem install bundler --conservative' + system('bundle check') || system!('bundle install') + + puts "\n== Updating database ==" + system! 'bin/rails db:migrate' + + puts "\n== Removing old logs and tempfiles ==" + system! 'bin/rails log:clear tmp:clear' + + puts "\n== Restarting application server ==" + system! 'bin/rails restart' +end diff --git a/test/dummy/bin/yarn b/test/dummy/bin/yarn new file mode 100755 index 0000000..c2bacef --- /dev/null +++ b/test/dummy/bin/yarn @@ -0,0 +1,11 @@ +#!/usr/bin/env ruby +VENDOR_PATH = File.expand_path('..', __dir__) +Dir.chdir(VENDOR_PATH) do + begin + exec "yarnpkg #{ARGV.join(" ")}" + rescue Errno::ENOENT + $stderr.puts "Yarn executable was not detected in the system." + $stderr.puts "Download Yarn at https://yarnpkg.com/en/docs/install" + exit 1 + end +end diff --git a/test/dummy/config.ru b/test/dummy/config.ru new file mode 100644 index 0000000..f7ba0b5 --- /dev/null +++ b/test/dummy/config.ru @@ -0,0 +1,5 @@ +# This file is used by Rack-based servers to start the application. + +require_relative 'config/environment' + +run Rails.application diff --git a/test/dummy/config/application.rb b/test/dummy/config/application.rb new file mode 100644 index 0000000..a18f21c --- /dev/null +++ b/test/dummy/config/application.rb @@ -0,0 +1,18 @@ +require_relative 'boot' + +require 'rails/all' + +Bundler.require(*Rails.groups) +require "boxroom" + +module Dummy + class Application < Rails::Application + # Initialize configuration defaults for originally generated Rails version. + config.load_defaults 5.1 + + # Settings in config/environments/* take precedence over those specified here. + # Application configuration should go into files in config/initializers + # -- all .rb files in that directory are automatically loaded. + end +end + diff --git a/test/dummy/config/boot.rb b/test/dummy/config/boot.rb new file mode 100644 index 0000000..c9aef85 --- /dev/null +++ b/test/dummy/config/boot.rb @@ -0,0 +1,5 @@ +# Set up gems listed in the Gemfile. +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../../Gemfile', __dir__) + +require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE']) +$LOAD_PATH.unshift File.expand_path('../../../lib', __dir__) diff --git a/test/dummy/config/cable.yml b/test/dummy/config/cable.yml new file mode 100644 index 0000000..d3dfabd --- /dev/null +++ b/test/dummy/config/cable.yml @@ -0,0 +1,10 @@ +development: + adapter: async + +test: + adapter: async + +production: + adapter: redis + url: redis://localhost:6379/1 + channel_prefix: dummy_production diff --git a/test/dummy/config/database.yml b/test/dummy/config/database.yml new file mode 100644 index 0000000..0d02f24 --- /dev/null +++ b/test/dummy/config/database.yml @@ -0,0 +1,25 @@ +# SQLite version 3.x +# gem install sqlite3 +# +# Ensure the SQLite 3 gem is defined in your Gemfile +# gem 'sqlite3' +# +default: &default + adapter: sqlite3 + pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 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 diff --git a/test/dummy/config/environment.rb b/test/dummy/config/environment.rb new file mode 100644 index 0000000..426333b --- /dev/null +++ b/test/dummy/config/environment.rb @@ -0,0 +1,5 @@ +# Load the Rails application. +require_relative 'application' + +# Initialize the Rails application. +Rails.application.initialize! diff --git a/test/dummy/config/environments/development.rb b/test/dummy/config/environments/development.rb new file mode 100644 index 0000000..55d8c9e --- /dev/null +++ b/test/dummy/config/environments/development.rb @@ -0,0 +1,54 @@ +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. + config.consider_all_requests_local = true + + # Enable/disable caching. By default caching is disabled. + if Rails.root.join('tmp/caching-dev.txt').exist? + config.action_controller.perform_caching = true + + config.cache_store = :memory_store + config.public_file_server.headers = { + 'Cache-Control' => "public, max-age=#{2.days.seconds.to_i}" + } + else + config.action_controller.perform_caching = false + + config.cache_store = :null_store + end + + # Don't care if the mailer can't send. + config.action_mailer.raise_delivery_errors = false + + config.action_mailer.perform_caching = 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 + + # Suppress logger output for asset requests. + config.assets.quiet = true + + # Raises error for missing translations + # config.action_view.raise_on_missing_translations = true + + # Use an evented file watcher to asynchronously detect changes in source code, + # routes, locales, etc. This feature depends on the listen gem. + # config.file_watcher = ActiveSupport::EventedFileUpdateChecker +end diff --git a/test/dummy/config/environments/production.rb b/test/dummy/config/environments/production.rb new file mode 100644 index 0000000..6ea0018 --- /dev/null +++ b/test/dummy/config/environments/production.rb @@ -0,0 +1,91 @@ +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 + + # Attempt to read encrypted secrets from `config/secrets.yml.enc`. + # Requires an encryption key in `ENV["RAILS_MASTER_KEY"]` or + # `config/secrets.yml.key`. + config.read_encrypted_secrets = true + + # Disable serving static files from the `/public` folder by default since + # Apache or NGINX already handles this. + config.public_file_server.enabled = 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 + + # `config.assets.precompile` and `config.assets.version` have moved to config/initializers/assets.rb + + # Enable serving of images, stylesheets, and JavaScripts from an asset server. + # config.action_controller.asset_host = 'http://assets.example.com' + + # 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 + + # Mount Action Cable outside main process or domain + # config.action_cable.mount_path = nil + # config.action_cable.url = 'wss://example.com/cable' + # config.action_cable.allowed_request_origins = [ 'http://example.com', /http:\/\/example.*/ ] + + # 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 = [ :request_id ] + + # Use a different cache store in production. + # config.cache_store = :mem_cache_store + + # Use a real queuing backend for Active Job (and separate queues per environment) + # config.active_job.queue_adapter = :resque + # config.active_job.queue_name_prefix = "dummy_#{Rails.env}" + config.action_mailer.perform_caching = false + + # 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 + + # Use a different logger for distributed setups. + # require 'syslog/logger' + # config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new 'app-name') + + if ENV["RAILS_LOG_TO_STDOUT"].present? + logger = ActiveSupport::Logger.new(STDOUT) + logger.formatter = config.log_formatter + config.logger = ActiveSupport::TaggedLogging.new(logger) + end + + # Do not dump schema after migrations. + config.active_record.dump_schema_after_migration = false +end diff --git a/test/dummy/config/environments/test.rb b/test/dummy/config/environments/test.rb new file mode 100644 index 0000000..8e5cbde --- /dev/null +++ b/test/dummy/config/environments/test.rb @@ -0,0 +1,42 @@ +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 public file server for tests with Cache-Control for performance. + config.public_file_server.enabled = true + config.public_file_server.headers = { + 'Cache-Control' => "public, max-age=#{1.hour.seconds.to_i}" + } + + # 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 + config.action_mailer.perform_caching = 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 + + # 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 diff --git a/test/dummy/config/initializers/application_controller_renderer.rb b/test/dummy/config/initializers/application_controller_renderer.rb new file mode 100644 index 0000000..89d2efa --- /dev/null +++ b/test/dummy/config/initializers/application_controller_renderer.rb @@ -0,0 +1,8 @@ +# Be sure to restart your server when you modify this file. + +# ActiveSupport::Reloader.to_prepare do +# ApplicationController.renderer.defaults.merge!( +# http_host: 'example.org', +# https: false +# ) +# end diff --git a/test/dummy/config/initializers/assets.rb b/test/dummy/config/initializers/assets.rb new file mode 100644 index 0000000..4b828e8 --- /dev/null +++ b/test/dummy/config/initializers/assets.rb @@ -0,0 +1,14 @@ +# 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' + +# Add additional assets to the asset load path. +# Rails.application.config.assets.paths << Emoji.images_path +# Add Yarn node_modules folder to the asset load path. +Rails.application.config.assets.paths << Rails.root.join('node_modules') + +# Precompile additional assets. +# application.js, application.css, and all non-JS/CSS in the app/assets +# folder are already added. +# Rails.application.config.assets.precompile += %w( admin.js admin.css ) diff --git a/test/dummy/config/initializers/backtrace_silencers.rb b/test/dummy/config/initializers/backtrace_silencers.rb new file mode 100644 index 0000000..59385cd --- /dev/null +++ b/test/dummy/config/initializers/backtrace_silencers.rb @@ -0,0 +1,7 @@ +# 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! diff --git a/test/dummy/config/initializers/cookies_serializer.rb b/test/dummy/config/initializers/cookies_serializer.rb new file mode 100644 index 0000000..5a6a32d --- /dev/null +++ b/test/dummy/config/initializers/cookies_serializer.rb @@ -0,0 +1,5 @@ +# Be sure to restart your server when you modify this file. + +# Specify a serializer for the signed and encrypted cookie jars. +# Valid options are :json, :marshal, and :hybrid. +Rails.application.config.action_dispatch.cookies_serializer = :json diff --git a/test/dummy/config/initializers/filter_parameter_logging.rb b/test/dummy/config/initializers/filter_parameter_logging.rb new file mode 100644 index 0000000..4a994e1 --- /dev/null +++ b/test/dummy/config/initializers/filter_parameter_logging.rb @@ -0,0 +1,4 @@ +# 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] diff --git a/test/dummy/config/initializers/inflections.rb b/test/dummy/config/initializers/inflections.rb new file mode 100644 index 0000000..ac033bf --- /dev/null +++ b/test/dummy/config/initializers/inflections.rb @@ -0,0 +1,16 @@ +# 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 diff --git a/test/dummy/config/initializers/mime_types.rb b/test/dummy/config/initializers/mime_types.rb new file mode 100644 index 0000000..dc18996 --- /dev/null +++ b/test/dummy/config/initializers/mime_types.rb @@ -0,0 +1,4 @@ +# 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 diff --git a/test/dummy/config/initializers/wrap_parameters.rb b/test/dummy/config/initializers/wrap_parameters.rb new file mode 100644 index 0000000..bbfc396 --- /dev/null +++ b/test/dummy/config/initializers/wrap_parameters.rb @@ -0,0 +1,14 @@ +# 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] +end + +# To enable root element in JSON for ActiveRecord objects. +# ActiveSupport.on_load(:active_record) do +# self.include_root_in_json = true +# end diff --git a/test/dummy/config/locales/en.yml b/test/dummy/config/locales/en.yml new file mode 100644 index 0000000..decc5a8 --- /dev/null +++ b/test/dummy/config/locales/en.yml @@ -0,0 +1,33 @@ +# 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. +# +# The following keys must be escaped otherwise they will not be retrieved by +# the default I18n backend: +# +# true, false, on, off, yes, no +# +# Instead, surround them with single quotes. +# +# en: +# 'true': 'foo' +# +# To learn more, please read the Rails Internationalization guide +# available at http://guides.rubyonrails.org/i18n.html. + +en: + hello: "Hello world" diff --git a/test/dummy/config/puma.rb b/test/dummy/config/puma.rb new file mode 100644 index 0000000..1e19380 --- /dev/null +++ b/test/dummy/config/puma.rb @@ -0,0 +1,56 @@ +# Puma can serve each request in a thread from an internal thread pool. +# The `threads` method setting takes two numbers: a minimum and maximum. +# Any libraries that use thread pools should be configured to match +# the maximum value specified for Puma. Default is set to 5 threads for minimum +# and maximum; this matches the default thread size of Active Record. +# +threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 } +threads threads_count, threads_count + +# Specifies the `port` that Puma will listen on to receive requests; default is 3000. +# +port ENV.fetch("PORT") { 3000 } + +# Specifies the `environment` that Puma will run in. +# +environment ENV.fetch("RAILS_ENV") { "development" } + +# Specifies the number of `workers` to boot in clustered mode. +# Workers are forked webserver processes. If using threads and workers together +# the concurrency of the application would be max `threads` * `workers`. +# Workers do not work on JRuby or Windows (both of which do not support +# processes). +# +# workers ENV.fetch("WEB_CONCURRENCY") { 2 } + +# Use the `preload_app!` method when specifying a `workers` number. +# This directive tells Puma to first boot the application and load code +# before forking the application. This takes advantage of Copy On Write +# process behavior so workers use less memory. If you use this option +# you need to make sure to reconnect any threads in the `on_worker_boot` +# block. +# +# preload_app! + +# If you are preloading your application and using Active Record, it's +# recommended that you close any connections to the database before workers +# are forked to prevent connection leakage. +# +# before_fork do +# ActiveRecord::Base.connection_pool.disconnect! if defined?(ActiveRecord) +# end + +# The code in the `on_worker_boot` will be called if you are using +# clustered mode by specifying a number of `workers`. After each worker +# process is booted, this block will be run. If you are using the `preload_app!` +# option, you will want to use this block to reconnect to any threads +# or connections that may have been created at application boot, as Ruby +# cannot share connections between processes. +# +# on_worker_boot do +# ActiveRecord::Base.establish_connection if defined?(ActiveRecord) +# end +# + +# Allow puma to be restarted by `rails restart` command. +plugin :tmp_restart diff --git a/test/dummy/config/routes.rb b/test/dummy/config/routes.rb new file mode 100644 index 0000000..72926de --- /dev/null +++ b/test/dummy/config/routes.rb @@ -0,0 +1,3 @@ +Rails.application.routes.draw do + mount Boxroom::Engine => "/boxroom" +end diff --git a/test/dummy/config/secrets.yml b/test/dummy/config/secrets.yml new file mode 100644 index 0000000..fc63416 --- /dev/null +++ b/test/dummy/config/secrets.yml @@ -0,0 +1,32 @@ +# 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 `rails secret` to generate a secure secret key. + +# Make sure the secrets in this file are kept private +# if you're sharing your code publicly. + +# Shared secrets are available across all environments. + +# shared: +# api_key: a1B2c3D4e5F6 + +# Environmental secrets are only available for that specific environment. + +development: + secret_key_base: 78494ed70673753c6f483e51ec3d207f9815f32a815f8a5e22ccb19d93973b28b1cbbf636e0bfe1f42430fc2e09293839e9bae1747ad8bad6ee84a062c08e03a + +test: + secret_key_base: 391840a9588b36699c9f3bf7077da743159cf67bf8424e70d2e6948204408d1a3869f3b80844c799d0372ef9eb57381333f8145db9f99f0fe210ee53ebd71b5d + +# Do not keep production secrets in the unencrypted secrets file. +# Instead, either read values from the environment. +# Or, use `bin/rails secrets:setup` to configure encrypted secrets +# and move the `production:` environment over there. + +production: + secret_key_base: <%= ENV["SECRET_KEY_BASE"] %> diff --git a/test/dummy/config/spring.rb b/test/dummy/config/spring.rb new file mode 100644 index 0000000..c9119b4 --- /dev/null +++ b/test/dummy/config/spring.rb @@ -0,0 +1,6 @@ +%w( + .ruby-version + .rbenv-vars + tmp/restart.txt + tmp/caching-dev.txt +).each { |path| Spring.watch(path) } diff --git a/test/dummy/lib/assets/.keep b/test/dummy/lib/assets/.keep new file mode 100644 index 0000000..e69de29 diff --git a/test/dummy/log/.keep b/test/dummy/log/.keep new file mode 100644 index 0000000..e69de29 diff --git a/test/dummy/package.json b/test/dummy/package.json new file mode 100644 index 0000000..caa2d7b --- /dev/null +++ b/test/dummy/package.json @@ -0,0 +1,5 @@ +{ + "name": "dummy", + "private": true, + "dependencies": {} +} diff --git a/test/dummy/public/404.html b/test/dummy/public/404.html new file mode 100644 index 0000000..2be3af2 --- /dev/null +++ b/test/dummy/public/404.html @@ -0,0 +1,67 @@ + + + + The page you were looking for doesn't exist (404) + + + + + + +
+
+

The page you were looking for doesn't exist.

+

You may have mistyped the address or the page may have moved.

+
+

If you are the application owner check the logs for more information.

+
+ + diff --git a/test/dummy/public/422.html b/test/dummy/public/422.html new file mode 100644 index 0000000..c08eac0 --- /dev/null +++ b/test/dummy/public/422.html @@ -0,0 +1,67 @@ + + + + The change you wanted was rejected (422) + + + + + + +
+
+

The change you wanted was rejected.

+

Maybe you tried to change something you didn't have access to.

+
+

If you are the application owner check the logs for more information.

+
+ + diff --git a/test/dummy/public/500.html b/test/dummy/public/500.html new file mode 100644 index 0000000..78a030a --- /dev/null +++ b/test/dummy/public/500.html @@ -0,0 +1,66 @@ + + + + We're sorry, but something went wrong (500) + + + + + + +
+
+

We're sorry, but something went wrong.

+
+

If you are the application owner check the logs for more information.

+
+ + diff --git a/test/dummy/public/apple-touch-icon-precomposed.png b/test/dummy/public/apple-touch-icon-precomposed.png new file mode 100644 index 0000000..e69de29 diff --git a/test/dummy/public/apple-touch-icon.png b/test/dummy/public/apple-touch-icon.png new file mode 100644 index 0000000..e69de29 diff --git a/test/dummy/public/favicon.ico b/test/dummy/public/favicon.ico new file mode 100644 index 0000000..e69de29 diff --git a/test/factories.rb b/test/factories.rb new file mode 100644 index 0000000..37224b5 --- /dev/null +++ b/test/factories.rb @@ -0,0 +1,45 @@ +FactoryGirl.define do + factory :folder do + sequence(:name) { |i| "test#{i}" } + parent { Folder.where(:name => 'Root folder').first_or_create } + end +end + +FactoryGirl.define do + factory :group do + sequence(:name) { |i| "test#{i}" } + end +end + +FactoryGirl.define do + factory :share_link do + emails 'email1@domain.com, email2@domain.com' + link_expires_at { 2.weeks.from_now.end_of_day } + end +end + +FactoryGirl.define do + factory :user_file do + attachment { fixture_file } + sequence(:attachment_file_name) { |i| "test#{i}.txt" } + folder { Folder.where(:name => 'Root folder').first_or_create } + end +end + +FactoryGirl.define do + factory :user do + sequence(:name) { |i| "test#{i}" } + sequence(:email) { |i| "test#{i}@test.com" } + password 'secret123' + password_confirmation { |u| u.password } + password_required true + reset_password_token '' + dont_clear_reset_password_token false + remember_token '' + is_admin false + end +end + +def fixture_file + File.open("#{Rails.root}/test/fixtures/textfile.txt") +end diff --git a/test/fixtures/textfile.txt b/test/fixtures/textfile.txt new file mode 100644 index 0000000..9daeafb --- /dev/null +++ b/test/fixtures/textfile.txt @@ -0,0 +1 @@ +test diff --git a/test/integration/navigation_test.rb b/test/integration/navigation_test.rb new file mode 100644 index 0000000..f5d1ec2 --- /dev/null +++ b/test/integration/navigation_test.rb @@ -0,0 +1,8 @@ +require 'test_helper' + +class NavigationTest < ActionDispatch::IntegrationTest + # test "the truth" do + # assert true + # end +end + diff --git a/test/test_helper.rb b/test/test_helper.rb new file mode 100644 index 0000000..5a85c6c --- /dev/null +++ b/test/test_helper.rb @@ -0,0 +1,29 @@ +require File.expand_path("../../test/dummy/config/environment.rb", __FILE__) +ActiveRecord::Migrator.migrations_paths = [File.expand_path("../../test/dummy/db/migrate", __FILE__)] +ActiveRecord::Migrator.migrations_paths << File.expand_path('../../db/migrate', __FILE__) +require "rails/test_help" + +# Filter out Minitest backtrace while allowing backtrace from other libraries +# to be shown. +Minitest.backtrace_filter = Minitest::BacktraceFilter.new + + +# Load fixtures from the engine +if ActiveSupport::TestCase.respond_to?(:fixture_path=) + ActiveSupport::TestCase.fixture_path = File.expand_path("../fixtures", __FILE__) + ActionDispatch::IntegrationTest.fixture_path = ActiveSupport::TestCase.fixture_path + ActiveSupport::TestCase.file_fixture_path = ActiveSupport::TestCase.fixture_path + "/files" + ActiveSupport::TestCase.fixtures :all +end + +# ENV["RAILS_ENV"] = "test" +# require File.expand_path('../../config/environment', __FILE__) +# require 'rails/test_help' +# +# class ActiveSupport::TestCase +# include FactoryGirl::Syntax::Methods +# +# def clear_root_folder +# Folder.instance_variable_set('@root_folder', nil) +# end +# end diff --git a/test/unit/clipboard_test.rb b/test/unit/clipboard_test.rb new file mode 100644 index 0000000..f397150 --- /dev/null +++ b/test/unit/clipboard_test.rb @@ -0,0 +1,134 @@ +require 'test_helper' + +class ClipboardTest < ActiveSupport::TestCase + test 'a folder can be added to the clipboard' do + folder = create(:folder) + clipboard = Clipboard.new + assert clipboard.folders.empty? + assert clipboard.empty? + + clipboard.add(folder) + assert_equal clipboard.folders.count, 1 + assert !clipboard.empty? + end + + test 'a file can be added to the clipboard' do + file = create(:user_file) + clipboard = Clipboard.new + assert clipboard.files.empty? + assert clipboard.empty? + + clipboard.add(file) + assert_equal clipboard.files.count, 1 + assert !clipboard.empty? + end + + test 'a folder can be removed from the clipboard' do + folder = create(:folder) + clipboard = Clipboard.new + clipboard.add(folder) + assert_equal clipboard.folders.count, 1 + assert !clipboard.empty? + + clipboard.remove(folder) + assert clipboard.folders.empty? + assert clipboard.empty? + end + + test 'a file can be removed from the clipboard' do + file = create(:user_file) + clipboard = Clipboard.new + clipboard.add(file) + assert_equal clipboard.files.count, 1 + assert !clipboard.empty? + + clipboard.remove(file) + assert clipboard.files.empty? + assert clipboard.empty? + end + + test 'the same folder cannot be added twice' do + folder = create(:folder) + clipboard = Clipboard.new + clipboard.add(folder) + assert_equal clipboard.folders.count, 1 + + another_folder = create(:folder) + clipboard.add(another_folder) + assert_equal clipboard.folders.count, 2 + + clipboard.add(folder) + assert_equal clipboard.folders.count, 2 + end + + test 'the same file cannot be added twice' do + file = create(:user_file) + clipboard = Clipboard.new + clipboard.add(file) + assert_equal clipboard.files.count, 1 + + another_file = create(:user_file) + clipboard.add(another_file) + assert_equal clipboard.files.count, 2 + + clipboard.add(file) + assert_equal clipboard.files.count, 2 + end + + test 'when a folder is updated the referenced folder on the clipboard must also change' do + folder = create(:folder, :name => 'Test') + clipboard = Clipboard.new + clipboard.add(folder) + assert_equal clipboard.folders.first.name, 'Test' + + folder.update_attributes(:name => 'Name changed') + assert_equal clipboard.folders.first.name, 'Name changed' + end + + test 'when a file is updated the referenced file on the clipboard must also change' do + file = create(:user_file) + clipboard = Clipboard.new + clipboard.add(file) + assert_not_equal clipboard.files.first.attachment_file_name, 'Name changed.txt' + + file.update_attributes(:attachment_file_name => 'Name changed.txt') + assert_equal clipboard.files.first.attachment_file_name, 'Name changed.txt' + end + + test 'a deleted folder must also be deleted from the clipboard' do + folder = create(:folder) + clipboard = Clipboard.new + clipboard.add(folder) + assert !clipboard.folders.empty? + + folder.destroy + assert clipboard.empty? + assert clipboard.folders.empty? + end + + test 'a deleted file must also be deleted from the clipboard' do + file = create(:user_file) + clipboard = Clipboard.new + clipboard.add(file) + assert !clipboard.files.empty? + + file.destroy + assert clipboard.empty? + assert clipboard.files.empty? + end + + test 'reset clears all the files and folders from the clipboard' do + clipboard = Clipboard.new + 3.times { clipboard.add(create(:user_file)) } + 3.times { clipboard.add(create(:folder)) } + + assert_equal clipboard.files.size, 3 + assert_equal clipboard.folders.size, 3 + assert !clipboard.empty? + + clipboard.reset + assert clipboard.files.empty? + assert clipboard.folders.empty? + assert clipboard.empty? + end +end diff --git a/test/unit/folder_test.rb b/test/unit/folder_test.rb new file mode 100644 index 0000000..135b2ee --- /dev/null +++ b/test/unit/folder_test.rb @@ -0,0 +1,207 @@ +require 'test_helper' + +class FolderTest < ActiveSupport::TestCase + def setup + clear_root_folder + end + + test 'dependent files get deleted' do + folder1 = create(:folder) + assert_equal Folder.all.count, 2 # Root folder gets created automatically + + 3.times { create(:user_file, :folder => folder1) } + assert_equal folder1.user_files.count, 3 + + folder2 = create(:folder) + assert_equal Folder.all.count, 3 + + 5.times { create(:user_file, :folder => folder2) } + assert_equal folder2.user_files.count, 5 + assert_equal UserFile.all.count, 8 + + folder1.destroy + assert_equal UserFile.all.count, 5 + + folder2.destroy + assert_equal UserFile.all.count, 0 + end + + test 'dependent permissions get deleted' do + root = create(:folder, :name => 'Root folder', :parent => nil) # Root folder + assert_equal Folder.all.count, 1 + + 3.times { create(:group) } + assert Group.all.count > 0 + assert_equal root.permissions.count, Group.all.count + + folder1 = create(:folder) + folder2 = create(:folder) + assert_equal folder1.permissions.count, 3 + assert_equal folder2.permissions.count, 3 + assert_equal Permission.all.count, 9 + + folder1.destroy + assert_equal Permission.all.count, 6 + + folder2.destroy + assert_equal Permission.all.count, 3 + end + + test 'name is unique' do + folder = create(:folder, :name => 'Test') + assert Folder.exists?(:name => 'Test') + + folder2 = Folder.new(:name => 'Test') + folder2.parent = folder + assert folder2.save + + folder3 = Folder.new(:name => 'Test') + folder3.parent = folder + assert !folder3.save + end + + test 'name is not empty' do + folder = Folder.new + assert !folder.save + end + + test 'cannot create a folder without a parent' do + folder = Folder.new(:name => 'Test') + assert_nil folder.parent + assert_raise(RuntimeError) { folder.save } + end + + test 'permissions get created' do + root = create(:folder, :name => 'Root folder', :parent => nil) # Root folder + assert_equal Folder.all.count, 1 + + create(:group) + assert Group.all.count > 0 + assert_equal root.permissions.count, Group.all.count + + root.permissions.each do |permission| + assert !permission.can_create + assert permission.can_read + assert !permission.can_update + assert !permission.can_delete + + # Change the permissions + permission.update_attributes(:can_create => true, :can_update => true) + end + + folder = create(:folder) + assert_equal Folder.all.count, 2 + assert_equal folder.permissions.count, Group.all.count + + # Test if updated permissions get copied correctly + folder.permissions.each do |permission| + assert permission.can_create + assert permission.can_read + assert permission.can_update + assert !permission.can_delete + end + end + + test 'cannot delete root folder' do + folder = create(:folder) + root = Folder.root + + assert_raise(RuntimeError) { root.destroy } + assert folder.destroy + end + + test 'cannot copy a folder to anything other than a folder' do + file = create(:user_file) + folder1 = create(:folder) + folder2 = create(:folder) + + assert_raise(RuntimeError) { folder1.copy(nil) } + assert_raise(ActiveRecord::AssociationTypeMismatch) { folder1.copy('A string...') } + assert_raise(ActiveRecord::AssociationTypeMismatch) { folder1.copy(file) } + assert folder1.copy(folder2) + end + + test 'copy a folder' do + folder1 = create(:folder) + 5.times { create(:user_file, :folder => folder1) } + + folder2 = create(:folder) + 3.times { create(:user_file, :folder => folder2) } + + assert_raise(ActiveRecord::RecordInvalid) { folder1.copy(Folder.root) } + assert_equal UserFile.all.count, 8 + assert_equal folder2.children.count, 0 + assert folder1.copy(folder2) + assert_equal UserFile.all.count, 13 + assert_equal folder2.children.count, 1 + end + + test 'cannot move a folder to anything other than a folder' do + file = create(:user_file) + folder1 = create(:folder) + folder2 = create(:folder) + + assert_raise(RuntimeError) { folder1.move(nil) } + assert_raise(ActiveRecord::AssociationTypeMismatch) { folder1.move('A string...') } + assert_raise(ActiveRecord::AssociationTypeMismatch) { folder1.move(file) } + assert folder1.move(folder2) + end + + test 'move a folder' do + folder1 = create(:folder) + folder2 = create(:folder, :parent => folder1) + folder3 = create(:folder) + + assert folder1.parent_of?(folder2) + assert !folder1.parent_of?(folder3) + + # Should not be able to move a folder to its own sub-folder + assert_raise(RuntimeError) { folder1.move(folder2) } + + assert_equal Folder.all.count, 4 + assert_equal folder1.parent, Folder.root + + folder1.move(folder3) + assert_equal folder1.parent, folder3 + assert_equal Folder.all.count, 4 + + assert folder3.parent_of?(folder1) + assert folder3.parent_of?(folder2) + end + + test 'whether a folder is root or not' do + folder1 = create(:folder) + assert !folder1.is_root? + + folder2 = Folder.new + assert !folder2.is_root? + + root = Folder.root + assert root.is_root? + end + + test 'whether a folder has children or not' do + folder = create(:folder) + assert !folder.has_children? + + root = Folder.root + assert_equal folder.parent, root + assert root.has_children? + + folder2 = create(:folder, :parent => folder) + assert folder.has_children? + + folder.destroy + assert !root.has_children? + end + + test 'that the root folder is really the root folder' do + folder = create(:folder) + assert !folder.is_root? + + root = Folder.root + assert root.is_root? + assert_equal root.name, 'Root folder' + assert_nil root.parent + end +end diff --git a/test/unit/group_test.rb b/test/unit/group_test.rb new file mode 100644 index 0000000..fa786fa --- /dev/null +++ b/test/unit/group_test.rb @@ -0,0 +1,72 @@ +require 'test_helper' + +class GroupTest < ActiveSupport::TestCase + test 'dependent permissions get deleted' do + 3.times { create(:folder) } + assert_equal Folder.all.count, 4 # Root folder gets created automatically + + group1 = create(:group) + group2 = create(:group) + assert_equal group1.permissions.count, 4 + assert_equal group2.permissions.count, 4 + assert_equal Permission.all.count, 8 + + group1.destroy + assert_equal Permission.all.count, 4 + + group2.destroy + assert_equal Permission.all.count, 0 + end + + test 'name is unique' do + create(:group, :name => 'Users') + assert Group.exists?(:name => 'Users') + + group = Group.new(:name => 'Users') + assert !group.save + end + + test 'name is not empty' do + group = Group.new + assert !group.save + end + + test 'admin permissions get created' do + create(:folder) + assert Folder.all.count > 0 + + group = create(:group, :name => 'Admins') + assert_equal group.permissions.count, Folder.all.count + + group.permissions.each do |permission| + assert permission.can_create + assert permission.can_read + assert permission.can_update + assert permission.can_delete + end + end + + test 'permissions get created' do + create(:folder) + assert Folder.all.count > 0 + + group = create(:group) + assert_equal group.permissions.count, Folder.all.count + + group.permissions.each do |permission| + assert !permission.can_create + assert_equal permission.can_read, permission.folder.is_root? + assert !permission.can_update + assert !permission.can_delete + end + end + + test 'cannot delete admins group' do + admins = create(:group, :name => 'Admins') + normal_group = create(:group) + + assert admins.admins_group? + assert_raise(RuntimeError) { admins.destroy } + assert normal_group.destroy + end +end diff --git a/test/unit/share_link_test.rb b/test/unit/share_link_test.rb new file mode 100644 index 0000000..f815f2d --- /dev/null +++ b/test/unit/share_link_test.rb @@ -0,0 +1,78 @@ +require 'test_helper' + +class ShareLinkTest < ActiveSupport::TestCase + test 'emails is not empty' do + assert_raise(ActiveRecord::RecordInvalid) { create(:share_link, :emails => '') } + end + + test 'link expires at is not empty' do + assert_raise(ActiveRecord::RecordInvalid) { create(:share_link, :link_expires_at => '') } + end + + test 'emails is not longer than 255 characters' do + share_link = create(:share_link) + + # 255 chars + share_link.emails = 'email@domain.com, another-email@domain.com, email@domain.com, another-email@domain.com, email@domain.com, another-email@domain.com, email@domain.com, another-email@domain.com, email@domain.com, anotheremail@domain.com, email@domain.com, another@domain.com' + assert share_link.save + + # 256 chars + share_link.emails = 'email@domain.com, another-email@domain.com, email@domain.com, another-email@domain.com, email@domain.com, another-email@domain.com, email@domain.com, another-email@domain.com, email@domain.com, anotheremail@domain.com, email@domain.com, anothere@domain.com' + assert !share_link.save + end + + test 'the format of emails is valid' do + assert_raise(ActiveRecord::RecordInvalid) { create(:share_link, :emails => 'mail@domain.com, @.com') } + assert_raise(ActiveRecord::RecordInvalid) { create(:share_link, :emails => 'mail@domain.com, @test.com') } + assert_raise(ActiveRecord::RecordInvalid) { create(:share_link, :emails => 'mail@domain.com, test@.com, another-email@domain.com') } + assert_raise(ActiveRecord::RecordInvalid) { create(:share_link, :emails => 'mail@domain.com, test@test.') } + assert_raise(ActiveRecord::RecordInvalid) { create(:share_link, :emails => 'mail@domain.com, test@$%^.com') } + assert_raise(ActiveRecord::RecordInvalid) { create(:share_link, :emails => 'mail@domain.com, test@test.c') } + assert_raise(ActiveRecord::RecordInvalid) { create(:share_link, :emails => 'mail@domain.com, test@test.$$$') } + end + + test 'a link token gets generated' do + share_link1 = create(:share_link) + assert !share_link1.link_token.blank? + + share_link2 = ShareLink.new + share_link2.user_file = create(:user_file) + share_link2.emails = 'mail@domain.com' + share_link2.link_expires_at = 2.weeks.from_now.end_of_day + assert share_link2.link_token.blank? + + share_link2.save + assert !share_link2.link_token.blank? + end + + test 'active share links' do + expiry_dates = [1.week.ago, 1.week.from_now, 2.weeks.from_now, 3.weeks.from_now, 1.month.from_now] + + expiry_dates.each do |expiry_date| + create(:share_link, :link_expires_at => expiry_date) + end + + assert_equal ShareLink.active_share_links.count, 4 + end + + test 'the correct file is returned for a given link token' do + user_file = create(:user_file) + + share_link1 = create(:share_link) + share_link1.user_file = user_file + share_link1.save + + share_link2 = create(:share_link, :link_expires_at => 1.week.ago.end_of_day) + share_link2.user_file = user_file + share_link2.save + + random_token = SecureRandom.hex(10) + assert_raise(NoMethodError) { ShareLink.file_for_token(random_token) } + + old_link_token = share_link2.link_token + assert_raise(RuntimeError) { ShareLink.file_for_token(old_link_token) } + + valid_link_token = share_link1.link_token + assert_equal ShareLink.file_for_token(valid_link_token), user_file + end +end diff --git a/test/unit/user_file_test.rb b/test/unit/user_file_test.rb new file mode 100644 index 0000000..292c19e --- /dev/null +++ b/test/unit/user_file_test.rb @@ -0,0 +1,137 @@ +require 'test_helper' + +class UserFileTest < ActiveSupport::TestCase + def setup + clear_root_folder + end + + test 'dependent share links get deleted' do + file1 = create(:user_file) + assert_equal UserFile.all.count, 1 + + 3.times { create(:share_link, :user_file => file1) } + assert_equal file1.share_links.count, 3 + + file2 = create(:user_file) + assert_equal UserFile.all.count, 2 + + 5.times { create(:share_link, :user_file => file2) } + assert_equal file2.share_links.count, 5 + assert_equal ShareLink.all.count, 8 + + file1.destroy + assert_equal ShareLink.all.count, 5 + + file2.destroy + assert_equal ShareLink.all.count, 0 + end + + test 'attachment is not empty' do + folder = create(:folder) + file = folder.user_files.build + assert !file.save + + file.attachment = fixture_file + assert file.save + end + + test 'folder is not empty' do + file = UserFile.new(:attachment => fixture_file) + assert !file.save + + folder = create(:folder) + file.folder = folder + assert file.save + end + + test 'attachment file name is unique' do + file = create(:user_file) + file.update_attributes(:attachment_file_name => 'Test.txt') + assert UserFile.exists?(:attachment_file_name => 'Test.txt') + + folder = create(:folder) + file2 = folder.user_files.build(:attachment => fixture_file) + file2.attachment_file_name = 'Test.txt' + assert file2.save + + file3 = Folder.root.user_files.build(:attachment => fixture_file) + file3.attachment_file_name = 'Test.txt' + assert !file3.save + end + + test 'attachment file name cannot contain invalid characters' do + file = create(:user_file) + + %w{< > : " / \ | ? *}.each do |invalid_character| + file.attachment_file_name = "Test#{invalid_character}.txt" + assert !file.save + end + + file.attachment_file_name = 'Test.txt' + assert file.save + end + + test 'cannot copy a file to anything other than a folder' do + file1 = create(:user_file) + file2 = create(:user_file) + folder = create(:folder) + + assert_raise(ActiveRecord::RecordInvalid) { file1.copy(nil) } + assert_raise(ActiveRecord::AssociationTypeMismatch) { file1.copy('A string...') } + assert_raise(ActiveRecord::AssociationTypeMismatch) { file1.copy(file2) } + assert file1.copy(folder) + end + + test 'copy a file' do + folder = create(:folder) + file = create(:user_file) + + assert_raise(ActiveRecord::RecordInvalid) { file.copy(Folder.root) } + assert_equal UserFile.all.count, 1 + assert_equal folder.user_files.count, 0 + + file.copy(folder) + assert_equal UserFile.all.count, 2 + assert_equal folder.user_files.count, 1 + + new_file = UserFile.find_by_attachment_file_name_and_folder_id(file.attachment_file_name, folder.id) + assert File.exists?(new_file.attachment.path) + end + + test 'cannot move a file to anything other than a folder' do + file1 = create(:user_file) + file2 = create(:user_file) + folder = create(:folder) + + assert_raise(ActiveRecord::RecordInvalid) { file1.move(nil) } + assert_raise(ActiveRecord::AssociationTypeMismatch) { file1.move('A string...') } + assert_raise(ActiveRecord::AssociationTypeMismatch) { file1.move(file2) } + assert file1.move(folder) + end + + test 'move a file' do + folder = create(:folder) + folder2 = create(:folder) + file = create(:user_file) + + assert file.copy(folder) + assert_equal UserFile.all.count, 2 + assert_not_equal file.folder, folder + assert_raise(ActiveRecord::RecordInvalid) { file.move(folder) } + + assert file.move(folder2) + assert_equal UserFile.all.count, 2 + assert_equal file.folder, folder2 + end + + test 'file has correct extension' do + file = create(:user_file) + assert_equal file.extension, 'txt' + + file.update_attributes(:attachment_file_name => 'test.pdf') + assert_equal file.extension, 'pdf' + + file.update_attributes(:attachment_file_name => 'test') + assert file.extension.blank? + end +end diff --git a/test/unit/user_test.rb b/test/unit/user_test.rb new file mode 100644 index 0000000..a121f3a --- /dev/null +++ b/test/unit/user_test.rb @@ -0,0 +1,237 @@ +require 'test_helper' + +class UserTest < ActiveSupport::TestCase + test 'password is valid' do + assert_raise(ActiveRecord::RecordInvalid) { create(:user, :password => '123456', :password_confirmation => '654321') } + assert_raise(ActiveRecord::RecordInvalid) { create(:user, :password => '123') } + assert_raise(ActiveRecord::RecordInvalid) { create(:user, :password => '') } + assert create(:user, :password => '123456') + + user = create(:user) + user.password_required = false + user.password = '' + user.password_confirmation = '' + assert user.save + end + + test 'name can be empty for a new user' do + create(:user, :name => '', :email => 'test@test.com') + assert User.exists?(:name => '', :email => 'test@test.com') + end + + test 'signup_token and signup_token_expires_at are set for a new user' do + user = create(:user, :name => '', :email => 'test@test.com') + assert !user.signup_token.empty? + assert user.signup_token_expires_at > 1.hour.from_now + end + + test 'name cannot be empty for an existing user' do + user = create(:user) + user.name = '' + assert_raise(ActiveRecord::RecordInvalid) { user.save! } + end + + test 'signup_token and signup_token_expires_at are nil for an existing user' do + user = create(:user, :name => '', :email => 'test@test.com') + user.name = 'test' + user.save + assert user.signup_token.nil? + assert user.signup_token_expires_at.nil? + end + + test 'email is not empty' do + assert_raise(ActiveRecord::RecordInvalid) { create(:user, :email => '') } + end + + test 'name is unique' do + create(:user, :name => 'Test') + assert User.exists?(:name => 'Test') + assert_raise(ActiveRecord::RecordInvalid) { create(:user, :name => 'Test') } + end + + test 'email is unique' do + create(:user, :email => 'test@test.com') + assert User.exists?(:email => 'test@test.com') + assert_raise(ActiveRecord::RecordInvalid) { create(:user, :email => 'test@test.com') } + end + + test 'email is valid' do + assert_raise(ActiveRecord::RecordInvalid) { create(:user, :email => '@.com') } + assert_raise(ActiveRecord::RecordInvalid) { create(:user, :email => '@test.com') } + assert_raise(ActiveRecord::RecordInvalid) { create(:user, :email => 'test@.com') } + assert_raise(ActiveRecord::RecordInvalid) { create(:user, :email => 'test@test.') } + assert_raise(ActiveRecord::RecordInvalid) { create(:user, :email => 'test@$%^.com') } + assert_raise(ActiveRecord::RecordInvalid) { create(:user, :email => 'test@test.c') } + assert_raise(ActiveRecord::RecordInvalid) { create(:user, :email => 'test@test.$$$') } + assert_nothing_raised(ActiveRecord::RecordInvalid) { create(:user, :email => 'test@test.com') } + end + + test 'reset_password_token gets cleared' do + token = SecureRandom.base64(32) + user = create(:user, :reset_password_token => token, :dont_clear_reset_password_token => true) + assert_equal user.reset_password_token, token + + user2 = User.find_by_reset_password_token(token) + user2.save + assert user2.reset_password_token.blank? + end + + test 'root folder and admins group get created' do + admin = create(:user, :is_admin => true) + assert_equal Folder.where(:name => 'Root folder').count, 1 + assert_equal Group.where(:name => 'Admins').count, 1 + assert_equal admin.groups.count, 1 + end + + test 'cannot delete admin user' do + admin = create(:user, :is_admin => true) + normal_user = create(:user) + + assert_raise(RuntimeError) { admin.destroy } + assert normal_user.destroy + end + + test 'user permissions' do + admin = create(:user, :is_admin => true) + user = create(:user) + root = Folder.root + folder = create(:folder) + group = create(:group) + + %w{create read update delete}.each { |method| assert admin.send("can_#{method}", root) } + %w{create read update delete}.each { |method| assert admin.send("can_#{method}", folder) } + %w{create read update delete}.each { |method| assert !user.send("can_#{method}", root) } + %w{create read update delete}.each { |method| assert !user.send("can_#{method}", folder) } + + user.groups << group + assert user.can_read(root) + %w{create update delete}.each { |method| assert !user.send("can_#{method}", root) } + %w{create read update delete}.each { |method| assert !user.send("can_#{method}", folder) } + + folder.permissions.where(:group_id => group).update_all(:can_create => true) + assert user.can_create(folder) + %w{read update delete}.each { |method| assert !user.send("can_#{method}", folder) } + + folder.permissions.where(:group_id => group).update_all(:can_read => true) + %w{create read}.each { |method| assert user.send("can_#{method}", folder) } + %w{update delete}.each { |method| assert !user.send("can_#{method}", folder) } + + folder.permissions.where(:group_id => group).update_all(:can_update => true) + %w{create read update}.each { |method| assert user.send("can_#{method}", folder) } + assert !user.can_delete(folder) + + folder.permissions.where(:group_id => group).update_all(:can_delete => true) + %w{create read update delete}.each { |method| assert user.send("can_#{method}", folder) } + + assert user.can_read(root) + %w{create update delete}.each { |method| assert !user.send("can_#{method}", root) } + %w{create read update delete}.each { |method| assert admin.send("can_#{method}", root) } + %w{create read update delete}.each { |method| assert admin.send("can_#{method}", folder) } + end + + test 'hashed_password and password_salt do not change when leaving the password empty' do + user = create(:user) + assert !user.password_salt.blank? + assert !user.hashed_password.blank? + + salt = user.password_salt + hash = user.hashed_password + + user.password_required = false + user.password = '' + user.password_confirmation = '' + + assert user.save + assert_equal user.password_salt, salt + assert_equal user.hashed_password, hash + end + + test 'hashed_password and password_salt change when updating the password' do + user = create(:user) + salt = user.password_salt + hash = user.hashed_password + + user.password = 'test1234' + user.password_confirmation = 'test1234' + + assert user.save + assert_not_equal user.password_salt, salt + assert_not_equal user.hashed_password, hash + assert User.authenticate(user.name, 'test1234') + end + + test 'whether a user is member of admins or not' do + admin = create(:user, :is_admin => true) + assert admin.member_of_admins? + + user = create(:user) + assert !user.member_of_admins? + + user.groups << Group.find_by_name('Admins') + assert user.member_of_admins? + end + + test 'whether reset_password_token refreshes' do + user = create(:user) + assert user.reset_password_token.blank? + + user.refresh_reset_password_token + assert !user.reset_password_token.blank? + assert_in_delta user.reset_password_token_expires_at, 1.hour.from_now, 1.second + + token = user.reset_password_token + user.refresh_reset_password_token + + assert !user.reset_password_token.blank? + assert_not_equal user.reset_password_token, token + end + + test 'whether remember_token refreshes' do + user = create(:user) + assert user.remember_token.blank? + + user.refresh_remember_token + assert !user.remember_token.blank? + + token = user.remember_token + user.refresh_remember_token + + assert !user.remember_token.blank? + assert_not_equal user.remember_token, token + end + + test 'whether forget_me clears remember_token' do + user = create(:user) + user.refresh_remember_token + assert !user.remember_token.blank? + + user.forget_me + assert user.remember_token.blank? + assert !user.changed? # There are no unsaved changes: `forget_me` saved the record + end + + test 'authentication' do + user = create(:user, :name => 'testname', :password => 'secret') + assert !User.authenticate(nil, nil) + assert !User.authenticate('', '') + assert !User.authenticate('testname', nil) + assert !User.authenticate('testname', '') + assert !User.authenticate(nil, 'secret') + assert !User.authenticate('', 'secret') + assert !User.authenticate('test', 'test') + assert User.authenticate('testname', 'secret') + end + + test 'whether there is an admin user or not' do + assert User.no_admin_yet? + + normal_user = create(:user) + assert User.no_admin_yet? + + # make normal_user admin + normal_user.is_admin = true + normal_user.save + + assert !User.no_admin_yet? + end +end