CVE-2023-48220: Insufficient Information (NVD-CWE-noinfo)
value: Decidim is a participatory democracy framework. Starting in version 0.4.rc3 and prior to version 2.0.9 of the `devise_invitable` gem, the invites feature allows users to accept the invitation for an unlimited amount of time through the password reset functionality. This issue creates vulnerable dependencies starting in version 0.0.1.alpha3 and prior to versions 0.26.9, 0.27.5, and 0.28.0 of the `decidim,` `decidim-admin`, and `decidim-system` gems. When using the password reset functionality, the `devise_invitable` gem always accepts the pending invitation if the user has been invited. The only check done is if the user has been invited but the code does not ensure that the pending invitation is still valid as defined by the `invite_for` expiry period. Decidim sets this configuration to `2.weeks` so this configuration should be respected. The bug is in the `devise_invitable` gem and should be fixed there and the dependency should be upgraded in Decidim once the fix becomes available. `devise_invitable` to version `2.0.9` and above fix this issue. Versions 0.26.9, 0.27.5, and 0.28.0 of the `decidim,` `decidim-admin`, and `decidim-system` gems contain this fix. As a workaround, invitations can be cancelled directly from the database.
CWE description: There is insufficient information about the issue to classify it; details are unkown or unspecified.
Published: 2024-02-20T18:15Z
Repository: https://github.com/decidim/decidim
Language: Ruby
Files changed: .hound.yml, .rubocop.yml, Gemfile, Gemfile.lock, Rakefile, common_gemfile.rb, decidim-core/Gemfile, decidim-core/Gemfile.lock, decidim-core/Rakefile, decidim-core/app/assets/javascripts/decidim.js, decidim-core/app/assets/stylesheets/decidim.scss, decidim-core/app/models/decidim/organization.rb, decidim-core/app/models/decidim/user.rb, decidim-core/app/views/layouts/decidim/_header.html.erb, decidim-core/app/views/users/mailer/invitation_instructions.html.erb, decidim-core/app/views/users/mailer/invitation_instructions.text.erb, decidim-core/bin/rails, decidim-core/config/i18n-tasks.yml, decidim-core/config/initializers/devise.rb, decidim-core/config/locales/en.yml, decidim-core/config/routes.rb, decidim-core/db/migrate/20160919104837_create_decidim_organizations.rb, decidim-core/db/migrate/20160920140207_devise_invitable_add_to_decidim_users.rb, decidim-core/db/migrate/20160920141039_user_belongs_to_organization.rb, decidim-core/db/migrate/20160920141151_user_has_roles.rb, decidim-core/decidim-core.gemspec, decidim-core/lib/decidim/core.rb, decidim-core/lib/decidim/core/engine.rb, decidim-core/lib/decidim/devise_failure_app.rb, decidim-core/lib/generators/decidim/install_generator.rb, decidim-core/lib/tasks/factory_girl.rake, decidim-core/spec/factories.rb, decidim-core/spec/i18n_spec.rb, decidim-core/spec/models/decidim/organization_spec.rb, decidim-core/spec/models/decidim/user_spec.rb, decidim-core/spec/spec_helper.rb, decidim-core/spec/support/database_cleaner.rb, decidim-core/spec/support/factory_girl.rb, decidim-system/Gemfile, decidim-system/Gemfile.lock, decidim-system/README.md, decidim-system/Rakefile, decidim-system/app/assets/config/decidim_system_manifest.js, decidim-system/app/assets/javascripts/decidim/system.js, decidim-system/app/assets/stylesheets/decidim/system.scss, decidim-system/app/assets/stylesheets/decidim/system/_actions.scss, decidim-system/app/assets/stylesheets/decidim/system/_foundation_and_overrides.scss, decidim-system/app/assets/stylesheets/decidim/system/_layout.scss, decidim-system/app/assets/stylesheets/decidim/system/_login.scss, decidim-system/app/assets/stylesheets/decidim/system/_settings.scss, decidim-system/app/assets/stylesheets/decidim/system/_sidebar.scss, decidim-system/app/assets/stylesheets/decidim/system/_tables.scss, decidim-system/app/commands/decidim/system/create_admin.rb, decidim-system/app/commands/decidim/system/register_organization.rb, decidim-system/app/commands/decidim/system/update_admin.rb, decidim-system/app/commands/decidim/system/update_organization.rb, decidim-system/app/controllers/decidim/system/admins_controller.rb, decidim-system/app/controllers/decidim/system/application_controller.rb, decidim-system/app/controllers/decidim/system/dashboard_controller.rb, decidim-system/app/controllers/decidim/system/devise/passwords_controller.rb, decidim-system/app/controllers/decidim/system/devise/sessions_controller.rb, decidim-system/app/controllers/decidim/system/organizations_controller.rb, decidim-system/app/forms/decidim/system/admin_form.rb, decidim-system/app/forms/decidim/system/register_organization_form.rb, decidim-system/app/forms/decidim/system/update_organization_form.rb, decidim-system/app/helpers/decidim/system/application_helper.rb, decidim-system/app/jobs/decidim/system/application_job.rb, decidim-system/app/mailers/decidim/system/application_mailer.rb, decidim-system/app/models/decidim/system/admin.rb, decidim-system/app/models/decidim/system/application_record.rb, decidim-system/app/views/decidim/system/admins/_form.html.erb, decidim-system/app/views/decidim/system/admins/edit.html.erb, decidim-system/app/views/decidim/system/admins/index.html.erb, decidim-system/app/views/decidim/system/admins/new.html.erb, decidim-system/app/views/decidim/system/admins/show.html.erb, decidim-system/app/views/decidim/system/dashboard/show.html.erb, decidim-system/app/views/decidim/system/devise/mailers/password_change.html.erb, decidim-system/app/views/decidim/system/devise/mailers/reset_password_instructions.html.erb, decidim-system/app/views/decidim/system/devise/passwords/edit.html.erb, decidim-system/app/views/decidim/system/devise/passwords/new.html.erb, decidim-system/app/views/decidim/system/devise/sessions/new.html.erb, decidim-system/app/views/decidim/system/devise/shared/_links.html.erb, decidim-system/app/views/decidim/system/organizations/edit.html.erb, decidim-system/app/views/decidim/system/organizations/index.html.erb, decidim-system/app/views/decidim/system/organizations/new.html.erb, decidim-system/app/views/decidim/system/organizations/show.html.erb, decidim-system/app/views/layouts/decidim/system/_header.html.erb, decidim-system/app/views/layouts/decidim/system/_login_items.html.erb, decidim-system/app/views/layouts/decidim/system/_sidebar.html.erb, decidim-system/app/views/layouts/decidim/system/application.html.erb, decidim-system/app/views/layouts/decidim/system/login.html.erb, decidim-system/bin/rails, decidim-system/config/i18n-tasks.yml, decidim-system/config/locales/en.yml, decidim-system/config/routes.rb, decidim-system/db/migrate/20160919105637_devise_create_decidim_admins.rb, decidim-system/decidim-system.gemspec, decidim-system/lib/decidim/system.rb, decidim-system/lib/decidim/system/engine.rb, decidim-system/lib/generators/decidim/system/dummy_generator.rb, decidim-system/lib/tasks/decidim/system_tasks.rake, decidim-system/spec/commands/decidim/system/create_admin_spec.rb, decidim-system/spec/commands/decidim/system/register_organization_spec.rb, decidim-system/spec/factories.rb, decidim-system/spec/features/manage_admins_spec.rb, decidim-system/spec/features/organizations_spec.rb, decidim-system/spec/features/sessions_spec.rb, decidim-system/spec/i18n_spec.rb, decidim-system/spec/spec_helper.rb, decidim-system/spec/support/database_cleaner.rb, decidim-system/spec/support/factory_girl.rb, decidim-system/spec/support/warden.rb, decidim-system/spec/support/wisper.rb, decidim.gemspec, lib/decidim.rb, lib/generators/decidim/templates/Gemfile.erb, spec/decidim_spec.rb
Commit date: 2016-09-23 15:40:38 +0200
Commit message: System admin (#9)

Add system panel
Diff: diff --git a/.hound.yml b/.hound.yml
index abca34aae..8798c91f8 100644
--- a/.hound.yml
+++ b/.hound.yml
@@ -1,4 +1,8 @@
 ruby:
   config_file: .rubocop.yml
+scss:
+  enabled: false
+jshint:
+  enabled: false
 
 fail_on_violations: true
\ No newline at end of file
diff --git a/.rubocop.yml b/.rubocop.yml
index dedeeaada..86e259501 100644
--- a/.rubocop.yml
+++ b/.rubocop.yml
@@ -21,13 +21,13 @@ AllCops:
     - '**/*Fastfile'
   Exclude:
     - '**/Gemfile'
     - 'vendor/**/*'
     - 'spec/*'
-    - 'decidim-core/spec/**/*'
-    - 'decidim-core/test/**/*'
-    - 'decidim-core/db/**/*'
+    - 'decidim-*/spec/**/*'
+    - 'decidim-*/test/**/*'
+    - 'decidim-*/db/**/*'
   # Default formatter will be used if no -f/--format option is given.
   DefaultFormatter: progress
   # Cop names are not displayed in offense messages by default. Change behavior
   # by overriding DisplayCopNames, or by giving the -D/--display-cop-names
   # option.
@@ -91,10 +91,14 @@ Style/Alias:
   EnforcedStyle: prefer_alias
   SupportedStyles:
     - prefer_alias
     - prefer_alias_method
 
+Style/AccessorMethodName:
+  Exclude:
+    - "lib/generators/decidim/app_generator.rb"
+
 # Align the elements of a hash literal if they span more than one line.
 Style/AlignHash:
   # Alignment of entries using hash rocket as separator. Valid values are:
   #
   # key - left alignment of keys
@@ -291,10 +295,11 @@ Style/CaseIndentation:
   # But it can be overridden by setting this parameter
   # This only matters if IndentOneStep is true
   IndentationWidth: ~
 
 Style/ClassAndModuleChildren:
+  Enabled: false
   # Checks the style of children definitions at classes and modules.
   #
   # Basically there are two different styles:
   #
   # `nested` - have each child on a separate line
@@ -812,10 +817,14 @@ Style/PredicateName:
   # Exclude Rspec specs because there is a strong convetion to write spec
   # helpers in the form of `have_something` or `be_something`.
   Exclude:
     - 'spec/**/*'
 
+Style/Documentation:
+  Exclude:
+    - '**/*/spec/**/*_spec.rb'
+
 Style/RaiseArgs:
   EnforcedStyle: exploded
   SupportedStyles:
     - compact # raise Exception.new(msg)
     - exploded # raise Exception, msg
@@ -1079,10 +1088,11 @@ Style/WordArray:
 
 Metrics/AbcSize:
   # The ABC size is a calculated magnitude, so this number can be an Integer or
   # a Float.
   Max: 15
+  Enabled: false
 
 Metrics/BlockNesting:
   Max: 3
 
 Metrics/ClassLength:
diff --git a/Gemfile b/Gemfile
index 7aca71e73..2a1ec2d48 100644
--- a/Gemfile
+++ b/Gemfile
@@ -3,5 +3,10 @@ eval(File.read(File.dirname(__FILE__) + "/common_gemfile.rb"))
 
 # Specify your gem's dependencies in decidim.gemspec
 gemspec
 gem "rspec_junit_formatter", "0.2.3", group: :test, require: false
 gem "codecov", require: false, group: :test
+
+gemspec path: "."
+gemspec path: "decidim-core"
+
+gem "rubocop"
diff --git a/Gemfile.lock b/Gemfile.lock
index cee121929..317eea9b1 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -1,15 +1,53 @@
+GIT
+  remote: git://github.com/sgruhier/foundation_rails_helper.git
+  revision: 809f127b76747b53fb199ff4e5d3f06aa3d35f97
+  specs:
+    foundation_rails_helper (2.0.0)
+      actionpack (>= 4.1)
+      activemodel (>= 4.1)
+      activesupport (>= 4.1)
+      railties (>= 4.1)
+      tzinfo (~> 1.2, >= 1.2.2)
+
 PATH
   remote: .
   specs:
     decidim (0.0.1.alpha2)
       decidim-core (= 0.0.1.alpha2)
+      decidim-system (= 0.0.1.alpha2)
+      rails (~> 5.0.0)
+    decidim-system (0.0.1.alpha2)
+      active_link_to (~> 1.0.0)
+      decidim-core
+      devise (~> 4.2)
+      devise_invitable (~> 1.7.0)
+      foundation-rails (~> 6.2.3.0)
+      foundation_rails_helper (~> 2.0.0)
+      jbuilder (~> 2.5)
+      jquery-rails (~> 4.0)
+      jquery-turbolinks (~> 2.1.0)
       rails (~> 5.0.0)
+      rectify (~> 0.6)
+      sass-rails (~> 5.0.0)
+      turbolinks (~> 5.0.0)
+
+PATH
+  remote: decidim-core
+  specs:
     decidim-core (0.0.1.alpha2)
-      devise
-      foundation-rails (~> 6.2.3)
+      active_link_to (~> 1.0.0)
+      devise (~> 4.2)
+      foundation-rails (~> 6.2.3.0)
+      foundation_rails_helper (~> 2.0.0)
+      jbuilder (~> 2.5)
+      jquery-rails (~> 4.0)
+      jquery-turbolinks (~> 2.1.0)
       rails (~> 5.0.0)
+      rectify (~> 0.6)
+      sass-rails (~> 5.0.0)
+      turbolinks (~> 5.0.0)
 
 GEM
   remote: https://rubygems.org/
   specs:
     actioncable (5.0.0.1)
@@ -33,10 +71,12 @@ GEM
       activesupport (= 5.0.0.1)
       builder (~> 3.1)
       erubis (~> 2.7.0)
       rails-dom-testing (~> 2.0)
       rails-html-sanitizer (~> 1.0, >= 1.0.2)
+    active_link_to (1.0.3)
+      actionpack
     activejob (5.0.0.1)
       activesupport (= 5.0.0.1)
       globalid (>= 0.3.6)
     activemodel (5.0.0.1)
       activesupport (= 5.0.0.1)
@@ -49,10 +89,15 @@ GEM
       i18n (~> 0.7)
       minitest (~> 5.1)
       tzinfo (~> 1.1)
     addressable (2.4.0)
     arel (7.1.2)
+    ast (2.3.0)
+    axiom-types (0.1.1)
+      descendants_tracker (~> 0.0.4)
+      ice_nine (~> 0.11.0)
+      thread_safe (~> 0.3, >= 0.3.1)
     babel-source (5.8.35)
     babel-transpiler (0.7.0)
       babel-source (>= 4.0, < 6)
       execjs (~> 2.0)
     bcrypt (3.1.11)
@@ -67,43 +112,69 @@ GEM
       xpath (~> 2.0)
     codecov (0.1.5)
       json
       simplecov
       url
-    coffee-rails (4.2.1)
-      coffee-script (>= 2.2.0)
-      railties (>= 4.0.0, < 5.2.x)
-    coffee-script (2.4.1)
-      coffee-script-source
-      execjs
-    coffee-script-source (1.10.0)
+    coercible (1.0.0)
+      descendants_tracker (~> 0.0.1)
     concurrent-ruby (1.0.2)
+    database_cleaner (1.5.3)
+    descendants_tracker (0.0.4)
+      thread_safe (~> 0.3, >= 0.3.1)
     devise (4.2.0)
       bcrypt (~> 3.0)
       orm_adapter (~> 0.1)
       railties (>= 4.1.0, < 5.1)
       responders
       warden (~> 1.2.3)
+    devise_invitable (1.7.0)
+      actionmailer (>= 4.0.0)
+      devise (>= 4.0.0)
     diff-lcs (1.2.5)
     docile (1.1.5)
+    easy_translate (0.5.0)
+      json
+      thread
+      thread_safe
+    equalizer (0.0.11)
     erubis (2.7.0)
     execjs (2.7.0)
+    factory_girl (4.7.0)
+      activesupport (>= 3.0.0)
+    factory_girl_rails (4.7.0)
+      factory_girl (~> 4.7.0)
+      railties (>= 3.0.0)
     ffi (1.9.14)
     foundation-rails (6.2.3.0)
       railties (>= 3.1.0)
       sass (>= 3.3.0, < 3.5)
       sprockets-es6 (>= 0.9.0)
     globalid (0.3.7)
       activesupport (>= 4.1.0)
+    highline (1.7.8)
     i18n (0.7.0)
+    i18n-tasks (0.9.5)
+      activesupport (>= 4.0.2)
+      ast (>= 2.1.0)
+      easy_translate (>= 0.5.0)
+      erubis
+      highline (>= 1.7.3)
+      i18n
+      parser (>= 2.2.3.0)
+      term-ansicolor (>= 1.3.2)
+      terminal-table (>= 1.5.1)
+    ice_nine (0.11.2)
     jbuilder (2.6.0)
       activesupport (>= 3.0.0, < 5.1)
       multi_json (~> 1.2)
     jquery-rails (4.2.1)
       rails-dom-testing (>= 1, < 3)
       railties (>= 4.2.0)
       thor (>= 0.14, < 2.0)
+    jquery-turbolinks (2.1.0)
+      railties (>= 3.1.0)
+      turbolinks
     json (2.0.2)
     listen (3.0.8)
       rb-fsevent (~> 0.9, >= 0.9.4)
       rb-inotify (~> 0.9, >= 0.9.7)
     loofah (2.0.3)
@@ -120,12 +191,15 @@ GEM
     nio4r (1.2.1)
     nokogiri (1.6.8)
       mini_portile2 (~> 2.1.0)
       pkg-config (~> 1.1.7)
     orm_adapter (0.5.0)
+    parser (2.3.1.4)
+      ast (~> 2.2)
     pg (0.18.4)
     pkg-config (1.1.7)
+    powerpack (0.1.1)
     rack (2.0.1)
     rack-test (0.6.3)
       rack (>= 1.0)
     rails (5.0.0.1)
       actioncable (= 5.0.0.1)
@@ -148,14 +222,21 @@ GEM
       actionpack (= 5.0.0.1)
       activesupport (= 5.0.0.1)
       method_source
       rake (>= 0.8.7)
       thor (>= 0.18.1, < 2.0)
-    rake (10.5.0)
+    rainbow (2.1.0)
+    rake (11.3.0)
     rb-fsevent (0.9.7)
     rb-inotify (0.9.7)
       ffi (>= 0.5.0)
+    rectify (0.6.1)
+      activemodel (>= 4.1.0)
+      activerecord (>= 4.1.0)
+      activesupport (>= 4.1.0)
+      virtus (~> 1.0.5)
+      wisper (>= 1.6.1)
     responders (2.3.0)
       railties (>= 4.2.0, < 5.1)
     rspec (3.5.0)
       rspec-core (~> 3.5.0)
       rspec-expectations (~> 3.5.0)
@@ -178,10 +259,17 @@ GEM
       rspec-support (~> 3.5.0)
     rspec-support (3.5.0)
     rspec_junit_formatter (0.2.3)
       builder (< 4)
       rspec-core (>= 2, < 4, != 2.12.0)
+    rubocop (0.43.0)
+      parser (>= 2.3.1.1, < 3.0)
+      powerpack (~> 0.1)
+      rainbow (>= 1.99.1, < 3.0)
+      ruby-progressbar (~> 1.7)
+      unicode-display_width (~> 1.0, >= 1.0.1)
+    ruby-progressbar (1.8.1)
     sass (3.4.22)
     sass-rails (5.0.6)
       railties (>= 4.0.0, < 6)
       sass (~> 3.1)
       sprockets (>= 2.8, < 4.0)
@@ -201,26 +289,38 @@ GEM
       sprockets (>= 3.0.0)
     sprockets-rails (3.1.1)
       actionpack (>= 4.0)
       activesupport (>= 4.0)
       sprockets (>= 3.0.0)
+    term-ansicolor (1.3.2)
+      tins (~> 1.0)
+    terminal-table (1.7.3)
+      unicode-display_width (~> 1.1.1)
     thor (0.19.1)
+    thread (0.2.2)
     thread_safe (0.3.5)
     tilt (2.0.5)
+    tins (1.12.0)
     turbolinks (5.0.1)
       turbolinks-source (~> 5)
     turbolinks-source (5.0.0)
     tzinfo (1.2.2)
       thread_safe (~> 0.1)
-    uglifier (3.0.2)
-      execjs (>= 0.3.0, < 3)
+    unicode-display_width (1.1.1)
     url (0.3.2)
+    virtus (1.0.5)
+      axiom-types (~> 0.1)
+      coercible (~> 1.0)
+      descendants_tracker (~> 0.0, >= 0.0.3)
+      equalizer (~> 0.0, >= 0.0.9)
     warden (1.2.6)
       rack (>= 1.0)
     websocket-driver (0.6.4)
       websocket-extensions (>= 0.1.0)
     websocket-extensions (0.1.2)
+    wisper (1.6.1)
+    wisper-rspec (0.0.2)
     xpath (2.0.0)
       nokogiri (~> 1.3)
 
 PLATFORMS
   ruby
@@ -228,23 +328,24 @@ PLATFORMS
 DEPENDENCIES
   bundler (~> 1.12)
   byebug
   capybara (~> 2.4)
   codecov
-  coffee-rails (~> 4.2)
+  database_cleaner (~> 1.5.0)
   decidim!
-  jbuilder (~> 2.5)
-  jquery-rails
+  decidim-core!
+  factory_girl_rails
+  foundation_rails_helper!
+  i18n-tasks (~> 0.9.5)
   listen
   pg
-  rake (~> 10.0)
+  rake (~> 11.0)
   rspec (~> 3.0)
   rspec-rails (~> 3.5)
   rspec_junit_formatter (= 0.2.3)
-  sass-rails (~> 5.0)
-  turbolinks (~> 5)
-  uglifier (>= 1.3.0)
+  rubocop
+  wisper-rspec
 
 RUBY VERSION
    ruby 2.3.1p112
 
 BUNDLED WITH
diff --git a/Rakefile b/Rakefile
index 28cd6bce7..b8e469823 100644
--- a/Rakefile
+++ b/Rakefile
@@ -6,30 +6,21 @@ begin
   require "decidim/testing_support/common_rake"
 rescue LoadError
   raise "Could not find decidim/testing_support/common_rake. You need to run this command using Bundler."
 end
 
-DECIDIM_GEMS = %w(core).freeze
+DECIDIM_GEMS = %w(core system).freeze
 
 RSpec::Core::RakeTask.new(:spec)
 
 task default: :test
 
 desc "Runs all tests in all Decidim engines"
-task test: :test_app do
+task :test do
   DECIDIM_GEMS.each do |gem_name|
     Dir.chdir("#{File.dirname(__FILE__)}/decidim-#{gem_name}") do
-      sh "rspec"
-    end
-  end
-end
-
-desc "Generates a dummy app for testing for every Decidim engine"
-task :test_app do
-  DECIDIM_GEMS.each do |gem_name|
-    Dir.chdir("#{File.dirname(__FILE__)}/decidim-#{gem_name}") do
-      sh "rake test_app"
+      sh "rake"
     end
   end
 end
 
 desc "Pushes a new build for each gem."
diff --git a/common_gemfile.rb b/common_gemfile.rb
index cdfefe08f..bfe1918a3 100644
--- a/common_gemfile.rb
+++ b/common_gemfile.rb
@@ -1,24 +1,9 @@
 # frozen_string_literal: true
 source "https://rubygems.org"
 
-ruby '2.3.1'
+ruby "2.3.1"
 
 gem "pg"
+gem "listen"
 
-# Rails 5 deps
-gem "sass-rails", "~> 5.0"
-gem "uglifier", ">= 1.3.0"
-gem "coffee-rails", "~> 4.2"
-gem "jquery-rails"
-gem "turbolinks", "~> 5"
-gem "jbuilder", "~> 2.5"
-
-group :development do
-  gem "byebug"
-  gem "listen"
-end
-
-group :test do
-  gem "capybara", "~> 2.4"
-  gem "rspec-rails", "~> 3.5"
-end
+gem "foundation_rails_helper", github: "sgruhier/foundation_rails_helper"
diff --git a/decidim-core/Gemfile b/decidim-core/Gemfile
index f6d3424ed..cb0eed623 100644
--- a/decidim-core/Gemfile
+++ b/decidim-core/Gemfile
@@ -11,5 +11,8 @@ gemspec
 # 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]
+
+gemspec path: "../decidim-system"
+gemspec path: ".."
diff --git a/decidim-core/Gemfile.lock b/decidim-core/Gemfile.lock
index 6ea4dfa95..a5c6125e3 100644
--- a/decidim-core/Gemfile.lock
+++ b/decidim-core/Gemfile.lock
@@ -1,13 +1,57 @@
+GIT
+  remote: git://github.com/sgruhier/foundation_rails_helper.git
+  revision: 809f127b76747b53fb199ff4e5d3f06aa3d35f97
+  specs:
+    foundation_rails_helper (2.0.0)
+      actionpack (>= 4.1)
+      activemodel (>= 4.1)
+      activesupport (>= 4.1)
+      railties (>= 4.1)
+      tzinfo (~> 1.2, >= 1.2.2)
+
+PATH
+  remote: ../decidim-system
+  specs:
+    decidim-system (0.0.1.alpha2)
+      active_link_to (~> 1.0.0)
+      decidim-core
+      devise (~> 4.2)
+      devise_invitable (~> 1.7.0)
+      foundation-rails (~> 6.2.3.0)
+      foundation_rails_helper (~> 2.0.0)
+      jbuilder (~> 2.5)
+      jquery-rails (~> 4.0)
+      jquery-turbolinks (~> 2.1.0)
+      rails (~> 5.0.0)
+      rectify (~> 0.6)
+      sass-rails (~> 5.0.0)
+      turbolinks (~> 5.0.0)
+
+PATH
+  remote: ..
+  specs:
+    decidim (0.0.1.alpha2)
+      decidim-core (= 0.0.1.alpha2)
+      decidim-system (= 0.0.1.alpha2)
+      rails (~> 5.0.0)
+
 PATH
   remote: .
   specs:
     decidim-core (0.0.1.alpha2)
-      devise
+      active_link_to (~> 1.0.0)
+      devise (~> 4.2)
       foundation-rails (~> 6.2.3.0)
+      foundation_rails_helper (~> 2.0.0)
+      jbuilder (~> 2.5)
+      jquery-rails (~> 4.0)
+      jquery-turbolinks (~> 2.1.0)
       rails (~> 5.0.0)
+      rectify (~> 0.6)
       sass-rails (~> 5.0.0)
+      turbolinks (~> 5.0.0)
 
 GEM
   remote: https://rubygems.org/
   specs:
     actioncable (5.0.0.1)
@@ -31,10 +75,12 @@ GEM
       activesupport (= 5.0.0.1)
       builder (~> 3.1)
       erubis (~> 2.7.0)
       rails-dom-testing (~> 2.0)
       rails-html-sanitizer (~> 1.0, >= 1.0.2)
+    active_link_to (1.0.3)
+      actionpack
     activejob (5.0.0.1)
       activesupport (= 5.0.0.1)
       globalid (>= 0.3.6)
     activemodel (5.0.0.1)
       activesupport (= 5.0.0.1)
@@ -47,10 +93,15 @@ GEM
       i18n (~> 0.7)
       minitest (~> 5.1)
       tzinfo (~> 1.1)
     addressable (2.4.0)
     arel (7.1.2)
+    ast (2.3.0)
+    axiom-types (0.1.1)
+      descendants_tracker (~> 0.0.4)
+      ice_nine (~> 0.11.0)
+      thread_safe (~> 0.3, >= 0.3.1)
     babel-source (5.8.35)
     babel-transpiler (0.7.0)
       babel-source (>= 4.0, < 6)
       execjs (~> 2.0)
     bcrypt (3.1.11)
@@ -61,42 +112,71 @@ GEM
       mime-types (>= 1.16)
       nokogiri (>= 1.3.3)
       rack (>= 1.0.0)
       rack-test (>= 0.5.4)
       xpath (~> 2.0)
-    coffee-rails (4.2.1)
-      coffee-script (>= 2.2.0)
-      railties (>= 4.0.0, < 5.2.x)
-    coffee-script (2.4.1)
-      coffee-script-source
-      execjs
-    coffee-script-source (1.10.0)
+    coercible (1.0.0)
+      descendants_tracker (~> 0.0.1)
     concurrent-ruby (1.0.2)
+    database_cleaner (1.5.3)
+    descendants_tracker (0.0.4)
+      thread_safe (~> 0.3, >= 0.3.1)
     devise (4.2.0)
       bcrypt (~> 3.0)
       orm_adapter (~> 0.1)
       railties (>= 4.1.0, < 5.1)
       responders
       warden (~> 1.2.3)
+    devise_invitable (1.7.0)
+      actionmailer (>= 4.0.0)
+      devise (>= 4.0.0)
     diff-lcs (1.2.5)
+    easy_translate (0.5.0)
+      json
+      thread
+      thread_safe
+    equalizer (0.0.11)
     erubis (2.7.0)
     execjs (2.7.0)
+    factory_girl (4.7.0)
+      activesupport (>= 3.0.0)
+    factory_girl_rails (4.7.0)
+      factory_girl (~> 4.7.0)
+      railties (>= 3.0.0)
     ffi (1.9.14)
     foundation-rails (6.2.3.0)
       railties (>= 3.1.0)
       sass (>= 3.3.0, < 3.5)
       sprockets-es6 (>= 0.9.0)
     globalid (0.3.7)
       activesupport (>= 4.1.0)
+    highline (1.7.8)
     i18n (0.7.0)
+    i18n-tasks (0.9.5)
+      activesupport (>= 4.0.2)
+      ast (>= 2.1.0)
+      easy_translate (>= 0.5.0)
+      erubis
+      highline (>= 1.7.3)
+      i18n
+      parser (>= 2.2.3.0)
+      term-ansicolor (>= 1.3.2)
+      terminal-table (>= 1.5.1)
+    ice_nine (0.11.2)
     jbuilder (2.6.0)
       activesupport (>= 3.0.0, < 5.1)
       multi_json (~> 1.2)
     jquery-rails (4.2.1)
       rails-dom-testing (>= 1, < 3)
       railties (>= 4.2.0)
       thor (>= 0.14, < 2.0)
+    jquery-turbolinks (2.1.0)
+      railties (>= 3.1.0)
+      turbolinks
+    json (2.0.2)
+    launchy (2.4.3)
+      addressable (~> 2.3)
     listen (3.0.8)
       rb-fsevent (~> 0.9, >= 0.9.4)
       rb-inotify (~> 0.9, >= 0.9.7)
     loofah (2.0.3)
       nokogiri (>= 1.5.9)
@@ -112,10 +192,12 @@ GEM
     nio4r (1.2.1)
     nokogiri (1.6.8)
       mini_portile2 (~> 2.1.0)
       pkg-config (~> 1.1.7)
     orm_adapter (0.5.0)
+    parser (2.3.1.4)
+      ast (~> 2.2)
     pg (0.18.4)
     pkg-config (1.1.7)
     rack (2.0.1)
     rack-test (0.6.3)
       rack (>= 1.0)
@@ -144,12 +226,22 @@ GEM
       thor (>= 0.18.1, < 2.0)
     rake (11.2.2)
     rb-fsevent (0.9.7)
     rb-inotify (0.9.7)
       ffi (>= 0.5.0)
+    rectify (0.6.1)
+      activemodel (>= 4.1.0)
+      activerecord (>= 4.1.0)
+      activesupport (>= 4.1.0)
+      virtus (~> 1.0.5)
+      wisper (>= 1.6.1)
     responders (2.3.0)
       railties (>= 4.2.0, < 5.1)
+    rspec (3.5.0)
+      rspec-core (~> 3.5.0)
+      rspec-expectations (~> 3.5.0)
+      rspec-mocks (~> 3.5.0)
     rspec-core (3.5.2)
       rspec-support (~> 3.5.0)
     rspec-expectations (3.5.0)
       diff-lcs (>= 1.2.0, < 2.0)
       rspec-support (~> 3.5.0)
@@ -177,48 +269,65 @@ GEM
       rack (> 1, < 3)
     sprockets-es6 (0.9.1)
       babel-source (>= 5.8.11)
       babel-transpiler
       sprockets (>= 3.0.0)
-    sprockets-rails (3.1.1)
+    sprockets-rails (3.2.0)
       actionpack (>= 4.0)
       activesupport (>= 4.0)
       sprockets (>= 3.0.0)
+    term-ansicolor (1.3.2)
+      tins (~> 1.0)
+    terminal-table (1.7.3)
+      unicode-display_width (~> 1.1.1)
     thor (0.19.1)
+    thread (0.2.2)
     thread_safe (0.3.5)
     tilt (2.0.5)
+    tins (1.12.0)
     turbolinks (5.0.1)
       turbolinks-source (~> 5)
     turbolinks-source (5.0.0)
     tzinfo (1.2.2)
       thread_safe (~> 0.1)
-    uglifier (3.0.2)
-      execjs (>= 0.3.0, < 3)
+    unicode-display_width (1.1.1)
+    virtus (1.0.5)
+      axiom-types (~> 0.1)
+      coercible (~> 1.0)
+      descendants_tracker (~> 0.0, >= 0.0.3)
+      equalizer (~> 0.0, >= 0.0.9)
     warden (1.2.6)
       rack (>= 1.0)
     websocket-driver (0.6.4)
       websocket-extensions (>= 0.1.0)
     websocket-extensions (0.1.2)
+    wisper (1.6.1)
+    wisper-rspec (0.0.2)
     xpath (2.0.0)
       nokogiri (~> 1.3)
 
 PLATFORMS
   ruby
 
 DEPENDENCIES
+  bundler (~> 1.12)
   byebug
   capybara (~> 2.4)
-  coffee-rails (~> 4.2)
+  database_cleaner (~> 1.5.0)
+  decidim!
   decidim-core!
-  jbuilder (~> 2.5)
-  jquery-rails
+  decidim-system!
+  factory_girl_rails
+  foundation_rails_helper!
+  i18n-tasks (~> 0.9.5)
+  launchy
   listen
   pg
+  rake (~> 11.0)
+  rspec (~> 3.0)
   rspec-rails (~> 3.5)
-  sass-rails (~> 5.0)
-  turbolinks (~> 5)
-  uglifier (>= 1.3.0)
+  wisper-rspec
 
 RUBY VERSION
    ruby 2.3.1p112
 
 BUNDLED WITH
diff --git a/decidim-core/Rakefile b/decidim-core/Rakefile
index a06ad6dbf..fb726bee1 100644
--- a/decidim-core/Rakefile
+++ b/decidim-core/Rakefile
@@ -8,20 +8,28 @@ end
 require "decidim/testing_support/common_rake"
 require "rdoc/task"
 
 RDoc::Task.new(:rdoc) do |rdoc|
   rdoc.rdoc_dir = "rdoc"
-  rdoc.title    = "Decidim"
+  rdoc.title    = "Decidim::Core"
   rdoc.options << "--line-numbers"
   rdoc.rdoc_files.include("README.md")
   rdoc.rdoc_files.include("lib/**/*.rb")
 end
 
 load "rails/tasks/statistics.rake"
 
 require "bundler/gem_tasks"
 
+task default: :test
+
 desc "Generates a dummy app for testing"
 task :test_app do
   ENV["LIB_NAME"] = "decidim/core"
   Rake::Task["common:test_app"].invoke
 end
+
+task test: :test_app do
+  Dir.chdir(File.dirname(__FILE__).to_s) do
+    sh "rspec spec"
+  end
+end
diff --git a/decidim-core/app/assets/javascripts/decidim.js b/decidim-core/app/assets/javascripts/decidim.js
index 2efd7194e..f6bb9f8ad 100644
--- a/decidim-core/app/assets/javascripts/decidim.js
+++ b/decidim-core/app/assets/javascripts/decidim.js
@@ -8,9 +8,8 @@
 // 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 .
 //= require foundation
 
 $(function(){ $(document).foundation(); });
diff --git a/decidim-core/app/assets/stylesheets/decidim.scss b/decidim-core/app/assets/stylesheets/decidim.scss
index 5a120f612..45c0bb2ed 100644
--- a/decidim-core/app/assets/stylesheets/decidim.scss
+++ b/decidim-core/app/assets/stylesheets/decidim.scss
@@ -8,10 +8,9 @@
  * 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
  */
 
 @import "foundation_and_overrides";
diff --git a/decidim-core/app/models/decidim/organization.rb b/decidim-core/app/models/decidim/organization.rb
new file mode 100644
index 000000000..f5130c800
--- /dev/null
+++ b/decidim-core/app/models/decidim/organization.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+module Decidim
+  # Organizations are one of the main models of Decidim. In a single Decidim
+  # installation we can find many organizations and each of them can start
+  # their own participatory processes.
+  class Organization < ApplicationRecord
+    validates :name, :host, uniqueness: true
+  end
+end
diff --git a/decidim-core/app/models/decidim/user.rb b/decidim-core/app/models/decidim/user.rb
index 514ec0d55..b3885cbdc 100644
--- a/decidim-core/app/models/decidim/user.rb
+++ b/decidim-core/app/models/decidim/user.rb
@@ -1,10 +1,23 @@
 # frozen_string_literal: true
 module Decidim
   # A User is a citizen that wants to join the platform to participate.
   class User < ApplicationRecord
-    # Include default devise modules. Others available are:
-    # :confirmable, :lockable, :timeoutable and :omniauthable
-    devise :database_authenticatable, :registerable,
+    devise :invitable, :database_authenticatable, :registerable,
            :recoverable, :rememberable, :trackable, :validatable
+
+    belongs_to :organization, foreign_key: "decidim_organization_id", class_name: Decidim::Organization
+
+    ROLES = %w(admin moderator official).freeze
+
+    validates :organization, presence: true
+    validates :roles, inclusion: { in: ROLES }, allow_blank: true
+
+    # Checks if the user is an admin in the organization it belongs to. This
+    # should probably be deleted and add a system to authorize actions.
+    #
+    # Returns Booolean.
+    def admin?
+      roles.include?("admin")
+    end
   end
 end
diff --git a/decidim-core/app/views/layouts/decidim/_header.html.erb b/decidim-core/app/views/layouts/decidim/_header.html.erb
index 666de5981..294b5f1de 100644
--- a/decidim-core/app/views/layouts/decidim/_header.html.erb
+++ b/decidim-core/app/views/layouts/decidim/_header.html.erb
@@ -1,2 +1,3 @@
 <h1>Decidim</h1>
+<%= display_flash_messages %>
 <hr />
diff --git a/decidim-core/app/views/users/mailer/invitation_instructions.html.erb b/decidim-core/app/views/users/mailer/invitation_instructions.html.erb
new file mode 100644
index 000000000..4f31391af
--- /dev/null
+++ b/decidim-core/app/views/users/mailer/invitation_instructions.html.erb
@@ -0,0 +1,11 @@
+<p><%= t("devise.mailer.invitation_instructions.hello", email: @resource.email) %></p>
+
+<p><%= t("devise.mailer.invitation_instructions.someone_invited_you", application: Decidim.config.application_name) %></p>
+
+<p><%= link_to t("devise.mailer.invitation_instructions.accept"), accept_invitation_url(@resource, :invitation_token => @token) %></p>
+
+<% if @resource.invitation_due_at %>
+  <p><%= t("devise.mailer.invitation_instructions.accept_until", due_date: l(@resource.invitation_due_at, format: :'devise.mailer.invitation_instructions.accept_until_format')) %></p>
+<% end %>
+
+<p><%= t("devise.mailer.invitation_instructions.ignore").html_safe %></p>
diff --git a/decidim-core/app/views/users/mailer/invitation_instructions.text.erb b/decidim-core/app/views/users/mailer/invitation_instructions.text.erb
new file mode 100644
index 000000000..2db4ae70b
--- /dev/null
+++ b/decidim-core/app/views/users/mailer/invitation_instructions.text.erb
@@ -0,0 +1,11 @@
+<%= t("devise.mailer.invitation_instructions.hello", email: @resource.email) %>
+
+<%= t("devise.mailer.invitation_instructions.someone_invited_you", application: Decidim.config.application_name) %>
+
+<%= accept_invitation_url(@resource, :invitation_token => @token) %>
+
+<% if @resource.invitation_due_at %>
+  <%= t("devise.mailer.invitation_instructions.accept_until", due_date: l(@resource.invitation_due_at, format: :'devise.mailer.invitation_instructions.accept_until_format')) %>
+<% end %>
+
+<%= strip_tags t("devise.mailer.invitation_instructions.ignore") %>
diff --git a/decidim-core/bin/rails b/decidim-core/bin/rails
index 035fefa33..e681ac30d 100755
--- a/decidim-core/bin/rails
+++ b/decidim-core/bin/rails
@@ -2,11 +2,11 @@
 # frozen_string_literal: true
 # 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/decidim/engine", __FILE__)
+ENGINE_PATH = File.expand_path("../../lib/decidim/core/engine", __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"])
 
diff --git a/decidim-core/config/i18n-tasks.yml b/decidim-core/config/i18n-tasks.yml
new file mode 100644
index 000000000..f7e347ca6
--- /dev/null
+++ b/decidim-core/config/i18n-tasks.yml
@@ -0,0 +1,120 @@
+# i18n-tasks finds and manages missing and unused translations: https://github.com/glebm/i18n-tasks
+
+# The "main" locale.
+base_locale: en
+## All available locales are inferred from the data by default. Alternatively, specify them explicitly:
+# locales: [es, fr]
+## Reporting locale, default: en. Available: en, ru.
+# internal_locale: en
+
+# Read and write translations.
+data:
+  ## Translations are read from the file system. Supported format: YAML, JSON.
+  ## Provide a custom adapter:
+  # adapter: I18n::Tasks::Data::FileSystem
+
+  # Locale files or `File.find` patterns where translations are read from:
+  read:
+    ## Default:
+    # - config/locales/%{locale}.yml
+    ## More files:
+    # - config/locales/**/*.%{locale}.yml
+    ## Another gem (replace %#= with %=):
+    # - "<%#= %x[bundle show vagrant].chomp %>/templates/locales/%{locale}.yml"
+
+  # Locale files to write new keys to, based on a list of key pattern => file rules. Matched from top to bottom:
+  # `i18n-tasks normalize -p` will force move the keys according to these rules
+  write:
+    ## For example, write devise and simple form keys to their respective files:
+    # - ['{devise, simple_form}.*', 'config/locales/\1.%{locale}.yml']
+    ## Catch-all default:
+    # - config/locales/%{locale}.yml
+
+  ## Specify the router (see Readme for details). Valid values: conservative_router, pattern_router, or a custom class.
+  # router: convervative_router
+
+  yaml:
+    write:
+      # do not wrap lines at 80 characters
+      line_width: -1
+
+  ## Pretty-print JSON:
+  # json:
+  #   write:
+  #     indent: '  '
+  #     space: ' '
+  #     object_nl: "\n"
+  #     array_nl: "\n"
+
+# Find translate calls
+search:
+  ## Paths or `File.find` patterns to search in:
+  # paths:
+  #  - app/
+
+  ## Root directories for relative keys resolution.
+  # relative_roots:
+  #   - app/controllers
+  #   - app/helpers
+  #   - app/mailers
+  #   - app/presenters
+  #   - app/views
+
+  ## Files or `File.fnmatch` patterns to exclude from search. Some files are always excluded regardless of this setting:
+  ##   %w(*.jpg *.png *.gif *.svg *.ico *.eot *.otf *.ttf *.woff *.woff2 *.pdf *.css *.sass *.scss *.less *.yml *.json)
+  exclude:
+    - app/assets/images
+    - app/assets/fonts
+
+  ## Alternatively, the only files or `File.fnmatch patterns` to search in `paths`:
+  ## If specified, this settings takes priority over `exclude`, but `exclude` still applies.
+  # only: ["*.rb", "*.html.slim"]
+
+  ## If `strict` is `false`, guess usages such as t("categories.#{category}.title"). The default is `true`.
+  # strict: true
+
+  ## Multiple scanners can be used. Their results are merged.
+  ## The options specified above are passed down to each scanner. Per-scanner options can be specified as well.
+  ## See this example of a custom scanner: https://github.com/glebm/i18n-tasks/wiki/A-custom-scanner-example
+
+## Google Translate
+# translation:
+#   # Get an API key and set billing info at https://code.google.com/apis/console to use Google Translate
+#   api_key: "AbC-dEf5"
+
+## Do not consider these keys missing:
+ignore_missing:
+- '{devise,simple_form}.*'
+
+## Consider these keys used:
+ignore_unused:
+  - '{time.formats}.*'
+# - 'activerecord.attributes.*'
+# - '{devise,kaminari,will_paginate}.*'
+# - 'simple_form.{yes,no}'
+# - 'simple_form.{placeholders,hints,labels}.*'
+# - 'simple_form.{error_notification,required}.:'
+
+## Exclude these keys from the `i18n-tasks eq-base' report:
+# ignore_eq_base:
+#   all:
+#     - common.ok
+#   fr,es:
+#     - common.brand
+
+## Ignore these keys completely:
+# ignore:
+#  - kaminari.*
+
+## Sometimes, it isn't possible for i18n-tasks to match the key correctly,
+## e.g. in case of a relative key defined in a helper method.
+## In these cases you can use the built-in PatternMapper to map patterns to keys, e.g.:
+#
+# <%#= I18n::Tasks.add_scanner 'I18n::Tasks::Scanners::PatternMapper',
+#        only: %w(*.html.haml *.html.slim),
+#        patterns: [['= title\b', '.page_title']] %>
+#
+# The PatternMapper can also match key literals via a special %{key} interpolation, e.g.:
+#
+# <%#= I18n::Tasks.add_scanner 'I18n::Tasks::Scanners::PatternMapper',
+#        patterns: [['\bSpree\.t[( ]\s*%{key}', 'spree.%{key}']] %>
diff --git a/decidim-core/config/initializers/devise.rb b/decidim-core/config/initializers/devise.rb
index 453bedd9d..03f3283c8 100644
--- a/decidim-core/config/initializers/devise.rb
+++ b/decidim-core/config/initializers/devise.rb
@@ -1,8 +1,11 @@
 # frozen_string_literal: true
 # Use this hook to configure devise mailer, warden hooks and so forth.
 # Many of these configuration options can be set straight in your model.
+
+require "decidim/devise_failure_app"
+
 Devise.setup do |config|
   # The secret key used by Devise. Devise uses this key to generate
   # random tokens. Changing this key will render invalid all existing
   # confirmation, reset password and unlock tokens in the database.
   # Devise will use the `secret_key_base` as its `secret_key`
@@ -114,10 +117,58 @@ Devise.setup do |config|
   # config.pepper = 'da466a45a1744ca79cc920a565749cf42b1cbcda0478b299a0db973e1a157fc43d1f578ec8dd393b4ef104274272a3621d203f49f473432a46b8a28ecc9bb4ae'
 
   # Send a notification email when the user's password is changed
   # config.send_password_change_notification = false
 
+  # ==> Configuration for :invitable
+  # The period the generated invitation token is valid, after
+  # this period, the invited resource won't be able to accept the invitation.
+  # When invite_for is 0 (the default), the invitation won't expire.
+  config.invite_for = 2.weeks
+
+  # Number of invitations users can send.
+  # - If invitation_limit is nil, there is no limit for invitations, users can
+  # send unlimited invitations, invitation_limit column is not used.
+  # - If invitation_limit is 0, users can't send invitations by default.
+  # - If invitation_limit n > 0, users can send n invitations.
+  # You can change invitation_limit column for some users so they can send more
+  # or less invitations, even with global invitation_limit = 0
+  # Default: nil
+  # config.invitation_limit = 5
+
+  # The key to be used to check existing users when sending an invitation
+  # and the regexp used to test it when validate_on_invite is not set.
+  # config.invite_key = {:email => /\A[^@]+@[^@]+\z/}
+  # config.invite_key = {:email => /\A[^@]+@[^@]+\z/, :username => nil}
+
+  # Flag that force a record to be valid before being actually invited
+  # Default: false
+  # config.validate_on_invite = true
+
+  # Resend invitation if user with invited status is invited again
+  # Default: true
+  # config.resend_invitation = false
+
+  # The class name of the inviting model. If this is nil,
+  # the #invited_by association is declared to be polymorphic.
+  # Default: nil
+  # config.invited_by_class_name = 'User'
+
+  # The foreign key to the inviting model (if invited_by_class_name is set)
+  # Default: :invited_by_id
+  # config.invited_by_foreign_key = :invited_by_id
+
+  # The column name used for counter_cache column. If this is nil,
+  # the #invited_by association is declared without counter_cache.
+  # Default: nil
+  # config.invited_by_counter_cache = :invitations_count
+
+  # Auto-login after the user accepts the invite. If this is false,
+  # the user will need to manually log in after accepting the invite.
+  # Default: true
+  # config.allow_insecure_sign_in_after_accept = false
+
   # ==> Configuration for :confirmable
   # A period that the user is allowed to access the website even without
   # confirming their account. For instance, if set to 2.days, the user will be
   # able to access the website for two days without confirming their account,
   # access will be blocked just in the third day. Default is 0.days, meaning
@@ -221,11 +272,11 @@ Devise.setup do |config|
 
   # ==> Scopes configuration
   # Turn scoped views on. Before rendering "sessions/new", it will first check for
   # "users/sessions/new". It's turned off by default because it's slower if you
   # are using only default views.
-  # config.scoped_views = false
+  config.scoped_views = true
 
   # Configure the default scope given to Warden. By default it's the first
   # devise role declared in your routes (usually :user).
   # config.default_scope = :user
 
@@ -254,24 +305,23 @@ Devise.setup do |config|
 
   # ==> Warden configuration
   # If you want to use other strategies, that are not supported by Devise, or
   # change the failure app, you can configure them inside the config.warden block.
   #
-  # config.warden do |manager|
-  #   manager.intercept_401 = false
-  #   manager.default_strategies(scope: :user).unshift :some_external_strategy
-  # end
+  config.warden do |manager|
+    manager.failure_app = Decidim::DeviseFailureApp
+  end
 
   # ==> Mountable engine configurations
   # When using Devise inside an engine, let's call it `MyEngine`, and this engine
   # is mountable, there are some extra configurations to be taken into account.
   # The following options are available, assuming the engine is mounted as:
   #
   #     mount MyEngine, at: '/my_engine'
   #
   # The router that invoked `devise_for`, in the example above, would be:
-  config.router_name = :decidim
+  # config.router_name = :decidim
   #
   # When using OmniAuth, Devise cannot automatically set OmniAuth path,
   # so you need to do it manually. For the users scope, it would be:
   # config.omniauth_path_prefix = '/my_engine/users/auth'
 end
diff --git a/decidim-core/config/locales/devise.en.yml b/decidim-core/config/locales/devise.en.yml
deleted file mode 100644
index bd4c3ebc6..000000000
--- a/decidim-core/config/locales/devise.en.yml
+++ /dev/null
@@ -1,62 +0,0 @@
-# Additional translations at https://github.com/plataformatec/devise/wiki/I18n
-
-en:
-  devise:
-    confirmations:
-      confirmed: "Your email address has been successfully confirmed."
-      send_instructions: "You will receive an email with instructions for how to confirm your email address in a few minutes."
-      send_paranoid_instructions: "If your email address exists in our database, you will receive an email with instructions for how to confirm your email address in a few minutes."
-    failure:
-      already_authenticated: "You are already signed in."
-      inactive: "Your account is not activated yet."
-      invalid: "Invalid %{authentication_keys} or password."
-      locked: "Your account is locked."
-      last_attempt: "You have one more attempt before your account is locked."
-      not_found_in_database: "Invalid %{authentication_keys} or password."
-      timeout: "Your session expired. Please sign in again to continue."
-      unauthenticated: "You need to sign in or sign up before continuing."
-      unconfirmed: "You have to confirm your email address before continuing."
-    mailer:
-      confirmation_instructions:
-        subject: "Confirmation instructions"
-      reset_password_instructions:
-        subject: "Reset password instructions"
-      unlock_instructions:
-        subject: "Unlock instructions"
-      password_change:
-        subject: "Password Changed"
-    omniauth_callbacks:
-      failure: "Could not authenticate you from %{kind} because \"%{reason}\"."
-      success: "Successfully authenticated from %{kind} account."
-    passwords:
-      no_token: "You can't access this page without coming from a password reset email. If you do come from a password reset email, please make sure you used the full URL provided."
-      send_instructions: "You will receive an email with instructions on how to reset your password in a few minutes."
-      send_paranoid_instructions: "If your email address exists in our database, you will receive a password recovery link at your email address in a few minutes."
-      updated: "Your password has been changed successfully. You are now signed in."
-      updated_not_active: "Your password has been changed successfully."
-    registrations:
-      destroyed: "Bye! Your account has been successfully cancelled. We hope to see you again soon."
-      signed_up: "Welcome! You have signed up successfully."
-      signed_up_but_inactive: "You have signed up successfully. However, we could not sign you in because your account is not yet activated."
-      signed_up_but_locked: "You have signed up successfully. However, we could not sign you in because your account is locked."
-      signed_up_but_unconfirmed: "A message with a confirmation link has been sent to your email address. Please follow the link to activate your account."
-      update_needs_confirmation: "You updated your account successfully, but we need to verify your new email address. Please check your email and follow the confirm link to confirm your new email address."
-      updated: "Your account has been updated successfully."
-    sessions:
-      signed_in: "Signed in successfully."
-      signed_out: "Signed out successfully."
-      already_signed_out: "Signed out successfully."
-    unlocks:
-      send_instructions: "You will receive an email with instructions for how to unlock your account in a few minutes."
-      send_paranoid_instructions: "If your account exists, you will receive an email with instructions for how to unlock it in a few minutes."
-      unlocked: "Your account has been unlocked successfully. Please sign in to continue."
-  errors:
-    messages:
-      already_confirmed: "was already confirmed, please try signing in"
-      confirmation_period_expired: "needs to be confirmed within %{period}, please request a new one"
-      expired: "has expired, please request a new one"
-      not_found: "not found"
-      not_locked: "was not locked"
-      not_saved:
-        one: "1 error prohibited this %{resource} from being saved:"
-        other: "%{count} errors prohibited this %{resource} from being saved:"
diff --git a/decidim-core/config/locales/en.yml b/decidim-core/config/locales/en.yml
new file mode 100644
index 000000000..e20a592a2
--- /dev/null
+++ b/decidim-core/config/locales/en.yml
@@ -0,0 +1,18 @@
+---
+en:
+  devise:
+    mailer:
+      invitation_instructions:
+        accept: Accept invitation
+        accept_until: This invitation will be due in %{due_date}.
+        hello: Hello %{email}
+        ignore: |-
+          If you don't want to accept the invitation, please ignore this email.<br />
+          Your account won't be created until you access the link above and set your password.
+        someone_invited_you: Someone has invited you to %{application}, you can accept it through the link below.
+  time:
+    formats:
+      devise:
+        mailer:
+          invitation_instructions:
+            accept_until_format: "%B %d, %Y %I:%M %p"
diff --git a/decidim-core/config/routes.rb b/decidim-core/config/routes.rb
index 66d35bc6e..80904df6c 100644
--- a/decidim-core/config/routes.rb
+++ b/decidim-core/config/routes.rb
@@ -1,5 +1,6 @@
 # frozen_string_literal: true
+
 Decidim::Core::Engine.routes.draw do
-  devise_for :users, class_name: "Decidim::User", module: :devise
+  devise_for :users, class_name: "Decidim::User", module: :'decidim/devise', router_name: :decidim
   root to: "home#show"
 end
diff --git a/decidim-core/db/migrate/20160919104837_create_decidim_organizations.rb b/decidim-core/db/migrate/20160919104837_create_decidim_organizations.rb
new file mode 100644
index 000000000..fb75ce096
--- /dev/null
+++ b/decidim-core/db/migrate/20160919104837_create_decidim_organizations.rb
@@ -0,0 +1,13 @@
+class CreateDecidimOrganizations < ActiveRecord::Migration[5.0]
+  def change
+    create_table :decidim_organizations do |t|
+      t.string :name, null: false
+      t.string :host, null: false
+
+      t.timestamps
+    end
+
+    add_index :decidim_organizations, :name, unique: true
+    add_index :decidim_organizations, :host, unique: true
+  end
+end
diff --git a/decidim-core/db/migrate/20160920140207_devise_invitable_add_to_decidim_users.rb b/decidim-core/db/migrate/20160920140207_devise_invitable_add_to_decidim_users.rb
new file mode 100644
index 000000000..018a18728
--- /dev/null
+++ b/decidim-core/db/migrate/20160920140207_devise_invitable_add_to_decidim_users.rb
@@ -0,0 +1,23 @@
+class DeviseInvitableAddToDecidimUsers < ActiveRecord::Migration
+  def up
+    change_table :decidim_users do |t|
+      t.string     :invitation_token
+      t.datetime   :invitation_created_at
+      t.datetime   :invitation_sent_at
+      t.datetime   :invitation_accepted_at
+      t.integer    :invitation_limit
+      t.references :invited_by, polymorphic: true
+      t.integer    :invitations_count, default: 0
+      t.index      :invitations_count
+      t.index      :invitation_token, unique: true # for invitable
+      t.index      :invited_by_id
+    end
+  end
+
+  def down
+    change_table :decidim_users do |t|
+      t.remove_references :invited_by, polymorphic: true
+      t.remove :invitations_count, :invitation_limit, :invitation_sent_at, :invitation_accepted_at, :invitation_token, :invitation_created_at
+    end
+  end
+end
diff --git a/decidim-core/db/migrate/20160920141039_user_belongs_to_organization.rb b/decidim-core/db/migrate/20160920141039_user_belongs_to_organization.rb
new file mode 100644
index 000000000..a94090d2b
--- /dev/null
+++ b/decidim-core/db/migrate/20160920141039_user_belongs_to_organization.rb
@@ -0,0 +1,5 @@
+class UserBelongsToOrganization < ActiveRecord::Migration[5.0]
+  def change
+    add_reference :decidim_users, :decidim_organization, index: true, foreign_key: true
+  end
+end
diff --git a/decidim-core/db/migrate/20160920141151_user_has_roles.rb b/decidim-core/db/migrate/20160920141151_user_has_roles.rb
new file mode 100644
index 000000000..79fca7275
--- /dev/null
+++ b/decidim-core/db/migrate/20160920141151_user_has_roles.rb
@@ -0,0 +1,5 @@
+class UserHasRoles < ActiveRecord::Migration[5.0]
+  def change
+    add_column :decidim_users, :roles, :string, array: true, default: []
+  end
+end
diff --git a/decidim-core/decidim-core.gemspec b/decidim-core/decidim-core.gemspec
index c4b204040..5158b5a34 100644
--- a/decidim-core/decidim-core.gemspec
+++ b/decidim-core/decidim-core.gemspec
@@ -16,9 +16,24 @@ Gem::Specification.new do |s|
   s.license     = "MIT"
 
   s.files = Dir["{app,config,db,lib}/**/*", "MIT-LICENSE", "Rakefile", "README.md"]
 
   s.add_dependency "rails", Decidim.rails_version
-  s.add_dependency "devise"
+  s.add_dependency "devise", "~> 4.2"
+  s.add_dependency "rectify", "~> 0.6"
   s.add_dependency "foundation-rails", "~> 6.2.3.0"
   s.add_dependency "sass-rails", "~> 5.0.0"
+  s.add_dependency "jquery-rails", "~> 4.0"
+  s.add_dependency "turbolinks", Decidim.rails_version
+  s.add_dependency "jquery-turbolinks", "~> 2.1.0"
+  s.add_dependency "jbuilder", "~> 2.5"
+  s.add_dependency "foundation_rails_helper", "~> 2.0.0"
+  s.add_dependency "active_link_to", "~> 1.0.0"
+
+  s.add_development_dependency "factory_girl_rails"
+  s.add_development_dependency "database_cleaner", "~> 1.5.0"
+  s.add_development_dependency "capybara", "~> 2.4"
+  s.add_development_dependency "rspec-rails", "~> 3.5"
+  s.add_development_dependency "byebug"
+  s.add_development_dependency "wisper-rspec"
+  s.add_development_dependency "i18n-tasks", "~> 0.9.5"
 end
diff --git a/decidim-core/lib/decidim/core.rb b/decidim-core/lib/decidim/core.rb
index 809adf40d..d43e594ed 100644
--- a/decidim-core/lib/decidim/core.rb
+++ b/decidim-core/lib/decidim/core.rb
@@ -1,11 +1,8 @@
 # frozen_string_literal: true
 require "decidim/core/engine"
 require "decidim/core/version"
-require "devise"
-
-require "foundation-rails"
 
 # Decidim configuration.
 module Decidim
   @config = OpenStruct.new
 
diff --git a/decidim-core/lib/decidim/core/engine.rb b/decidim-core/lib/decidim/core/engine.rb
index 5f5a61141..323fa72bc 100644
--- a/decidim-core/lib/decidim/core/engine.rb
+++ b/decidim-core/lib/decidim/core/engine.rb
@@ -1,9 +1,21 @@
 # frozen_string_literal: true
 require "rails"
 require "active_support/all"
 
+require "devise"
+require "devise_invitable"
+require "jquery-rails"
+require "sass-rails"
+require "turbolinks"
+require "jquery-turbolinks"
+require "foundation-rails"
+require "foundation_rails_helper"
+require "jbuilder"
+require "active_link_to"
+require "rectify"
+
 module Decidim
   module Core
     # Decidim's core Rails Engine.
     class Engine < ::Rails::Engine
       isolate_namespace Decidim
diff --git a/decidim-core/lib/decidim/devise_failure_app.rb b/decidim-core/lib/decidim/devise_failure_app.rb
new file mode 100644
index 000000000..2e8e90cd9
--- /dev/null
+++ b/decidim-core/lib/decidim/devise_failure_app.rb
@@ -0,0 +1,36 @@
+# encoding: utf-8
+# frozen_string_literal: true
+
+module Decidim
+  # We've provided a custom class in order to be able to deactivate the
+  # script_name hack that doesn't seem to be affecting us (it is actually
+  # introducing a bug).
+  class DeviseFailureApp < Devise::FailureApp
+    def scope_url
+      opts  = {}
+
+      # Initialize script_name with nil to prevent infinite loops in
+      # authenticated mounted engines in rails 4.2 and 5.0
+
+      # The line below is what we commented LOL ^^
+      # opts[:script_name] = nil
+
+      route = route(scope)
+
+      opts[:format] = request_format unless skip_format?
+
+      opts[:script_name] = relative_url_root if relative_url_root?
+
+      router_name = Devise.mappings[scope].router_name || Devise.available_router_name
+      context = send(router_name)
+
+      if context.respond_to?(route)
+        context.send(route, opts)
+      elsif respond_to?(:root_url)
+        root_url(opts)
+      else
+        "/"
+      end
+    end
+  end
+end
diff --git a/decidim-core/lib/generators/decidim/install_generator.rb b/decidim-core/lib/generators/decidim/install_generator.rb
index a9958f207..254841ae7 100644
--- a/decidim-core/lib/generators/decidim/install_generator.rb
+++ b/decidim-core/lib/generators/decidim/install_generator.rb
@@ -15,10 +15,11 @@ module Decidim
 
       class_option :migrate, type: :boolean, default: false,
                              desc: "Run migrations after installing decidim"
 
       def install
+        route "mount Decidim::System::Engine => '/system'"
         route "mount Decidim::Core::Engine => '/'"
       end
 
       def copy_migrations
         rake "railties:install:migrations"
@@ -58,19 +59,28 @@ module Decidim
 
       def append_assets
         append_file "app/assets/javascripts/application.js", "//= require decidim"
         inject_into_file "app/assets/stylesheets/application.css",
                          before: "*= require_tree ." do
-          "*= require decidim\n "
+          "*= require decidim\n"
+        end
+      end
+
+      def test_mail_host
+        inject_into_file "config/environments/test.rb",
+                         after: "config.action_mailer.delivery_method = :test" do
+          "\n  config.action_mailer.default_url_options = { host: \"test.citizencorp.com\" }"
         end
       end
 
       private
 
       def prepare_database
-        rake "db:drop"
+        rake "db:environment:set RAILS_ENV=development"
+        rake "db:drop:all"
         rake "db:create"
         rake "db:migrate"
+        rake "db:test:prepare"
       end
     end
   end
 end
diff --git a/decidim-core/lib/tasks/factory_girl.rake b/decidim-core/lib/tasks/factory_girl.rake
new file mode 100644
index 000000000..977dc4e4a
--- /dev/null
+++ b/decidim-core/lib/tasks/factory_girl.rake
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+namespace :factory_girl do
+  desc "Verify that all FactoryGirl factories are valid"
+  task lint: :environment do
+    if Rails.env.test?
+      begin
+        DatabaseCleaner.start
+        FactoryGirl.lint
+      ensure
+        DatabaseCleaner.clean
+      end
+    else
+      system("bundle exec rake factory_girl:lint RAILS_ENV='test'")
+    end
+  end
+end
diff --git a/decidim-core/spec/factories.rb b/decidim-core/spec/factories.rb
new file mode 100644
index 000000000..db134b835
--- /dev/null
+++ b/decidim-core/spec/factories.rb
@@ -0,0 +1,25 @@
+FactoryGirl.define do
+  factory :organization, class: Decidim::Organization do
+    sequence(:name) { |n| "Citizen Corp ##{n}" }
+    sequence(:host) { |n| "#{n}.citizen.corp" }
+  end
+
+  factory :user, class: Decidim::User do
+    sequence(:email)      { |n| "user#{n}@citizen.corp" }
+    password              "password1234"
+    password_confirmation "password1234"
+    organization
+
+    trait :admin do
+      roles ["admin"]
+    end
+
+    trait :moderator do
+      roles ["moderator"]
+    end
+
+    trait :official do
+      roles ["official"]
+    end
+  end
+end
diff --git a/decidim-core/spec/i18n_spec.rb b/decidim-core/spec/i18n_spec.rb
new file mode 100644
index 000000000..e7126127e
--- /dev/null
+++ b/decidim-core/spec/i18n_spec.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+require 'i18n/tasks'
+
+RSpec.describe 'I18n' do
+  let(:i18n) { I18n::Tasks::BaseTask.new }
+  let(:missing_keys) { i18n.missing_keys }
+  let(:unused_keys) { i18n.unused_keys }
+
+  it 'does not have missing keys' do
+    expect(missing_keys).to be_empty,
+      "Missing #{missing_keys.leaves.count} i18n keys, run `i18n-tasks missing' to show them"
+  end
+
+  it 'does not have unused keys' do
+    expect(unused_keys).to be_empty,
+      "#{unused_keys.leaves.count} unused i18n keys, run `i18n-tasks unused' to show them"
+  end
+end
diff --git a/decidim-core/spec/models/decidim/organization_spec.rb b/decidim-core/spec/models/decidim/organization_spec.rb
new file mode 100644
index 000000000..a6c0e18ba
--- /dev/null
+++ b/decidim-core/spec/models/decidim/organization_spec.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+require "spec_helper"
+
+describe "Organization", :db do
+  let(:organization) { create(:organization) }
+
+  it "is valid" do
+    expect(organization).to be_valid
+  end
+end
diff --git a/decidim-core/spec/models/decidim/user_spec.rb b/decidim-core/spec/models/decidim/user_spec.rb
new file mode 100644
index 000000000..10edb0d51
--- /dev/null
+++ b/decidim-core/spec/models/decidim/user_spec.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+require "spec_helper"
+
+describe "User", :db do
+  let(:user) { build(:user) }
+
+  it "is valid" do
+    expect(user).to be_valid
+  end
+
+  describe "admin?" do
+    context "when the user is an admin" do
+      before do
+        user.roles = ["admin"]
+      end
+
+      it { expect(user.admin?).to eq true }
+    end
+
+    context "when the user is not an admin" do
+      before do
+        user.roles = []
+      end
+
+      it { expect(user.admin?).to eq false }
+    end
+  end
+end
diff --git a/decidim-core/spec/spec_helper.rb b/decidim-core/spec/spec_helper.rb
index d422c892d..5f52deb6d 100644
--- a/decidim-core/spec/spec_helper.rb
+++ b/decidim-core/spec/spec_helper.rb
@@ -15,10 +15,13 @@ rescue LoadError
   puts "Could not load dummy application. Please ensure you have run `bundle exec rake test_app`"
   exit
 end
 
 require "rspec/rails"
+require "factory_girl_rails"
+require "database_cleaner"
+require "byebug"
 
 # Requires supporting files with custom matchers and macros, etc,
 # in ./support/ and its subdirectories.
 Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
 
diff --git a/decidim-core/spec/support/database_cleaner.rb b/decidim-core/spec/support/database_cleaner.rb
new file mode 100644
index 000000000..2211979de
--- /dev/null
+++ b/decidim-core/spec/support/database_cleaner.rb
@@ -0,0 +1,12 @@
+RSpec.configure do |config|
+  config.before(:suite) do
+    DatabaseCleaner.strategy = :transaction
+    DatabaseCleaner.clean_with(:truncation)
+  end
+
+  config.around(:each) do |example|
+    DatabaseCleaner.cleaning do
+      example.run
+    end
+  end
+end
diff --git a/decidim-core/spec/support/factory_girl.rb b/decidim-core/spec/support/factory_girl.rb
new file mode 100644
index 000000000..eec437fb3
--- /dev/null
+++ b/decidim-core/spec/support/factory_girl.rb
@@ -0,0 +1,3 @@
+RSpec.configure do |config|
+  config.include FactoryGirl::Syntax::Methods
+end
diff --git a/decidim-core/test/controllers/decidim/home_controller_test.rb b/decidim-core/test/controllers/decidim/home_controller_test.rb
deleted file mode 100644
index b8bf5cd09..000000000
--- a/decidim-core/test/controllers/decidim/home_controller_test.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-# frozen_string_literal: true
-require "test_helper"
-
-module Decidim
-  class HomeControllerTest < ActionDispatch::IntegrationTest
-    include Engine.routes.url_helpers
-
-    # test "the truth" do
-    #   assert true
-    # end
-  end
-end
diff --git a/decidim-core/test/fixtures/decidim/users.yml b/decidim-core/test/fixtures/decidim/users.yml
deleted file mode 100644
index 80aed36e3..000000000
--- a/decidim-core/test/fixtures/decidim/users.yml
+++ /dev/null
@@ -1,11 +0,0 @@
-# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
-
-# This model initially had no columns defined. If you add columns to the
-# model remove the '{}' from the fixture names and add the columns immediately
-# below each fixture, per the syntax in the comments below
-#
-one: {}
-# column: value
-#
-two: {}
-# column: value
diff --git a/decidim-core/test/lib/generators/decidim/decidim_generator_test.rb b/decidim-core/test/lib/generators/decidim/decidim_generator_test.rb
deleted file mode 100644
index 92b6cf466..000000000
--- a/decidim-core/test/lib/generators/decidim/decidim_generator_test.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-require "test_helper"
-require "generators/decidim/decidim_generator"
-
-module Decidim
-  class DecidimGeneratorTest < Rails::Generators::TestCase
-    tests DecidimGenerator
-    destination Rails.root.join("tmp/generators")
-    setup :prepare_destination
-
-    # test "generator runs without errors" do
-    #   assert_nothing_raised do
-    #     run_generator ["arguments"]
-    #   end
-    # end
-  end
-end
diff --git a/decidim-core/test/lib/generators/decidim/install_generator_test.rb b/decidim-core/test/lib/generators/decidim/install_generator_test.rb
deleted file mode 100644
index 0b3230893..000000000
--- a/decidim-core/test/lib/generators/decidim/install_generator_test.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-require "test_helper"
-require "generators/install/install_generator"
-
-module Decidim
-  class InstallGeneratorTest < Rails::Generators::TestCase
-    tests InstallGenerator
-    destination Rails.root.join("tmp/generators")
-    setup :prepare_destination
-
-    # test "generator runs without errors" do
-    #   assert_nothing_raised do
-    #     run_generator ["arguments"]
-    #   end
-    # end
-  end
-end
diff --git a/decidim-core/test/lib/generators/decidim/installation_generator_test.rb b/decidim-core/test/lib/generators/decidim/installation_generator_test.rb
deleted file mode 100644
index 30622f8d5..000000000
--- a/decidim-core/test/lib/generators/decidim/installation_generator_test.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-require "test_helper"
-require "generators/installation/installation_generator"
-
-module Decidim
-  class InstallationGeneratorTest < Rails::Generators::TestCase
-    tests InstallationGenerator
-    destination Rails.root.join("tmp/generators")
-    setup :prepare_destination
-
-    # test "generator runs without errors" do
-    #   assert_nothing_raised do
-    #     run_generator ["arguments"]
-    #   end
-    # end
-  end
-end
diff --git a/decidim-core/test/models/decidim/user_test.rb b/decidim-core/test/models/decidim/user_test.rb
deleted file mode 100644
index feb4165bb..000000000
--- a/decidim-core/test/models/decidim/user_test.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-# frozen_string_literal: true
-require "test_helper"
-
-module Decidim
-  class UserTest < ActiveSupport::TestCase
-    # test "the truth" do
-    #   assert true
-    # end
-  end
-end
diff --git a/decidim-system/Gemfile b/decidim-system/Gemfile
new file mode 100644
index 000000000..31e9c548b
--- /dev/null
+++ b/decidim-system/Gemfile
@@ -0,0 +1,17 @@
+eval(File.read(File.dirname(__FILE__) + "/../common_gemfile.rb"))
+
+# Declare your gem's dependencies in decidim-system.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]
+
+gemspec path: "../decidim-core"
+gemspec path: ".."
diff --git a/decidim-system/Gemfile.lock b/decidim-system/Gemfile.lock
new file mode 100644
index 000000000..42d5af88b
--- /dev/null
+++ b/decidim-system/Gemfile.lock
@@ -0,0 +1,334 @@
+GIT
+  remote: git://github.com/sgruhier/foundation_rails_helper.git
+  revision: d8819b3a5f9d82251aac7559e0d07505c9777717
+  specs:
+    foundation_rails_helper (2.0.0)
+      actionpack (>= 4.1)
+      activemodel (>= 4.1)
+      activesupport (>= 4.1)
+      railties (>= 4.1)
+      tzinfo (~> 1.2, >= 1.2.2)
+
+PATH
+  remote: ../decidim-core
+  specs:
+    decidim-core (0.0.1.alpha2)
+      active_link_to (~> 1.0.0)
+      devise (~> 4.2)
+      foundation-rails (~> 6.2.3.0)
+      foundation_rails_helper (~> 2.0.0)
+      jbuilder (~> 2.5)
+      jquery-rails (~> 4.0)
+      jquery-turbolinks (~> 2.1.0)
+      rails (~> 5.0.0)
+      rectify (~> 0.6)
+      sass-rails (~> 5.0.0)
+      turbolinks (~> 5.0.0)
+
+PATH
+  remote: ..
+  specs:
+    decidim (0.0.1.alpha2)
+      decidim-core (= 0.0.1.alpha2)
+      decidim-system (= 0.0.1.alpha2)
+      rails (~> 5.0.0)
+
+PATH
+  remote: .
+  specs:
+    decidim-system (0.0.1.alpha2)
+      active_link_to (~> 1.0.0)
+      decidim-core
+      devise (~> 4.2)
+      devise_invitable (~> 1.7.0)
+      foundation-rails (~> 6.2.3.0)
+      foundation_rails_helper (~> 2.0.0)
+      jbuilder (~> 2.5)
+      jquery-rails (~> 4.0)
+      jquery-turbolinks (~> 2.1.0)
+      rails (~> 5.0.0)
+      rectify (~> 0.6)
+      sass-rails (~> 5.0.0)
+      turbolinks (~> 5.0.0)
+
+GEM
+  remote: https://rubygems.org/
+  specs:
+    actioncable (5.0.0.1)
+      actionpack (= 5.0.0.1)
+      nio4r (~> 1.2)
+      websocket-driver (~> 0.6.1)
+    actionmailer (5.0.0.1)
+      actionpack (= 5.0.0.1)
+      actionview (= 5.0.0.1)
+      activejob (= 5.0.0.1)
+      mail (~> 2.5, >= 2.5.4)
+      rails-dom-testing (~> 2.0)
+    actionpack (5.0.0.1)
+      actionview (= 5.0.0.1)
+      activesupport (= 5.0.0.1)
+      rack (~> 2.0)
+      rack-test (~> 0.6.3)
+      rails-dom-testing (~> 2.0)
+      rails-html-sanitizer (~> 1.0, >= 1.0.2)
+    actionview (5.0.0.1)
+      activesupport (= 5.0.0.1)
+      builder (~> 3.1)
+      erubis (~> 2.7.0)
+      rails-dom-testing (~> 2.0)
+      rails-html-sanitizer (~> 1.0, >= 1.0.2)
+    active_link_to (1.0.3)
+      actionpack
+    activejob (5.0.0.1)
+      activesupport (= 5.0.0.1)
+      globalid (>= 0.3.6)
+    activemodel (5.0.0.1)
+      activesupport (= 5.0.0.1)
+    activerecord (5.0.0.1)
+      activemodel (= 5.0.0.1)
+      activesupport (= 5.0.0.1)
+      arel (~> 7.0)
+    activesupport (5.0.0.1)
+      concurrent-ruby (~> 1.0, >= 1.0.2)
+      i18n (~> 0.7)
+      minitest (~> 5.1)
+      tzinfo (~> 1.1)
+    addressable (2.4.0)
+    arel (7.1.2)
+    ast (2.3.0)
+    axiom-types (0.1.1)
+      descendants_tracker (~> 0.0.4)
+      ice_nine (~> 0.11.0)
+      thread_safe (~> 0.3, >= 0.3.1)
+    babel-source (5.8.35)
+    babel-transpiler (0.7.0)
+      babel-source (>= 4.0, < 6)
+      execjs (~> 2.0)
+    bcrypt (3.1.11)
+    builder (3.2.2)
+    byebug (9.0.5)
+    capybara (2.9.0)
+      addressable
+      mime-types (>= 1.16)
+      nokogiri (>= 1.3.3)
+      rack (>= 1.0.0)
+      rack-test (>= 0.5.4)
+      xpath (~> 2.0)
+    coercible (1.0.0)
+      descendants_tracker (~> 0.0.1)
+    concurrent-ruby (1.0.2)
+    database_cleaner (1.5.3)
+    descendants_tracker (0.0.4)
+      thread_safe (~> 0.3, >= 0.3.1)
+    devise (4.2.0)
+      bcrypt (~> 3.0)
+      orm_adapter (~> 0.1)
+      railties (>= 4.1.0, < 5.1)
+      responders
+      warden (~> 1.2.3)
+    devise_invitable (1.7.0)
+      actionmailer (>= 4.0.0)
+      devise (>= 4.0.0)
+    diff-lcs (1.2.5)
+    easy_translate (0.5.0)
+      json
+      thread
+      thread_safe
+    equalizer (0.0.11)
+    erubis (2.7.0)
+    execjs (2.7.0)
+    factory_girl (4.7.0)
+      activesupport (>= 3.0.0)
+    factory_girl_rails (4.7.0)
+      factory_girl (~> 4.7.0)
+      railties (>= 3.0.0)
+    ffi (1.9.14)
+    foundation-rails (6.2.3.0)
+      railties (>= 3.1.0)
+      sass (>= 3.3.0, < 3.5)
+      sprockets-es6 (>= 0.9.0)
+    globalid (0.3.7)
+      activesupport (>= 4.1.0)
+    highline (1.7.8)
+    i18n (0.7.0)
+    i18n-tasks (0.9.5)
+      activesupport (>= 4.0.2)
+      ast (>= 2.1.0)
+      easy_translate (>= 0.5.0)
+      erubis
+      highline (>= 1.7.3)
+      i18n
+      parser (>= 2.2.3.0)
+      term-ansicolor (>= 1.3.2)
+      terminal-table (>= 1.5.1)
+    ice_nine (0.11.2)
+    jbuilder (2.6.0)
+      activesupport (>= 3.0.0, < 5.1)
+      multi_json (~> 1.2)
+    jquery-rails (4.2.1)
+      rails-dom-testing (>= 1, < 3)
+      railties (>= 4.2.0)
+      thor (>= 0.14, < 2.0)
+    jquery-turbolinks (2.1.0)
+      railties (>= 3.1.0)
+      turbolinks
+    json (2.0.2)
+    launchy (2.4.3)
+      addressable (~> 2.3)
+    listen (3.0.8)
+      rb-fsevent (~> 0.9, >= 0.9.4)
+      rb-inotify (~> 0.9, >= 0.9.7)
+    loofah (2.0.3)
+      nokogiri (>= 1.5.9)
+    mail (2.6.4)
+      mime-types (>= 1.16, < 4)
+    method_source (0.8.2)
+    mime-types (3.1)
+      mime-types-data (~> 3.2015)
+    mime-types-data (3.2016.0521)
+    mini_portile2 (2.1.0)
+    minitest (5.9.0)
+    multi_json (1.12.1)
+    nio4r (1.2.1)
+    nokogiri (1.6.8)
+      mini_portile2 (~> 2.1.0)
+      pkg-config (~> 1.1.7)
+    orm_adapter (0.5.0)
+    parser (2.3.1.4)
+      ast (~> 2.2)
+    pg (0.18.4)
+    pkg-config (1.1.7)
+    rack (2.0.1)
+    rack-test (0.6.3)
+      rack (>= 1.0)
+    rails (5.0.0.1)
+      actioncable (= 5.0.0.1)
+      actionmailer (= 5.0.0.1)
+      actionpack (= 5.0.0.1)
+      actionview (= 5.0.0.1)
+      activejob (= 5.0.0.1)
+      activemodel (= 5.0.0.1)
+      activerecord (= 5.0.0.1)
+      activesupport (= 5.0.0.1)
+      bundler (>= 1.3.0, < 2.0)
+      railties (= 5.0.0.1)
+      sprockets-rails (>= 2.0.0)
+    rails-dom-testing (2.0.1)
+      activesupport (>= 4.2.0, < 6.0)
+      nokogiri (~> 1.6.0)
+    rails-html-sanitizer (1.0.3)
+      loofah (~> 2.0)
+    railties (5.0.0.1)
+      actionpack (= 5.0.0.1)
+      activesupport (= 5.0.0.1)
+      method_source
+      rake (>= 0.8.7)
+      thor (>= 0.18.1, < 2.0)
+    rake (11.3.0)
+    rb-fsevent (0.9.7)
+    rb-inotify (0.9.7)
+      ffi (>= 0.5.0)
+    rectify (0.6.1)
+      activemodel (>= 4.1.0)
+      activerecord (>= 4.1.0)
+      activesupport (>= 4.1.0)
+      virtus (~> 1.0.5)
+      wisper (>= 1.6.1)
+    responders (2.3.0)
+      railties (>= 4.2.0, < 5.1)
+    rspec (3.5.0)
+      rspec-core (~> 3.5.0)
+      rspec-expectations (~> 3.5.0)
+      rspec-mocks (~> 3.5.0)
+    rspec-core (3.5.3)
+      rspec-support (~> 3.5.0)
+    rspec-expectations (3.5.0)
+      diff-lcs (>= 1.2.0, < 2.0)
+      rspec-support (~> 3.5.0)
+    rspec-mocks (3.5.0)
+      diff-lcs (>= 1.2.0, < 2.0)
+      rspec-support (~> 3.5.0)
+    rspec-rails (3.5.2)
+      actionpack (>= 3.0)
+      activesupport (>= 3.0)
+      railties (>= 3.0)
+      rspec-core (~> 3.5.0)
+      rspec-expectations (~> 3.5.0)
+      rspec-mocks (~> 3.5.0)
+      rspec-support (~> 3.5.0)
+    rspec-support (3.5.0)
+    sass (3.4.22)
+    sass-rails (5.0.6)
+      railties (>= 4.0.0, < 6)
+      sass (~> 3.1)
+      sprockets (>= 2.8, < 4.0)
+      sprockets-rails (>= 2.0, < 4.0)
+      tilt (>= 1.1, < 3)
+    sprockets (3.7.0)
+      concurrent-ruby (~> 1.0)
+      rack (> 1, < 3)
+    sprockets-es6 (0.9.1)
+      babel-source (>= 5.8.11)
+      babel-transpiler
+      sprockets (>= 3.0.0)
+    sprockets-rails (3.2.0)
+      actionpack (>= 4.0)
+      activesupport (>= 4.0)
+      sprockets (>= 3.0.0)
+    term-ansicolor (1.3.2)
+      tins (~> 1.0)
+    terminal-table (1.7.3)
+      unicode-display_width (~> 1.1.1)
+    thor (0.19.1)
+    thread (0.2.2)
+    thread_safe (0.3.5)
+    tilt (2.0.5)
+    tins (1.12.0)
+    turbolinks (5.0.1)
+      turbolinks-source (~> 5)
+    turbolinks-source (5.0.0)
+    tzinfo (1.2.2)
+      thread_safe (~> 0.1)
+    unicode-display_width (1.1.1)
+    virtus (1.0.5)
+      axiom-types (~> 0.1)
+      coercible (~> 1.0)
+      descendants_tracker (~> 0.0, >= 0.0.3)
+      equalizer (~> 0.0, >= 0.0.9)
+    warden (1.2.6)
+      rack (>= 1.0)
+    websocket-driver (0.6.4)
+      websocket-extensions (>= 0.1.0)
+    websocket-extensions (0.1.2)
+    wisper (1.6.1)
+    wisper-rspec (0.0.2)
+    xpath (2.0.0)
+      nokogiri (~> 1.3)
+
+PLATFORMS
+  ruby
+
+DEPENDENCIES
+  bundler (~> 1.12)
+  byebug
+  capybara (~> 2.4)
+  database_cleaner (~> 1.5.0)
+  decidim!
+  decidim-core!
+  decidim-system!
+  factory_girl_rails
+  foundation_rails_helper!
+  i18n-tasks (~> 0.9.5)
+  launchy
+  listen
+  pg
+  rake (~> 11.0)
+  rspec (~> 3.0)
+  rspec-rails (~> 3.5)
+  wisper-rspec
+
+RUBY VERSION
+   ruby 2.3.1p112
+
+BUNDLED WITH
+   1.13.1
diff --git a/decidim-system/README.md b/decidim-system/README.md
new file mode 100644
index 000000000..cd1a3c320
--- /dev/null
+++ b/decidim-system/README.md
@@ -0,0 +1,28 @@
+# Decidim::System
+Short description and motivation.
+
+## Usage
+How to use my plugin.
+
+## Installation
+Add this line to your application's Gemfile:
+
+```ruby
+gem 'decidim-system'
+```
+
+And then execute:
+```bash
+$ bundle
+```
+
+Or install it yourself as:
+```bash
+$ gem install decidim-system
+```
+
+## Contributing
+Contribution directions go here.
+
+## License
+The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
diff --git a/decidim-system/Rakefile b/decidim-system/Rakefile
new file mode 100644
index 000000000..b4893e9d8
--- /dev/null
+++ b/decidim-system/Rakefile
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+begin
+  require "bundler/setup"
+rescue LoadError
+  puts "You must `gem install bundler` and `bundle install` to run rake tasks"
+end
+
+require_relative "../decidim-core/lib/decidim/testing_support/common_rake"
+require "rdoc/task"
+
+RDoc::Task.new(:rdoc) do |rdoc|
+  rdoc.rdoc_dir = "rdoc"
+  rdoc.title    = "Decidim::System"
+  rdoc.options << "--line-numbers"
+  rdoc.rdoc_files.include("README.md")
+  rdoc.rdoc_files.include("lib/**/*.rb")
+end
+
+load "rails/tasks/statistics.rake"
+
+require "bundler/gem_tasks"
+
+task default: :test
+
+desc "Generates a dummy app for testing"
+task :test_app do
+  ENV["LIB_NAME"] = "decidim/system"
+  Rake::Task["common:test_app"].invoke
+end
+
+task test: :test_app do
+  Dir.chdir(File.dirname(__FILE__).to_s) do
+    sh "rspec spec"
+  end
+end
diff --git a/decidim-system/app/assets/config/decidim_system_manifest.js b/decidim-system/app/assets/config/decidim_system_manifest.js
new file mode 100644
index 000000000..754e5ef93
--- /dev/null
+++ b/decidim-system/app/assets/config/decidim_system_manifest.js
@@ -0,0 +1,2 @@
+//= link_directory ../javascripts/decidim/system .js
+//= link_directory ../stylesheets/decidim/system .css
diff --git a/template.rb b/decidim-system/app/assets/images/decidim/system/.keep
similarity index 100%
rename from template.rb
rename to decidim-system/app/assets/images/decidim/system/.keep
diff --git a/decidim-system/app/assets/javascripts/decidim/system.js b/decidim-system/app/assets/javascripts/decidim/system.js
new file mode 100644
index 000000000..d102e795f
--- /dev/null
+++ b/decidim-system/app/assets/javascripts/decidim/system.js
@@ -0,0 +1,21 @@
+// 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 jquery
+//= require jquery.turbolinks
+//= require jquery_ujs
+//= require foundation
+//= require_self
+
+$(function(){ $(document).foundation(); });
+
+//= require turbolinks
diff --git a/decidim-system/app/assets/stylesheets/decidim/system.scss b/decidim-system/app/assets/stylesheets/decidim/system.scss
new file mode 100644
index 000000000..0442febc3
--- /dev/null
+++ b/decidim-system/app/assets/stylesheets/decidim/system.scss
@@ -0,0 +1,8 @@
+@import 'https://fonts.googleapis.com/css?family=Montserrat:400,700';
+
+@import "system/foundation_and_overrides";
+@import "system/layout";
+@import "system/login";
+@import "system/sidebar";
+@import "system/tables";
+@import "system/actions";
diff --git a/decidim-system/app/assets/stylesheets/decidim/system/_actions.scss b/decidim-system/app/assets/stylesheets/decidim/system/_actions.scss
new file mode 100644
index 000000000..4e6025036
--- /dev/null
+++ b/decidim-system/app/assets/stylesheets/decidim/system/_actions.scss
@@ -0,0 +1,8 @@
+.actions{
+  text-align: right;
+
+  &.title{
+    margin-bottom: $global-margin;
+    font-size: 1.2em;
+  }
+}
\ No newline at end of file
diff --git a/decidim-system/app/assets/stylesheets/decidim/system/_foundation_and_overrides.scss b/decidim-system/app/assets/stylesheets/decidim/system/_foundation_and_overrides.scss
new file mode 100644
index 000000000..3aff02e8c
--- /dev/null
+++ b/decidim-system/app/assets/stylesheets/decidim/system/_foundation_and_overrides.scss
@@ -0,0 +1,52 @@
+@charset "utf-8";
+
+@import "settings";
+@import "foundation";
+
+// If you'd like to include motion-ui the foundation-rails gem comes prepackaged with it, uncomment the 3 @imports, if you are not using the gem you need to install the motion-ui sass package.
+//
+// @import 'motion-ui/motion-ui';
+
+// We include everything by default.  To slim your CSS, remove components you don't use.
+
+@include foundation-global-styles;
+@include foundation-flex-grid;
+@include foundation-typography;
+@include foundation-button;
+@include foundation-forms;
+@include foundation-visibility-classes;
+@include foundation-flex-classes;
+@include foundation-accordion;
+@include foundation-accordion-menu;
+@include foundation-badge;
+@include foundation-breadcrumbs;
+@include foundation-button-group;
+@include foundation-callout;
+@include foundation-close-button;
+@include foundation-drilldown-menu;
+@include foundation-dropdown;
+@include foundation-dropdown-menu;
+@include foundation-flex-video;
+@include foundation-label;
+@include foundation-media-object;
+@include foundation-menu;
+@include foundation-menu-icon;
+@include foundation-off-canvas;
+@include foundation-orbit;
+@include foundation-pagination;
+@include foundation-progress-bar;
+@include foundation-slider;
+@include foundation-sticky;
+@include foundation-reveal;
+@include foundation-switch;
+@include foundation-table;
+@include foundation-tabs;
+@include foundation-thumbnail;
+@include foundation-title-bar;
+@include foundation-tooltip;
+@include foundation-top-bar;
+
+// If you'd like to include motion-ui the foundation-rails gem comes prepackaged with it, uncomment the 3 @imports, if you are not using the gem you need to install the motion-ui sass package.
+//
+// @include motion-ui-transitions;
+// @include motion-ui-animations;
diff --git a/decidim-system/app/assets/stylesheets/decidim/system/_layout.scss b/decidim-system/app/assets/stylesheets/decidim/system/_layout.scss
new file mode 100644
index 000000000..ef05a04d4
--- /dev/null
+++ b/decidim-system/app/assets/stylesheets/decidim/system/_layout.scss
@@ -0,0 +1,16 @@
+.off-canvas, .sidebar, .off-canvas-wrapper{
+  min-height: 100vh;
+}
+
+.off-canvas{
+  color: #fff;
+}
+
+.main-content{
+  padding: $global-padding 0;
+  min-height: 100vh;
+}
+
+.page-title{
+  margin-bottom: $global-margin;
+}
\ No newline at end of file
diff --git a/decidim-system/app/assets/stylesheets/decidim/system/_login.scss b/decidim-system/app/assets/stylesheets/decidim/system/_login.scss
new file mode 100644
index 000000000..c9e389221
--- /dev/null
+++ b/decidim-system/app/assets/stylesheets/decidim/system/_login.scss
@@ -0,0 +1,36 @@
+body.login{
+  background: $light-gray;
+  position: relative;
+
+  .login-form-wrapper{
+    @include grid-row;
+    @include flex;
+
+    height: 100vh;
+
+    .login-form{
+      @include grid-column(12);
+      @include grid-column-position(center);
+
+      @include breakpoint(medium){
+        @include grid-column(8);
+        @include grid-column-position(center);
+      }
+
+      @include breakpoint(large){
+        @include grid-column(6);
+        @include grid-column-position(center);
+      }
+    }
+
+    @include breakpoint(medium){
+      @include flex-align(center, middle);
+      transform: translateY(-8%);
+    }
+
+    .login-form-inner{
+      background-color: $white;
+      padding: $global-padding;
+    }
+  }
+}
\ No newline at end of file
diff --git a/decidim-system/app/assets/stylesheets/decidim/system/_settings.scss b/decidim-system/app/assets/stylesheets/decidim/system/_settings.scss
new file mode 100644
index 000000000..e73db74a2
--- /dev/null
+++ b/decidim-system/app/assets/stylesheets/decidim/system/_settings.scss
@@ -0,0 +1,566 @@
+//  Foundation for Sites Settings
+//  -----------------------------
+//
+//  Table of Contents:
+//
+//   1. Global
+//   2. Breakpoints
+//   3. The Grid
+//   4. Base Typography
+//   5. Typography Helpers
+//   6. Abide
+//   7. Accordion
+//   8. Accordion Menu
+//   9. Badge
+//  10. Breadcrumbs
+//  11. Button
+//  12. Button Group
+//  13. Callout
+//  14. Close Button
+//  15. Drilldown
+//  16. Dropdown
+//  17. Dropdown Menu
+//  18. Flex Video
+//  19. Forms
+//  20. Label
+//  21. Media Object
+//  22. Menu
+//  23. Meter
+//  24. Off-canvas
+//  25. Orbit
+//  26. Pagination
+//  27. Progress Bar
+//  28. Reveal
+//  29. Slider
+//  30. Switch
+//  31. Table
+//  32. Tabs
+//  33. Thumbnail
+//  34. Title Bar
+//  35. Tooltip
+//  36. Top Bar
+
+@import "util/util";
+
+// 1. Global
+// ---------
+
+// $global-font-size: 100%;
+// $global-width: rem-calc(1200);
+// $global-lineheight: 1.5;
+$foundation-palette: (
+  primary: #2199e8,
+  secondary: #777,
+  success: #3adb76,
+  warning: #ffae00,
+  alert: #ec5840,
+);
+$light-gray: #e6e6e6;
+// $medium-gray: #cacaca;
+// $dark-gray: #8a8a8a;
+$black: #232323;
+// $white: #fefefe;
+// $body-background: $white;
+// $body-font-color: $black;
+$body-font-family: 'Montserrat', sans-serif;
+// $body-antialiased: true;
+// $global-margin: 1rem;
+// $global-padding: 1rem;
+// $global-weight-normal: normal;
+// $global-weight-bold: bold;
+// $global-radius: 0;
+// $global-text-direction: ltr;
+$global-flexbox: true;
+// $print-transparent-backgrounds: true;
+
+@include add-foundation-colors;
+
+// 2. Breakpoints
+// --------------
+
+// $breakpoints: (
+//   small: 0,
+//   medium: 640px,
+//   large: 1024px,
+//   xlarge: 1200px,
+//   xxlarge: 1440px,
+// );
+// $breakpoint-classes: (small medium large);
+
+// 3. The Grid
+// -----------
+
+// $grid-row-width: $global-width;
+// $grid-column-count: 12;
+// $grid-column-gutter: (
+//   small: 20px,
+//   medium: 30px,
+// );
+// $grid-column-align-edge: true;
+// $block-grid-max: 8;
+
+// 4. Base Typography
+// ------------------
+
+// $header-font-family: $body-font-family;
+// $header-font-weight: $global-weight-normal;
+// $header-font-style: normal;
+// $font-family-monospace: Consolas, 'Liberation Mono', Courier, monospace;
+// $header-sizes: (
+//   small: (
+//     'h1': 24,
+//     'h2': 20,
+//     'h3': 19,
+//     'h4': 18,
+//     'h5': 17,
+//     'h6': 16,
+//   ),
+//   medium: (
+//     'h1': 48,
+//     'h2': 40,
+//     'h3': 31,
+//     'h4': 25,
+//     'h5': 20,
+//     'h6': 16,
+//   ),
+// );
+// $header-color: inherit;
+// $header-lineheight: 1.4;
+// $header-margin-bottom: 0.5rem;
+// $header-text-rendering: optimizeLegibility;
+// $small-font-size: 80%;
+// $header-small-font-color: $medium-gray;
+// $paragraph-lineheight: 1.6;
+// $paragraph-margin-bottom: 1rem;
+// $paragraph-text-rendering: optimizeLegibility;
+// $code-color: $black;
+// $code-font-family: $font-family-monospace;
+// $code-font-weight: $global-weight-normal;
+// $code-background: $light-gray;
+// $code-border: 1px solid $medium-gray;
+// $code-padding: rem-calc(2 5 1);
+// $anchor-color: $primary-color;
+// $anchor-color-hover: scale-color($anchor-color, $lightness: -14%);
+// $anchor-text-decoration: none;
+// $anchor-text-decoration-hover: none;
+// $hr-width: $global-width;
+// $hr-border: 1px solid $medium-gray;
+// $hr-margin: rem-calc(20) auto;
+// $list-lineheight: $paragraph-lineheight;
+// $list-margin-bottom: $paragraph-margin-bottom;
+// $list-style-type: disc;
+// $list-style-position: outside;
+// $list-side-margin: 1.25rem;
+// $list-nested-side-margin: 1.25rem;
+// $defnlist-margin-bottom: 1rem;
+// $defnlist-term-weight: $global-weight-bold;
+// $defnlist-term-margin-bottom: 0.3rem;
+// $blockquote-color: $dark-gray;
+// $blockquote-padding: rem-calc(9 20 0 19);
+// $blockquote-border: 1px solid $medium-gray;
+// $cite-font-size: rem-calc(13);
+// $cite-color: $dark-gray;
+// $keystroke-font: $font-family-monospace;
+// $keystroke-color: $black;
+// $keystroke-background: $light-gray;
+// $keystroke-padding: rem-calc(2 4 0);
+// $keystroke-radius: $global-radius;
+// $abbr-underline: 1px dotted $black;
+
+// 5. Typography Helpers
+// ---------------------
+
+// $lead-font-size: $global-font-size * 1.25;
+// $lead-lineheight: 1.6;
+// $subheader-lineheight: 1.4;
+// $subheader-color: $dark-gray;
+// $subheader-font-weight: $global-weight-normal;
+// $subheader-margin-t#23262Cop: 0.2rem;
+// $subheader-margin-bottom: 0.5rem;
+// $stat-font-size: 2.5rem;
+
+// 6. Abide
+// --------
+
+// $abide-inputs: true;
+// $abide-labels: true;
+// $input-background-invalid: map-get($foundation-palette, alert);
+// $form-label-color-invalid: map-get($foundation-palette, alert);
+// $input-error-color: map-get($foundation-palette, alert);
+// $input-error-font-size: rem-calc(12);
+// $input-error-font-weight: $global-weight-bold;
+
+// 7. Accordion
+// ------------
+
+// $accordion-background: $white;
+// $accordion-plusminus: true;
+// $accordion-item-color: foreground($accordion-background, $primary-color);
+// $accordion-item-background-hover: $light-gray;
+// $accordion-item-padding: 1.25rem 1rem;
+// $accordion-content-background: $white;
+// $accordion-content-border: 1px solid $light-gray;
+// $accordion-content-color: foreground($accordion-content-background, $body-font-color);
+// $accordion-content-padding: 1rem;
+
+// 8. Accordion Menu
+// -----------------
+
+// $accordionmenu-arrows: true;
+// $accordionmenu-arrow-color: $primary-color;
+
+// 9. Badge
+// --------
+
+// $badge-background: $primary-color;
+// $badge-color: foreground($badge-background);
+// $badge-padding: 0.3em;
+// $badge-minwidth: 2.1em;
+// $badge-font-size: 0.6rem;
+
+// 10. Breadcrumbs
+// ---------------
+
+// $breadcrumbs-margin: 0 0 $global-margin 0;
+// $breadcrumbs-item-font-size: rem-calc(11);
+// $breadcrumbs-item-color: $primary-color;
+// $breadcrumbs-item-color-current: $black;
+// $breadcrumbs-item-color-disabled: $medium-gray;
+// $breadcrumbs-item-margin: 0.75rem;
+// $breadcrumbs-item-uppercase: true;
+// $breadcrumbs-item-slash: true;
+
+// 11. Button
+// ----------
+
+// $button-padding: 0.85em 1em;
+$button-margin: 0;
+// $button-fill: solid;
+// $button-background: $primary-color;
+// $button-background-hover: scale-color($button-background, $lightness: -15%);
+// $button-color: $white;
+// $button-color-alt: $black;
+// $button-radius: $global-radius;
+// $button-sizes: (
+//   tiny: 0.6rem,
+//   small: 0.75rem,
+//   default: 0.9rem,
+//   large: 1.25rem,
+// );
+// $button-opacity-disabled: 0.25;
+
+// 12. Button Group
+// ----------------
+
+// $buttongroup-margin: 1rem;
+// $buttongroup-spacing: 1px;
+// $buttongroup-child-selector: ".button";
+// $buttongroup-expand-max: 6;
+
+// 13. Callout
+// -----------
+
+// $callout-background: $white;
+// $callout-background-fade: 85%;
+// $callout-border: 1px solid rgba($black, 0.25);
+// $callout-margin: 0 0 1rem 0;
+// $callout-padding: 1rem;
+// $callout-font-color: $body-font-color;
+// $callout-font-color-alt: $body-background;
+// $callout-radius: $global-radius;
+// $callout-link-tint: 30%;
+
+// 14. Close Button
+// ----------------
+
+// $closebutton-position: right top;
+// $closebutton-offset-horizontal: 1rem;
+// $closebutton-offset-vertical: 0.5rem;
+// $closebutton-size: 2em;
+// $closebutton-lineheight: 1;
+// $closebutton-color: $dark-gray;
+// $closebutton-color-hover: $black;
+
+// 15. Drilldown
+// -------------
+
+// $drilldown-transition: transform 0.15s linear;
+// $drilldown-arrows: true;
+// $drilldown-arrow-color: $primary-color;
+// $drilldown-background: $white;
+
+// 16. Dropdown
+// ------------
+
+// $dropdown-padding: 1rem;
+// $dropdown-border: 1px solid $medium-gray;
+// $dropdown-font-size: 1rem;
+// $dropdown-width: 300px;
+// $dropdown-radius: $global-radius;
+// $dropdown-sizes: (
+//   tiny: 100px,
+//   small: 200px,
+//   large: 400px,
+// );
+
+// 17. Dropdown Menu
+// -----------------
+
+// $dropdownmenu-arrows: true;
+// $dropdownmenu-arrow-color: $anchor-color;
+// $dropdownmenu-min-width: 200px;
+// $dropdownmenu-background: $white;
+// $dropdownmenu-border: 1px solid $medium-gray;
+
+// 18. Flex Video
+// --------------
+
+// $flexvideo-margin-bottom: rem-calc(16);
+// $flexvideo-ratio: 4 by 3;
+// $flexvideo-ratio-widescreen: 16 by 9;
+
+// 19. Forms
+// ---------
+
+// $fieldset-border: 1px solid $medium-gray;
+// $fieldset-padding: rem-calc(20);
+// $fieldset-margin: rem-calc(18 0);
+// $legend-padding: rem-calc(0 3);
+// $form-spacing: rem-calc(16);
+// $helptext-color: $black;
+// $helptext-font-size: rem-calc(13);
+// $helptext-font-style: italic;
+// $input-prefix-color: $black;
+// $input-prefix-background: $light-gray;
+// $input-prefix-border: 1px solid $medium-gray;
+// $input-prefix-padding: 1rem;
+// $form-label-color: $black;
+// $form-label-font-size: rem-calc(14);
+// $form-label-font-weight: $global-weight-normal;
+// $form-label-line-height: 1.8;
+// $select-background: $white;
+// $select-triangle-color: $dark-gray;
+// $select-radius: $global-radius;
+// $input-color: $black;
+// $input-placeholder-color: $medium-gray;
+// $input-font-family: inherit;
+// $input-font-size: rem-calc(16);
+// $input-background: $white;
+// $input-background-focus: $white;
+// $input-background-disabled: $light-gray;
+// $input-border: 1px solid $medium-gray;
+// $input-border-focus: 1px solid $dark-gray;
+// $input-shadow: inset 0 1px 2px rgba($black, 0.1);
+// $input-shadow-focus: 0 0 5px $medium-gray;
+// $input-cursor-disabled: not-allowed;
+// $input-transition: box-shadow 0.5s, border-color 0.25s ease-in-out;
+// $input-number-spinners: true;
+// $input-radius: $global-radius;
+
+// 20. Label
+// ---------
+
+// $label-background: $primary-color;
+// $label-color: foreground($label-background);
+// $label-font-size: 0.8rem;
+// $label-padding: 0.33333rem 0.5rem;
+// $label-radius: $global-radius;
+
+// 21. Media Object
+// ----------------
+
+// $mediaobject-margin-bottom: $global-margin;
+// $mediaobject-section-padding: $global-padding;
+// $mediaobject-image-width-stacked: 100%;
+
+// 22. Menu
+// --------
+
+// $menu-margin: 0;
+// $menu-margin-nested: 1rem;
+// $menu-item-padding: 0.7rem 1rem;
+// $menu-item-color-active: $white;
+// $menu-item-background-active: map-get($foundation-palette, primary);
+// $menu-icon-spacing: 0.25rem;
+
+// 23. Meter
+// ---------
+
+// $meter-height: 1rem;
+// $meter-radius: $global-radius;
+// $meter-background: $medium-gray;
+// $meter-fill-good: $success-color;
+// $meter-fill-medium: $warning-color;
+// $meter-fill-bad: $alert-color;
+
+// 24. Off-canvas
+// --------------
+
+// $offcanvas-size: 250px;
+$offcanvas-background: $black;
+// $offcanvas-zindex: -1;
+// $offcanvas-transition-length: 0.5s;
+// $offcanvas-transition-timing: ease;
+// $offcanvas-fixed-reveal: true;
+// $offcanvas-exit-background: rgba($white, 0.25);
+// $maincontent-class: "off-canvas-content";
+$maincontent-shadow: none;
+
+// 25. Orbit
+// ---------
+
+// $orbit-bullet-background: $medium-gray;
+// $orbit-bullet-background-active: $dark-gray;
+// $orbit-bullet-diameter: 1.2rem;
+// $orbit-bullet-margin: 0.1rem;
+// $orbit-bullet-margin-top: 0.8rem;
+// $orbit-bullet-margin-bottom: 0.8rem;
+// $orbit-caption-background: rgba($black, 0.5);
+// $orbit-caption-padding: 1rem;
+// $orbit-control-background-hover: rgba($black, 0.5);
+// $orbit-control-padding: 1rem;
+// $orbit-control-zindex: 10;
+
+// 26. Pagination
+// --------------
+
+// $pagination-font-size: rem-calc(14);
+// $pagination-margin-bottom: $global-margin;
+// $pagination-item-color: $black;
+// $pagination-item-padding: rem-calc(3 10);
+// $pagination-item-spacing: rem-calc(1);
+// $pagination-radius: $global-radius;
+// $pagination-item-background-hover: $light-gray;
+// $pagination-item-background-current: $primary-color;
+// $pagination-item-color-current: foreground($pagination-item-background-current);
+// $pagination-item-color-disabled: $medium-gray;
+// $pagination-ellipsis-color: $black;
+// $pagination-mobile-items: false;
+// $pagination-arrows: true;
+
+// 27. Progress Bar
+// ----------------
+
+// $progress-height: 1rem;
+// $progress-background: $medium-gray;
+// $progress-margin-bottom: $global-margin;
+// $progress-meter-background: $primary-color;
+// $progress-radius: $global-radius;
+
+// 28. Reveal
+// ----------
+
+// $reveal-background: $white;
+// $reveal-width: 600px;
+// $reveal-max-width: $global-width;
+// $reveal-padding: $global-padding;
+// $reveal-border: 1px solid $medium-gray;
+// $reveal-radius: $global-radius;
+// $reveal-zindex: 1005;
+// $reveal-overlay-background: rgba($black, 0.45);
+
+// 29. Slider
+// ----------
+
+// $slider-width-vertical: 0.5rem;
+// $slider-transition: all 0.2s ease-in-out;
+// $slider-height: 0.5rem;
+// $slider-background: $light-gray;
+// $slider-fill-background: $medium-gray;
+// $slider-handle-height: 1.4rem;
+// $slider-handle-width: 1.4rem;
+// $slider-handle-background: $primary-color;
+// $slider-opacity-disabled: 0.25;
+// $slider-radius: $global-radius;
+
+// 30. Switch
+// ----------
+
+// $switch-background: $medium-gray;
+// $switch-background-active: $primary-color;
+// $switch-height: 2rem;
+// $switch-height-tiny: 1.5rem;
+// $switch-height-small: 1.75rem;
+// $switch-height-large: 2.5rem;
+// $switch-radius: $global-radius;
+// $switch-margin: $global-margin;
+// $switch-paddle-background: $white;
+// $switch-paddle-offset: 0.25rem;
+// $switch-paddle-radius: $global-radius;
+// $switch-paddle-transition: all 0.25s ease-out;
+
+// 31. Table
+// ---------
+
+// $table-background: $white;
+// $table-color-scale: 5%;
+// $table-border: 1px solid smart-scale($table-background, $table-color-scale);
+// $table-padding: rem-calc(8 10 10);
+// $table-hover-scale: 2%;
+// $table-row-hover: darken($table-background, $table-hover-scale);
+// $table-row-stripe-hover: darken($table-background, $table-color-scale + $table-hover-scale);
+// $table-striped-background: smart-scale($table-background, $table-color-scale);
+// $table-stripe: even;
+// $table-head-background: smart-scale($table-background, $table-color-scale / 2);
+// $table-foot-background: smart-scale($table-background, $table-color-scale);
+// $table-head-font-color: $body-font-color;
+// $show-header-for-stacked: false;
+
+// 32. Tabs
+// --------
+
+// $tab-margin: 0;
+// $tab-background: $white;
+// $tab-background-active: $light-gray;
+// $tab-item-font-size: rem-calc(12);
+// $tab-item-background-hover: $white;
+// $tab-item-padding: 1.25rem 1.5rem;
+// $tab-expand-max: 6;
+// $tab-content-background: $white;
+// $tab-content-border: $light-gray;
+// $tab-content-color: foreground($tab-background, $primary-color);
+// $tab-content-padding: 1rem;
+
+// 33. Thumbnail
+// -------------
+
+// $thumbnail-border: solid 4px $white;
+// $thumbnail-margin-bottom: $global-margin;
+// $thumbnail-shadow: 0 0 0 1px rgba($black, 0.2);
+// $thumbnail-shadow-hover: 0 0 6px 1px rgba($primary-color, 0.5);
+// $thumbnail-transition: box-shadow 200ms ease-out;
+// $thumbnail-radius: $global-radius;
+
+// 34. Title Bar
+// -------------
+
+$titlebar-background: map-get($foundation-palette, primary);
+// $titlebar-color: $white;
+// $titlebar-padding: 0.5rem;
+// $titlebar-text-font-weight: bold;
+// $titlebar-icon-color: $white;
+// $titlebar-icon-color-hover: $medium-gray;
+// $titlebar-icon-spacing: 0.25rem;
+
+// 35. Tooltip
+// -----------
+
+// $has-tip-font-weight: $global-weight-bold;
+// $has-tip-border-bottom: dotted 1px $dark-gray;
+// $tooltip-background-color: $black;
+// $tooltip-color: $white;
+// $tooltip-padding: 0.75rem;
+// $tooltip-font-size: $small-font-size;
+// $tooltip-pip-width: 0.75rem;
+// $tooltip-pip-height: $tooltip-pip-width * 0.866;
+// $tooltip-radius: $global-radius;
+
+// 36. Top Bar
+// -----------
+
+// $topbar-padding: 0.5rem;
+// $topbar-background: $light-gray;
+// $topbar-submenu-background: $topbar-background;
+// $topbar-title-spacing: 1rem;
+// $topbar-input-width: 200px;
+// $topbar-unstack-breakpoint: medium;
diff --git a/decidim-system/app/assets/stylesheets/decidim/system/_sidebar.scss b/decidim-system/app/assets/stylesheets/decidim/system/_sidebar.scss
new file mode 100644
index 000000000..1e4034ded
--- /dev/null
+++ b/decidim-system/app/assets/stylesheets/decidim/system/_sidebar.scss
@@ -0,0 +1,73 @@
+@mixin menu-title{
+  text-transform: uppercase;
+  letter-spacing: 5px;
+}
+
+.title-bar-title{
+  @include menu-title;
+}
+
+.sidebar{
+  color: $light-gray;
+
+  .title{
+    background-color: black;
+    background-color: map-get($foundation-palette, primary);
+
+    h1{
+      margin: 0;
+      padding: 0;
+      font-size: rem-calc(18);
+      font-weight: bold;
+    }
+
+    a{
+      display: block;
+      color: inherit;
+      padding: rem-calc(20) $global-padding;
+      @include menu-title;
+    }
+
+    @include show-for(large);
+  }
+
+  .main-menu{
+    border-top: 1px solid black;
+    border-bottom: 1px solid black;
+    a{
+      padding: $global-padding;
+      display: block;
+      color: $light-gray;
+      text-transform: uppercase;
+      font-weight: bold;
+      font-size: 0.9em;
+      border-left: 2px solid transparent;
+
+      transition: all 0.3s;
+
+      &.active {
+        border-color: map-get($foundation-palette, primary);
+        &, &:hover{
+          background-color: #101010;
+        }
+      }
+
+      &:hover {
+        background-color: #1a1a1a;
+      }
+    }
+  }
+
+  .session-box {
+    padding: $global-padding 0;
+
+    @include grid-row;
+
+    .admin-email {
+      @include grid-column(8);
+      text-overflow: ellipsis;
+      overflow: hidden;
+    }
+    .sign-out{ @include grid-column(4); }
+  }
+}
\ No newline at end of file
diff --git a/decidim-system/app/assets/stylesheets/decidim/system/_tables.scss b/decidim-system/app/assets/stylesheets/decidim/system/_tables.scss
new file mode 100644
index 000000000..47350f7ab
--- /dev/null
+++ b/decidim-system/app/assets/stylesheets/decidim/system/_tables.scss
@@ -0,0 +1,5 @@
+table{
+  td.actions, th.actions{
+    text-align: right;
+  }
+}
\ No newline at end of file
diff --git a/decidim-system/app/commands/decidim/system/create_admin.rb b/decidim-system/app/commands/decidim/system/create_admin.rb
new file mode 100644
index 000000000..b441dab48
--- /dev/null
+++ b/decidim-system/app/commands/decidim/system/create_admin.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+module Decidim
+  module System
+    # A command with all the business logic when creating a new admin in
+    # the system.
+    class CreateAdmin < Rectify::Command
+      # Public: Initializes the command.
+      #
+      # form - A form object with the params.
+      def initialize(form)
+        @form = form
+      end
+
+      # Executes the command. Braodcasts these events:
+      #
+      # - :ok when everything is valid.
+      # - :invalid if the form wasn't valid and we couldn't proceed.
+      #
+      # Returns nothing.
+      def call
+        return broadcast(:invalid) if form.invalid?
+
+        create_admin
+        broadcast(:ok)
+      end
+
+      private
+
+      attr_reader :form
+
+      def create_admin
+        Admin.create!(
+          email: form.email,
+          password: form.password,
+          password_confirmation: form.password_confirmation
+        )
+      end
+    end
+  end
+end
diff --git a/decidim-system/app/commands/decidim/system/register_organization.rb b/decidim-system/app/commands/decidim/system/register_organization.rb
new file mode 100644
index 000000000..1825c4022
--- /dev/null
+++ b/decidim-system/app/commands/decidim/system/register_organization.rb
@@ -0,0 +1,51 @@
+# frozen_string_literal: true
+module Decidim
+  module System
+    # A command with all the business logic when creating a new organization in
+    # the system. It creates the organization and invites the admin to the
+    # system.
+    class RegisterOrganization < Rectify::Command
+      # Public: Initializes the command.
+      #
+      # form - A form object with the params.
+      def initialize(form)
+        @form = form
+      end
+
+      # Executes the command. Braodcasts these events:
+      #
+      # - :ok when everything is valid.
+      # - :invalid if the form wasn't valid and we couldn't proceed.
+      #
+      # Returns nothing.
+      def call
+        return broadcast(:invalid) if form.invalid?
+
+        transaction do
+          organization = create_organization
+          invite_admin(organization)
+        end
+
+        broadcast(:ok)
+      rescue ActiveRecord::RecordInvalid, ActiveRecord::RecordNotUnique
+        broadcast(:invalid)
+      end
+
+      private
+
+      attr_reader :form
+
+      def create_organization
+        Decidim::Organization.create!(name: form.name, host: form.host)
+      end
+
+      def invite_admin(organization)
+        Decidim::User.invite!(
+          email: form.organization_admin_email,
+          organization: organization,
+          roles: ["admin"]
+        )
+      end
+    end
+  end
+end
diff --git a/decidim-system/app/commands/decidim/system/update_admin.rb b/decidim-system/app/commands/decidim/system/update_admin.rb
new file mode 100644
index 000000000..a61f64902
--- /dev/null
+++ b/decidim-system/app/commands/decidim/system/update_admin.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+module Decidim
+  module System
+    # A command with all the business logic when updating an admin in
+    # the system.
+    class UpdateAdmin < Rectify::Command
+      # Public: Initializes the command.
+      #
+      # form - A form object with the params.
+      def initialize(admin, form)
+        @admin = admin
+        @form = form
+      end
+
+      # Executes the command. Braodcasts these events:
+      #
+      # - :ok when everything is valid.
+      # - :invalid if the form wasn't valid and we couldn't proceed.
+      #
+      # Returns nothing.
+      def call
+        return broadcast(:invalid) if form.invalid?
+
+        update_admin
+        broadcast(:ok)
+      end
+
+      private
+
+      attr_reader :form
+
+      def update_admin
+        @admin.update_attributes!(attributes)
+      end
+
+      def attributes
+        {
+          email: form.email
+        }.merge(password_attributes)
+      end
+
+      def password_attributes
+        return {} if form.password == form.password_confirmation && form.password.blank?
+
+        {
+          password: form.password,
+          password_confirmation: form.password_confirmation
+        }
+      end
+    end
+  end
+end
diff --git a/decidim-system/app/commands/decidim/system/update_organization.rb b/decidim-system/app/commands/decidim/system/update_organization.rb
new file mode 100644
index 000000000..a04169431
--- /dev/null
+++ b/decidim-system/app/commands/decidim/system/update_organization.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+module Decidim
+  module System
+    # A command with all the business logic when creating a new organization in
+    # the system. It creates the organization and invites the admin to the
+    # system.
+    class UpdateOrganization < Rectify::Command
+      # Public: Initializes the command.
+      #
+      # form - A form object with the params.
+      def initialize(id, form)
+        @organization_id = id
+        @form = form
+      end
+
+      # Executes the command. Braodcasts these events:
+      #
+      # - :ok when everything is valid.
+      # - :invalid if the form wasn't valid and we couldn't proceed.
+      #
+      # Returns nothing.
+      def call
+        return broadcast(:invalid) if form.invalid?
+
+        transaction do
+          save_organization
+        end
+
+        broadcast(:ok)
+      rescue ActiveRecord::RecordInvalid, ActiveRecord::RecordNotUnique
+        broadcast(:invalid)
+      end
+
+      private
+
+      attr_reader :form, :organization_id
+
+      def organization
+        @organization ||= Organization.find(organization_id)
+      end
+
+      def save_organization
+        organization.name = form.name
+        organization.host = form.host
+        organization.save!
+      end
+    end
+  end
+end
diff --git a/decidim-system/app/controllers/decidim/system/admins_controller.rb b/decidim-system/app/controllers/decidim/system/admins_controller.rb
new file mode 100644
index 000000000..e3ebf9e47
--- /dev/null
+++ b/decidim-system/app/controllers/decidim/system/admins_controller.rb
@@ -0,0 +1,67 @@
+# frozen_string_literal: true
+require_dependency "decidim/system/application_controller"
+
+module Decidim
+  module System
+    # Controller that allows managing all the Admins.
+    #
+    class AdminsController < ApplicationController
+      def index
+        @admins = Admin.all
+      end
+
+      def new
+        @form = AdminForm.new
+      end
+
+      def create
+        @form = AdminForm.from_params(params)
+
+        CreateAdmin.call(@form) do
+          on(:ok) do
+            flash[:notice] = I18n.t("admins.create.success", scope: "decidim.system")
+            redirect_to admins_path
+          end
+
+          on(:invalid) do
+            flash.now[:alert] = I18n.t("admins.create.error", scope: "decidim.system")
+            render :new
+          end
+        end
+      end
+
+      def edit
+        @admin = Admin.find(params[:id])
+        @form = AdminForm.from_model(@admin)
+      end
+
+      def update
+        @admin = Admin.find(params[:id])
+        @form = AdminForm.from_params(params)
+
+        UpdateAdmin.call(@admin, @form) do
+          on(:ok) do
+            flash[:notice] = I18n.t("admins.update.success", scope: "decidim.system")
+            redirect_to admins_path
+          end
+
+          on(:invalid) do
+            flash.now[:alert] = I18n.t("admins.update.error", scope: "decidim.system")
+            render :new
+          end
+        end
+      end
+
+      def show
+        @admin = Admin.find(params[:id])
+      end
+
+      def destroy
+        @admin = Admin.find(params[:id]).destroy!
+        flash[:notice] = I18n.t("admins.destroy.success", scope: "decidim.system")
+
+        redirect_to admins_path
+      end
+    end
+  end
+end
diff --git a/decidim-system/app/controllers/decidim/system/application_controller.rb b/decidim-system/app/controllers/decidim/system/application_controller.rb
new file mode 100644
index 000000000..26a4028e9
--- /dev/null
+++ b/decidim-system/app/controllers/decidim/system/application_controller.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+module Decidim
+  module System
+    # The main application controller that inherits from Rails.
+    class ApplicationController < ActionController::Base
+      protect_from_forgery with: :exception, prepend: true
+    end
+  end
+end
diff --git a/decidim-system/app/controllers/decidim/system/dashboard_controller.rb b/decidim-system/app/controllers/decidim/system/dashboard_controller.rb
new file mode 100644
index 000000000..3abafd6ca
--- /dev/null
+++ b/decidim-system/app/controllers/decidim/system/dashboard_controller.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+require_dependency "decidim/system/application_controller"
+
+module Decidim
+  module System
+    class DashboardController < ApplicationController
+    end
+  end
+end
diff --git a/decidim-system/app/controllers/decidim/system/devise/passwords_controller.rb b/decidim-system/app/controllers/decidim/system/devise/passwords_controller.rb
new file mode 100644
index 000000000..ff4b7bd66
--- /dev/null
+++ b/decidim-system/app/controllers/decidim/system/devise/passwords_controller.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+module Decidim
+  module System
+    module Devise
+      # A controller so admins can recover their passwords.
+      class PasswordsController < Devise::PasswordsController
+        layout "decidim/system/login"
+      end
+    end
+  end
+end
diff --git a/decidim-system/app/controllers/decidim/system/devise/sessions_controller.rb b/decidim-system/app/controllers/decidim/system/devise/sessions_controller.rb
new file mode 100644
index 000000000..e42dc8c05
--- /dev/null
+++ b/decidim-system/app/controllers/decidim/system/devise/sessions_controller.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+module Decidim
+  module System
+    module Devise
+      # A controller so admins can log-in and use their backend.
+      class SessionsController < ::Devise::SessionsController
+        helper Decidim::System::ApplicationHelper
+        layout "decidim/system/login"
+      end
+    end
+  end
+end
diff --git a/decidim-system/app/controllers/decidim/system/organizations_controller.rb b/decidim-system/app/controllers/decidim/system/organizations_controller.rb
new file mode 100644
index 000000000..68d77b90d
--- /dev/null
+++ b/decidim-system/app/controllers/decidim/system/organizations_controller.rb
@@ -0,0 +1,59 @@
+# frozen_string_literal: true
+require_dependency "decidim/system/application_controller"
+
+module Decidim
+  module System
+    # Controller to manage Organizations (tenants).
+    #
+    class OrganizationsController < ApplicationController
+      def new
+        @form = RegisterOrganizationForm.new
+      end
+
+      def create
+        @form = RegisterOrganizationForm.from_params(params)
+
+        RegisterOrganization.call(@form) do
+          on(:ok) do
+            flash[:notice] = t("organizations.create.success", scope: "decidim.system")
+            redirect_to organizations_path
+          end
+
+          on(:invalid) do
+            flash.now[:alert] = t("organizations.create.error", scope: "decidim.system")
+            render :new
+          end
+        end
+      end
+
+      def index
+        @organizations = Organization.all
+      end
+
+      def show
+        @organization = Organization.find(params[:id])
+      end
+
+      def edit
+        organization = Organization.find(params[:id])
+        @form = UpdateOrganizationForm.from_model(organization)
+      end
+
+      def update
+        @form = UpdateOrganizationForm.from_params(params)
+
+        UpdateOrganization.call(params[:id], @form) do
+          on(:ok) do
+            flash[:notice] = t("organizations.update.success", scope: "decidim.system")
+            redirect_to organizations_path
+          end
+
+          on(:invalid) do
+            flash.now[:alert] = I18n.t("organizations.update.error", scope: "decidim.system")
+            render :edit
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/decidim-system/app/forms/decidim/system/admin_form.rb b/decidim-system/app/forms/decidim/system/admin_form.rb
new file mode 100644
index 000000000..26e31d744
--- /dev/null
+++ b/decidim-system/app/forms/decidim/system/admin_form.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+module Decidim
+  module System
+    # A form object used to create organizations from the system dashboard.
+    #
+    class AdminForm < Rectify::Form
+      mimic :admin
+
+      attribute :email, String
+      attribute :password, String
+      attribute :password_confirmation, String
+
+      validates :email, presence: true
+      validates :password, presence: true, unless: :admin_exists?
+      validates :password_confirmation, presence: true, unless: :admin_exists?
+
+      validate :email, :email_uniqueness
+
+      private
+
+      def email_uniqueness
+        return unless Admin.where(email: email).where.not(id: id).any?
+
+        errors.add(:email, I18n.t("models.admin.validations.email_uniqueness",
+                                  scope: "decidim.system"))
+      end
+
+      def admin_exists?
+        id.present?
+      end
+    end
+  end
+end
diff --git a/decidim-system/app/forms/decidim/system/register_organization_form.rb b/decidim-system/app/forms/decidim/system/register_organization_form.rb
new file mode 100644
index 000000000..66479fb8f
--- /dev/null
+++ b/decidim-system/app/forms/decidim/system/register_organization_form.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+module Decidim
+  module System
+    # A form object used to create organizations from the system dashboard.
+    #
+    class RegisterOrganizationForm < UpdateOrganizationForm
+      mimic :organization
+
+      attribute :organization_admin_email, String
+
+      validates :organization_admin_email, presence: true
+    end
+  end
+end
diff --git a/decidim-system/app/forms/decidim/system/update_organization_form.rb b/decidim-system/app/forms/decidim/system/update_organization_form.rb
new file mode 100644
index 000000000..99ac38a9a
--- /dev/null
+++ b/decidim-system/app/forms/decidim/system/update_organization_form.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+module Decidim
+  module System
+    # A form object used to update organizations from the system dashboard.
+    #
+    class UpdateOrganizationForm < Rectify::Form
+      mimic :organization
+
+      attribute :name, String
+      attribute :host, String
+
+      validate :validate_organization_uniqueness
+
+      private
+
+      def validate_organization_uniqueness
+        errors.add(:name, :taken) if Decidim::Organization.where(name: name).where.not(id: id).exists?
+        errors.add(:host, :taken) if Decidim::Organization.where(host: host).where.not(id: id).exists?
+      end
+    end
+  end
+end
diff --git a/decidim-system/app/helpers/decidim/system/application_helper.rb b/decidim-system/app/helpers/decidim/system/application_helper.rb
new file mode 100644
index 000000000..aac9187ee
--- /dev/null
+++ b/decidim-system/app/helpers/decidim/system/application_helper.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+module Decidim
+  module System
+    # Custom helpers, scoped to the system panel.
+    #
+    module ApplicationHelper
+      def title
+        "Decidim"
+      end
+
+      def field_name(model, field)
+        st "models.#{model}.fields.#{field}"
+      end
+    end
+  end
+end
diff --git a/decidim-system/app/jobs/decidim/system/application_job.rb b/decidim-system/app/jobs/decidim/system/application_job.rb
new file mode 100644
index 000000000..cced20cff
--- /dev/null
+++ b/decidim-system/app/jobs/decidim/system/application_job.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+module Decidim
+  module System
+    # Custom ApplicationJob scoped to the system panel.
+    #
+    class ApplicationJob < ActiveJob::Base
+    end
+  end
+end
diff --git a/decidim-system/app/mailers/decidim/system/application_mailer.rb b/decidim-system/app/mailers/decidim/system/application_mailer.rb
new file mode 100644
index 000000000..fa6b7dec3
--- /dev/null
+++ b/decidim-system/app/mailers/decidim/system/application_mailer.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+module Decidim
+  module System
+    # Custom application mailer, scoped to the system mailer.
+    #
+    class ApplicationMailer < ActionMailer::Base
+      default from: "from@example.com"
+      layout "mailer"
+    end
+  end
+end
diff --git a/decidim-system/app/models/decidim/system/admin.rb b/decidim-system/app/models/decidim/system/admin.rb
new file mode 100644
index 000000000..e39176160
--- /dev/null
+++ b/decidim-system/app/models/decidim/system/admin.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+module Decidim
+  module System
+    # Admins are the users in charge of managing a Decidim installation.
+    class Admin < ApplicationRecord
+      devise :database_authenticatable, :recoverable, :rememberable, :validatable
+
+      validates :email, uniqueness: true
+    end
+  end
+end
diff --git a/decidim-system/app/models/decidim/system/application_record.rb b/decidim-system/app/models/decidim/system/application_record.rb
new file mode 100644
index 000000000..d46b53b2c
--- /dev/null
+++ b/decidim-system/app/models/decidim/system/application_record.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+module Decidim
+  module System
+    # Custom ApplicationRecord scoped to the system panel.
+    #
+    class ApplicationRecord < ActiveRecord::Base
+      self.abstract_class = true
+    end
+  end
+end
diff --git a/decidim-system/app/views/decidim/system/admins/_form.html.erb b/decidim-system/app/views/decidim/system/admins/_form.html.erb
new file mode 100644
index 000000000..062dee8f6
--- /dev/null
+++ b/decidim-system/app/views/decidim/system/admins/_form.html.erb
@@ -0,0 +1,11 @@
+<div class="field">
+  <%= form.text_field :email, autofocus: true %>
+</div>
+
+<div class="field">
+  <%= form.password_field :password %>
+</div>
+
+<div class="field">
+  <%= form.password_field :password_confirmation %>
+</div>
diff --git a/decidim-system/app/views/decidim/system/admins/edit.html.erb b/decidim-system/app/views/decidim/system/admins/edit.html.erb
new file mode 100644
index 000000000..5c8ed7646
--- /dev/null
+++ b/decidim-system/app/views/decidim/system/admins/edit.html.erb
@@ -0,0 +1,11 @@
+<% content_for :title do %>
+  <h2><%= t ".title" %></h2>
+<% end %>
+
+<%= form_for(@form) do |f| %>
+  <%= render partial: 'form', object: f %>
+
+  <div class="actions">
+    <%= f.submit t(".update") %>
+  </div>
+<% end %>
diff --git a/decidim-system/app/views/decidim/system/admins/index.html.erb b/decidim-system/app/views/decidim/system/admins/index.html.erb
new file mode 100644
index 000000000..0b743c623
--- /dev/null
+++ b/decidim-system/app/views/decidim/system/admins/index.html.erb
@@ -0,0 +1,33 @@
+<% content_for :title do %>
+  <h2><%= t ".title" %></h2>
+<% end %>
+
+<div class="actions title">
+  <%= link_to t("actions.new", scope: "decidim.system", name: t("models.admin.name", scope: "decidim.system")), ['new', 'admin'], class: 'new' %>
+</div>
+
+<table class="stack">
+  <thead>
+    <tr>
+      <th><%= t("models.admin.fields.email", scope: "decidim.system") %></th>
+      <th><%= t("models.admin.fields.created_at", scope: "decidim.system") %></th>
+      <th class="actions"><%= t("actions.title", scope: "decidim.system") %></th>
+    </tr>
+  </thead>
+  <tbody>
+    <% @admins.each do |admin| %>
+      <tr>
+        <td>
+          <%= link_to admin.email, admin %><br />
+        </td>
+        <td>
+          <%= l admin.created_at, format: :short %>
+        </td>
+        <td class="actions">
+          <%= link_to t("actions.edit", scope: "decidim.system"), ['edit', admin] %>
+          <%= link_to t("actions.destroy", scope: "decidim.system"), admin, method: :delete, class: "small alert button", data: { confirm: t("actions.confirm_destroy", scope: "decidim.system") } %>
+        </td>
+      </tr>
+    <% end %>
+  </tbody>
+</table>
diff --git a/decidim-system/app/views/decidim/system/admins/new.html.erb b/decidim-system/app/views/decidim/system/admins/new.html.erb
new file mode 100644
index 000000000..d6c285fe8
--- /dev/null
+++ b/decidim-system/app/views/decidim/system/admins/new.html.erb
@@ -0,0 +1,11 @@
+<% content_for :title do %>
+  <h2><%= t ".title" %></h2>
+<% end %>
+
+<%= form_for(@form) do |f| %>
+  <%= render partial: 'form', object: f %>
+
+  <div class="actions">
+    <%= f.submit t(".create") %>
+  </div>
+<% end %>
diff --git a/decidim-system/app/views/decidim/system/admins/show.html.erb b/decidim-system/app/views/decidim/system/admins/show.html.erb
new file mode 100644
index 000000000..89bb30644
--- /dev/null
+++ b/decidim-system/app/views/decidim/system/admins/show.html.erb
@@ -0,0 +1,9 @@
+<% content_for :title do %>
+  <h2><%= link_to @admin.email, @admin %></h2>
+<% end %>
+
+<div class="actions">
+  <hr />
+  <%= link_to "Edit", ['edit', @admin] %>
+  <%= link_to "Destroy", @admin, method: :delete, class: "alert button", data: { confirm: "Are you sure you want to do this?" } %>
+</div>
diff --git a/decidim-system/app/views/decidim/system/dashboard/show.html.erb b/decidim-system/app/views/decidim/system/dashboard/show.html.erb
new file mode 100644
index 000000000..6c93fb0f1
--- /dev/null
+++ b/decidim-system/app/views/decidim/system/dashboard/show.html.erb
@@ -0,0 +1,3 @@
+<% content_for :title do %>
+  <h2><%= t("decidim.system.titles.dashboard") %></h2>
+<% end %>
diff --git a/decidim-system/app/views/decidim/system/devise/mailers/password_change.html.erb b/decidim-system/app/views/decidim/system/devise/mailers/password_change.html.erb
new file mode 100644
index 000000000..b41daf476
--- /dev/null
+++ b/decidim-system/app/views/decidim/system/devise/mailers/password_change.html.erb
@@ -0,0 +1,3 @@
+<p>Hello <%= @resource.email %>!</p>
+
+<p>We're contacting you to notify you that your password has been changed.</p>
diff --git a/decidim-system/app/views/decidim/system/devise/mailers/reset_password_instructions.html.erb b/decidim-system/app/views/decidim/system/devise/mailers/reset_password_instructions.html.erb
new file mode 100644
index 000000000..f667dc12f
--- /dev/null
+++ b/decidim-system/app/views/decidim/system/devise/mailers/reset_password_instructions.html.erb
@@ -0,0 +1,8 @@
+<p>Hello <%= @resource.email %>!</p>
+
+<p>Someone has requested a link to change your password. You can do this through the link below.</p>
+
+<p><%= link_to 'Change my password', edit_password_url(@resource, reset_password_token: @token) %></p>
+
+<p>If you didn't request this, please ignore this email.</p>
+<p>Your password won't change until you access the link above and create a new one.</p>
diff --git a/decidim-system/app/views/decidim/system/devise/passwords/edit.html.erb b/decidim-system/app/views/decidim/system/devise/passwords/edit.html.erb
new file mode 100644
index 000000000..dba934a70
--- /dev/null
+++ b/decidim-system/app/views/decidim/system/devise/passwords/edit.html.erb
@@ -0,0 +1,23 @@
+<h2>Change your password</h2>
+
+<%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :put }) do |f| %>
+  <%= devise_error_messages! %>
+  <%= f.hidden_field :reset_password_token %>
+
+  <div class="field">
+    <% if @minimum_password_length %>
+      <em>(<%= @minimum_password_length %> characters minimum)</em><br />
+    <% end %>
+    <%= f.password_field :password, autofocus: true, autocomplete: "off" %>
+  </div>
+
+  <div class="field">
+    <%= f.password_field :password_confirmation, autocomplete: "off" %>
+  </div>
+
+  <div class="actions">
+    <%= f.submit "Change my password" %>
+  </div>
+<% end %>
+
+<%= render "decidim/system/devise/shared/links" %>
diff --git a/decidim-system/app/views/decidim/system/devise/passwords/new.html.erb b/decidim-system/app/views/decidim/system/devise/passwords/new.html.erb
new file mode 100644
index 000000000..f861a7513
--- /dev/null
+++ b/decidim-system/app/views/decidim/system/devise/passwords/new.html.erb
@@ -0,0 +1,15 @@
+<h2>Forgot your password?</h2>
+
+<%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :post }) do |f| %>
+  <%= devise_error_messages! %>
+
+  <div class="field">
+    <%= f.email_field :email, autofocus: true %>
+  </div>
+
+  <div class="actions">
+    <%= f.submit "Send me reset password instructions" %>
+  </div>
+<% end %>
+
+<%= render "decidim/system/devise/shared/links" %>
diff --git a/decidim-system/app/views/decidim/system/devise/sessions/new.html.erb b/decidim-system/app/views/decidim/system/devise/sessions/new.html.erb
new file mode 100644
index 000000000..503d3a66f
--- /dev/null
+++ b/decidim-system/app/views/decidim/system/devise/sessions/new.html.erb
@@ -0,0 +1,23 @@
+<h2>Log in</h2>
+
+<%= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %>
+  <div class="field">
+    <%= f.email_field :email, autofocus: true %>
+  </div>
+
+  <div class="field">
+    <%= f.password_field :password, autocomplete: "off" %>
+  </div>
+
+  <% if devise_mapping.rememberable? -%>
+    <div class="field">
+      <%= f.check_box :remember_me %>
+    </div>
+  <% end -%>
+
+  <div class="actions">
+    <%= f.submit "Log in" %>
+  </div>
+<% end %>
+
+<%= render "decidim/system/devise/shared/links" %>
diff --git a/decidim-system/app/views/decidim/system/devise/shared/_links.html.erb b/decidim-system/app/views/decidim/system/devise/shared/_links.html.erb
new file mode 100644
index 000000000..e6a3e4196
--- /dev/null
+++ b/decidim-system/app/views/decidim/system/devise/shared/_links.html.erb
@@ -0,0 +1,25 @@
+<%- if controller_name != 'sessions' %>
+  <%= link_to "Log in", new_session_path(resource_name) %><br />
+<% end -%>
+
+<%- if devise_mapping.registerable? && controller_name != 'registrations' %>
+  <%= link_to "Sign up", new_registration_path(resource_name) %><br />
+<% end -%>
+
+<%- if devise_mapping.recoverable? && controller_name != 'passwords' && controller_name != 'registrations' %>
+  <%= link_to "Forgot your password?", new_password_path(resource_name) %><br />
+<% end -%>
+
+<%- if devise_mapping.confirmable? && controller_name != 'confirmations' %>
+  <%= link_to "Didn't receive confirmation instructions?", new_confirmation_path(resource_name) %><br />
+<% end -%>
+
+<%- if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'unlocks' %>
+  <%= link_to "Didn't receive unlock instructions?", new_unlock_path(resource_name) %><br />
+<% end -%>
+
+<%- if devise_mapping.omniauthable? %>
+  <%- resource_class.omniauth_providers.each do |provider| %>
+    <%= link_to "Sign in with #{OmniAuth::Utils.camelize(provider)}", omniauth_authorize_path(resource_name, provider) %><br />
+  <% end -%>
+<% end -%>
diff --git a/decidim-system/app/views/decidim/system/organizations/edit.html.erb b/decidim-system/app/views/decidim/system/organizations/edit.html.erb
new file mode 100644
index 000000000..79805ac5f
--- /dev/null
+++ b/decidim-system/app/views/decidim/system/organizations/edit.html.erb
@@ -0,0 +1,13 @@
+<%= form_for(@form) do |f| %>
+  <div class="field">
+    <%= f.text_field :name, autofocus: true %>
+  </div>
+
+  <div class="field">
+    <%= f.text_field :host %>
+  </div>
+
+  <div class="actions">
+    <%= f.submit t("decidim.system.actions.save") %>
+  </div>
+<% end %>
diff --git a/decidim-system/app/views/decidim/system/organizations/index.html.erb b/decidim-system/app/views/decidim/system/organizations/index.html.erb
new file mode 100644
index 000000000..e8df7b01d
--- /dev/null
+++ b/decidim-system/app/views/decidim/system/organizations/index.html.erb
@@ -0,0 +1,34 @@
+<% content_for :title do %>
+  <h2><%= t ".title" %></h2>
+<% end %>
+
+<div class="actions title">
+  <%= link_to t("actions.new", scope: "decidim.system", name: t("models.organization.name", scope: "decidim.system")), ['new', 'organization'], class: 'new' %>
+</div>
+
+<table class="stack">
+  <thead>
+    <tr>
+      <th><%= t("models.organization.fields.name", scope: "decidim.system") %></th>
+      <th><%= t("models.organization.fields.created_at", scope: "decidim.system") %></th>
+      <th class="actions"><%= t("actions.title", scope: "decidim.system") %></th>
+    </tr>
+  </thead>
+  <tbody>
+    <% @organizations.each do |organization| %>
+      <tr>
+        <td>
+          <%= link_to organization.name, organization %><br />
+          <%= organization.host %>
+        </td>
+        <td>
+          <%= l organization.created_at, format: :short %>
+        </td>
+        <td class="actions">
+          <%= link_to t("actions.edit", scope: "decidim.system"), ['edit', organization] %>
+          <%= link_to t("actions.destroy", scope: "decidim.system"), organization, method: :delete, class: "small alert button", data: { confirm: t("actions.confirm_destroy", scope: "decidim.system") } %>
+        </td>
+      </tr>
+    <% end %>
+  </tbody>
+</table>
diff --git a/decidim-system/app/views/decidim/system/organizations/new.html.erb b/decidim-system/app/views/decidim/system/organizations/new.html.erb
new file mode 100644
index 000000000..1e493f1e6
--- /dev/null
+++ b/decidim-system/app/views/decidim/system/organizations/new.html.erb
@@ -0,0 +1,21 @@
+<% content_for :title do %>
+  <h2><%= t ".title" %></h2>
+<% end %>
+
+<%= form_for(@form) do |f| %>
+  <div class="field">
+    <%= f.text_field :name, autofocus: true %>
+  </div>
+
+  <div class="field">
+    <%= f.text_field :host %>
+  </div>
+
+  <div class="field">
+    <%= f.email_field :organization_admin_email %>
+  </div>
+
+  <div class="actions">
+    <%= f.submit t("decidim.system.models.organization.actions.save_and_invite") %>
+  </div>
+<% end %>
diff --git a/decidim-system/app/views/decidim/system/organizations/show.html.erb b/decidim-system/app/views/decidim/system/organizations/show.html.erb
new file mode 100644
index 000000000..88ca91298
--- /dev/null
+++ b/decidim-system/app/views/decidim/system/organizations/show.html.erb
@@ -0,0 +1,10 @@
+<% content_for :title do %>
+  <h2><%= link_to @organization.name, @organization %></h2>
+  <h3 class="subheader"><%= @organization.host %></h3>
+<% end %>
+
+<div class="actions">
+  <hr />
+  <%= link_to t("decidim.system.actions.edit"), ['edit', @organization] %>
+  <%= link_to t("decidim.system.actions.destroy"), @organization, method: :delete, class: "alert button", data: { confirm: t("decidim.system.actions.confirm_destroy") } %>
+</div>
diff --git a/decidim-system/app/views/layouts/decidim/system/_header.html.erb b/decidim-system/app/views/layouts/decidim/system/_header.html.erb
new file mode 100644
index 000000000..54221040e
--- /dev/null
+++ b/decidim-system/app/views/layouts/decidim/system/_header.html.erb
@@ -0,0 +1,4 @@
+<meta name="viewport" content="width=device-width, initial-scale=1">
+<%= csrf_meta_tags %>
+<%= stylesheet_link_tag    'decidim/system', media: 'all', 'data-turbolinks-track': 'reload' %>
+<%= javascript_include_tag 'decidim/system', 'data-turbolinks-track': 'reload' %>
diff --git a/decidim-system/app/views/layouts/decidim/system/_login_items.html.erb b/decidim-system/app/views/layouts/decidim/system/_login_items.html.erb
new file mode 100644
index 000000000..caf2dbe00
--- /dev/null
+++ b/decidim-system/app/views/layouts/decidim/system/_login_items.html.erb
@@ -0,0 +1,8 @@
+<div class="session-box">
+  <div class="admin-email">
+    <%= current_admin.email %>
+  </div>
+  <div class="sign-out">
+    <%= link_to('Logout', destroy_admin_session_path, :method => :delete) %>
+  </div>
+</div>
diff --git a/decidim-system/app/views/layouts/decidim/system/_sidebar.html.erb b/decidim-system/app/views/layouts/decidim/system/_sidebar.html.erb
new file mode 100644
index 000000000..e132d09b7
--- /dev/null
+++ b/decidim-system/app/views/layouts/decidim/system/_sidebar.html.erb
@@ -0,0 +1,15 @@
+<div class="title">
+  <h1>
+    <%= link_to root_path do %>
+      <%= title %>
+    <% end %>
+  </h1>
+</div>
+
+<nav class="main-menu">
+  <%= active_link_to t("menu.dashboard", scope: "decidim.system"), root_path, active: :exact %>
+  <%= active_link_to t("menu.organizations", scope: "decidim.system"), organizations_path, active: :inclusive %>
+  <%= active_link_to t("menu.admins", scope: "decidim.system"), admins_path, active: :inclusive %>
+</nav>
+
+<%= render partial: 'layouts/decidim/system/login_items' %>
diff --git a/decidim-system/app/views/layouts/decidim/system/application.html.erb b/decidim-system/app/views/layouts/decidim/system/application.html.erb
new file mode 100644
index 000000000..1f00d6a3c
--- /dev/null
+++ b/decidim-system/app/views/layouts/decidim/system/application.html.erb
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Decidim - System</title>
+<%= render partial: 'layouts/decidim/system/header' %>
+</head>
+
+<body>
+  <div class="off-canvas-wrapper">
+    <div class="off-canvas-wrapper-inner" data-off-canvas-wrapper>
+      <div class="off-canvas position-left reveal-for-large" id="my-info" data-off-canvas data-position="left">
+        <div class="sidebar">
+          <%= render partial: 'layouts/decidim/system/sidebar' %>
+        </div>
+      </div>
+
+      <div class="off-canvas-content" data-off-canvas-content>
+        <div class="title-bar hide-for-large">
+          <div class="title-bar-left">
+            <button class="menu-icon" type="button" data-open="my-info"></button>
+            <span class="title-bar-title"><%= title %></span>
+          </div>
+        </div>
+        <div class="row main-content">
+          <div class="small-12 column">
+            <% if content_for?(:title) %>
+              <section class="page-title">
+                <%= content_for :title %>
+              </section>
+            <% end %>
+
+            <%= display_flash_messages %>
+            <%= yield %>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</body>
+</html>
diff --git a/decidim-system/app/views/layouts/decidim/system/login.html.erb b/decidim-system/app/views/layouts/decidim/system/login.html.erb
new file mode 100644
index 000000000..f2af6dc65
--- /dev/null
+++ b/decidim-system/app/views/layouts/decidim/system/login.html.erb
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>Decidim - Login</title>
+    <%= render partial: 'layouts/decidim/system/header' %>
+  </head>
+
+  <body class="login">
+    <div class="login-form-wrapper">
+      <div class="login-form">
+        <h1>Decidim</h1>
+        <%= display_flash_messages %>
+        <div class="login-form-inner">
+          <%= yield %>
+        </div>
+      </div>
+    </div>
+  </body>
+</html>
diff --git a/decidim-system/bin/rails b/decidim-system/bin/rails
new file mode 100755
index 000000000..7714657bc
--- /dev/null
+++ b/decidim-system/bin/rails
@@ -0,0 +1,14 @@
+#!/usr/bin/env ruby
+# frozen_string_literal: true
+# 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/decidim/system/engine", __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/decidim-system/config/i18n-tasks.yml b/decidim-system/config/i18n-tasks.yml
new file mode 100644
index 000000000..4cad6b582
--- /dev/null
+++ b/decidim-system/config/i18n-tasks.yml
@@ -0,0 +1,120 @@
+# i18n-tasks finds and manages missing and unused translations: https://github.com/glebm/i18n-tasks
+
+# The "main" locale.
+base_locale: en
+## All available locales are inferred from the data by default. Alternatively, specify them explicitly:
+# locales: [es, fr]
+## Reporting locale, default: en. Available: en, ru.
+# internal_locale: en
+
+# Read and write translations.
+data:
+  ## Translations are read from the file system. Supported format: YAML, JSON.
+  ## Provide a custom adapter:
+  # adapter: I18n::Tasks::Data::FileSystem
+
+  # Locale files or `File.find` patterns where translations are read from:
+  read:
+    ## Default:
+    # - config/locales/%{locale}.yml
+    ## More files:
+    # - config/locales/**/*.%{locale}.yml
+    ## Another gem (replace %#= with %=):
+    # - "<%#= %x[bundle show vagrant].chomp %>/templates/locales/%{locale}.yml"
+
+  # Locale files to write new keys to, based on a list of key pattern => file rules. Matched from top to bottom:
+  # `i18n-tasks normalize -p` will force move the keys according to these rules
+  write:
+    ## For example, write devise and simple form keys to their respective files:
+    # - ['{devise, simple_form}.*', 'config/locales/\1.%{locale}.yml']
+    ## Catch-all default:
+    # - config/locales/%{locale}.yml
+
+  ## Specify the router (see Readme for details). Valid values: conservative_router, pattern_router, or a custom class.
+  # router: convervative_router
+
+  yaml:
+    write:
+      # do not wrap lines at 80 characters
+      line_width: -1
+
+  ## Pretty-print JSON:
+  # json:
+  #   write:
+  #     indent: '  '
+  #     space: ' '
+  #     object_nl: "\n"
+  #     array_nl: "\n"
+
+# Find translate calls
+search:
+  ## Paths or `File.find` patterns to search in:
+  # paths:
+  #  - app/
+
+  ## Root directories for relative keys resolution.
+  # relative_roots:
+  #   - app/controllers
+  #   - app/helpers
+  #   - app/mailers
+  #   - app/presenters
+  #   - app/views
+
+  ## Files or `File.fnmatch` patterns to exclude from search. Some files are always excluded regardless of this setting:
+  ##   %w(*.jpg *.png *.gif *.svg *.ico *.eot *.otf *.ttf *.woff *.woff2 *.pdf *.css *.sass *.scss *.less *.yml *.json)
+  exclude:
+    - app/assets/images
+    - app/assets/fonts
+
+  ## Alternatively, the only files or `File.fnmatch patterns` to search in `paths`:
+  ## If specified, this settings takes priority over `exclude`, but `exclude` still applies.
+  # only: ["*.rb", "*.html.slim"]
+
+  ## If `strict` is `false`, guess usages such as t("categories.#{category}.title"). The default is `true`.
+  # strict: true
+
+  ## Multiple scanners can be used. Their results are merged.
+  ## The options specified above are passed down to each scanner. Per-scanner options can be specified as well.
+  ## See this example of a custom scanner: https://github.com/glebm/i18n-tasks/wiki/A-custom-scanner-example
+
+## Google Translate
+# translation:
+#   # Get an API key and set billing info at https://code.google.com/apis/console to use Google Translate
+#   api_key: "AbC-dEf5"
+
+## Do not consider these keys missing:
+# ignore_missing:
+# - 'errors.messages.{accepted,blank,invalid,too_short,too_long}'
+# - '{devise,simple_form}.*'
+
+## Consider these keys used:
+# ignore_unused:
+# - 'activerecord.attributes.*'
+# - '{devise,kaminari,will_paginate}.*'
+# - 'simple_form.{yes,no}'
+# - 'simple_form.{placeholders,hints,labels}.*'
+# - 'simple_form.{error_notification,required}.:'
+
+## Exclude these keys from the `i18n-tasks eq-base' report:
+# ignore_eq_base:
+#   all:
+#     - common.ok
+#   fr,es:
+#     - common.brand
+
+## Ignore these keys completely:
+# ignore:
+#  - kaminari.*
+
+## Sometimes, it isn't possible for i18n-tasks to match the key correctly,
+## e.g. in case of a relative key defined in a helper method.
+## In these cases you can use the built-in PatternMapper to map patterns to keys, e.g.:
+#
+# <%#= I18n::Tasks.add_scanner 'I18n::Tasks::Scanners::PatternMapper',
+#        only: %w(*.html.haml *.html.slim),
+#        patterns: [['= title\b', '.page_title']] %>
+#
+# The PatternMapper can also match key literals via a special %{key} interpolation, e.g.:
+#
+# <%#= I18n::Tasks.add_scanner 'I18n::Tasks::Scanners::PatternMapper',
+#        patterns: [['\bSpree\.t[( ]\s*%{key}', 'spree.%{key}']] %>
diff --git a/decidim-system/config/locales/en.yml b/decidim-system/config/locales/en.yml
new file mode 100644
index 000000000..73b731dc3
--- /dev/null
+++ b/decidim-system/config/locales/en.yml
@@ -0,0 +1,60 @@
+---
+en:
+  decidim:
+    system:
+      actions:
+        confirm_destroy: Are you sure you want to delete this?
+        destroy: Destroy
+        edit: Edit
+        new: New %{name}
+        save: Save
+        title: Actions
+      admins:
+        create:
+          error: There was an error when creating a new admin.
+          success: Admin created successfully
+        destroy:
+          success: Admin successfully destroyed
+        edit:
+          title: Edit admin
+          update: Update admin
+        index:
+          title: Admins
+        new:
+          create: Create admin
+          title: New admin
+        update:
+          error: There was an error when updating this admin.
+          success: Admin updated successfully
+      menu:
+        admins: Admins
+        dashboard: Dashboard
+        organizations: Organizations
+      models:
+        admin:
+          fields:
+            created_at: Created at
+            email: Email
+          name: Admin
+          validations:
+            email_uniqueness: another admin with the same email already exists
+        organization:
+          actions:
+            save_and_invite: Create organization & invite admin
+          fields:
+            created_at: Created at
+            name: Name
+          name: Organization
+      organizations:
+        create:
+          error: There was an error when creating a new organization.
+          success: Organization created successfully.
+        index:
+          title: Organizations
+        new:
+          title: New organization
+        update:
+          error: There was an error when updating this organization.
+          success: Organization updated successfully.
+      titles:
+        dashboard: Dashboard
diff --git a/decidim-system/config/routes.rb b/decidim-system/config/routes.rb
new file mode 100644
index 000000000..7ac5ed29c
--- /dev/null
+++ b/decidim-system/config/routes.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+Decidim::System::Engine.routes.draw do
+  devise_for :admins,
+             class_name: "Decidim::System::Admin",
+             module: :'decidim/system/devise',
+             router_name: "decidim_system"
+
+  authenticate(:admin) do
+    resources :organizations
+    resources :admins
+    root to: "dashboard#show"
+  end
+end
diff --git a/decidim-system/db/migrate/20160919105637_devise_create_decidim_admins.rb b/decidim-system/db/migrate/20160919105637_devise_create_decidim_admins.rb
new file mode 100644
index 000000000..2b05443ae
--- /dev/null
+++ b/decidim-system/db/migrate/20160919105637_devise_create_decidim_admins.rb
@@ -0,0 +1,26 @@
+class DeviseCreateDecidimAdmins < ActiveRecord::Migration[5.0]
+  def change
+    create_table :decidim_system_admins do |t|
+      ## Database authenticatable
+      t.string :email,              null: false, default: ""
+      t.string :encrypted_password, null: false, default: ""
+
+      ## Recoverable
+      t.string   :reset_password_token
+      t.datetime :reset_password_sent_at
+
+      ## Rememberable
+      t.datetime :remember_created_at
+
+      ## Lockable
+      t.integer  :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
+      t.string   :unlock_token # Only if unlock strategy is :email or :both
+      t.datetime :locked_at
+
+      t.timestamps null: false
+    end
+
+    add_index :decidim_system_admins, :email,                unique: true
+    add_index :decidim_system_admins, :reset_password_token, unique: true
+  end
+end
diff --git a/decidim-system/decidim-system.gemspec b/decidim-system/decidim-system.gemspec
new file mode 100644
index 000000000..a3edcf02d
--- /dev/null
+++ b/decidim-system/decidim-system.gemspec
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+$LOAD_PATH.push File.expand_path("../lib", __FILE__)
+
+# Maintain your gem's version:
+require_relative "../decidim-core/lib/decidim/core/version"
+
+# Describe your gem and declare its dependencies:
+Gem::Specification.new do |s|
+  s.name        = "decidim-system"
+  s.version     = Decidim.version
+  s.authors     = ["Josep Jaume Rey Peroy", "Marc Riera Casals", "Oriol Gual Oliva"]
+  s.email       = ["josepjaume@gmail.com", "mrc2407@gmail.com", "oriolgual@gmail.com"]
+  s.homepage    = ""
+  s.summary     = "System administration"
+  s.description = "System administration to create new organization in an installation."
+  s.license     = "MIT"
+
+  s.files = Dir["{app,config,db,lib}/**/*", "MIT-LICENSE", "Rakefile", "README.md"]
+
+  s.add_dependency "decidim-core"
+  s.add_dependency "rails", Decidim.rails_version
+  s.add_dependency "devise", "~> 4.2"
+  s.add_dependency "rectify", "~> 0.6"
+  s.add_dependency "devise_invitable", "~> 1.7.0"
+  s.add_dependency "foundation-rails", "~> 6.2.3.0"
+  s.add_dependency "sass-rails", "~> 5.0.0"
+  s.add_dependency "jquery-rails", "~> 4.0"
+  s.add_dependency "turbolinks", Decidim.rails_version
+  s.add_dependency "jquery-turbolinks", "~> 2.1.0"
+  s.add_dependency "jbuilder", "~> 2.5"
+  s.add_dependency "foundation_rails_helper", "~> 2.0.0"
+  s.add_dependency "active_link_to", "~> 1.0.0"
+
+  s.add_development_dependency "factory_girl_rails"
+  s.add_development_dependency "database_cleaner", "~> 1.5.0"
+  s.add_development_dependency "capybara", "~> 2.4"
+  s.add_development_dependency "rspec-rails", "~> 3.5"
+  s.add_development_dependency "byebug"
+  s.add_development_dependency "wisper-rspec"
+  s.add_development_dependency "pg"
+  s.add_development_dependency "listen"
+  s.add_development_dependency "launchy"
+  s.add_development_dependency "i18n-tasks", "~> 0.9.5"
+end
diff --git a/decidim-system/lib/decidim/system.rb b/decidim-system/lib/decidim/system.rb
new file mode 100644
index 000000000..b5afb0380
--- /dev/null
+++ b/decidim-system/lib/decidim/system.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+require "decidim/system/engine"
+
+module Decidim
+  # This module contains all the logic related to a system-wide
+  # administration panel. The scope of the domain is to be able
+  # to manage Organizations (tenants), as well as have a bird's
+  # eye view of the whole system.
+  #
+  module System
+  end
+end
diff --git a/decidim-system/lib/decidim/system/engine.rb b/decidim-system/lib/decidim/system/engine.rb
new file mode 100644
index 000000000..12dac2ffd
--- /dev/null
+++ b/decidim-system/lib/decidim/system/engine.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+require "rails"
+require "active_support/all"
+
+require "decidim/core"
+require "devise"
+require "jquery-rails"
+require "sass-rails"
+require "turbolinks"
+require "jquery-turbolinks"
+require "foundation-rails"
+require "foundation_rails_helper"
+require "jbuilder"
+require "rectify"
+
+module Decidim
+  module System
+    # Decidim's core Rails Engine.
+    class Engine < ::Rails::Engine
+      isolate_namespace Decidim::System
+
+      config.to_prepare do
+        Rails.application.config.assets.precompile += %w(
+          decidim/system.js
+          decidim/system.css
+        )
+      end
+    end
+  end
+end
diff --git a/decidim-system/lib/generators/decidim/system/dummy_generator.rb b/decidim-system/lib/generators/decidim/system/dummy_generator.rb
new file mode 100644
index 000000000..9c1b395a8
--- /dev/null
+++ b/decidim-system/lib/generators/decidim/system/dummy_generator.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+require "rails/generators"
+require_relative "../../../../lib/generators/decidim/app_generator"
+
+module Decidim
+  module System
+    module Generators
+      # Generates a dummy test Rails app for the given library folder. It uses
+      # the `AppGenerator` class to actually generate the Rails app, so this
+      # generator only sets the path and some flags.
+      #
+      # The Rails app will be installed with some flags to disable git, tests,
+      # Gemfile and other options. Refer to the `create_dummy_app` method to see
+      # all the flags passed to the `AppGenerator` class, which is the one that
+      # actually generates the Rails app.
+      #
+      # Remember that, for how generators work, actions are executed based on the
+      # definition order of the public methods.
+      class DummyGenerator < Rails::Generators::Base
+        desc "Generate dummy app for testing purposes"
+
+        class_option :lib_name, type: :string,
+                                desc: "The library where the dummy app will be installed"
+
+        class_option :migrate, type: :boolean, default: false,
+                               desc: "Run migrations after installing decidim"
+
+        def cleanup
+          remove_directory_if_exists(dummy_path)
+        end
+
+        def create_dummy_app
+          Decidim::Generators::AppGenerator.start [
+            dummy_path,
+            "--skip_gemfile",
+            "--skip-bundle",
+            "--skip-git",
+            "--skip-keeps",
+            "--skip-test",
+            "--migrate=#{options[:migrate]}"
+          ]
+        end
+
+        private
+
+        def dummy_path
+          ENV["DUMMY_PATH"] || "spec/#{short_lib_name}_dummy"
+        end
+
+        def remove_directory_if_exists(path)
+          remove_dir(path) if File.directory?(path)
+        end
+
+        def short_lib_name
+          options[:lib_name].split("/").last
+        end
+      end
+    end
+  end
+end
diff --git a/decidim-system/lib/tasks/decidim/system_tasks.rake b/decidim-system/lib/tasks/decidim/system_tasks.rake
new file mode 100644
index 000000000..5ae8b6e88
--- /dev/null
+++ b/decidim-system/lib/tasks/decidim/system_tasks.rake
@@ -0,0 +1,5 @@
+# frozen_string_literal: true
+# desc "Explaining what the task does"
+# task :decidim_system do
+#   # Task goes here
+# end
diff --git a/decidim-system/spec/commands/decidim/system/create_admin_spec.rb b/decidim-system/spec/commands/decidim/system/create_admin_spec.rb
new file mode 100644
index 000000000..b35855af5
--- /dev/null
+++ b/decidim-system/spec/commands/decidim/system/create_admin_spec.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+require "spec_helper"
+
+module Decidim
+  module System
+    describe CreateAdmin, :db do
+      describe "call" do
+        let(:form) { AdminForm.new(params) }
+        let(:command) { described_class.new(form) }
+
+        describe "when the admin already exists" do
+          before do
+            create(:admin, email: "email@foo.bar")
+          end
+
+          let(:params) do
+            {
+              email: "email@foo.bar"
+            }
+          end
+
+          it "broadcasts invalid" do
+            expect { command.call }.to broadcast(:invalid)
+          end
+        end
+
+        describe "when the admin doesn't exist" do
+          before do
+            create(:admin, email: "email@foo.bar")
+          end
+
+          let(:params) do
+            {
+              email: "different_email@foo.bar",
+              password: "fake123",
+              password_confirmation: "fake123"
+            }
+          end
+
+          it "broadcasts ok and creates an admin" do
+            expect { command.call }.to broadcast(:ok)
+            expect(Admin.where(email: "different_email@foo.bar")).to exist
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/decidim-system/spec/commands/decidim/system/register_organization_spec.rb b/decidim-system/spec/commands/decidim/system/register_organization_spec.rb
new file mode 100644
index 000000000..671b9f981
--- /dev/null
+++ b/decidim-system/spec/commands/decidim/system/register_organization_spec.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: true
+require "spec_helper"
+
+module Decidim
+  module System
+    describe RegisterOrganization, :db do
+      describe "call" do
+        let(:form) do
+          RegisterOrganizationForm.new(params)
+        end
+
+        let(:command) { described_class.new(form) }
+
+        context "when the form is valid" do
+          let(:params) do
+            {
+              name: "Gotham City",
+              host: "decide.gotham.gov",
+              organization_admin_email: "f.laguardia@gotham.gov"
+            }
+          end
+
+          it "returns a valid response" do
+            expect { command.call }.to broadcast(:ok)
+          end
+
+          it "creates a new organization" do
+            expect { command.call }.to change { Organization.count }.by(1)
+            organization = Organization.last
+
+            expect(organization.name).to eq("Gotham City")
+            expect(organization.host).to eq("decide.gotham.gov")
+          end
+
+          it "invites a user as organization admin" do
+            expect { command.call }.to change { User.count }.by(1)
+            admin = User.last
+
+            expect(admin.email).to eq("f.laguardia@gotham.gov")
+            expect(admin.organization.name).to eq("Gotham City")
+            expect(admin).to be_admin
+            expect(admin).to be_created_by_invite
+          end
+        end
+
+        context "when the form is invalid" do
+          let(:params) do
+            {
+              name: nil,
+              host: "foo.com"
+            }
+          end
+
+          it "returns an invalid response" do
+            expect { command.call }.to broadcast(:invalid)
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/decidim-system/spec/factories.rb b/decidim-system/spec/factories.rb
new file mode 100644
index 000000000..a0ea71bce
--- /dev/null
+++ b/decidim-system/spec/factories.rb
@@ -0,0 +1,9 @@
+require_relative "../../decidim-core/spec/factories"
+
+FactoryGirl.define do
+  factory :admin, class: Decidim::System::Admin do
+    sequence(:email)      { |n| "admin#{n}@citizen.corp" }
+    password              "password1234"
+    password_confirmation "password1234"
+  end
+end
diff --git a/decidim-system/spec/features/manage_admins_spec.rb b/decidim-system/spec/features/manage_admins_spec.rb
new file mode 100644
index 000000000..f5702a722
--- /dev/null
+++ b/decidim-system/spec/features/manage_admins_spec.rb
@@ -0,0 +1,67 @@
+# frozen_string_literal: true
+
+require "spec_helper"
+
+describe "Manage admins", type: :feature do
+  let(:admin) { create(:admin) }
+  let!(:admin2) { create(:admin) }
+
+  before do
+    login_as admin, scope: :admin
+    visit decidim_system.admins_path
+  end
+
+  it "creates a new admin" do
+    find(".actions .new").click
+
+    within ".new_admin" do
+      fill_in :admin_email, with: "admin@foo.bar"
+      fill_in :admin_password, with: "fake123"
+      fill_in :admin_password_confirmation, with: "fake123"
+
+      find("*[type=submit]").click
+    end
+
+    within ".flash" do
+      expect(page).to have_content("successfully")
+    end
+
+    within "table" do
+      expect(page).to have_content("admin@foo.bar")
+    end
+  end
+
+  it "updates an admin" do
+    within find("tr", text: admin.email) do
+      click_link "Edit"
+    end
+
+    within ".edit_admin" do
+      fill_in :admin_email, with: "admin@another.domain"
+
+      find("*[type=submit]").click
+    end
+
+    within ".flash" do
+      expect(page).to have_content("successfully")
+    end
+
+    within "table" do
+      expect(page).to have_content("admin@another.domain")
+    end
+  end
+
+  it "deletes an admin" do
+    within find("tr", text: admin2.email) do
+      click_link "Destroy"
+    end
+
+    within ".flash" do
+      expect(page).to have_content("successfully")
+    end
+
+    within "table" do
+      expect(page).to_not have_content(admin2.email)
+    end
+  end
+end
diff --git a/decidim-system/spec/features/organizations_spec.rb b/decidim-system/spec/features/organizations_spec.rb
new file mode 100644
index 000000000..4a60dc470
--- /dev/null
+++ b/decidim-system/spec/features/organizations_spec.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: true
+
+require "spec_helper"
+
+describe "Organizations", type: :feature do
+  let(:admin) { create(:admin) }
+
+  context "authenticated admin" do
+    before do
+      login_as admin, scope: :admin
+      visit decidim_system.root_path
+    end
+
+    context "creating an organization" do
+      before do
+        click_link "Organizations"
+        click_link "New"
+      end
+
+      it "creates a new organization" do
+        fill_in "Name", with: "Citizen Corp"
+        fill_in "Host", with: "www.citizen.corp"
+        fill_in "Organization admin email", with: "mayor@citizen.corp"
+        click_button "Create organization & invite admin"
+
+        expect(page).to have_css("div.flash.success")
+        expect(page).to have_content("Citizen Corp")
+      end
+
+      context "with invalid data" do
+        it "doesn't create an organization" do
+          fill_in "Name", with: "Bad"
+          click_button "Create organization & invite admin"
+
+          expect(page).to have_css("div.flash.alert")
+          expect(page).to_not have_content("Organization created successfully")
+        end
+      end
+    end
+
+    context "editing an organization" do
+      let!(:organization) { create(:organization, name: "Citizen Corp") }
+
+      before do
+        click_link "Organizations"
+        within("table tbody tr:first") do
+          click_link "Edit"
+        end
+      end
+
+      it "edits the data" do
+        fill_in "Name", with: "Citizens Rule!"
+        fill_in "Host", with: "www.foo.org"
+        click_button "Save"
+
+        expect(page).to have_css("div.flash.success")
+        expect(page).to have_content("Citizens Rule!")
+      end
+    end
+  end
+end
diff --git a/decidim-system/spec/features/sessions_spec.rb b/decidim-system/spec/features/sessions_spec.rb
new file mode 100644
index 000000000..586852abd
--- /dev/null
+++ b/decidim-system/spec/features/sessions_spec.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+require "spec_helper"
+
+describe "Sessions", type: :feature do
+  let!(:admin) do
+    create(:admin, email: "admin@example.org",
+                   password: "123456",
+                   password_confirmation: "123456")
+  end
+
+  before(:each) do
+    visit decidim_system.root_path
+  end
+
+  context "when using a correct username and password" do
+    it "lets you into the system panel" do
+      within ".new_admin" do
+        fill_in :admin_email, with: "admin@example.org"
+        fill_in :admin_password, with: "123456"
+        click_button "Log in"
+      end
+
+      expect(page).to have_content("Dashboard")
+    end
+  end
+
+  context "when using an incorrectusername and password" do
+    it "doesn't let you in the admin panel" do
+      within ".new_admin" do
+        fill_in :admin_email, with: "admin@example.org"
+        fill_in :admin_password, with: "forged_password"
+        find("*[type=submit]").click
+      end
+
+      expect(page).not_to have_content("Dashboard")
+    end
+  end
+end
diff --git a/decidim-system/spec/i18n_spec.rb b/decidim-system/spec/i18n_spec.rb
new file mode 100644
index 000000000..e7126127e
--- /dev/null
+++ b/decidim-system/spec/i18n_spec.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+require 'i18n/tasks'
+
+RSpec.describe 'I18n' do
+  let(:i18n) { I18n::Tasks::BaseTask.new }
+  let(:missing_keys) { i18n.missing_keys }
+  let(:unused_keys) { i18n.unused_keys }
+
+  it 'does not have missing keys' do
+    expect(missing_keys).to be_empty,
+      "Missing #{missing_keys.leaves.count} i18n keys, run `i18n-tasks missing' to show them"
+  end
+
+  it 'does not have unused keys' do
+    expect(unused_keys).to be_empty,
+      "#{unused_keys.leaves.count} unused i18n keys, run `i18n-tasks unused' to show them"
+  end
+end
diff --git a/decidim-system/spec/spec_helper.rb b/decidim-system/spec/spec_helper.rb
new file mode 100644
index 000000000..28a3a27a5
--- /dev/null
+++ b/decidim-system/spec/spec_helper.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+ENV["RAILS_ENV"] ||= "test"
+
+if ENV["CI"]
+  require "simplecov"
+  SimpleCov.start
+
+  require "codecov"
+  SimpleCov.formatter = SimpleCov::Formatter::Codecov
+end
+
+begin
+  require File.expand_path("../system_dummy/config/environment", __FILE__)
+rescue LoadError
+  puts "Could not load dummy application. Please ensure you have run `bundle exec rake test_app`"
+  exit
+end
+
+require "rspec/rails"
+require "factory_girl_rails"
+require "database_cleaner"
+require "byebug"
+
+# Requires supporting files with custom matchers and macros, etc,
+# in ./support/ and its subdirectories.
+Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
+
+RSpec.configure do |config|
+  config.color = true
+  config.fail_fast = ENV["FAIL_FAST"] || false
+  config.infer_spec_type_from_file_location!
+  config.mock_with :rspec
+  config.raise_errors_for_deprecations!
+
+  # If you're not using ActiveRecord, or you'd prefer not to run each of your
+  # examples within a transaction, comment the following line or assign false
+  # instead of true.
+  config.use_transactional_fixtures = false
+end
diff --git a/decidim-system/spec/support/capybara.rb b/decidim-system/spec/support/capybara.rb
new file mode 100644
index 000000000..e69de29bb
diff --git a/decidim-system/spec/support/database_cleaner.rb b/decidim-system/spec/support/database_cleaner.rb
new file mode 100644
index 000000000..2211979de
--- /dev/null
+++ b/decidim-system/spec/support/database_cleaner.rb
@@ -0,0 +1,12 @@
+RSpec.configure do |config|
+  config.before(:suite) do
+    DatabaseCleaner.strategy = :transaction
+    DatabaseCleaner.clean_with(:truncation)
+  end
+
+  config.around(:each) do |example|
+    DatabaseCleaner.cleaning do
+      example.run
+    end
+  end
+end
diff --git a/decidim-system/spec/support/factory_girl.rb b/decidim-system/spec/support/factory_girl.rb
new file mode 100644
index 000000000..eec437fb3
--- /dev/null
+++ b/decidim-system/spec/support/factory_girl.rb
@@ -0,0 +1,3 @@
+RSpec.configure do |config|
+  config.include FactoryGirl::Syntax::Methods
+end
diff --git a/decidim-system/spec/support/warden.rb b/decidim-system/spec/support/warden.rb
new file mode 100644
index 000000000..ea2a1a865
--- /dev/null
+++ b/decidim-system/spec/support/warden.rb
@@ -0,0 +1,7 @@
+RSpec.configure do |config|
+  config.include Warden::Test::Helpers, type: :feature
+
+  config.after :each, type: :feature do
+    Warden.test_reset!
+  end
+end
diff --git a/decidim-system/spec/support/wisper.rb b/decidim-system/spec/support/wisper.rb
new file mode 100644
index 000000000..194b955ea
--- /dev/null
+++ b/decidim-system/spec/support/wisper.rb
@@ -0,0 +1,5 @@
+require 'wisper/rspec/matchers'
+
+RSpec::configure do |config|
+  config.include(Wisper::RSpec::BroadcastMatcher)
+end
diff --git a/decidim.gemspec b/decidim.gemspec
index 5e2faf1ed..87ba404c3 100644
--- a/decidim.gemspec
+++ b/decidim.gemspec
@@ -21,11 +21,12 @@ Gem::Specification.new do |spec|
   spec.bindir        = "bin"
   spec.executables   = ["decidim"]
   spec.require_paths = ["lib"]
 
   spec.add_dependency "decidim-core", Decidim.version
+  spec.add_dependency "decidim-system", Decidim.version
   spec.add_dependency "rails", Decidim.rails_version
 
   spec.add_development_dependency "bundler", "~> 1.12"
-  spec.add_development_dependency "rake", "~> 10.0"
+  spec.add_development_dependency "rake", "~> 11.0"
   spec.add_development_dependency "rspec", "~> 3.0"
 end
diff --git a/lib/decidim.rb b/lib/decidim.rb
index 904edf79f..f8bec565e 100644
--- a/lib/decidim.rb
+++ b/lib/decidim.rb
@@ -1,6 +1,7 @@
 # frozen_string_literal: true
 require "decidim/core"
+require "decidim/system"
 
 # Module declaration.
 module Decidim
 end
diff --git a/lib/generators/decidim/templates/Gemfile.erb b/lib/generators/decidim/templates/Gemfile.erb
index 9c0e20d42..f2d71f743 100644
--- a/lib/generators/decidim/templates/Gemfile.erb
+++ b/lib/generators/decidim/templates/Gemfile.erb
@@ -19,10 +19,13 @@ gem 'pg'
 
 gem 'jquery-rails'
 gem 'turbolinks', '~> 5'
 gem 'redis', '~> 3.0'
 
+gem 'foundation_rails_helper', github: 'sgruhier/foundation_rails_helper'
+
+
 group :development, :test do
   gem 'byebug', platform: :mri
 end
 
 group :development do
diff --git a/spec/decidim_spec.rb b/spec/decidim_spec.rb
index 39a3aceb4..9cff29dd5 100644
--- a/spec/decidim_spec.rb
+++ b/spec/decidim_spec.rb
@@ -1,7 +1,7 @@
 # frozen_string_literal: true
-require "spec_helper"
+require_relative "spec_helper"
 
 describe Decidim do
   it "has a version number" do
     expect(Decidim.version).not_to be nil
   end

Vulnerable code:     - 'decidim-core/spec/**/*'
    - 'decidim-core/test/**/*'
    - 'decidim-core/db/**/*'
      devise
      foundation-rails (~> 6.2.3)
    coffee-rails (4.2.1)
      coffee-script (>= 2.2.0)
      railties (>= 4.0.0, < 5.2.x)
    coffee-script (2.4.1)
      coffee-script-source
      execjs
    coffee-script-source (1.10.0)
    rake (10.5.0)
    uglifier (3.0.2)
      execjs (>= 0.3.0, < 3)
  coffee-rails (~> 4.2)
  jbuilder (~> 2.5)
  jquery-rails
  rake (~> 10.0)
  sass-rails (~> 5.0)
  turbolinks (~> 5)
  uglifier (>= 1.3.0)
DECIDIM_GEMS = %w(core).freeze
task test: :test_app do
      sh "rspec"
    end
  end
end

desc "Generates a dummy app for testing for every Decidim engine"
task :test_app do
  DECIDIM_GEMS.each do |gem_name|
    Dir.chdir("#{File.dirname(__FILE__)}/decidim-#{gem_name}") do
      sh "rake test_app"
ruby '2.3.1'
# Rails 5 deps
gem "sass-rails", "~> 5.0"
gem "uglifier", ">= 1.3.0"
gem "coffee-rails", "~> 4.2"
gem "jquery-rails"
gem "turbolinks", "~> 5"
gem "jbuilder", "~> 2.5"

group :development do
  gem "byebug"
  gem "listen"
end

group :test do
  gem "capybara", "~> 2.4"
  gem "rspec-rails", "~> 3.5"
end
      devise
    coffee-rails (4.2.1)
      coffee-script (>= 2.2.0)
      railties (>= 4.0.0, < 5.2.x)
    coffee-script (2.4.1)
      coffee-script-source
      execjs
    coffee-script-source (1.10.0)
    sprockets-rails (3.1.1)
    uglifier (3.0.2)
      execjs (>= 0.3.0, < 3)
  coffee-rails (~> 4.2)
  jbuilder (~> 2.5)
  jquery-rails
  sass-rails (~> 5.0)
  turbolinks (~> 5)
  uglifier (>= 1.3.0)
  rdoc.title    = "Decidim"
//= require_tree .
 *= require_tree .
    # Include default devise modules. Others available are:
    # :confirmable, :lockable, :timeoutable and :omniauthable
    devise :database_authenticatable, :registerable,
ENGINE_PATH = File.expand_path("../../lib/decidim/engine", __FILE__)
  # config.scoped_views = false
  # config.warden do |manager|
  #   manager.intercept_401 = false
  #   manager.default_strategies(scope: :user).unshift :some_external_strategy
  # end
  config.router_name = :decidim
# Additional translations at https://github.com/plataformatec/devise/wiki/I18n

en:
  devise:
    confirmations:
      confirmed: "Your email address has been successfully confirmed."
      send_instructions: "You will receive an email with instructions for how to confirm your email address in a few minutes."
      send_paranoid_instructions: "If your email address exists in our database, you will receive an email with instructions for how to confirm your email address in a few minutes."
    failure:
      already_authenticated: "You are already signed in."
      inactive: "Your account is not activated yet."
      invalid: "Invalid %{authentication_keys} or password."
      locked: "Your account is locked."
      last_attempt: "You have one more attempt before your account is locked."
      not_found_in_database: "Invalid %{authentication_keys} or password."
      timeout: "Your session expired. Please sign in again to continue."
      unauthenticated: "You need to sign in or sign up before continuing."
      unconfirmed: "You have to confirm your email address before continuing."
    mailer:
      confirmation_instructions:
        subject: "Confirmation instructions"
      reset_password_instructions:
        subject: "Reset password instructions"
      unlock_instructions:
        subject: "Unlock instructions"
      password_change:
        subject: "Password Changed"
    omniauth_callbacks:
      failure: "Could not authenticate you from %{kind} because \"%{reason}\"."
      success: "Successfully authenticated from %{kind} account."
    passwords:
      no_token: "You can't access this page without coming from a password reset email. If you do come from a password reset email, please make sure you used the full URL provided."
      send_instructions: "You will receive an email with instructions on how to reset your password in a few minutes."
      send_paranoid_instructions: "If your email address exists in our database, you will receive a password recovery link at your email address in a few minutes."
      updated: "Your password has been changed successfully. You are now signed in."
      updated_not_active: "Your password has been changed successfully."
    registrations:
      destroyed: "Bye! Your account has been successfully cancelled. We hope to see you again soon."
      signed_up: "Welcome! You have signed up successfully."
      signed_up_but_inactive: "You have signed up successfully. However, we could not sign you in because your account is not yet activated."
      signed_up_but_locked: "You have signed up successfully. However, we could not sign you in because your account is locked."
      signed_up_but_unconfirmed: "A message with a confirmation link has been sent to your email address. Please follow the link to activate your account."
      update_needs_confirmation: "You updated your account successfully, but we need to verify your new email address. Please check your email and follow the confirm link to confirm your new email address."
      updated: "Your account has been updated successfully."
    sessions:
      signed_in: "Signed in successfully."
      signed_out: "Signed out successfully."
      already_signed_out: "Signed out successfully."
    unlocks:
      send_instructions: "You will receive an email with instructions for how to unlock your account in a few minutes."
      send_paranoid_instructions: "If your account exists, you will receive an email with instructions for how to unlock it in a few minutes."
      unlocked: "Your account has been unlocked successfully. Please sign in to continue."
  errors:
    messages:
      already_confirmed: "was already confirmed, please try signing in"
      confirmation_period_expired: "needs to be confirmed within %{period}, please request a new one"
      expired: "has expired, please request a new one"
      not_found: "not found"
      not_locked: "was not locked"
      not_saved:
        one: "1 error prohibited this %{resource} from being saved:"
        other: "%{count} errors prohibited this %{resource} from being saved:"
  devise_for :users, class_name: "Decidim::User", module: :devise
  s.add_dependency "devise"
require "devise"

require "foundation-rails"
          "*= require decidim\n "
        rake "db:drop"
# frozen_string_literal: true
require "test_helper"

module Decidim
  class HomeControllerTest < ActionDispatch::IntegrationTest
    include Engine.routes.url_helpers

    # test "the truth" do
    #   assert true
    # end
  end
end
# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html

# This model initially had no columns defined. If you add columns to the
# model remove the '{}' from the fixture names and add the columns immediately
# below each fixture, per the syntax in the comments below
#
one: {}
# column: value
#
two: {}
# column: value
# frozen_string_literal: true
require "test_helper"
require "generators/decidim/decidim_generator"

module Decidim
  class DecidimGeneratorTest < Rails::Generators::TestCase
    tests DecidimGenerator
    destination Rails.root.join("tmp/generators")
    setup :prepare_destination

    # test "generator runs without errors" do
    #   assert_nothing_raised do
    #     run_generator ["arguments"]
    #   end
    # end
  end
end
# frozen_string_literal: true
require "test_helper"
require "generators/install/install_generator"

module Decidim
  class InstallGeneratorTest < Rails::Generators::TestCase
    tests InstallGenerator
    destination Rails.root.join("tmp/generators")
    setup :prepare_destination

    # test "generator runs without errors" do
    #   assert_nothing_raised do
    #     run_generator ["arguments"]
    #   end
    # end
  end
end
# frozen_string_literal: true
require "test_helper"
require "generators/installation/installation_generator"

module Decidim
  class InstallationGeneratorTest < Rails::Generators::TestCase
    tests InstallationGenerator
    destination Rails.root.join("tmp/generators")
    setup :prepare_destination

    # test "generator runs without errors" do
    #   assert_nothing_raised do
    #     run_generator ["arguments"]
    #   end
    # end
  end
end
# frozen_string_literal: true
require "test_helper"

module Decidim
  class UserTest < ActiveSupport::TestCase
    # test "the truth" do
    #   assert true
    # end
  end
end
  spec.add_development_dependency "rake", "~> 10.0"
require "spec_helper"
Fixed code: scss:
  enabled: false
jshint:
  enabled: false
    - 'decidim-*/spec/**/*'
    - 'decidim-*/test/**/*'
    - 'decidim-*/db/**/*'
Style/AccessorMethodName:
  Exclude:
    - "lib/generators/decidim/app_generator.rb"

  Enabled: false
Style/Documentation:
  Exclude:
    - '**/*/spec/**/*_spec.rb'

  Enabled: false

gemspec path: "."
gemspec path: "decidim-core"

gem "rubocop"
GIT
  remote: git://github.com/sgruhier/foundation_rails_helper.git
  revision: 809f127b76747b53fb199ff4e5d3f06aa3d35f97
  specs:
    foundation_rails_helper (2.0.0)
      actionpack (>= 4.1)
      activemodel (>= 4.1)
      activesupport (>= 4.1)
      railties (>= 4.1)
      tzinfo (~> 1.2, >= 1.2.2)

      decidim-system (= 0.0.1.alpha2)
      rails (~> 5.0.0)
    decidim-system (0.0.1.alpha2)
      active_link_to (~> 1.0.0)
      decidim-core
      devise (~> 4.2)
      devise_invitable (~> 1.7.0)
      foundation-rails (~> 6.2.3.0)
      foundation_rails_helper (~> 2.0.0)
      jbuilder (~> 2.5)
      jquery-rails (~> 4.0)
      jquery-turbolinks (~> 2.1.0)
      rectify (~> 0.6)
      sass-rails (~> 5.0.0)
      turbolinks (~> 5.0.0)

PATH
  remote: decidim-core
  specs:
      active_link_to (~> 1.0.0)
      devise (~> 4.2)
      foundation-rails (~> 6.2.3.0)
      foundation_rails_helper (~> 2.0.0)
      jbuilder (~> 2.5)
      jquery-rails (~> 4.0)
      jquery-turbolinks (~> 2.1.0)
      rectify (~> 0.6)
      sass-rails (~> 5.0.0)
      turbolinks (~> 5.0.0)
    active_link_to (1.0.3)
      actionpack
    ast (2.3.0)
    axiom-types (0.1.1)
      descendants_tracker (~> 0.0.4)
      ice_nine (~> 0.11.0)
      thread_safe (~> 0.3, >= 0.3.1)
    coercible (1.0.0)
      descendants_tracker (~> 0.0.1)
    database_cleaner (1.5.3)
    descendants_tracker (0.0.4)
      thread_safe (~> 0.3, >= 0.3.1)
    devise_invitable (1.7.0)
      actionmailer (>= 4.0.0)
      devise (>= 4.0.0)
    easy_translate (0.5.0)
      json
      thread
      thread_safe
    equalizer (0.0.11)
    factory_girl (4.7.0)
      activesupport (>= 3.0.0)
    factory_girl_rails (4.7.0)
      factory_girl (~> 4.7.0)
      railties (>= 3.0.0)
    highline (1.7.8)
    i18n-tasks (0.9.5)
      activesupport (>= 4.0.2)
      ast (>= 2.1.0)
      easy_translate (>= 0.5.0)
      erubis
      highline (>= 1.7.3)
      i18n
      parser (>= 2.2.3.0)
      term-ansicolor (>= 1.3.2)
      terminal-table (>= 1.5.1)
    ice_nine (0.11.2)
    jquery-turbolinks (2.1.0)
      railties (>= 3.1.0)
      turbolinks
    parser (2.3.1.4)
      ast (~> 2.2)
    powerpack (0.1.1)
    rainbow (2.1.0)
    rake (11.3.0)
    rectify (0.6.1)
      activemodel (>= 4.1.0)
      activerecord (>= 4.1.0)
      activesupport (>= 4.1.0)
      virtus (~> 1.0.5)
      wisper (>= 1.6.1)
    rubocop (0.43.0)
      parser (>= 2.3.1.1, < 3.0)
      powerpack (~> 0.1)
      rainbow (>= 1.99.1, < 3.0)
      ruby-progressbar (~> 1.7)
      unicode-display_width (~> 1.0, >= 1.0.1)
    ruby-progressbar (1.8.1)
    term-ansicolor (1.3.2)
      tins (~> 1.0)
    terminal-table (1.7.3)
      unicode-display_width (~> 1.1.1)
    thread (0.2.2)
    tins (1.12.0)
    unicode-display_width (1.1.1)
    virtus (1.0.5)
      axiom-types (~> 0.1)
      coercible (~> 1.0)
      descendants_tracker (~> 0.0, >= 0.0.3)
      equalizer (~> 0.0, >= 0.0.9)
    wisper (1.6.1)
    wisper-rspec (0.0.2)
  database_cleaner (~> 1.5.0)
  decidim-core!
  factory_girl_rails
  foundation_rails_helper!
  i18n-tasks (~> 0.9.5)
  rake (~> 11.0)
  rubocop
  wisper-rspec
DECIDIM_GEMS = %w(core system).freeze
task :test do
      sh "rake"
ruby "2.3.1"
gem "listen"
gem "foundation_rails_helper", github: "sgruhier/foundation_rails_helper"

gemspec path: "../decidim-system"
gemspec path: ".."
GIT
  remote: git://github.com/sgruhier/foundation_rails_helper.git
  revision: 809f127b76747b53fb199ff4e5d3f06aa3d35f97
  specs:
    foundation_rails_helper (2.0.0)
      actionpack (>= 4.1)
      activemodel (>= 4.1)
      activesupport (>= 4.1)
      railties (>= 4.1)
      tzinfo (~> 1.2, >= 1.2.2)

PATH
  remote: ../decidim-system
  specs:
    decidim-system (0.0.1.alpha2)
      active_link_to (~> 1.0.0)
      decidim-core
      devise (~> 4.2)
      devise_invitable (~> 1.7.0)
      foundation-rails (~> 6.2.3.0)
      foundation_rails_helper (~> 2.0.0)
      jbuilder (~> 2.5)
      jquery-rails (~> 4.0)
      jquery-turbolinks (~> 2.1.0)
      rails (~> 5.0.0)
      rectify (~> 0.6)
      sass-rails (~> 5.0.0)
      turbolinks (~> 5.0.0)

PATH
  remote: ..
  specs:
    decidim (0.0.1.alpha2)
      decidim-core (= 0.0.1.alpha2)
      decidim-system (= 0.0.1.alpha2)
      rails (~> 5.0.0)

      active_link_to (~> 1.0.0)
      devise (~> 4.2)
      foundation_rails_helper (~> 2.0.0)
      jbuilder (~> 2.5)
      jquery-rails (~> 4.0)
      jquery-turbolinks (~> 2.1.0)
      rectify (~> 0.6)
      turbolinks (~> 5.0.0)
    active_link_to (1.0.3)
      actionpack
    ast (2.3.0)
    axiom-types (0.1.1)
      descendants_tracker (~> 0.0.4)
      ice_nine (~> 0.11.0)
      thread_safe (~> 0.3, >= 0.3.1)
    coercible (1.0.0)
      descendants_tracker (~> 0.0.1)
    database_cleaner (1.5.3)
    descendants_tracker (0.0.4)
      thread_safe (~> 0.3, >= 0.3.1)
    devise_invitable (1.7.0)
      actionmailer (>= 4.0.0)
      devise (>= 4.0.0)
    easy_translate (0.5.0)
      json
      thread
      thread_safe
    equalizer (0.0.11)
    factory_girl (4.7.0)
      activesupport (>= 3.0.0)
    factory_girl_rails (4.7.0)
      factory_girl (~> 4.7.0)
      railties (>= 3.0.0)
    highline (1.7.8)
    i18n-tasks (0.9.5)
      activesupport (>= 4.0.2)
      ast (>= 2.1.0)
      easy_translate (>= 0.5.0)
      erubis
      highline (>= 1.7.3)
      i18n
      parser (>= 2.2.3.0)
      term-ansicolor (>= 1.3.2)
      terminal-table (>= 1.5.1)
    ice_nine (0.11.2)
    jquery-turbolinks (2.1.0)
      railties (>= 3.1.0)
      turbolinks
    json (2.0.2)
    launchy (2.4.3)
      addressable (~> 2.3)
    parser (2.3.1.4)
      ast (~> 2.2)
    rectify (0.6.1)
      activemodel (>= 4.1.0)
      activerecord (>= 4.1.0)
      activesupport (>= 4.1.0)
      virtus (~> 1.0.5)
      wisper (>= 1.6.1)
    rspec (3.5.0)
      rspec-core (~> 3.5.0)
      rspec-expectations (~> 3.5.0)
      rspec-mocks (~> 3.5.0)
    sprockets-rails (3.2.0)
    term-ansicolor (1.3.2)
      tins (~> 1.0)
    terminal-table (1.7.3)
      unicode-display_width (~> 1.1.1)
    thread (0.2.2)
    tins (1.12.0)
    unicode-display_width (1.1.1)
    virtus (1.0.5)
      axiom-types (~> 0.1)
      coercible (~> 1.0)
      descendants_tracker (~> 0.0, >= 0.0.3)
      equalizer (~> 0.0, >= 0.0.9)
    wisper (1.6.1)
    wisper-rspec (0.0.2)
  bundler (~> 1.12)
  database_cleaner (~> 1.5.0)
  decidim!
  decidim-system!
  factory_girl_rails
  foundation_rails_helper!
  i18n-tasks (~> 0.9.5)
  launchy
  rake (~> 11.0)
  rspec (~> 3.0)
  wisper-rspec
  rdoc.title    = "Decidim::Core"
task default: :test


task test: :test_app do
  Dir.chdir(File.dirname(__FILE__).to_s) do
    sh "rspec spec"
  end
end
# frozen_string_literal: true
module Decidim
  # Organizations are one of the main models of Decidim. In a single Decidim
  # installation we can find many organizations and each of them can start
  # their own participatory processes.
  class Organization < ApplicationRecord
    validates :name, :host, uniqueness: true
  end
end
    devise :invitable, :database_authenticatable, :registerable,

    belongs_to :organization, foreign_key: "decidim_organization_id", class_name: Decidim::Organization

    ROLES = %w(admin moderator official).freeze

    validates :organization, presence: true
    validates :roles, inclusion: { in: ROLES }, allow_blank: true

    # Checks if the user is an admin in the organization it belongs to. This
    # should probably be deleted and add a system to authorize actions.
    #
    # Returns Booolean.
    def admin?
      roles.include?("admin")
    end
<%= display_flash_messages %>
<p><%= t("devise.mailer.invitation_instructions.hello", email: @resource.email) %></p>

<p><%= t("devise.mailer.invitation_instructions.someone_invited_you", application: Decidim.config.application_name) %></p>

<p><%= link_to t("devise.mailer.invitation_instructions.accept"), accept_invitation_url(@resource, :invitation_token => @token) %></p>

<% if @resource.invitation_due_at %>
  <p><%= t("devise.mailer.invitation_instructions.accept_until", due_date: l(@resource.invitation_due_at, format: :'devise.mailer.invitation_instructions.accept_until_format')) %></p>
<% end %>

<p><%= t("devise.mailer.invitation_instructions.ignore").html_safe %></p>
<%= t("devise.mailer.invitation_instructions.hello", email: @resource.email) %>

<%= t("devise.mailer.invitation_instructions.someone_invited_you", application: Decidim.config.application_name) %>

<%= accept_invitation_url(@resource, :invitation_token => @token) %>

<% if @resource.invitation_due_at %>
  <%= t("devise.mailer.invitation_instructions.accept_until", due_date: l(@resource.invitation_due_at, format: :'devise.mailer.invitation_instructions.accept_until_format')) %>
<% end %>

<%= strip_tags t("devise.mailer.invitation_instructions.ignore") %>
ENGINE_PATH = File.expand_path("../../lib/decidim/core/engine", __FILE__)
# i18n-tasks finds and manages missing and unused translations: https://github.com/glebm/i18n-tasks

# The "main" locale.
base_locale: en
## All available locales are inferred from the data by default. Alternatively, specify them explicitly:
# locales: [es, fr]
## Reporting locale, default: en. Available: en, ru.
# internal_locale: en

# Read and write translations.
data:
  ## Translations are read from the file system. Supported format: YAML, JSON.
  ## Provide a custom adapter:
  # adapter: I18n::Tasks::Data::FileSystem

  # Locale files or `File.find` patterns where translations are read from:
  read:
    ## Default:
    # - config/locales/%{locale}.yml
    ## More files:
    # - config/locales/**/*.%{locale}.yml
    ## Another gem (replace %#= with %=):
    # - "<%#= %x[bundle show vagrant].chomp %>/templates/locales/%{locale}.yml"

  # Locale files to write new keys to, based on a list of key pattern => file rules. Matched from top to bottom:
  # `i18n-tasks normalize -p` will force move the keys according to these rules
  write:
    ## For example, write devise and simple form keys to their respective files:
    # - ['{devise, simple_form}.*', 'config/locales/\1.%{locale}.yml']
    ## Catch-all default:
    # - config/locales/%{locale}.yml

  ## Specify the router (see Readme for details). Valid values: conservative_router, pattern_router, or a custom class.
  # router: convervative_router

  yaml:
    write:
      # do not wrap lines at 80 characters
      line_width: -1

  ## Pretty-print JSON:
  # json:
  #   write:
  #     indent: '  '
  #     space: ' '
  #     object_nl: "\n"
  #     array_nl: "\n"

# Find translate calls
search:
  ## Paths or `File.find` patterns to search in:
  # paths:
  #  - app/

  ## Root directories for relative keys resolution.
  # relative_roots:
  #   - app/controllers
  #   - app/helpers
  #   - app/mailers
  #   - app/presenters
  #   - app/views

  ## Files or `File.fnmatch` patterns to exclude from search. Some files are always excluded regardless of this setting:
  ##   %w(*.jpg *.png *.gif *.svg *.ico *.eot *.otf *.ttf *.woff *.woff2 *.pdf *.css *.sass *.scss *.less *.yml *.json)
  exclude:
    - app/assets/images
    - app/assets/fonts

  ## Alternatively, the only files or `File.fnmatch patterns` to search in `paths`:
  ## If specified, this settings takes priority over `exclude`, but `exclude` still applies.
  # only: ["*.rb", "*.html.slim"]

  ## If `strict` is `false`, guess usages such as t("categories.#{category}.title"). The default is `true`.
  # strict: true

  ## Multiple scanners can be used. Their results are merged.
  ## The options specified above are passed down to each scanner. Per-scanner options can be specified as well.
  ## See this example of a custom scanner: https://github.com/glebm/i18n-tasks/wiki/A-custom-scanner-example

## Google Translate
# translation:
#   # Get an API key and set billing info at https://code.google.com/apis/console to use Google Translate
#   api_key: "AbC-dEf5"

## Do not consider these keys missing:
ignore_missing:
- '{devise,simple_form}.*'

## Consider these keys used:
ignore_unused:
  - '{time.formats}.*'
# - 'activerecord.attributes.*'
# - '{devise,kaminari,will_paginate}.*'
# - 'simple_form.{yes,no}'
# - 'simple_form.{placeholders,hints,labels}.*'
# - 'simple_form.{error_notification,required}.:'

## Exclude these keys from the `i18n-tasks eq-base' report:
# ignore_eq_base:
#   all:
#     - common.ok
#   fr,es:
#     - common.brand

## Ignore these keys completely:
# ignore:
#  - kaminari.*

## Sometimes, it isn't possible for i18n-tasks to match the key correctly,
## e.g. in case of a relative key defined in a helper method.
## In these cases you can use the built-in PatternMapper to map patterns to keys, e.g.:
#
# <%#= I18n::Tasks.add_scanner 'I18n::Tasks::Scanners::PatternMapper',
#        only: %w(*.html.haml *.html.slim),
#        patterns: [['= title\b', '.page_title']] %>
#
# The PatternMapper can also match key literals via a special %{key} interpolation, e.g.:
#
# <%#= I18n::Tasks.add_scanner 'I18n::Tasks::Scanners::PatternMapper',
#        patterns: [['\bSpree\.t[( ]\s*%{key}', 'spree.%{key}']] %>

require "decidim/devise_failure_app"

  # ==> Configuration for :invitable
  # The period the generated invitation token is valid, after
  # this period, the invited resource won't be able to accept the invitation.
  # When invite_for is 0 (the default), the invitation won't expire.
  config.invite_for = 2.weeks

  # Number of invitations users can send.
  # - If invitation_limit is nil, there is no limit for invitations, users can
  # send unlimited invitations, invitation_limit column is not used.
  # - If invitation_limit is 0, users can't send invitations by default.
  # - If invitation_limit n > 0, users can send n invitations.
  # You can change invitation_limit column for some users so they can send more
  # or less invitations, even with global invitation_limit = 0
  # Default: nil
  # config.invitation_limit = 5

  # The key to be used to check existing users when sending an invitation
  # and the regexp used to test it when validate_on_invite is not set.
  # config.invite_key = {:email => /\A[^@]+@[^@]+\z/}
  # config.invite_key = {:email => /\A[^@]+@[^@]+\z/, :username => nil}

  # Flag that force a record to be valid before being actually invited
  # Default: false
  # config.validate_on_invite = true

  # Resend invitation if user with invited status is invited again
  # Default: true
  # config.resend_invitation = false

  # The class name of the inviting model. If this is nil,
  # the #invited_by association is declared to be polymorphic.
  # Default: nil
  # config.invited_by_class_name = 'User'

  # The foreign key to the inviting model (if invited_by_class_name is set)
  # Default: :invited_by_id
  # config.invited_by_foreign_key = :invited_by_id

  # The column name used for counter_cache column. If this is nil,
  # the #invited_by association is declared without counter_cache.
  # Default: nil
  # config.invited_by_counter_cache = :invitations_count

  # Auto-login after the user accepts the invite. If this is false,
  # the user will need to manually log in after accepting the invite.
  # Default: true
  # config.allow_insecure_sign_in_after_accept = false

  config.scoped_views = true
  config.warden do |manager|
    manager.failure_app = Decidim::DeviseFailureApp
  end
  # config.router_name = :decidim
---
en:
  devise:
    mailer:
      invitation_instructions:
        accept: Accept invitation
        accept_until: This invitation will be due in %{due_date}.
        hello: Hello %{email}
        ignore: |-
          If you don't want to accept the invitation, please ignore this email.<br />
          Your account won't be created until you access the link above and set your password.
        someone_invited_you: Someone has invited you to %{application}, you can accept it through the link below.
  time:
    formats:
      devise:
        mailer:
          invitation_instructions:
            accept_until_format: "%B %d, %Y %I:%M %p"

  devise_for :users, class_name: "Decidim::User", module: :'decidim/devise', router_name: :decidim
class CreateDecidimOrganizations < ActiveRecord::Migration[5.0]
  def change
    create_table :decidim_organizations do |t|
      t.string :name, null: false
      t.string :host, null: false

      t.timestamps
    end

    add_index :decidim_organizations, :name, unique: true
    add_index :decidim_organizations, :host, unique: true
  end
end
class DeviseInvitableAddToDecidimUsers < ActiveRecord::Migration
  def up
    change_table :decidim_users do |t|
      t.string     :invitation_token
      t.datetime   :invitation_created_at
      t.datetime   :invitation_sent_at
      t.datetime   :invitation_accepted_at
      t.integer    :invitation_limit
      t.references :invited_by, polymorphic: true
      t.integer    :invitations_count, default: 0
      t.index      :invitations_count
      t.index      :invitation_token, unique: true # for invitable
      t.index      :invited_by_id
    end
  end

  def down
    change_table :decidim_users do |t|
      t.remove_references :invited_by, polymorphic: true
      t.remove :invitations_count, :invitation_limit, :invitation_sent_at, :invitation_accepted_at, :invitation_token, :invitation_created_at
    end
  end
end
class UserBelongsToOrganization < ActiveRecord::Migration[5.0]
  def change
    add_reference :decidim_users, :decidim_organization, index: true, foreign_key: true
  end
end
class UserHasRoles < ActiveRecord::Migration[5.0]
  def change
    add_column :decidim_users, :roles, :string, array: true, default: []
  end
end
  s.add_dependency "devise", "~> 4.2"
  s.add_dependency "rectify", "~> 0.6"
  s.add_dependency "jquery-rails", "~> 4.0"
  s.add_dependency "turbolinks", Decidim.rails_version
  s.add_dependency "jquery-turbolinks", "~> 2.1.0"
  s.add_dependency "jbuilder", "~> 2.5"
  s.add_dependency "foundation_rails_helper", "~> 2.0.0"
  s.add_dependency "active_link_to", "~> 1.0.0"

  s.add_development_dependency "factory_girl_rails"
  s.add_development_dependency "database_cleaner", "~> 1.5.0"
  s.add_development_dependency "capybara", "~> 2.4"
  s.add_development_dependency "rspec-rails", "~> 3.5"
  s.add_development_dependency "byebug"
  s.add_development_dependency "wisper-rspec"
  s.add_development_dependency "i18n-tasks", "~> 0.9.5"
require "devise"
require "devise_invitable"
require "jquery-rails"
require "sass-rails"
require "turbolinks"
require "jquery-turbolinks"
require "foundation-rails"
require "foundation_rails_helper"
require "jbuilder"
require "active_link_to"
require "rectify"

# encoding: utf-8
# frozen_string_literal: true

module Decidim
  # We've provided a custom class in order to be able to deactivate the
  # script_name hack that doesn't seem to be affecting us (it is actually
  # introducing a bug).
  class DeviseFailureApp < Devise::FailureApp
    def scope_url
      opts  = {}

      # Initialize script_name with nil to prevent infinite loops in
      # authenticated mounted engines in rails 4.2 and 5.0

      # The line below is what we commented LOL ^^
      # opts[:script_name] = nil

      route = route(scope)

      opts[:format] = request_format unless skip_format?

      opts[:script_name] = relative_url_root if relative_url_root?

      router_name = Devise.mappings[scope].router_name || Devise.available_router_name
      context = send(router_name)

      if context.respond_to?(route)
        context.send(route, opts)
      elsif respond_to?(:root_url)
        root_url(opts)
      else
        "/"
      end
    end
  end
end
        route "mount Decidim::System::Engine => '/system'"
          "*= require decidim\n"
        end
      end

      def test_mail_host
        inject_into_file "config/environments/test.rb",
                         after: "config.action_mailer.delivery_method = :test" do
          "\n  config.action_mailer.default_url_options = { host: \"test.citizencorp.com\" }"
        rake "db:environment:set RAILS_ENV=development"
        rake "db:drop:all"
        rake "db:test:prepare"
# frozen_string_literal: true
namespace :factory_girl do
  desc "Verify that all FactoryGirl factories are valid"
  task lint: :environment do
    if Rails.env.test?
      begin
        DatabaseCleaner.start
        FactoryGirl.lint
      ensure
        DatabaseCleaner.clean
      end
    else
      system("bundle exec rake factory_girl:lint RAILS_ENV='test'")
    end
  end
end
FactoryGirl.define do
  factory :organization, class: Decidim::Organization do
    sequence(:name) { |n| "Citizen Corp ##{n}" }
    sequence(:host) { |n| "#{n}.citizen.corp" }
  end

  factory :user, class: Decidim::User do
    sequence(:email)      { |n| "user#{n}@citizen.corp" }
    password              "password1234"
    password_confirmation "password1234"
    organization

    trait :admin do
      roles ["admin"]
    end

    trait :moderator do
      roles ["moderator"]
    end

    trait :official do
      roles ["official"]
    end
  end
end
# frozen_string_literal: true
require 'i18n/tasks'

RSpec.describe 'I18n' do
  let(:i18n) { I18n::Tasks::BaseTask.new }
  let(:missing_keys) { i18n.missing_keys }
  let(:unused_keys) { i18n.unused_keys }

  it 'does not have missing keys' do
    expect(missing_keys).to be_empty,
      "Missing #{missing_keys.leaves.count} i18n keys, run `i18n-tasks missing' to show them"
  end

  it 'does not have unused keys' do
    expect(unused_keys).to be_empty,
      "#{unused_keys.leaves.count} unused i18n keys, run `i18n-tasks unused' to show them"
  end
end
# frozen_string_literal: true
require "spec_helper"

describe "Organization", :db do
  let(:organization) { create(:organization) }

  it "is valid" do
    expect(organization).to be_valid
  end
end
# frozen_string_literal: true
require "spec_helper"

describe "User", :db do
  let(:user) { build(:user) }

  it "is valid" do
    expect(user).to be_valid
  end

  describe "admin?" do
    context "when the user is an admin" do
      before do
        user.roles = ["admin"]
      end

      it { expect(user.admin?).to eq true }
    end

    context "when the user is not an admin" do
      before do
        user.roles = []
      end

      it { expect(user.admin?).to eq false }
    end
  end
end
require "factory_girl_rails"
require "database_cleaner"
require "byebug"
RSpec.configure do |config|
  config.before(:suite) do
    DatabaseCleaner.strategy = :transaction
    DatabaseCleaner.clean_with(:truncation)
  end

  config.around(:each) do |example|
    DatabaseCleaner.cleaning do
      example.run
    end
  end
end
RSpec.configure do |config|
  config.include FactoryGirl::Syntax::Methods
end
eval(File.read(File.dirname(__FILE__) + "/../common_gemfile.rb"))

# Declare your gem's dependencies in decidim-system.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]

gemspec path: "../decidim-core"
gemspec path: ".."
GIT
  remote: git://github.com/sgruhier/foundation_rails_helper.git
  revision: d8819b3a5f9d82251aac7559e0d07505c9777717
  specs:
    foundation_rails_helper (2.0.0)
      actionpack (>= 4.1)
      activemodel (>= 4.1)
      activesupport (>= 4.1)
      railties (>= 4.1)
      tzinfo (~> 1.2, >= 1.2.2)

PATH
  remote: ../decidim-core
  specs:
    decidim-core (0.0.1.alpha2)
      active_link_to (~> 1.0.0)
      devise (~> 4.2)
      foundation-rails (~> 6.2.3.0)
      foundation_rails_helper (~> 2.0.0)
      jbuilder (~> 2.5)
      jquery-rails (~> 4.0)
      jquery-turbolinks (~> 2.1.0)
      rails (~> 5.0.0)
      rectify (~> 0.6)
      sass-rails (~> 5.0.0)
      turbolinks (~> 5.0.0)

PATH
  remote: ..
  specs:
    decidim (0.0.1.alpha2)
      decidim-core (= 0.0.1.alpha2)
      decidim-system (= 0.0.1.alpha2)
      rails (~> 5.0.0)

PATH
  remote: .
  specs:
    decidim-system (0.0.1.alpha2)
      active_link_to (~> 1.0.0)
      decidim-core
      devise (~> 4.2)
      devise_invitable (~> 1.7.0)
      foundation-rails (~> 6.2.3.0)
      foundation_rails_helper (~> 2.0.0)
      jbuilder (~> 2.5)
      jquery-rails (~> 4.0)
      jquery-turbolinks (~> 2.1.0)
      rails (~> 5.0.0)
      rectify (~> 0.6)
      sass-rails (~> 5.0.0)
      turbolinks (~> 5.0.0)

GEM
  remote: https://rubygems.org/
  specs:
    actioncable (5.0.0.1)
      actionpack (= 5.0.0.1)
      nio4r (~> 1.2)
      websocket-driver (~> 0.6.1)
    actionmailer (5.0.0.1)
      actionpack (= 5.0.0.1)
      actionview (= 5.0.0.1)
      activejob (= 5.0.0.1)
      mail (~> 2.5, >= 2.5.4)
      rails-dom-testing (~> 2.0)
    actionpack (5.0.0.1)
      actionview (= 5.0.0.1)
      activesupport (= 5.0.0.1)
      rack (~> 2.0)
      rack-test (~> 0.6.3)
      rails-dom-testing (~> 2.0)
      rails-html-sanitizer (~> 1.0, >= 1.0.2)
    actionview (5.0.0.1)
      activesupport (= 5.0.0.1)
      builder (~> 3.1)
      erubis (~> 2.7.0)
      rails-dom-testing (~> 2.0)
      rails-html-sanitizer (~> 1.0, >= 1.0.2)
    active_link_to (1.0.3)
      actionpack
    activejob (5.0.0.1)
      activesupport (= 5.0.0.1)
      globalid (>= 0.3.6)
    activemodel (5.0.0.1)
      activesupport (= 5.0.0.1)
    activerecord (5.0.0.1)
      activemodel (= 5.0.0.1)
      activesupport (= 5.0.0.1)
      arel (~> 7.0)
    activesupport (5.0.0.1)
      concurrent-ruby (~> 1.0, >= 1.0.2)
      i18n (~> 0.7)
      minitest (~> 5.1)
      tzinfo (~> 1.1)
    addressable (2.4.0)
    arel (7.1.2)
    ast (2.3.0)
    axiom-types (0.1.1)
      descendants_tracker (~> 0.0.4)
      ice_nine (~> 0.11.0)
      thread_safe (~> 0.3, >= 0.3.1)
    babel-source (5.8.35)
    babel-transpiler (0.7.0)
      babel-source (>= 4.0, < 6)
      execjs (~> 2.0)
    bcrypt (3.1.11)
    builder (3.2.2)
    byebug (9.0.5)
    capybara (2.9.0)
      addressable
      mime-types (>= 1.16)
      nokogiri (>= 1.3.3)
      rack (>= 1.0.0)
      rack-test (>= 0.5.4)
      xpath (~> 2.0)
    coercible (1.0.0)
      descendants_tracker (~> 0.0.1)
    concurrent-ruby (1.0.2)
    database_cleaner (1.5.3)
    descendants_tracker (0.0.4)
      thread_safe (~> 0.3, >= 0.3.1)
    devise (4.2.0)
      bcrypt (~> 3.0)
      orm_adapter (~> 0.1)
      railties (>= 4.1.0, < 5.1)
      responders
      warden (~> 1.2.3)
    devise_invitable (1.7.0)
      actionmailer (>= 4.0.0)
      devise (>= 4.0.0)
    diff-lcs (1.2.5)
    easy_translate (0.5.0)
      json
      thread
      thread_safe
    equalizer (0.0.11)
    erubis (2.7.0)
    execjs (2.7.0)
    factory_girl (4.7.0)
      activesupport (>= 3.0.0)
    factory_girl_rails (4.7.0)
      factory_girl (~> 4.7.0)
      railties (>= 3.0.0)
    ffi (1.9.14)
    foundation-rails (6.2.3.0)
      railties (>= 3.1.0)
      sass (>= 3.3.0, < 3.5)
      sprockets-es6 (>= 0.9.0)
    globalid (0.3.7)
      activesupport (>= 4.1.0)
    highline (1.7.8)
    i18n (0.7.0)
    i18n-tasks (0.9.5)
      activesupport (>= 4.0.2)
      ast (>= 2.1.0)
      easy_translate (>= 0.5.0)
      erubis
      highline (>= 1.7.3)
      i18n
      parser (>= 2.2.3.0)
      term-ansicolor (>= 1.3.2)
      terminal-table (>= 1.5.1)
    ice_nine (0.11.2)
    jbuilder (2.6.0)
      activesupport (>= 3.0.0, < 5.1)
      multi_json (~> 1.2)
    jquery-rails (4.2.1)
      rails-dom-testing (>= 1, < 3)
      railties (>= 4.2.0)
      thor (>= 0.14, < 2.0)
    jquery-turbolinks (2.1.0)
      railties (>= 3.1.0)
      turbolinks
    json (2.0.2)
    launchy (2.4.3)
      addressable (~> 2.3)
    listen (3.0.8)
      rb-fsevent (~> 0.9, >= 0.9.4)
      rb-inotify (~> 0.9, >= 0.9.7)
    loofah (2.0.3)
      nokogiri (>= 1.5.9)
    mail (2.6.4)
      mime-types (>= 1.16, < 4)
    method_source (0.8.2)
    mime-types (3.1)
      mime-types-data (~> 3.2015)
    mime-types-data (3.2016.0521)
    mini_portile2 (2.1.0)
    minitest (5.9.0)
    multi_json (1.12.1)
    nio4r (1.2.1)
    nokogiri (1.6.8)
      mini_portile2 (~> 2.1.0)
      pkg-config (~> 1.1.7)
    orm_adapter (0.5.0)
    parser (2.3.1.4)
      ast (~> 2.2)
    pg (0.18.4)
    pkg-config (1.1.7)
    rack (2.0.1)
    rack-test (0.6.3)
      rack (>= 1.0)
    rails (5.0.0.1)
      actioncable (= 5.0.0.1)
      actionmailer (= 5.0.0.1)
      actionpack (= 5.0.0.1)
      actionview (= 5.0.0.1)
      activejob (= 5.0.0.1)
      activemodel (= 5.0.0.1)
      activerecord (= 5.0.0.1)
      activesupport (= 5.0.0.1)
      bundler (>= 1.3.0, < 2.0)
      railties (= 5.0.0.1)
      sprockets-rails (>= 2.0.0)
    rails-dom-testing (2.0.1)
      activesupport (>= 4.2.0, < 6.0)
      nokogiri (~> 1.6.0)
    rails-html-sanitizer (1.0.3)
      loofah (~> 2.0)
    railties (5.0.0.1)
      actionpack (= 5.0.0.1)
      activesupport (= 5.0.0.1)
      method_source
      rake (>= 0.8.7)
      thor (>= 0.18.1, < 2.0)
    rake (11.3.0)
    rb-fsevent (0.9.7)
    rb-inotify (0.9.7)
      ffi (>= 0.5.0)
    rectify (0.6.1)
      activemodel (>= 4.1.0)
      activerecord (>= 4.1.0)
      activesupport (>= 4.1.0)
      virtus (~> 1.0.5)
      wisper (>= 1.6.1)
    responders (2.3.0)
      railties (>= 4.2.0, < 5.1)
    rspec (3.5.0)
      rspec-core (~> 3.5.0)
      rspec-expectations (~> 3.5.0)
      rspec-mocks (~> 3.5.0)
    rspec-core (3.5.3)
      rspec-support (~> 3.5.0)
    rspec-expectations (3.5.0)
      diff-lcs (>= 1.2.0, < 2.0)
      rspec-support (~> 3.5.0)
    rspec-mocks (3.5.0)
      diff-lcs (>= 1.2.0, < 2.0)
      rspec-support (~> 3.5.0)
    rspec-rails (3.5.2)
      actionpack (>= 3.0)
      activesupport (>= 3.0)
      railties (>= 3.0)
      rspec-core (~> 3.5.0)
      rspec-expectations (~> 3.5.0)
      rspec-mocks (~> 3.5.0)
      rspec-support (~> 3.5.0)
    rspec-support (3.5.0)
    sass (3.4.22)
    sass-rails (5.0.6)
      railties (>= 4.0.0, < 6)
      sass (~> 3.1)
      sprockets (>= 2.8, < 4.0)
      sprockets-rails (>= 2.0, < 4.0)
      tilt (>= 1.1, < 3)
    sprockets (3.7.0)
      concurrent-ruby (~> 1.0)
      rack (> 1, < 3)
    sprockets-es6 (0.9.1)
      babel-source (>= 5.8.11)
      babel-transpiler
      sprockets (>= 3.0.0)
    sprockets-rails (3.2.0)
      actionpack (>= 4.0)
      activesupport (>= 4.0)
      sprockets (>= 3.0.0)
    term-ansicolor (1.3.2)
      tins (~> 1.0)
    terminal-table (1.7.3)
      unicode-display_width (~> 1.1.1)
    thor (0.19.1)
    thread (0.2.2)
    thread_safe (0.3.5)
    tilt (2.0.5)
    tins (1.12.0)
    turbolinks (5.0.1)
      turbolinks-source (~> 5)
    turbolinks-source (5.0.0)
    tzinfo (1.2.2)
      thread_safe (~> 0.1)
    unicode-display_width (1.1.1)
    virtus (1.0.5)
      axiom-types (~> 0.1)
      coercible (~> 1.0)
      descendants_tracker (~> 0.0, >= 0.0.3)
      equalizer (~> 0.0, >= 0.0.9)
    warden (1.2.6)
      rack (>= 1.0)
    websocket-driver (0.6.4)
      websocket-extensions (>= 0.1.0)
    websocket-extensions (0.1.2)
    wisper (1.6.1)
    wisper-rspec (0.0.2)
    xpath (2.0.0)
      nokogiri (~> 1.3)

PLATFORMS
  ruby

DEPENDENCIES
  bundler (~> 1.12)
  byebug
  capybara (~> 2.4)
  database_cleaner (~> 1.5.0)
  decidim!
  decidim-core!
  decidim-system!
  factory_girl_rails
  foundation_rails_helper!
  i18n-tasks (~> 0.9.5)
  launchy
  listen
  pg
  rake (~> 11.0)
  rspec (~> 3.0)
  rspec-rails (~> 3.5)
  wisper-rspec

RUBY VERSION
   ruby 2.3.1p112

BUNDLED WITH
   1.13.1
# Decidim::System
Short description and motivation.

## Usage
How to use my plugin.

## Installation
Add this line to your application's Gemfile:

```ruby
gem 'decidim-system'
```

And then execute:
```bash
$ bundle
```

Or install it yourself as:
```bash
$ gem install decidim-system
```

## Contributing
Contribution directions go here.

## License
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
# frozen_string_literal: true
begin
  require "bundler/setup"
rescue LoadError
  puts "You must `gem install bundler` and `bundle install` to run rake tasks"
end

require_relative "../decidim-core/lib/decidim/testing_support/common_rake"
require "rdoc/task"

RDoc::Task.new(:rdoc) do |rdoc|
  rdoc.rdoc_dir = "rdoc"
  rdoc.title    = "Decidim::System"
  rdoc.options << "--line-numbers"
  rdoc.rdoc_files.include("README.md")
  rdoc.rdoc_files.include("lib/**/*.rb")
end

load "rails/tasks/statistics.rake"

require "bundler/gem_tasks"

task default: :test

desc "Generates a dummy app for testing"
task :test_app do
  ENV["LIB_NAME"] = "decidim/system"
  Rake::Task["common:test_app"].invoke
end

task test: :test_app do
  Dir.chdir(File.dirname(__FILE__).to_s) do
    sh "rspec spec"
  end
end
//= link_directory ../javascripts/decidim/system .js
//= link_directory ../stylesheets/decidim/system .css
// 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 jquery
//= require jquery.turbolinks
//= require jquery_ujs
//= require foundation
//= require_self

$(function(){ $(document).foundation(); });

//= require turbolinks
@import 'https://fonts.googleapis.com/css?family=Montserrat:400,700';

@import "system/foundation_and_overrides";
@import "system/layout";
@import "system/login";
@import "system/sidebar";
@import "system/tables";
@import "system/actions";
.actions{
  text-align: right;

  &.title{
    margin-bottom: $global-margin;
    font-size: 1.2em;
  }
}
@charset "utf-8";

@import "settings";
@import "foundation";

// If you'd like to include motion-ui the foundation-rails gem comes prepackaged with it, uncomment the 3 @imports, if you are not using the gem you need to install the motion-ui sass package.
//
// @import 'motion-ui/motion-ui';

// We include everything by default.  To slim your CSS, remove components you don't use.

@include foundation-global-styles;
@include foundation-flex-grid;
@include foundation-typography;
@include foundation-button;
@include foundation-forms;
@include foundation-visibility-classes;
@include foundation-flex-classes;
@include foundation-accordion;
@include foundation-accordion-menu;
@include foundation-badge;
@include foundation-breadcrumbs;
@include foundation-button-group;
@include foundation-callout;
@include foundation-close-button;
@include foundation-drilldown-menu;
@include foundation-dropdown;
@include foundation-dropdown-menu;
@include foundation-flex-video;
@include foundation-label;
@include foundation-media-object;
@include foundation-menu;
@include foundation-menu-icon;
@include foundation-off-canvas;
@include foundation-orbit;
@include foundation-pagination;
@include foundation-progress-bar;
@include foundation-slider;
@include foundation-sticky;
@include foundation-reveal;
@include foundation-switch;
@include foundation-table;
@include foundation-tabs;
@include foundation-thumbnail;
@include foundation-title-bar;
@include foundation-tooltip;
@include foundation-top-bar;

// If you'd like to include motion-ui the foundation-rails gem comes prepackaged with it, uncomment the 3 @imports, if you are not using the gem you need to install the motion-ui sass package.
//
// @include motion-ui-transitions;
// @include motion-ui-animations;
.off-canvas, .sidebar, .off-canvas-wrapper{
  min-height: 100vh;
}

.off-canvas{
  color: #fff;
}

.main-content{
  padding: $global-padding 0;
  min-height: 100vh;
}

.page-title{
  margin-bottom: $global-margin;
}
body.login{
  background: $light-gray;
  position: relative;

  .login-form-wrapper{
    @include grid-row;
    @include flex;

    height: 100vh;

    .login-form{
      @include grid-column(12);
      @include grid-column-position(center);

      @include breakpoint(medium){
        @include grid-column(8);
        @include grid-column-position(center);
      }

      @include breakpoint(large){
        @include grid-column(6);
        @include grid-column-position(center);
      }
    }

    @include breakpoint(medium){
      @include flex-align(center, middle);
      transform: translateY(-8%);
    }

    .login-form-inner{
      background-color: $white;
      padding: $global-padding;
    }
  }
}
//  Foundation for Sites Settings
//  -----------------------------
//
//  Table of Contents:
//
//   1. Global
//   2. Breakpoints
//   3. The Grid
//   4. Base Typography
//   5. Typography Helpers
//   6. Abide
//   7. Accordion
//   8. Accordion Menu
//   9. Badge
//  10. Breadcrumbs
//  11. Button
//  12. Button Group
//  13. Callout
//  14. Close Button
//  15. Drilldown
//  16. Dropdown
//  17. Dropdown Menu
//  18. Flex Video
//  19. Forms
//  20. Label
//  21. Media Object
//  22. Menu
//  23. Meter
//  24. Off-canvas
//  25. Orbit
//  26. Pagination
//  27. Progress Bar
//  28. Reveal
//  29. Slider
//  30. Switch
//  31. Table
//  32. Tabs
//  33. Thumbnail
//  34. Title Bar
//  35. Tooltip
//  36. Top Bar

@import "util/util";

// 1. Global
// ---------

// $global-font-size: 100%;
// $global-width: rem-calc(1200);
// $global-lineheight: 1.5;
$foundation-palette: (
  primary: #2199e8,
  secondary: #777,
  success: #3adb76,
  warning: #ffae00,
  alert: #ec5840,
);
$light-gray: #e6e6e6;
// $medium-gray: #cacaca;
// $dark-gray: #8a8a8a;
$black: #232323;
// $white: #fefefe;
// $body-background: $white;
// $body-font-color: $black;
$body-font-family: 'Montserrat', sans-serif;
// $body-antialiased: true;
// $global-margin: 1rem;
// $global-padding: 1rem;
// $global-weight-normal: normal;
// $global-weight-bold: bold;
// $global-radius: 0;
// $global-text-direction: ltr;
$global-flexbox: true;
// $print-transparent-backgrounds: true;

@include add-foundation-colors;

// 2. Breakpoints
// --------------

// $breakpoints: (
//   small: 0,
//   medium: 640px,
//   large: 1024px,
//   xlarge: 1200px,
//   xxlarge: 1440px,
// );
// $breakpoint-classes: (small medium large);

// 3. The Grid
// -----------

// $grid-row-width: $global-width;
// $grid-column-count: 12;
// $grid-column-gutter: (
//   small: 20px,
//   medium: 30px,
// );
// $grid-column-align-edge: true;
// $block-grid-max: 8;

// 4. Base Typography
// ------------------

// $header-font-family: $body-font-family;
// $header-font-weight: $global-weight-normal;
// $header-font-style: normal;
// $font-family-monospace: Consolas, 'Liberation Mono', Courier, monospace;
// $header-sizes: (
//   small: (
//     'h1': 24,
//     'h2': 20,
//     'h3': 19,
//     'h4': 18,
//     'h5': 17,
//     'h6': 16,
//   ),
//   medium: (
//     'h1': 48,
//     'h2': 40,
//     'h3': 31,
//     'h4': 25,
//     'h5': 20,
//     'h6': 16,
//   ),
// );
// $header-color: inherit;
// $header-lineheight: 1.4;
// $header-margin-bottom: 0.5rem;
// $header-text-rendering: optimizeLegibility;
// $small-font-size: 80%;
// $header-small-font-color: $medium-gray;
// $paragraph-lineheight: 1.6;
// $paragraph-margin-bottom: 1rem;
// $paragraph-text-rendering: optimizeLegibility;
// $code-color: $black;
// $code-font-family: $font-family-monospace;
// $code-font-weight: $global-weight-normal;
// $code-background: $light-gray;
// $code-border: 1px solid $medium-gray;
// $code-padding: rem-calc(2 5 1);
// $anchor-color: $primary-color;
// $anchor-color-hover: scale-color($anchor-color, $lightness: -14%);
// $anchor-text-decoration: none;
// $anchor-text-decoration-hover: none;
// $hr-width: $global-width;
// $hr-border: 1px solid $medium-gray;
// $hr-margin: rem-calc(20) auto;
// $list-lineheight: $paragraph-lineheight;
// $list-margin-bottom: $paragraph-margin-bottom;
// $list-style-type: disc;
// $list-style-position: outside;
// $list-side-margin: 1.25rem;
// $list-nested-side-margin: 1.25rem;
// $defnlist-margin-bottom: 1rem;
// $defnlist-term-weight: $global-weight-bold;
// $defnlist-term-margin-bottom: 0.3rem;
// $blockquote-color: $dark-gray;
// $blockquote-padding: rem-calc(9 20 0 19);
// $blockquote-border: 1px solid $medium-gray;
// $cite-font-size: rem-calc(13);
// $cite-color: $dark-gray;
// $keystroke-font: $font-family-monospace;
// $keystroke-color: $black;
// $keystroke-background: $light-gray;
// $keystroke-padding: rem-calc(2 4 0);
// $keystroke-radius: $global-radius;
// $abbr-underline: 1px dotted $black;

// 5. Typography Helpers
// ---------------------

// $lead-font-size: $global-font-size * 1.25;
// $lead-lineheight: 1.6;
// $subheader-lineheight: 1.4;
// $subheader-color: $dark-gray;
// $subheader-font-weight: $global-weight-normal;
// $subheader-margin-t#23262Cop: 0.2rem;
// $subheader-margin-bottom: 0.5rem;
// $stat-font-size: 2.5rem;

// 6. Abide
// --------

// $abide-inputs: true;
// $abide-labels: true;
// $input-background-invalid: map-get($foundation-palette, alert);
// $form-label-color-invalid: map-get($foundation-palette, alert);
// $input-error-color: map-get($foundation-palette, alert);
// $input-error-font-size: rem-calc(12);
// $input-error-font-weight: $global-weight-bold;

// 7. Accordion
// ------------

// $accordion-background: $white;
// $accordion-plusminus: true;
// $accordion-item-color: foreground($accordion-background, $primary-color);
// $accordion-item-background-hover: $light-gray;
// $accordion-item-padding: 1.25rem 1rem;
// $accordion-content-background: $white;
// $accordion-content-border: 1px solid $light-gray;
// $accordion-content-color: foreground($accordion-content-background, $body-font-color);
// $accordion-content-padding: 1rem;

// 8. Accordion Menu
// -----------------

// $accordionmenu-arrows: true;
// $accordionmenu-arrow-color: $primary-color;

// 9. Badge
// --------

// $badge-background: $primary-color;
// $badge-color: foreground($badge-background);
// $badge-padding: 0.3em;
// $badge-minwidth: 2.1em;
// $badge-font-size: 0.6rem;

// 10. Breadcrumbs
// ---------------

// $breadcrumbs-margin: 0 0 $global-margin 0;
// $breadcrumbs-item-font-size: rem-calc(11);
// $breadcrumbs-item-color: $primary-color;
// $breadcrumbs-item-color-current: $black;
// $breadcrumbs-item-color-disabled: $medium-gray;
// $breadcrumbs-item-margin: 0.75rem;
// $breadcrumbs-item-uppercase: true;
// $breadcrumbs-item-slash: true;

// 11. Button
// ----------

// $button-padding: 0.85em 1em;
$button-margin: 0;
// $button-fill: solid;
// $button-background: $primary-color;
// $button-background-hover: scale-color($button-background, $lightness: -15%);
// $button-color: $white;
// $button-color-alt: $black;
// $button-radius: $global-radius;
// $button-sizes: (
//   tiny: 0.6rem,
//   small: 0.75rem,
//   default: 0.9rem,
//   large: 1.25rem,
// );
// $button-opacity-disabled: 0.25;

// 12. Button Group
// ----------------

// $buttongroup-margin: 1rem;
// $buttongroup-spacing: 1px;
// $buttongroup-child-selector: ".button";
// $buttongroup-expand-max: 6;

// 13. Callout
// -----------

// $callout-background: $white;
// $callout-background-fade: 85%;
// $callout-border: 1px solid rgba($black, 0.25);
// $callout-margin: 0 0 1rem 0;
// $callout-padding: 1rem;
// $callout-font-color: $body-font-color;
// $callout-font-color-alt: $body-background;
// $callout-radius: $global-radius;
// $callout-link-tint: 30%;

// 14. Close Button
// ----------------

// $closebutton-position: right top;
// $closebutton-offset-horizontal: 1rem;
// $closebutton-offset-vertical: 0.5rem;
// $closebutton-size: 2em;
// $closebutton-lineheight: 1;
// $closebutton-color: $dark-gray;
// $closebutton-color-hover: $black;

// 15. Drilldown
// -------------

// $drilldown-transition: transform 0.15s linear;
// $drilldown-arrows: true;
// $drilldown-arrow-color: $primary-color;
// $drilldown-background: $white;

// 16. Dropdown
// ------------

// $dropdown-padding: 1rem;
// $dropdown-border: 1px solid $medium-gray;
// $dropdown-font-size: 1rem;
// $dropdown-width: 300px;
// $dropdown-radius: $global-radius;
// $dropdown-sizes: (
//   tiny: 100px,
//   small: 200px,
//   large: 400px,
// );

// 17. Dropdown Menu
// -----------------

// $dropdownmenu-arrows: true;
// $dropdownmenu-arrow-color: $anchor-color;
// $dropdownmenu-min-width: 200px;
// $dropdownmenu-background: $white;
// $dropdownmenu-border: 1px solid $medium-gray;

// 18. Flex Video
// --------------

// $flexvideo-margin-bottom: rem-calc(16);
// $flexvideo-ratio: 4 by 3;
// $flexvideo-ratio-widescreen: 16 by 9;

// 19. Forms
// ---------

// $fieldset-border: 1px solid $medium-gray;
// $fieldset-padding: rem-calc(20);
// $fieldset-margin: rem-calc(18 0);
// $legend-padding: rem-calc(0 3);
// $form-spacing: rem-calc(16);
// $helptext-color: $black;
// $helptext-font-size: rem-calc(13);
// $helptext-font-style: italic;
// $input-prefix-color: $black;
// $input-prefix-background: $light-gray;
// $input-prefix-border: 1px solid $medium-gray;
// $input-prefix-padding: 1rem;
// $form-label-color: $black;
// $form-label-font-size: rem-calc(14);
// $form-label-font-weight: $global-weight-normal;
// $form-label-line-height: 1.8;
// $select-background: $white;
// $select-triangle-color: $dark-gray;
// $select-radius: $global-radius;
// $input-color: $black;
// $input-placeholder-color: $medium-gray;
// $input-font-family: inherit;
// $input-font-size: rem-calc(16);
// $input-background: $white;
// $input-background-focus: $white;
// $input-background-disabled: $light-gray;
// $input-border: 1px solid $medium-gray;
// $input-border-focus: 1px solid $dark-gray;
// $input-shadow: inset 0 1px 2px rgba($black, 0.1);
// $input-shadow-focus: 0 0 5px $medium-gray;
// $input-cursor-disabled: not-allowed;
// $input-transition: box-shadow 0.5s, border-color 0.25s ease-in-out;
// $input-number-spinners: true;
// $input-radius: $global-radius;

// 20. Label
// ---------

// $label-background: $primary-color;
// $label-color: foreground($label-background);
// $label-font-size: 0.8rem;
// $label-padding: 0.33333rem 0.5rem;
// $label-radius: $global-radius;

// 21. Media Object
// ----------------

// $mediaobject-margin-bottom: $global-margin;
// $mediaobject-section-padding: $global-padding;
// $mediaobject-image-width-stacked: 100%;

// 22. Menu
// --------

// $menu-margin: 0;
// $menu-margin-nested: 1rem;
// $menu-item-padding: 0.7rem 1rem;
// $menu-item-color-active: $white;
// $menu-item-background-active: map-get($foundation-palette, primary);
// $menu-icon-spacing: 0.25rem;

// 23. Meter
// ---------

// $meter-height: 1rem;
// $meter-radius: $global-radius;
// $meter-background: $medium-gray;
// $meter-fill-good: $success-color;
// $meter-fill-medium: $warning-color;
// $meter-fill-bad: $alert-color;

// 24. Off-canvas
// --------------

// $offcanvas-size: 250px;
$offcanvas-background: $black;
// $offcanvas-zindex: -1;
// $offcanvas-transition-length: 0.5s;
// $offcanvas-transition-timing: ease;
// $offcanvas-fixed-reveal: true;
// $offcanvas-exit-background: rgba($white, 0.25);
// $maincontent-class: "off-canvas-content";
$maincontent-shadow: none;

// 25. Orbit
// ---------

// $orbit-bullet-background: $medium-gray;
// $orbit-bullet-background-active: $dark-gray;
// $orbit-bullet-diameter: 1.2rem;
// $orbit-bullet-margin: 0.1rem;
// $orbit-bullet-margin-top: 0.8rem;
// $orbit-bullet-margin-bottom: 0.8rem;
// $orbit-caption-background: rgba($black, 0.5);
// $orbit-caption-padding: 1rem;
// $orbit-control-background-hover: rgba($black, 0.5);
// $orbit-control-padding: 1rem;
// $orbit-control-zindex: 10;

// 26. Pagination
// --------------

// $pagination-font-size: rem-calc(14);
// $pagination-margin-bottom: $global-margin;
// $pagination-item-color: $black;
// $pagination-item-padding: rem-calc(3 10);
// $pagination-item-spacing: rem-calc(1);
// $pagination-radius: $global-radius;
// $pagination-item-background-hover: $light-gray;
// $pagination-item-background-current: $primary-color;
// $pagination-item-color-current: foreground($pagination-item-background-current);
// $pagination-item-color-disabled: $medium-gray;
// $pagination-ellipsis-color: $black;
// $pagination-mobile-items: false;
// $pagination-arrows: true;

// 27. Progress Bar
// ----------------

// $progress-height: 1rem;
// $progress-background: $medium-gray;
// $progress-margin-bottom: $global-margin;
// $progress-meter-background: $primary-color;
// $progress-radius: $global-radius;

// 28. Reveal
// ----------

// $reveal-background: $white;
// $reveal-width: 600px;
// $reveal-max-width: $global-width;
// $reveal-padding: $global-padding;
// $reveal-border: 1px solid $medium-gray;
// $reveal-radius: $global-radius;
// $reveal-zindex: 1005;
// $reveal-overlay-background: rgba($black, 0.45);

// 29. Slider
// ----------

// $slider-width-vertical: 0.5rem;
// $slider-transition: all 0.2s ease-in-out;
// $slider-height: 0.5rem;
// $slider-background: $light-gray;
// $slider-fill-background: $medium-gray;
// $slider-handle-height: 1.4rem;
// $slider-handle-width: 1.4rem;
// $slider-handle-background: $primary-color;
// $slider-opacity-disabled: 0.25;
// $slider-radius: $global-radius;

// 30. Switch
// ----------

// $switch-background: $medium-gray;
// $switch-background-active: $primary-color;
// $switch-height: 2rem;
// $switch-height-tiny: 1.5rem;
// $switch-height-small: 1.75rem;
// $switch-height-large: 2.5rem;
// $switch-radius: $global-radius;
// $switch-margin: $global-margin;
// $switch-paddle-background: $white;
// $switch-paddle-offset: 0.25rem;
// $switch-paddle-radius: $global-radius;
// $switch-paddle-transition: all 0.25s ease-out;

// 31. Table
// ---------

// $table-background: $white;
// $table-color-scale: 5%;
// $table-border: 1px solid smart-scale($table-background, $table-color-scale);
// $table-padding: rem-calc(8 10 10);
// $table-hover-scale: 2%;
// $table-row-hover: darken($table-background, $table-hover-scale);
// $table-row-stripe-hover: darken($table-background, $table-color-scale + $table-hover-scale);
// $table-striped-background: smart-scale($table-background, $table-color-scale);
// $table-stripe: even;
// $table-head-background: smart-scale($table-background, $table-color-scale / 2);
// $table-foot-background: smart-scale($table-background, $table-color-scale);
// $table-head-font-color: $body-font-color;
// $show-header-for-stacked: false;

// 32. Tabs
// --------

// $tab-margin: 0;
// $tab-background: $white;
// $tab-background-active: $light-gray;
// $tab-item-font-size: rem-calc(12);
// $tab-item-background-hover: $white;
// $tab-item-padding: 1.25rem 1.5rem;
// $tab-expand-max: 6;
// $tab-content-background: $white;
// $tab-content-border: $light-gray;
// $tab-content-color: foreground($tab-background, $primary-color);
// $tab-content-padding: 1rem;

// 33. Thumbnail
// -------------

// $thumbnail-border: solid 4px $white;
// $thumbnail-margin-bottom: $global-margin;
// $thumbnail-shadow: 0 0 0 1px rgba($black, 0.2);
// $thumbnail-shadow-hover: 0 0 6px 1px rgba($primary-color, 0.5);
// $thumbnail-transition: box-shadow 200ms ease-out;
// $thumbnail-radius: $global-radius;

// 34. Title Bar
// -------------

$titlebar-background: map-get($foundation-palette, primary);
// $titlebar-color: $white;
// $titlebar-padding: 0.5rem;
// $titlebar-text-font-weight: bold;
// $titlebar-icon-color: $white;
// $titlebar-icon-color-hover: $medium-gray;
// $titlebar-icon-spacing: 0.25rem;

// 35. Tooltip
// -----------

// $has-tip-font-weight: $global-weight-bold;
// $has-tip-border-bottom: dotted 1px $dark-gray;
// $tooltip-background-color: $black;
// $tooltip-color: $white;
// $tooltip-padding: 0.75rem;
// $tooltip-font-size: $small-font-size;
// $tooltip-pip-width: 0.75rem;
// $tooltip-pip-height: $tooltip-pip-width * 0.866;
// $tooltip-radius: $global-radius;

// 36. Top Bar
// -----------

// $topbar-padding: 0.5rem;
// $topbar-background: $light-gray;
// $topbar-submenu-background: $topbar-background;
// $topbar-title-spacing: 1rem;
// $topbar-input-width: 200px;
// $topbar-unstack-breakpoint: medium;
@mixin menu-title{
  text-transform: uppercase;
  letter-spacing: 5px;
}

.title-bar-title{
  @include menu-title;
}

.sidebar{
  color: $light-gray;

  .title{
    background-color: black;
    background-color: map-get($foundation-palette, primary);

    h1{
      margin: 0;
      padding: 0;
      font-size: rem-calc(18);
      font-weight: bold;
    }

    a{
      display: block;
      color: inherit;
      padding: rem-calc(20) $global-padding;
      @include menu-title;
    }

    @include show-for(large);
  }

  .main-menu{
    border-top: 1px solid black;
    border-bottom: 1px solid black;
    a{
      padding: $global-padding;
      display: block;
      color: $light-gray;
      text-transform: uppercase;
      font-weight: bold;
      font-size: 0.9em;
      border-left: 2px solid transparent;

      transition: all 0.3s;

      &.active {
        border-color: map-get($foundation-palette, primary);
        &, &:hover{
          background-color: #101010;
        }
      }

      &:hover {
        background-color: #1a1a1a;
      }
    }
  }

  .session-box {
    padding: $global-padding 0;

    @include grid-row;

    .admin-email {
      @include grid-column(8);
      text-overflow: ellipsis;
      overflow: hidden;
    }
    .sign-out{ @include grid-column(4); }
  }
}
table{
  td.actions, th.actions{
    text-align: right;
  }
}
# frozen_string_literal: true
module Decidim
  module System
    # A command with all the business logic when creating a new admin in
    # the system.
    class CreateAdmin < Rectify::Command
      # Public: Initializes the command.
      #
      # form - A form object with the params.
      def initialize(form)
        @form = form
      end

      # Executes the command. Braodcasts these events:
      #
      # - :ok when everything is valid.
      # - :invalid if the form wasn't valid and we couldn't proceed.
      #
      # Returns nothing.
      def call
        return broadcast(:invalid) if form.invalid?

        create_admin
        broadcast(:ok)
      end

      private

      attr_reader :form

      def create_admin
        Admin.create!(
          email: form.email,
          password: form.password,
          password_confirmation: form.password_confirmation
        )
      end
    end
  end
end
# frozen_string_literal: true
module Decidim
  module System
    # A command with all the business logic when creating a new organization in
    # the system. It creates the organization and invites the admin to the
    # system.
    class RegisterOrganization < Rectify::Command
      # Public: Initializes the command.
      #
      # form - A form object with the params.
      def initialize(form)
        @form = form
      end

      # Executes the command. Braodcasts these events:
      #
      # - :ok when everything is valid.
      # - :invalid if the form wasn't valid and we couldn't proceed.
      #
      # Returns nothing.
      def call
        return broadcast(:invalid) if form.invalid?

        transaction do
          organization = create_organization
          invite_admin(organization)
        end

        broadcast(:ok)
      rescue ActiveRecord::RecordInvalid, ActiveRecord::RecordNotUnique
        broadcast(:invalid)
      end

      private

      attr_reader :form

      def create_organization
        Decidim::Organization.create!(name: form.name, host: form.host)
      end

      def invite_admin(organization)
        Decidim::User.invite!(
          email: form.organization_admin_email,
          organization: organization,
          roles: ["admin"]
        )
      end
    end
  end
end
# frozen_string_literal: true
module Decidim
  module System
    # A command with all the business logic when updating an admin in
    # the system.
    class UpdateAdmin < Rectify::Command
      # Public: Initializes the command.
      #
      # form - A form object with the params.
      def initialize(admin, form)
        @admin = admin
        @form = form
      end

      # Executes the command. Braodcasts these events:
      #
      # - :ok when everything is valid.
      # - :invalid if the form wasn't valid and we couldn't proceed.
      #
      # Returns nothing.
      def call
        return broadcast(:invalid) if form.invalid?

        update_admin
        broadcast(:ok)
      end

      private

      attr_reader :form

      def update_admin
        @admin.update_attributes!(attributes)
      end

      def attributes
        {
          email: form.email
        }.merge(password_attributes)
      end

      def password_attributes
        return {} if form.password == form.password_confirmation && form.password.blank?

        {
          password: form.password,
          password_confirmation: form.password_confirmation
        }
      end
    end
  end
end
# frozen_string_literal: true
module Decidim
  module System
    # A command with all the business logic when creating a new organization in
    # the system. It creates the organization and invites the admin to the
    # system.
    class UpdateOrganization < Rectify::Command
      # Public: Initializes the command.
      #
      # form - A form object with the params.
      def initialize(id, form)
        @organization_id = id
        @form = form
      end

      # Executes the command. Braodcasts these events:
      #
      # - :ok when everything is valid.
      # - :invalid if the form wasn't valid and we couldn't proceed.
      #
      # Returns nothing.
      def call
        return broadcast(:invalid) if form.invalid?

        transaction do
          save_organization
        end

        broadcast(:ok)
      rescue ActiveRecord::RecordInvalid, ActiveRecord::RecordNotUnique
        broadcast(:invalid)
      end

      private

      attr_reader :form, :organization_id

      def organization
        @organization ||= Organization.find(organization_id)
      end

      def save_organization
        organization.name = form.name
        organization.host = form.host
        organization.save!
      end
    end
  end
end
# frozen_string_literal: true
require_dependency "decidim/system/application_controller"

module Decidim
  module System
    # Controller that allows managing all the Admins.
    #
    class AdminsController < ApplicationController
      def index
        @admins = Admin.all
      end

      def new
        @form = AdminForm.new
      end

      def create
        @form = AdminForm.from_params(params)

        CreateAdmin.call(@form) do
          on(:ok) do
            flash[:notice] = I18n.t("admins.create.success", scope: "decidim.system")
            redirect_to admins_path
          end

          on(:invalid) do
            flash.now[:alert] = I18n.t("admins.create.error", scope: "decidim.system")
            render :new
          end
        end
      end

      def edit
        @admin = Admin.find(params[:id])
        @form = AdminForm.from_model(@admin)
      end

      def update
        @admin = Admin.find(params[:id])
        @form = AdminForm.from_params(params)

        UpdateAdmin.call(@admin, @form) do
          on(:ok) do
            flash[:notice] = I18n.t("admins.update.success", scope: "decidim.system")
            redirect_to admins_path
          end

          on(:invalid) do
            flash.now[:alert] = I18n.t("admins.update.error", scope: "decidim.system")
            render :new
          end
        end
      end

      def show
        @admin = Admin.find(params[:id])
      end

      def destroy
        @admin = Admin.find(params[:id]).destroy!
        flash[:notice] = I18n.t("admins.destroy.success", scope: "decidim.system")

        redirect_to admins_path
      end
    end
  end
end
# frozen_string_literal: true
module Decidim
  module System
    # The main application controller that inherits from Rails.
    class ApplicationController < ActionController::Base
      protect_from_forgery with: :exception, prepend: true
    end
  end
end
# frozen_string_literal: true
require_dependency "decidim/system/application_controller"

module Decidim
  module System
    class DashboardController < ApplicationController
    end
  end
end
# frozen_string_literal: true
module Decidim
  module System
    module Devise
      # A controller so admins can recover their passwords.
      class PasswordsController < Devise::PasswordsController
        layout "decidim/system/login"
      end
    end
  end
end
# frozen_string_literal: true
module Decidim
  module System
    module Devise
      # A controller so admins can log-in and use their backend.
      class SessionsController < ::Devise::SessionsController
        helper Decidim::System::ApplicationHelper
        layout "decidim/system/login"
      end
    end
  end
end
# frozen_string_literal: true
require_dependency "decidim/system/application_controller"

module Decidim
  module System
    # Controller to manage Organizations (tenants).
    #
    class OrganizationsController < ApplicationController
      def new
        @form = RegisterOrganizationForm.new
      end

      def create
        @form = RegisterOrganizationForm.from_params(params)

        RegisterOrganization.call(@form) do
          on(:ok) do
            flash[:notice] = t("organizations.create.success", scope: "decidim.system")
            redirect_to organizations_path
          end

          on(:invalid) do
            flash.now[:alert] = t("organizations.create.error", scope: "decidim.system")
            render :new
          end
        end
      end

      def index
        @organizations = Organization.all
      end

      def show
        @organization = Organization.find(params[:id])
      end

      def edit
        organization = Organization.find(params[:id])
        @form = UpdateOrganizationForm.from_model(organization)
      end

      def update
        @form = UpdateOrganizationForm.from_params(params)

        UpdateOrganization.call(params[:id], @form) do
          on(:ok) do
            flash[:notice] = t("organizations.update.success", scope: "decidim.system")
            redirect_to organizations_path
          end

          on(:invalid) do
            flash.now[:alert] = I18n.t("organizations.update.error", scope: "decidim.system")
            render :edit
          end
        end
      end
    end
  end
end
# frozen_string_literal: true
module Decidim
  module System
    # A form object used to create organizations from the system dashboard.
    #
    class AdminForm < Rectify::Form
      mimic :admin

      attribute :email, String
      attribute :password, String
      attribute :password_confirmation, String

      validates :email, presence: true
      validates :password, presence: true, unless: :admin_exists?
      validates :password_confirmation, presence: true, unless: :admin_exists?

      validate :email, :email_uniqueness

      private

      def email_uniqueness
        return unless Admin.where(email: email).where.not(id: id).any?

        errors.add(:email, I18n.t("models.admin.validations.email_uniqueness",
                                  scope: "decidim.system"))
      end

      def admin_exists?
        id.present?
      end
    end
  end
end
# frozen_string_literal: true
module Decidim
  module System
    # A form object used to create organizations from the system dashboard.
    #
    class RegisterOrganizationForm < UpdateOrganizationForm
      mimic :organization

      attribute :organization_admin_email, String

      validates :organization_admin_email, presence: true
    end
  end
end
# frozen_string_literal: true
module Decidim
  module System
    # A form object used to update organizations from the system dashboard.
    #
    class UpdateOrganizationForm < Rectify::Form
      mimic :organization

      attribute :name, String
      attribute :host, String

      validate :validate_organization_uniqueness

      private

      def validate_organization_uniqueness
        errors.add(:name, :taken) if Decidim::Organization.where(name: name).where.not(id: id).exists?
        errors.add(:host, :taken) if Decidim::Organization.where(host: host).where.not(id: id).exists?
      end
    end
  end
end
# frozen_string_literal: true
module Decidim
  module System
    # Custom helpers, scoped to the system panel.
    #
    module ApplicationHelper
      def title
        "Decidim"
      end

      def field_name(model, field)
        st "models.#{model}.fields.#{field}"
      end
    end
  end
end
# frozen_string_literal: true
module Decidim
  module System
    # Custom ApplicationJob scoped to the system panel.
    #
    class ApplicationJob < ActiveJob::Base
    end
  end
end
# frozen_string_literal: true
module Decidim
  module System
    # Custom application mailer, scoped to the system mailer.
    #
    class ApplicationMailer < ActionMailer::Base
      default from: "from@example.com"
      layout "mailer"
    end
  end
end
# frozen_string_literal: true
module Decidim
  module System
    # Admins are the users in charge of managing a Decidim installation.
    class Admin < ApplicationRecord
      devise :database_authenticatable, :recoverable, :rememberable, :validatable

      validates :email, uniqueness: true
    end
  end
end
# frozen_string_literal: true
module Decidim
  module System
    # Custom ApplicationRecord scoped to the system panel.
    #
    class ApplicationRecord < ActiveRecord::Base
      self.abstract_class = true
    end
  end
end
<div class="field">
  <%= form.text_field :email, autofocus: true %>
</div>

<div class="field">
  <%= form.password_field :password %>
</div>

<div class="field">
  <%= form.password_field :password_confirmation %>
</div>
<% content_for :title do %>
  <h2><%= t ".title" %></h2>
<% end %>

<%= form_for(@form) do |f| %>
  <%= render partial: 'form', object: f %>

  <div class="actions">
    <%= f.submit t(".update") %>
  </div>
<% end %>
<% content_for :title do %>
  <h2><%= t ".title" %></h2>
<% end %>

<div class="actions title">
  <%= link_to t("actions.new", scope: "decidim.system", name: t("models.admin.name", scope: "decidim.system")), ['new', 'admin'], class: 'new' %>
</div>

<table class="stack">
  <thead>
    <tr>
      <th><%= t("models.admin.fields.email", scope: "decidim.system") %></th>
      <th><%= t("models.admin.fields.created_at", scope: "decidim.system") %></th>
      <th class="actions"><%= t("actions.title", scope: "decidim.system") %></th>
    </tr>
  </thead>
  <tbody>
    <% @admins.each do |admin| %>
      <tr>
        <td>
          <%= link_to admin.email, admin %><br />
        </td>
        <td>
          <%= l admin.created_at, format: :short %>
        </td>
        <td class="actions">
          <%= link_to t("actions.edit", scope: "decidim.system"), ['edit', admin] %>
          <%= link_to t("actions.destroy", scope: "decidim.system"), admin, method: :delete, class: "small alert button", data: { confirm: t("actions.confirm_destroy", scope: "decidim.system") } %>
        </td>
      </tr>
    <% end %>
  </tbody>
</table>
<% content_for :title do %>
  <h2><%= t ".title" %></h2>
<% end %>

<%= form_for(@form) do |f| %>
  <%= render partial: 'form', object: f %>

  <div class="actions">
    <%= f.submit t(".create") %>
  </div>
<% end %>
<% content_for :title do %>
  <h2><%= link_to @admin.email, @admin %></h2>
<% end %>

<div class="actions">
  <hr />
  <%= link_to "Edit", ['edit', @admin] %>
  <%= link_to "Destroy", @admin, method: :delete, class: "alert button", data: { confirm: "Are you sure you want to do this?" } %>
</div>
<% content_for :title do %>
  <h2><%= t("decidim.system.titles.dashboard") %></h2>
<% end %>
<p>Hello <%= @resource.email %>!</p>

<p>We're contacting you to notify you that your password has been changed.</p>
<p>Hello <%= @resource.email %>!</p>

<p>Someone has requested a link to change your password. You can do this through the link below.</p>

<p><%= link_to 'Change my password', edit_password_url(@resource, reset_password_token: @token) %></p>

<p>If you didn't request this, please ignore this email.</p>
<p>Your password won't change until you access the link above and create a new one.</p>
<h2>Change your password</h2>

<%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :put }) do |f| %>
  <%= devise_error_messages! %>
  <%= f.hidden_field :reset_password_token %>

  <div class="field">
    <% if @minimum_password_length %>
      <em>(<%= @minimum_password_length %> characters minimum)</em><br />
    <% end %>
    <%= f.password_field :password, autofocus: true, autocomplete: "off" %>
  </div>

  <div class="field">
    <%= f.password_field :password_confirmation, autocomplete: "off" %>
  </div>

  <div class="actions">
    <%= f.submit "Change my password" %>
  </div>
<% end %>

<%= render "decidim/system/devise/shared/links" %>
<h2>Forgot your password?</h2>

<%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :post }) do |f| %>
  <%= devise_error_messages! %>

  <div class="field">
    <%= f.email_field :email, autofocus: true %>
  </div>

  <div class="actions">
    <%= f.submit "Send me reset password instructions" %>
  </div>
<% end %>

<%= render "decidim/system/devise/shared/links" %>
<h2>Log in</h2>

<%= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %>
  <div class="field">
    <%= f.email_field :email, autofocus: true %>
  </div>

  <div class="field">
    <%= f.password_field :password, autocomplete: "off" %>
  </div>

  <% if devise_mapping.rememberable? -%>
    <div class="field">
      <%= f.check_box :remember_me %>
    </div>
  <% end -%>

  <div class="actions">
    <%= f.submit "Log in" %>
  </div>
<% end %>

<%= render "decidim/system/devise/shared/links" %>
<%- if controller_name != 'sessions' %>
  <%= link_to "Log in", new_session_path(resource_name) %><br />
<% end -%>

<%- if devise_mapping.registerable? && controller_name != 'registrations' %>
  <%= link_to "Sign up", new_registration_path(resource_name) %><br />
<% end -%>

<%- if devise_mapping.recoverable? && controller_name != 'passwords' && controller_name != 'registrations' %>
  <%= link_to "Forgot your password?", new_password_path(resource_name) %><br />
<% end -%>

<%- if devise_mapping.confirmable? && controller_name != 'confirmations' %>
  <%= link_to "Didn't receive confirmation instructions?", new_confirmation_path(resource_name) %><br />
<% end -%>

<%- if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'unlocks' %>
  <%= link_to "Didn't receive unlock instructions?", new_unlock_path(resource_name) %><br />
<% end -%>

<%- if devise_mapping.omniauthable? %>
  <%- resource_class.omniauth_providers.each do |provider| %>
    <%= link_to "Sign in with #{OmniAuth::Utils.camelize(provider)}", omniauth_authorize_path(resource_name, provider) %><br />
  <% end -%>
<% end -%>
<%= form_for(@form) do |f| %>
  <div class="field">
    <%= f.text_field :name, autofocus: true %>
  </div>

  <div class="field">
    <%= f.text_field :host %>
  </div>

  <div class="actions">
    <%= f.submit t("decidim.system.actions.save") %>
  </div>
<% end %>
<% content_for :title do %>
  <h2><%= t ".title" %></h2>
<% end %>

<div class="actions title">
  <%= link_to t("actions.new", scope: "decidim.system", name: t("models.organization.name", scope: "decidim.system")), ['new', 'organization'], class: 'new' %>
</div>

<table class="stack">
  <thead>
    <tr>
      <th><%= t("models.organization.fields.name", scope: "decidim.system") %></th>
      <th><%= t("models.organization.fields.created_at", scope: "decidim.system") %></th>
      <th class="actions"><%= t("actions.title", scope: "decidim.system") %></th>
    </tr>
  </thead>
  <tbody>
    <% @organizations.each do |organization| %>
      <tr>
        <td>
          <%= link_to organization.name, organization %><br />
          <%= organization.host %>
        </td>
        <td>
          <%= l organization.created_at, format: :short %>
        </td>
        <td class="actions">
          <%= link_to t("actions.edit", scope: "decidim.system"), ['edit', organization] %>
          <%= link_to t("actions.destroy", scope: "decidim.system"), organization, method: :delete, class: "small alert button", data: { confirm: t("actions.confirm_destroy", scope: "decidim.system") } %>
        </td>
      </tr>
    <% end %>
  </tbody>
</table>
<% content_for :title do %>
  <h2><%= t ".title" %></h2>
<% end %>

<%= form_for(@form) do |f| %>
  <div class="field">
    <%= f.text_field :name, autofocus: true %>
  </div>

  <div class="field">
    <%= f.text_field :host %>
  </div>

  <div class="field">
    <%= f.email_field :organization_admin_email %>
  </div>

  <div class="actions">
    <%= f.submit t("decidim.system.models.organization.actions.save_and_invite") %>
  </div>
<% end %>
<% content_for :title do %>
  <h2><%= link_to @organization.name, @organization %></h2>
  <h3 class="subheader"><%= @organization.host %></h3>
<% end %>

<div class="actions">
  <hr />
  <%= link_to t("decidim.system.actions.edit"), ['edit', @organization] %>
  <%= link_to t("decidim.system.actions.destroy"), @organization, method: :delete, class: "alert button", data: { confirm: t("decidim.system.actions.confirm_destroy") } %>
</div>
<meta name="viewport" content="width=device-width, initial-scale=1">
<%= csrf_meta_tags %>
<%= stylesheet_link_tag    'decidim/system', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= javascript_include_tag 'decidim/system', 'data-turbolinks-track': 'reload' %>
<div class="session-box">
  <div class="admin-email">
    <%= current_admin.email %>
  </div>
  <div class="sign-out">
    <%= link_to('Logout', destroy_admin_session_path, :method => :delete) %>
  </div>
</div>
<div class="title">
  <h1>
    <%= link_to root_path do %>
      <%= title %>
    <% end %>
  </h1>
</div>

<nav class="main-menu">
  <%= active_link_to t("menu.dashboard", scope: "decidim.system"), root_path, active: :exact %>
  <%= active_link_to t("menu.organizations", scope: "decidim.system"), organizations_path, active: :inclusive %>
  <%= active_link_to t("menu.admins", scope: "decidim.system"), admins_path, active: :inclusive %>
</nav>

<%= render partial: 'layouts/decidim/system/login_items' %>
<!DOCTYPE html>
<html>
<head>
<title>Decidim - System</title>
<%= render partial: 'layouts/decidim/system/header' %>
</head>

<body>
  <div class="off-canvas-wrapper">
    <div class="off-canvas-wrapper-inner" data-off-canvas-wrapper>
      <div class="off-canvas position-left reveal-for-large" id="my-info" data-off-canvas data-position="left">
        <div class="sidebar">
          <%= render partial: 'layouts/decidim/system/sidebar' %>
        </div>
      </div>

      <div class="off-canvas-content" data-off-canvas-content>
        <div class="title-bar hide-for-large">
          <div class="title-bar-left">
            <button class="menu-icon" type="button" data-open="my-info"></button>
            <span class="title-bar-title"><%= title %></span>
          </div>
        </div>
        <div class="row main-content">
          <div class="small-12 column">
            <% if content_for?(:title) %>
              <section class="page-title">
                <%= content_for :title %>
              </section>
            <% end %>

            <%= display_flash_messages %>
            <%= yield %>
          </div>
        </div>
      </div>
    </div>
  </div>
</body>
</html>
<!DOCTYPE html>
<html>
  <head>
    <title>Decidim - Login</title>
    <%= render partial: 'layouts/decidim/system/header' %>
  </head>

  <body class="login">
    <div class="login-form-wrapper">
      <div class="login-form">
        <h1>Decidim</h1>
        <%= display_flash_messages %>
        <div class="login-form-inner">
          <%= yield %>
        </div>
      </div>
    </div>
  </body>
</html>
#!/usr/bin/env ruby
# frozen_string_literal: true
# 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/decidim/system/engine", __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"
# i18n-tasks finds and manages missing and unused translations: https://github.com/glebm/i18n-tasks

# The "main" locale.
base_locale: en
## All available locales are inferred from the data by default. Alternatively, specify them explicitly:
# locales: [es, fr]
## Reporting locale, default: en. Available: en, ru.
# internal_locale: en

# Read and write translations.
data:
  ## Translations are read from the file system. Supported format: YAML, JSON.
  ## Provide a custom adapter:
  # adapter: I18n::Tasks::Data::FileSystem

  # Locale files or `File.find` patterns where translations are read from:
  read:
    ## Default:
    # - config/locales/%{locale}.yml
    ## More files:
    # - config/locales/**/*.%{locale}.yml
    ## Another gem (replace %#= with %=):
    # - "<%#= %x[bundle show vagrant].chomp %>/templates/locales/%{locale}.yml"

  # Locale files to write new keys to, based on a list of key pattern => file rules. Matched from top to bottom:
  # `i18n-tasks normalize -p` will force move the keys according to these rules
  write:
    ## For example, write devise and simple form keys to their respective files:
    # - ['{devise, simple_form}.*', 'config/locales/\1.%{locale}.yml']
    ## Catch-all default:
    # - config/locales/%{locale}.yml

  ## Specify the router (see Readme for details). Valid values: conservative_router, pattern_router, or a custom class.
  # router: convervative_router

  yaml:
    write:
      # do not wrap lines at 80 characters
      line_width: -1

  ## Pretty-print JSON:
  # json:
  #   write:
  #     indent: '  '
  #     space: ' '
  #     object_nl: "\n"
  #     array_nl: "\n"

# Find translate calls
search:
  ## Paths or `File.find` patterns to search in:
  # paths:
  #  - app/

  ## Root directories for relative keys resolution.
  # relative_roots:
  #   - app/controllers
  #   - app/helpers
  #   - app/mailers
  #   - app/presenters
  #   - app/views

  ## Files or `File.fnmatch` patterns to exclude from search. Some files are always excluded regardless of this setting:
  ##   %w(*.jpg *.png *.gif *.svg *.ico *.eot *.otf *.ttf *.woff *.woff2 *.pdf *.css *.sass *.scss *.less *.yml *.json)
  exclude:
    - app/assets/images
    - app/assets/fonts

  ## Alternatively, the only files or `File.fnmatch patterns` to search in `paths`:
  ## If specified, this settings takes priority over `exclude`, but `exclude` still applies.
  # only: ["*.rb", "*.html.slim"]

  ## If `strict` is `false`, guess usages such as t("categories.#{category}.title"). The default is `true`.
  # strict: true

  ## Multiple scanners can be used. Their results are merged.
  ## The options specified above are passed down to each scanner. Per-scanner options can be specified as well.
  ## See this example of a custom scanner: https://github.com/glebm/i18n-tasks/wiki/A-custom-scanner-example

## Google Translate
# translation:
#   # Get an API key and set billing info at https://code.google.com/apis/console to use Google Translate
#   api_key: "AbC-dEf5"

## Do not consider these keys missing:
# ignore_missing:
# - 'errors.messages.{accepted,blank,invalid,too_short,too_long}'
# - '{devise,simple_form}.*'

## Consider these keys used:
# ignore_unused:
# - 'activerecord.attributes.*'
# - '{devise,kaminari,will_paginate}.*'
# - 'simple_form.{yes,no}'
# - 'simple_form.{placeholders,hints,labels}.*'
# - 'simple_form.{error_notification,required}.:'

## Exclude these keys from the `i18n-tasks eq-base' report:
# ignore_eq_base:
#   all:
#     - common.ok
#   fr,es:
#     - common.brand

## Ignore these keys completely:
# ignore:
#  - kaminari.*

## Sometimes, it isn't possible for i18n-tasks to match the key correctly,
## e.g. in case of a relative key defined in a helper method.
## In these cases you can use the built-in PatternMapper to map patterns to keys, e.g.:
#
# <%#= I18n::Tasks.add_scanner 'I18n::Tasks::Scanners::PatternMapper',
#        only: %w(*.html.haml *.html.slim),
#        patterns: [['= title\b', '.page_title']] %>
#
# The PatternMapper can also match key literals via a special %{key} interpolation, e.g.:
#
# <%#= I18n::Tasks.add_scanner 'I18n::Tasks::Scanners::PatternMapper',
#        patterns: [['\bSpree\.t[( ]\s*%{key}', 'spree.%{key}']] %>
---
en:
  decidim:
    system:
      actions:
        confirm_destroy: Are you sure you want to delete this?
        destroy: Destroy
        edit: Edit
        new: New %{name}
        save: Save
        title: Actions
      admins:
        create:
          error: There was an error when creating a new admin.
          success: Admin created successfully
        destroy:
          success: Admin successfully destroyed
        edit:
          title: Edit admin
          update: Update admin
        index:
          title: Admins
        new:
          create: Create admin
          title: New admin
        update:
          error: There was an error when updating this admin.
          success: Admin updated successfully
      menu:
        admins: Admins
        dashboard: Dashboard
        organizations: Organizations
      models:
        admin:
          fields:
            created_at: Created at
            email: Email
          name: Admin
          validations:
            email_uniqueness: another admin with the same email already exists
        organization:
          actions:
            save_and_invite: Create organization & invite admin
          fields:
            created_at: Created at
            name: Name
          name: Organization
      organizations:
        create:
          error: There was an error when creating a new organization.
          success: Organization created successfully.
        index:
          title: Organizations
        new:
          title: New organization
        update:
          error: There was an error when updating this organization.
          success: Organization updated successfully.
      titles:
        dashboard: Dashboard
# frozen_string_literal: true
Decidim::System::Engine.routes.draw do
  devise_for :admins,
             class_name: "Decidim::System::Admin",
             module: :'decidim/system/devise',
             router_name: "decidim_system"

  authenticate(:admin) do
    resources :organizations
    resources :admins
    root to: "dashboard#show"
  end
end
class DeviseCreateDecidimAdmins < ActiveRecord::Migration[5.0]
  def change
    create_table :decidim_system_admins do |t|
      ## Database authenticatable
      t.string :email,              null: false, default: ""
      t.string :encrypted_password, null: false, default: ""

      ## Recoverable
      t.string   :reset_password_token
      t.datetime :reset_password_sent_at

      ## Rememberable
      t.datetime :remember_created_at

      ## Lockable
      t.integer  :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
      t.string   :unlock_token # Only if unlock strategy is :email or :both
      t.datetime :locked_at

      t.timestamps null: false
    end

    add_index :decidim_system_admins, :email,                unique: true
    add_index :decidim_system_admins, :reset_password_token, unique: true
  end
end
# frozen_string_literal: true
$LOAD_PATH.push File.expand_path("../lib", __FILE__)

# Maintain your gem's version:
require_relative "../decidim-core/lib/decidim/core/version"

# Describe your gem and declare its dependencies:
Gem::Specification.new do |s|
  s.name        = "decidim-system"
  s.version     = Decidim.version
  s.authors     = ["Josep Jaume Rey Peroy", "Marc Riera Casals", "Oriol Gual Oliva"]
  s.email       = ["josepjaume@gmail.com", "mrc2407@gmail.com", "oriolgual@gmail.com"]
  s.homepage    = ""
  s.summary     = "System administration"
  s.description = "System administration to create new organization in an installation."
  s.license     = "MIT"

  s.files = Dir["{app,config,db,lib}/**/*", "MIT-LICENSE", "Rakefile", "README.md"]

  s.add_dependency "decidim-core"
  s.add_dependency "rails", Decidim.rails_version
  s.add_dependency "devise", "~> 4.2"
  s.add_dependency "rectify", "~> 0.6"
  s.add_dependency "devise_invitable", "~> 1.7.0"
  s.add_dependency "foundation-rails", "~> 6.2.3.0"
  s.add_dependency "sass-rails", "~> 5.0.0"
  s.add_dependency "jquery-rails", "~> 4.0"
  s.add_dependency "turbolinks", Decidim.rails_version
  s.add_dependency "jquery-turbolinks", "~> 2.1.0"
  s.add_dependency "jbuilder", "~> 2.5"
  s.add_dependency "foundation_rails_helper", "~> 2.0.0"
  s.add_dependency "active_link_to", "~> 1.0.0"

  s.add_development_dependency "factory_girl_rails"
  s.add_development_dependency "database_cleaner", "~> 1.5.0"
  s.add_development_dependency "capybara", "~> 2.4"
  s.add_development_dependency "rspec-rails", "~> 3.5"
  s.add_development_dependency "byebug"
  s.add_development_dependency "wisper-rspec"
  s.add_development_dependency "pg"
  s.add_development_dependency "listen"
  s.add_development_dependency "launchy"
  s.add_development_dependency "i18n-tasks", "~> 0.9.5"
end
# frozen_string_literal: true
require "decidim/system/engine"

module Decidim
  # This module contains all the logic related to a system-wide
  # administration panel. The scope of the domain is to be able
  # to manage Organizations (tenants), as well as have a bird's
  # eye view of the whole system.
  #
  module System
  end
end
# frozen_string_literal: true
require "rails"
require "active_support/all"

require "decidim/core"
require "devise"
require "jquery-rails"
require "sass-rails"
require "turbolinks"
require "jquery-turbolinks"
require "foundation-rails"
require "foundation_rails_helper"
require "jbuilder"
require "rectify"

module Decidim
  module System
    # Decidim's core Rails Engine.
    class Engine < ::Rails::Engine
      isolate_namespace Decidim::System

      config.to_prepare do
        Rails.application.config.assets.precompile += %w(
          decidim/system.js
          decidim/system.css
        )
      end
    end
  end
end
# frozen_string_literal: true
require "rails/generators"
require_relative "../../../../lib/generators/decidim/app_generator"

module Decidim
  module System
    module Generators
      # Generates a dummy test Rails app for the given library folder. It uses
      # the `AppGenerator` class to actually generate the Rails app, so this
      # generator only sets the path and some flags.
      #
      # The Rails app will be installed with some flags to disable git, tests,
      # Gemfile and other options. Refer to the `create_dummy_app` method to see
      # all the flags passed to the `AppGenerator` class, which is the one that
      # actually generates the Rails app.
      #
      # Remember that, for how generators work, actions are executed based on the
      # definition order of the public methods.
      class DummyGenerator < Rails::Generators::Base
        desc "Generate dummy app for testing purposes"

        class_option :lib_name, type: :string,
                                desc: "The library where the dummy app will be installed"

        class_option :migrate, type: :boolean, default: false,
                               desc: "Run migrations after installing decidim"

        def cleanup
          remove_directory_if_exists(dummy_path)
        end

        def create_dummy_app
          Decidim::Generators::AppGenerator.start [
            dummy_path,
            "--skip_gemfile",
            "--skip-bundle",
            "--skip-git",
            "--skip-keeps",
            "--skip-test",
            "--migrate=#{options[:migrate]}"
          ]
        end

        private

        def dummy_path
          ENV["DUMMY_PATH"] || "spec/#{short_lib_name}_dummy"
        end

        def remove_directory_if_exists(path)
          remove_dir(path) if File.directory?(path)
        end

        def short_lib_name
          options[:lib_name].split("/").last
        end
      end
    end
  end
end
# frozen_string_literal: true
# desc "Explaining what the task does"
# task :decidim_system do
#   # Task goes here
# end
# frozen_string_literal: true
require "spec_helper"

module Decidim
  module System
    describe CreateAdmin, :db do
      describe "call" do
        let(:form) { AdminForm.new(params) }
        let(:command) { described_class.new(form) }

        describe "when the admin already exists" do
          before do
            create(:admin, email: "email@foo.bar")
          end

          let(:params) do
            {
              email: "email@foo.bar"
            }
          end

          it "broadcasts invalid" do
            expect { command.call }.to broadcast(:invalid)
          end
        end

        describe "when the admin doesn't exist" do
          before do
            create(:admin, email: "email@foo.bar")
          end

          let(:params) do
            {
              email: "different_email@foo.bar",
              password: "fake123",
              password_confirmation: "fake123"
            }
          end

          it "broadcasts ok and creates an admin" do
            expect { command.call }.to broadcast(:ok)
            expect(Admin.where(email: "different_email@foo.bar")).to exist
          end
        end
      end
    end
  end
end
# frozen_string_literal: true
require "spec_helper"

module Decidim
  module System
    describe RegisterOrganization, :db do
      describe "call" do
        let(:form) do
          RegisterOrganizationForm.new(params)
        end

        let(:command) { described_class.new(form) }

        context "when the form is valid" do
          let(:params) do
            {
              name: "Gotham City",
              host: "decide.gotham.gov",
              organization_admin_email: "f.laguardia@gotham.gov"
            }
          end

          it "returns a valid response" do
            expect { command.call }.to broadcast(:ok)
          end

          it "creates a new organization" do
            expect { command.call }.to change { Organization.count }.by(1)
            organization = Organization.last

            expect(organization.name).to eq("Gotham City")
            expect(organization.host).to eq("decide.gotham.gov")
          end

          it "invites a user as organization admin" do
            expect { command.call }.to change { User.count }.by(1)
            admin = User.last

            expect(admin.email).to eq("f.laguardia@gotham.gov")
            expect(admin.organization.name).to eq("Gotham City")
            expect(admin).to be_admin
            expect(admin).to be_created_by_invite
          end
        end

        context "when the form is invalid" do
          let(:params) do
            {
              name: nil,
              host: "foo.com"
            }
          end

          it "returns an invalid response" do
            expect { command.call }.to broadcast(:invalid)
          end
        end
      end
    end
  end
end
require_relative "../../decidim-core/spec/factories"

FactoryGirl.define do
  factory :admin, class: Decidim::System::Admin do
    sequence(:email)      { |n| "admin#{n}@citizen.corp" }
    password              "password1234"
    password_confirmation "password1234"
  end
end
# frozen_string_literal: true

require "spec_helper"

describe "Manage admins", type: :feature do
  let(:admin) { create(:admin) }
  let!(:admin2) { create(:admin) }

  before do
    login_as admin, scope: :admin
    visit decidim_system.admins_path
  end

  it "creates a new admin" do
    find(".actions .new").click

    within ".new_admin" do
      fill_in :admin_email, with: "admin@foo.bar"
      fill_in :admin_password, with: "fake123"
      fill_in :admin_password_confirmation, with: "fake123"

      find("*[type=submit]").click
    end

    within ".flash" do
      expect(page).to have_content("successfully")
    end

    within "table" do
      expect(page).to have_content("admin@foo.bar")
    end
  end

  it "updates an admin" do
    within find("tr", text: admin.email) do
      click_link "Edit"
    end

    within ".edit_admin" do
      fill_in :admin_email, with: "admin@another.domain"

      find("*[type=submit]").click
    end

    within ".flash" do
      expect(page).to have_content("successfully")
    end

    within "table" do
      expect(page).to have_content("admin@another.domain")
    end
  end

  it "deletes an admin" do
    within find("tr", text: admin2.email) do
      click_link "Destroy"
    end

    within ".flash" do
      expect(page).to have_content("successfully")
    end

    within "table" do
      expect(page).to_not have_content(admin2.email)
    end
  end
end
# frozen_string_literal: true

require "spec_helper"

describe "Organizations", type: :feature do
  let(:admin) { create(:admin) }

  context "authenticated admin" do
    before do
      login_as admin, scope: :admin
      visit decidim_system.root_path
    end

    context "creating an organization" do
      before do
        click_link "Organizations"
        click_link "New"
      end

      it "creates a new organization" do
        fill_in "Name", with: "Citizen Corp"
        fill_in "Host", with: "www.citizen.corp"
        fill_in "Organization admin email", with: "mayor@citizen.corp"
        click_button "Create organization & invite admin"

        expect(page).to have_css("div.flash.success")
        expect(page).to have_content("Citizen Corp")
      end

      context "with invalid data" do
        it "doesn't create an organization" do
          fill_in "Name", with: "Bad"
          click_button "Create organization & invite admin"

          expect(page).to have_css("div.flash.alert")
          expect(page).to_not have_content("Organization created successfully")
        end
      end
    end

    context "editing an organization" do
      let!(:organization) { create(:organization, name: "Citizen Corp") }

      before do
        click_link "Organizations"
        within("table tbody tr:first") do
          click_link "Edit"
        end
      end

      it "edits the data" do
        fill_in "Name", with: "Citizens Rule!"
        fill_in "Host", with: "www.foo.org"
        click_button "Save"

        expect(page).to have_css("div.flash.success")
        expect(page).to have_content("Citizens Rule!")
      end
    end
  end
end
# frozen_string_literal: true
require "spec_helper"

describe "Sessions", type: :feature do
  let!(:admin) do
    create(:admin, email: "admin@example.org",
                   password: "123456",
                   password_confirmation: "123456")
  end

  before(:each) do
    visit decidim_system.root_path
  end

  context "when using a correct username and password" do
    it "lets you into the system panel" do
      within ".new_admin" do
        fill_in :admin_email, with: "admin@example.org"
        fill_in :admin_password, with: "123456"
        click_button "Log in"
      end

      expect(page).to have_content("Dashboard")
    end
  end

  context "when using an incorrectusername and password" do
    it "doesn't let you in the admin panel" do
      within ".new_admin" do
        fill_in :admin_email, with: "admin@example.org"
        fill_in :admin_password, with: "forged_password"
        find("*[type=submit]").click
      end

      expect(page).not_to have_content("Dashboard")
    end
  end
end
# frozen_string_literal: true
require 'i18n/tasks'

RSpec.describe 'I18n' do
  let(:i18n) { I18n::Tasks::BaseTask.new }
  let(:missing_keys) { i18n.missing_keys }
  let(:unused_keys) { i18n.unused_keys }

  it 'does not have missing keys' do
    expect(missing_keys).to be_empty,
      "Missing #{missing_keys.leaves.count} i18n keys, run `i18n-tasks missing' to show them"
  end

  it 'does not have unused keys' do
    expect(unused_keys).to be_empty,
      "#{unused_keys.leaves.count} unused i18n keys, run `i18n-tasks unused' to show them"
  end
end
# frozen_string_literal: true
ENV["RAILS_ENV"] ||= "test"

if ENV["CI"]
  require "simplecov"
  SimpleCov.start

  require "codecov"
  SimpleCov.formatter = SimpleCov::Formatter::Codecov
end

begin
  require File.expand_path("../system_dummy/config/environment", __FILE__)
rescue LoadError
  puts "Could not load dummy application. Please ensure you have run `bundle exec rake test_app`"
  exit
end

require "rspec/rails"
require "factory_girl_rails"
require "database_cleaner"
require "byebug"

# Requires supporting files with custom matchers and macros, etc,
# in ./support/ and its subdirectories.
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }

RSpec.configure do |config|
  config.color = true
  config.fail_fast = ENV["FAIL_FAST"] || false
  config.infer_spec_type_from_file_location!
  config.mock_with :rspec
  config.raise_errors_for_deprecations!

  # If you're not using ActiveRecord, or you'd prefer not to run each of your
  # examples within a transaction, comment the following line or assign false
  # instead of true.
  config.use_transactional_fixtures = false
end
RSpec.configure do |config|
  config.before(:suite) do
    DatabaseCleaner.strategy = :transaction
    DatabaseCleaner.clean_with(:truncation)
  end

  config.around(:each) do |example|
    DatabaseCleaner.cleaning do
      example.run
    end
  end
end
RSpec.configure do |config|
  config.include FactoryGirl::Syntax::Methods
end
RSpec.configure do |config|
  config.include Warden::Test::Helpers, type: :feature

  config.after :each, type: :feature do
    Warden.test_reset!
  end
end
require 'wisper/rspec/matchers'

RSpec::configure do |config|
  config.include(Wisper::RSpec::BroadcastMatcher)
end
  spec.add_dependency "decidim-system", Decidim.version
  spec.add_development_dependency "rake", "~> 11.0"
require "decidim/system"
gem 'foundation_rails_helper', github: 'sgruhier/foundation_rails_helper'


require_relative "spec_helper"