diff --git a/Gemfile b/Gemfile index 52c0d7ee..165f7640 100644 --- a/Gemfile +++ b/Gemfile @@ -1,4 +1,5 @@ source 'https://rubygems.org' +ruby "~> 2.3.0" gem 'rails', '4.2.7.1' gem 'puma', '~> 3.6.0' @@ -58,15 +59,22 @@ gem 'mixpanel-ruby' gem 'social-share-button' # Apps -gem 'easy_translate' +#gem 'easy_translate' gem 'levenshtein-ffi' +# Forum +gem 'thredded', '~> 0.13.2' +gem 'rails-ujs' +gem 'delayed_job_active_record' + # Tech debt & hacks gem 'binding_of_caller' # see has_changelog.rb group :production do gem 'rails_12factor' gem 'uglifier', '>= 1.3.0' + + gem 'newrelic_rpm' end group :test, :production do @@ -100,4 +108,4 @@ end group :test, :development do gem 'pry' -end \ No newline at end of file +end diff --git a/Gemfile.lock b/Gemfile.lock index ca433cc4..7e76fdd5 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -26,6 +26,8 @@ GEM erubis (~> 2.7.0) rails-dom-testing (~> 1.0, >= 1.0.5) rails-html-sanitizer (~> 1.0, >= 1.0.2) + active_record_union (1.2.0) + activerecord (>= 4.0) activejob (4.2.7.1) activesupport (= 4.2.7.1) globalid (>= 0.3.0) @@ -47,11 +49,17 @@ GEM ast (2.3.0) authority (3.2.2) activesupport (>= 3.0.0) + autoprefixer-rails (7.1.2.3) + execjs aws-sdk (1.66.0) aws-sdk-v1 (= 1.66.0) aws-sdk-v1 (1.66.0) json (~> 1.4) nokogiri (>= 1.4.4) + babel-source (5.8.35) + babel-transpiler (0.7.0) + babel-source (>= 4.0, < 6) + execjs (~> 2.0) bcrypt (3.1.11) better_errors (2.1.1) coderay (>= 1.0.0) @@ -94,6 +102,7 @@ GEM tins (>= 1.6.0, < 2) crack (0.4.3) safe_yaml (~> 1.0.0) + crass (1.0.2) cucumber (2.4.0) builder (>= 2.1.2) cucumber-core (~> 1.5.0) @@ -114,7 +123,14 @@ GEM database_cleaner (1.5.3) dateslices (0.0.4) rails (> 4) + db_text_search (0.2.2) + activerecord (>= 4.1.15, < 6.0) debug_inspector (0.0.2) + delayed_job (4.1.3) + activesupport (>= 3.0, < 5.2) + delayed_job_active_record (4.1.2) + activerecord (>= 3.0, < 5.2) + delayed_job (>= 3.0, < 5) devise (4.2.0) bcrypt (~> 3.0) orm_adapter (~> 0.1) @@ -125,10 +141,6 @@ GEM docile (1.1.5) domain_name (0.5.20161021) unf (>= 0.0.5, < 1.0.0) - easy_translate (0.5.0) - json - thread - thread_safe erubis (2.7.0) execjs (2.7.0) factory_girl (4.7.0) @@ -136,9 +148,13 @@ GEM factory_girl_rails (4.7.0) factory_girl (~> 4.7.0) railties (>= 3.0.0) + fast_blank (1.0.0) ffi (1.9.14) filesize (0.1.1) formatador (0.2.5) + friendly_id (5.2.1) + activerecord (>= 4.0.0) + gemoji (2.1.0) gherkin (4.0.0) globalid (0.3.7) activesupport (>= 4.1.0) @@ -159,13 +175,33 @@ GEM guard (~> 2.0) rubocop (~> 0.20) hashdiff (0.3.2) + html-pipeline (2.6.0) + activesupport (>= 2) + nokogiri (>= 1.4) + htmlentities (4.3.4) http-cookie (1.0.3) domain_name (~> 0.5) httparty (0.13.7) json (~> 1.8) multi_xml (>= 0.5.2) i18n (0.8.0) + inline_svg (1.2.2) + activesupport (>= 3.0) + nokogiri (>= 1.6) json (1.8.6) + kaminari (1.0.1) + activesupport (>= 4.1.0) + kaminari-actionview (= 1.0.1) + kaminari-activerecord (= 1.0.1) + kaminari-core (= 1.0.1) + kaminari-actionview (1.0.1) + actionview + kaminari-core (= 1.0.1) + kaminari-activerecord (1.0.1) + activerecord + kaminari-core (= 1.0.1) + kaminari-core (1.0.1) + kramdown (1.14.0) levenshtein-ffi (1.1.0) ffi (~> 1.9) libv8 (3.16.14.15) @@ -191,16 +227,29 @@ GEM mini_portile2 (2.1.0) minitest (5.10.1) mixpanel-ruby (2.2.0) + moneta (1.0.0) multi_json (1.12.1) multi_test (0.1.2) multi_xml (0.6.0) + mustache (1.0.5) nenv (0.3.0) netrc (0.11.0) + newrelic_rpm (4.5.0.337) nokogiri (1.7.0.1) mini_portile2 (~> 2.1.0) + nokogumbo (1.4.13) + nokogiri notiffany (0.1.1) nenv (~> 0.1) shellany (~> 0.0) + onebox (1.8.16) + fast_blank (>= 1.0.0) + htmlentities (~> 4.3) + moneta (~> 1.0) + multi_json (~> 1.11) + mustache + nokogiri (~> 1.7) + sanitize orm_adapter (0.5.0) paperclip (4.2.4) activemodel (>= 3.2.0) @@ -218,6 +267,8 @@ GEM puma (3.6.0) puma-heroku (1.0.0) puma (~> 3.0) + pundit (1.1.0) + activesupport (>= 3.0.0) rack (1.6.5) rack-test (0.6.3) rack (>= 1.0) @@ -244,6 +295,8 @@ GEM rails-jquery-autocomplete (1.0.3) rails (>= 3.2) rails-perftest (0.0.6) + rails-ujs (0.1.0) + railties (>= 3.1) rails_12factor (0.0.3) rails_serve_static_assets rails_stdout_logging @@ -261,6 +314,7 @@ GEM json rack rb-fsevent (0.9.7) + rb-gravatar (1.0.5) rb-inotify (0.9.7) ffi (>= 0.5.0) redcarpet (3.3.4) @@ -271,6 +325,7 @@ GEM http-cookie (>= 1.0.2, < 2.0) mime-types (>= 1.16, < 4.0) netrc (~> 0.8) + rinku (2.0.2) rmagick (2.13.4) rspec (3.5.0) rspec-core (~> 3.5.0) @@ -307,6 +362,10 @@ GEM ruby_dep (1.4.0) rubyzip (1.2.0) safe_yaml (1.0.4) + sanitize (4.5.0) + crass (~> 1.0.2) + nokogiri (>= 1.4.4) + nokogumbo (~> 1.4.1) sass (3.4.22) sass-rails (5.0.6) railties (>= 4.0.0, < 6) @@ -333,6 +392,10 @@ GEM sprockets (3.7.1) concurrent-ruby (~> 1.0) rack (> 1, < 3) + sprockets-es6 (0.9.2) + babel-source (>= 5.8.11) + babel-transpiler + sprockets (>= 3.0.0) sprockets-rails (3.2.0) actionpack (>= 4.0) activesupport (>= 4.0) @@ -346,9 +409,30 @@ GEM libv8 (~> 3.16.14.0) ref thor (0.19.4) - thread (0.2.2) thread_safe (0.3.5) + thredded (0.13.2) + active_record_union (>= 1.2.0) + autoprefixer-rails + db_text_search (~> 0.2.0) + friendly_id + gemoji (~> 2.1.0) + html-pipeline + htmlentities + inline_svg + kaminari + kramdown + nokogiri + onebox (~> 1.8, >= 1.8.13) + pundit (>= 1.1.0) + rails (>= 4.2.0) + rb-gravatar + rinku + sanitize + sass (>= 3.4.21) + sprockets-es6 + timeago_js tilt (2.0.5) + timeago_js (3.0.2) tins (1.12.0) tzinfo (1.2.2) thread_safe (~> 0.1) @@ -388,8 +472,8 @@ DEPENDENCIES cucumber-rails database_cleaner dateslices + delayed_job_active_record devise - easy_translate factory_girl_rails filesize guard @@ -400,6 +484,7 @@ DEPENDENCIES medium-editor-rails meta-tags mixpanel-ruby + newrelic_rpm paperclip pg pry @@ -409,6 +494,7 @@ DEPENDENCIES rails (= 4.2.7.1) rails-jquery-autocomplete rails-perftest + rails-ujs rails_12factor raygun4ruby redcarpet @@ -427,9 +513,13 @@ DEPENDENCIES sqlite3 stripe therubyracer + thredded (~> 0.13.2) tzinfo-data uglifier (>= 1.3.0) webmock +RUBY VERSION + ruby 2.3.1p112 + BUNDLED WITH - 1.14.4 + 1.16.0.pre.3 diff --git a/README.rdoc b/README.rdoc index d7db7918..3b7c7f3c 100644 --- a/README.rdoc +++ b/README.rdoc @@ -1,12 +1,12 @@ -= notebook += Notebook.ai {Build Status}[https://travis-ci.org/indentlabs/notebook] {}[https://codeclimate.com/github/indentlabs/notebook] {}[https://codeclimate.com/github/indentlabs/notebook/coverage] {Inline docs}[http://inch-ci.org/github/indentlabs/notebook] - -== What is notebook? + +== What is Notebook.ai? see {live website}[http://notebook.ai/] - + notebook is a set of tools for writers, game designers, and roleplayers to create magnificent universes – and everything within them. From a simple interface in your browser, on your phone, or on your tablet, you can do everything you'd ever want to do while creating your own little (or big!) world. diff --git a/app/assets/stylesheets/documents.scss b/app/assets/stylesheets/documents.scss deleted file mode 100644 index ec6aac28..00000000 --- a/app/assets/stylesheets/documents.scss +++ /dev/null @@ -1,3 +0,0 @@ -// Place all the styles related to the Documents controller here. -// They will automatically be included in application.css. -// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/assets/stylesheets/emails.scss b/app/assets/stylesheets/emails.scss deleted file mode 100644 index 35db24d0..00000000 --- a/app/assets/stylesheets/emails.scss +++ /dev/null @@ -1,3 +0,0 @@ -// Place all the styles related to the Emails controller here. -// They will automatically be included in application.css. -// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/assets/stylesheets/lab.scss b/app/assets/stylesheets/lab.scss deleted file mode 100644 index 7288a665..00000000 --- a/app/assets/stylesheets/lab.scss +++ /dev/null @@ -1,3 +0,0 @@ -// Place all the styles related to the Lab controller here. -// They will automatically be included in application.css. -// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/assets/stylesheets/navigator.css b/app/assets/stylesheets/navigator.css deleted file mode 100644 index 4bfbeb09..00000000 --- a/app/assets/stylesheets/navigator.css +++ /dev/null @@ -1,3 +0,0 @@ -// Place all the styles related to the Navigator controller here. -// They will automatically be included in application.css. -// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/assets/stylesheets/voting.scss b/app/assets/stylesheets/voting.scss deleted file mode 100644 index 17469c52..00000000 --- a/app/assets/stylesheets/voting.scss +++ /dev/null @@ -1,3 +0,0 @@ -// Place all the styles related to the Voting controller here. -// They will automatically be included in application.css. -// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/authorizers/collective_content_authorizer.rb b/app/authorizers/collective_content_authorizer.rb index 64606da0..cd77b85e 100644 --- a/app/authorizers/collective_content_authorizer.rb +++ b/app/authorizers/collective_content_authorizer.rb @@ -1,6 +1,7 @@ class CollectiveContentAuthorizer < ContentAuthorizer def self.creatable_by? user - return true + return false if ENV.key?('CONTENT_BLACKLIST') && ENV['CONTENT_BLACKLIST'].split(',').include?(user.email) + [ PermissionService.billing_plan_allows_collective_content?(user: user), PermissionService.user_can_collaborate_in_universe_that_allows_collective_content?(user: user) diff --git a/app/authorizers/core_content_authorizer.rb b/app/authorizers/core_content_authorizer.rb index 4fd998b4..0050fdf4 100644 --- a/app/authorizers/core_content_authorizer.rb +++ b/app/authorizers/core_content_authorizer.rb @@ -1,6 +1,7 @@ class CoreContentAuthorizer < ContentAuthorizer def self.creatable_by? user - return true + return false if ENV.key?('CONTENT_BLACKLIST') && ENV['CONTENT_BLACKLIST'].split(',').include?(user.email) + [ PermissionService.billing_plan_allows_core_content?(user: user) ].any? diff --git a/app/authorizers/extended_content_authorizer.rb b/app/authorizers/extended_content_authorizer.rb index 420c36b0..28c0b781 100644 --- a/app/authorizers/extended_content_authorizer.rb +++ b/app/authorizers/extended_content_authorizer.rb @@ -1,6 +1,7 @@ class ExtendedContentAuthorizer < ContentAuthorizer def self.creatable_by? user - return true + return false if ENV.key?('CONTENT_BLACKLIST') && ENV['CONTENT_BLACKLIST'].split(',').include?(user.email) + [ PermissionService.billing_plan_allows_extended_content?(user: user), PermissionService.user_can_collaborate_in_universe_that_allows_extended_content?(user: user) diff --git a/app/authorizers/universe_core_content_authorizer.rb b/app/authorizers/universe_core_content_authorizer.rb index 82f0113f..793be96c 100644 --- a/app/authorizers/universe_core_content_authorizer.rb +++ b/app/authorizers/universe_core_content_authorizer.rb @@ -1,6 +1,7 @@ class UniverseCoreContentAuthorizer < CoreContentAuthorizer def self.creatable_by? user - return true + return false if ENV.key?('CONTENT_BLACKLIST') && ENV['CONTENT_BLACKLIST'].split(',').include?(user.email) + [ PermissionService.user_has_fewer_owned_universes_than_plan_limit?(user: user), PermissionService.user_is_on_premium_plan?(user: user) diff --git a/app/controllers/content_controller.rb b/app/controllers/content_controller.rb index 8093efc8..59c0e560 100644 --- a/app/controllers/content_controller.rb +++ b/app/controllers/content_controller.rb @@ -34,6 +34,8 @@ class ContentController < ApplicationController # TODO: Secure this with content class whitelist lel @content = content_type.find(params[:id]) + return if ENV['CONTENT_BLACKLIST'].split(',').include?(@content.user.email) + if (current_user || User.new).can_read? @content @question = @content.question if current_user.present? and current_user == @content.user diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb index 80711e39..777d289f 100644 --- a/app/controllers/registrations_controller.rb +++ b/app/controllers/registrations_controller.rb @@ -15,7 +15,7 @@ class RegistrationsController < Devise::RegistrationsController end def account_update_params - params.require(:user).permit(:name, :email, :password, :password_confirmation, :current_password, :email_updates, :fluid_preference) + params.require(:user).permit(:name, :email, :username, :password, :password_confirmation, :current_password, :email_updates, :fluid_preference) end protected diff --git a/app/models/user.rb b/app/models/user.rb index 9a008063..8e2ac5d3 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -11,6 +11,8 @@ class User < ActiveRecord::Base include HasContent include Authority::UserAbilities + validates_uniqueness_of :username, allow_nil: true, allow_blank: true + has_many :subscriptions has_many :billing_plans, through: :subscriptions def on_premium_plan? @@ -139,4 +141,12 @@ class User < ActiveRecord::Base :email ] end + + def forum_username + username = self.username.present? ? "@#{self.username}" : nil + username ||= self.name.present? ? self.name : nil + username ||= 'Anonymous Author' + + username + end end diff --git a/app/views/content/index.html.erb b/app/views/content/index.html.erb index fc5ab6e9..3640273f 100644 --- a/app/views/content/index.html.erb +++ b/app/views/content/index.html.erb @@ -83,20 +83,3 @@ <% end %> - -
-
- You've been upgraded to a free Premium account for the month of October! -

- Notebook.ai just hit 10,000 users! To celebrate, every single user is free to create any kind of Notebook.ai page (like <%= content_type.humanize.downcase.pluralize %>!) for the entire month of October. -

-
-

- Whatever you create is yours forever — you'll never lose access to it, even after October. - Get ready for National Novel Writing Month and worldbuild away! -

-
-
- Read more -
-
\ No newline at end of file diff --git a/app/views/devise/registrations/edit.html.erb b/app/views/devise/registrations/edit.html.erb index 7a7a4aa7..3e1966ee 100644 --- a/app/views/devise/registrations/edit.html.erb +++ b/app/views/devise/registrations/edit.html.erb @@ -6,13 +6,18 @@

Personal information

- <%= f.label :name %>
- <%= f.text_field :name %> + <%= f.label 'Name (visible on your profile and forum posts)' %>
+ <%= f.text_field :name, autofocus: true %>
- <%= f.label :email %>
- <%= f.email_field :email, autofocus: true %> + <%= f.label 'Email (always completely private)' %>
+ <%= f.email_field :email %> +
+ +
+ <%= f.label 'Username (users can @mention you with your username on the forums)' %>
+ <%= f.text_field :username %>
@@ -54,7 +59,7 @@
<%= f.check_box :email_updates %> <%= f.label :email_updates do %> - If this box is checked, you will receive occasional updates by email about new Notebook.ai features. + I want to receive occasional updates by email about new Notebook.ai features. <% end %>
diff --git a/app/views/layouts/_navbar.html.erb b/app/views/layouts/_navbar.html.erb index 7218a1e9..910d7a57 100644 --- a/app/views/layouts/_navbar.html.erb +++ b/app/views/layouts/_navbar.html.erb @@ -19,7 +19,7 @@
  • - <%= link_to privacy_policy_path do %> + <%= link_to main_app.privacy_policy_path do %> verified_user Privacy policy <% end %> @@ -57,14 +57,14 @@
  • - <%= link_to subscription_path do %> + <%= link_to main_app.subscription_path do %> credit_card Account billing   <% end %>
  • - <%= link_to edit_user_registration_path do %> + <%= link_to main_app.edit_user_registration_path do %> settings Account settings   @@ -75,13 +75,13 @@
  • - <%= link_to prompts_path do %> + <%= link_to main_app.prompts_path do %> lightbulb_outline Worldbuilding prompts <% end %>
  • - <%= link_to notebook_export_path do %> + <%= link_to main_app.notebook_export_path do %> file_download Notebook downloads <% end %>
  • - <%= link_to destroy_user_session_path do %> + <%= link_to main_app.destroy_user_session_path do %> power_settings_new Sign out <% end %> @@ -111,20 +111,20 @@