about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--app/assets/images/background-photo.jpgbin0 -> 1329145 bytes
-rw-r--r--app/assets/stylesheets/application.scss206
-rw-r--r--app/controllers/auth/passwords_controller.rb34
-rw-r--r--app/controllers/auth/registrations_controller.rb22
-rw-r--r--app/controllers/auth/sessions_controller.rb27
-rw-r--r--app/models/account.rb1
-rw-r--r--app/models/user.rb1
-rw-r--r--app/views/auth/mailer/password_change.html.erb3
-rw-r--r--app/views/auth/mailer/reset_password_instructions.html.erb8
-rw-r--r--app/views/auth/passwords/edit.html.erb25
-rw-r--r--app/views/auth/passwords/new.html.haml9
-rw-r--r--app/views/auth/registrations/edit.html.haml11
-rw-r--r--app/views/auth/registrations/new.html.haml17
-rw-r--r--app/views/auth/sessions/new.html.haml9
-rw-r--r--app/views/auth/shared/_links.html.haml19
-rw-r--r--app/views/home/index.html.haml2
-rw-r--r--app/views/layouts/application.html.haml5
-rw-r--r--app/views/layouts/auth.html.haml10
-rw-r--r--config/routes.rb6
19 files changed, 398 insertions, 17 deletions
diff --git a/app/assets/images/background-photo.jpg b/app/assets/images/background-photo.jpg
new file mode 100644
index 000000000..3f2eeb121
--- /dev/null
+++ b/app/assets/images/background-photo.jpg
Binary files differdiff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss
index 552356a22..c7b8814f5 100644
--- a/app/assets/stylesheets/application.scss
+++ b/app/assets/stylesheets/application.scss
@@ -7,15 +7,73 @@ $darker-background-color: #e3dede;
 $text-color: #333030;
 $lighter-text-color: #8b8687;
 
-@import url("https://fonts.googleapis.com/css?family=Noto+Sans:400,700,400italic");
+@import url(https://fonts.googleapis.com/css?family=Roboto:400,500,400italic);
+@import url(https://fonts.googleapis.com/css?family=Roboto+Mono);
 @import "font-awesome-sprockets";
 @import "font-awesome";
 
+/* http://meyerweb.com/eric/tools/css/reset/
+   v2.0 | 20110126
+   License: none (public domain)
+*/
+
+html, body, div, span, applet, object, iframe,
+h1, h2, h3, h4, h5, h6, p, blockquote, pre,
+a, abbr, acronym, address, big, cite, code,
+del, dfn, em, img, ins, kbd, q, s, samp,
+small, strike, strong, sub, sup, tt, var,
+b, u, i, center,
+dl, dt, dd, ol, ul, li,
+fieldset, form, label, legend,
+table, caption, tbody, tfoot, thead, tr, th, td,
+article, aside, canvas, details, embed,
+figure, figcaption, footer, header, hgroup,
+menu, nav, output, ruby, section, summary,
+time, mark, audio, video {
+  margin: 0;
+  padding: 0;
+  border: 0;
+  font-size: 100%;
+  font: inherit;
+  vertical-align: baseline;
+}
+
+/* HTML5 display-role reset for older browsers */
+article, aside, details, figcaption, figure,
+footer, header, hgroup, menu, nav, section {
+  display: block;
+}
+
+body {
+  line-height: 1;
+}
+
+ol, ul {
+  list-style: none;
+}
+
+blockquote, q {
+  quotes: none;
+}
+
+blockquote:before, blockquote:after,
+q:before, q:after {
+  content: '';
+  content: none;
+}
+
+table {
+  border-collapse: collapse;
+  border-spacing: 0;
+}
+
 body {
-  font-family: 'Noto Sans', sans-serif;
-  background: $background-color image-url('background-pattern.png');
+  font-family: 'Roboto', sans-serif;
+  background: $background-color image-url('background-photo.jpeg');
+  background-size: cover;
   font-size: 13px;
   line-height: 18px;
+  font-weight: 400;
   color: $text-color;
 }
 
@@ -25,19 +83,143 @@ body {
   margin-top: 40px;
 }
 
-.footer {
-  text-align: center;
-  padding: 100px 0;
-  font-size: 12px;
-  color: $text-color;
+.logo-container {
+  width: 400px;
+  margin: 100px auto;
+  cursor: default;
+
+  h1 {
+    display: block;
+    text-align: center;
+    color: #fff;
+    font-size: 48px;
+    line-height: 48px;
+    font-weight: 500;
+
+    small {
+      display: block;
+      font-size: 12px;
+      font-weight: 400;
+      font-family: 'Roboto Mono', monospace;
+    }
+  }
+}
+
+.form-container {
+  width: 400px;
+  margin: 0 auto;
+
+  .field {
+    margin-bottom: 15px;
+  }
+
+  input[type=text], input[type=email], input[type=password] {
+    background: transparent;
+    border: 0;
+    border-bottom: 2px solid #9baec8;
+    padding: 7px 0;
+    font-size: 16px;
+    color: #fff;
+    display: block;
+    width: 100%;
+    outline: 0;
+
+    &:invalid {
+      box-shadow: none;
+    }
+
+    &:focus:invalid {
+      border-bottom-color: #df405a;
+    }
+
+    &:required:valid {
+      border-bottom-color: #79bd9a;
+    }
+
+    &:active, &:focus {
+      border-bottom-color: #2b90d9;
+    }
+  }
+
+  .field_with_error {
+    input[type=text], input[type=email], input[type=password] {
+      border-bottom-color: #df405a;
+    }
+  }
+
+  .actions {
+    margin-top: 30px;
+
+    button {
+      display: block;
+      width: 100%;
+      border: 0;
+      border-radius: 4px;
+      background: #2b90d9;
+      color: #fff;
+      font-size: 18px;
+      padding: 10px;
+      text-transform: uppercase;
+      cursor: pointer;
+      font-weight: 500;
+      outline: 0;
+
+      &:hover {
+        background-color: lighten(#2b90d9, 5%);
+      }
 
-  .mastodon-link {
-    color: $quaternary-color;
-    text-decoration: none;
-    font-weight: bold;
+      &:active, &:focus {
+        position: relative;
+        top: 1px;
+        background-color: darken(#2b90d9, 5%);
+      }
+    }
+  }
+
+  .form-footer {
+    margin-top: 30px;
+    text-align: center;
+
+
+    a {
+      color: #9baec8;
+      text-decoration: none;
+
+      &:hover {
+        color: #d9e1e8;
+        text-decoration: underline;
+      }
+    }
+  }
+
+  #error_explanation {
+    background: #282c37;
+    color: #9baec8;
+    border-radius: 4px;
+    padding: 15px 10px;
+    margin-bottom: 30px;
+    box-shadow: 0 0 5px rgba(0, 0, 0, 0.2);
+
+    h2 {
+      font-weight: 500;
+      margin-bottom: 5px;
+    }
+
+    li {
+      margin-left: 15px;
+      list-style: circle;
+    }
   }
 }
 
+.no-list {
+  list-style: none;
+
+  li {
+    display: inline-block;
+    margin: 0 5px;
+  }
+}
 
 @import 'home';
 @import 'accounts';
diff --git a/app/controllers/auth/passwords_controller.rb b/app/controllers/auth/passwords_controller.rb
new file mode 100644
index 000000000..5c964bda0
--- /dev/null
+++ b/app/controllers/auth/passwords_controller.rb
@@ -0,0 +1,34 @@
+class Auth::PasswordsController < Devise::PasswordsController
+  layout 'auth'
+
+  # GET /resource/password/new
+  # def new
+  #   super
+  # end
+
+  # POST /resource/password
+  # def create
+  #   super
+  # end
+
+  # GET /resource/password/edit?reset_password_token=abcdef
+  # def edit
+  #   super
+  # end
+
+  # PUT /resource/password
+  # def update
+  #   super
+  # end
+
+  # protected
+
+  # def after_resetting_password_path_for(resource)
+  #   super(resource)
+  # end
+
+  # The path used after sending reset password instructions
+  # def after_sending_reset_password_instructions_path_for(resource_name)
+  #   super(resource_name)
+  # end
+end
diff --git a/app/controllers/auth/registrations_controller.rb b/app/controllers/auth/registrations_controller.rb
new file mode 100644
index 000000000..3114ae60a
--- /dev/null
+++ b/app/controllers/auth/registrations_controller.rb
@@ -0,0 +1,22 @@
+class Auth::RegistrationsController < Devise::RegistrationsController
+  layout 'auth'
+
+  before_filter :configure_sign_up_params, only: [:create]
+
+  protected
+
+  def build_resource(hash = nil)
+    super(hash)
+    self.resource.build_account if self.resource.account.nil?
+  end
+
+  def configure_sign_up_params
+    devise_parameter_sanitizer.for(:sign_up) do |u|
+      u.permit(:email, :password, :password_confirmation, account_attributes: [:username])
+    end
+  end
+
+  def after_sign_up_path_for(resource)
+    account_path(resource.account)
+  end
+end
diff --git a/app/controllers/auth/sessions_controller.rb b/app/controllers/auth/sessions_controller.rb
new file mode 100644
index 000000000..d1bcc7c17
--- /dev/null
+++ b/app/controllers/auth/sessions_controller.rb
@@ -0,0 +1,27 @@
+class Auth::SessionsController < Devise::SessionsController
+  layout 'auth'
+
+  # before_filter :configure_sign_in_params, only: [:create]
+
+  # GET /resource/sign_in
+  # def new
+  #   super
+  # end
+
+  # POST /resource/sign_in
+  # def create
+  #   super
+  # end
+
+  # DELETE /resource/sign_out
+  # def destroy
+  #   super
+  # end
+
+  # protected
+
+  # If you have extra params to permit, append them to the sanitizer.
+  # def configure_sign_in_params
+  #   devise_parameter_sanitizer.for(:sign_in) << :attribute
+  # end
+end
diff --git a/app/models/account.rb b/app/models/account.rb
index 6a4aa16b4..47e43f0ac 100644
--- a/app/models/account.rb
+++ b/app/models/account.rb
@@ -1,6 +1,7 @@
 class Account < ActiveRecord::Base
   # Local users
   has_one :user, inverse_of: :account
+  validates :username, uniqueness: { scope: :domain }
 
   # Avatar upload
   attr_reader :avatar_remote_url
diff --git a/app/models/user.rb b/app/models/user.rb
index 999aa0d39..038ff21c6 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -2,6 +2,7 @@ class User < ActiveRecord::Base
   devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable
 
   belongs_to :account, inverse_of: :user
+  accepts_nested_attributes_for :account
 
   validates :account, presence: true
 end
diff --git a/app/views/auth/mailer/password_change.html.erb b/app/views/auth/mailer/password_change.html.erb
new file mode 100644
index 000000000..b41daf476
--- /dev/null
+++ b/app/views/auth/mailer/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/app/views/auth/mailer/reset_password_instructions.html.erb b/app/views/auth/mailer/reset_password_instructions.html.erb
new file mode 100644
index 000000000..f667dc12f
--- /dev/null
+++ b/app/views/auth/mailer/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/app/views/auth/passwords/edit.html.erb b/app/views/auth/passwords/edit.html.erb
new file mode 100644
index 000000000..6a796b050
--- /dev/null
+++ b/app/views/auth/passwords/edit.html.erb
@@ -0,0 +1,25 @@
+<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">
+    <%= f.label :password, "New password" %><br />
+    <% 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.label :password_confirmation, "Confirm new password" %><br />
+    <%= f.password_field :password_confirmation, autocomplete: "off" %>
+  </div>
+
+  <div class="actions">
+    <%= f.submit "Change my password" %>
+  </div>
+<% end %>
+
+<%= render "devise/shared/links" %>
diff --git a/app/views/auth/passwords/new.html.haml b/app/views/auth/passwords/new.html.haml
new file mode 100644
index 000000000..2677feea0
--- /dev/null
+++ b/app/views/auth/passwords/new.html.haml
@@ -0,0 +1,9 @@
+= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :post }) do |f|
+  = devise_error_messages!
+
+  .field
+    = f.email_field :email, autofocus: true, required: true, placeholder: 'E-mail address'
+  .actions
+    = f.button "Reset password", type: 'submit'
+
+.form-footer= render "auth/shared/links"
diff --git a/app/views/auth/registrations/edit.html.haml b/app/views/auth/registrations/edit.html.haml
new file mode 100644
index 000000000..943230b34
--- /dev/null
+++ b/app/views/auth/registrations/edit.html.haml
@@ -0,0 +1,11 @@
+= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f|
+  = devise_error_messages!
+
+  .field
+    = f.password_field :password, autocomplete: "off", placeholder: 'New password'
+  .field
+    = f.password_field :password_confirmation, autocomplete: "off", placeholder: 'Confirm new password'
+  .field
+    = f.password_field :current_password, autocomplete: "off", placeholder: 'Current password'
+  .actions
+    = f.button "Save changes", type: 'submit'
diff --git a/app/views/auth/registrations/new.html.haml b/app/views/auth/registrations/new.html.haml
new file mode 100644
index 000000000..c8532ec38
--- /dev/null
+++ b/app/views/auth/registrations/new.html.haml
@@ -0,0 +1,17 @@
+= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f|
+  = devise_error_messages!
+
+  = f.fields_for :account do |ff|
+    .field
+      = ff.text_field :username, autofocus: true, placeholder: 'Username', required: true
+
+  .field
+    = f.email_field :email, placeholder: 'E-mail address', required: true
+  .field
+    = f.password_field :password, autocomplete: "off", placeholder: 'Password', required: true
+  .field
+    = f.password_field :password_confirmation, autocomplete: "off", placeholder: 'Confirm password', required: true
+  .actions
+    = f.button "Sign up", type: 'submit'
+
+.form-footer= render "auth/shared/links"
diff --git a/app/views/auth/sessions/new.html.haml b/app/views/auth/sessions/new.html.haml
new file mode 100644
index 000000000..220d0ec79
--- /dev/null
+++ b/app/views/auth/sessions/new.html.haml
@@ -0,0 +1,9 @@
+= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f|
+  .field
+    = f.email_field :email, autofocus: true, placeholder: 'E-mail address', required: true
+  .field
+    = f.password_field :password, autocomplete: "off", placeholder: 'Password', required: true
+  .actions
+    = f.button "Log in", type: 'submit'
+
+.form-footer= render "auth/shared/links"
diff --git a/app/views/auth/shared/_links.html.haml b/app/views/auth/shared/_links.html.haml
new file mode 100644
index 000000000..6f89eed75
--- /dev/null
+++ b/app/views/auth/shared/_links.html.haml
@@ -0,0 +1,19 @@
+%ul.no-list
+  - if controller_name != 'sessions'
+    %li= link_to "Log in", new_session_path(resource_name)
+
+  - if devise_mapping.registerable? && controller_name != 'registrations'
+    %li= link_to "Sign up", new_registration_path(resource_name)
+
+  - if devise_mapping.recoverable? && controller_name != 'passwords' && controller_name != 'registrations'
+    %li= link_to "Forgot your password?", new_password_path(resource_name)
+
+  - if devise_mapping.confirmable? && controller_name != 'confirmations'
+    %li= link_to "Didn't receive confirmation instructions?", new_confirmation_path(resource_name)
+
+  - if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'unlocks'
+    %li= link_to "Didn't receive unlock instructions?", new_unlock_path(resource_name)
+
+  - if devise_mapping.omniauthable?
+    - resource_class.omniauth_providers.each do |provider|
+      %li= link_to "Sign in with #{OmniAuth::Utils.camelize(provider)}", omniauth_authorize_path(resource_name, provider)
diff --git a/app/views/home/index.html.haml b/app/views/home/index.html.haml
index 862374a98..11894d72c 100644
--- a/app/views/home/index.html.haml
+++ b/app/views/home/index.html.haml
@@ -1 +1,3 @@
 Mastodon
+
+= link_to 'Logout', destroy_user_session_path, method: :delete
diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml
index f15217203..25b3b5b49 100644
--- a/app/views/layouts/application.html.haml
+++ b/app/views/layouts/application.html.haml
@@ -9,7 +9,4 @@
     = yield :header_tags
   %body
     .container
-      = yield
-    .footer
-      Powered by
-      = link_to 'Mastodon', 'https://github.com/Gargron/mastodon', class: 'mastodon-link'
+      = content_for?(:content) ? yield(:content) : yield
diff --git a/app/views/layouts/auth.html.haml b/app/views/layouts/auth.html.haml
new file mode 100644
index 000000000..dd0e7f166
--- /dev/null
+++ b/app/views/layouts/auth.html.haml
@@ -0,0 +1,10 @@
+- content_for :content do
+  .logo-container
+    %h1
+      Mastodon
+      %small= Rails.configuration.x.local_domain
+
+  .form-container
+    = yield
+
+= render template: "layouts/application"
diff --git a/config/routes.rb b/config/routes.rb
index e74f8c368..8014a2fb2 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -2,7 +2,11 @@ Rails.application.routes.draw do
   get '.well-known/host-meta', to: 'xrd#host_meta', as: :host_meta
   get '.well-known/webfinger', to: 'xrd#webfinger', as: :webfinger
 
-  devise_for :users, path: 'auth'
+  devise_for :users, path: 'auth', controllers: {
+    sessions:           'auth/sessions',
+    registrations:      'auth/registrations',
+    passwords:          'auth/passwords'
+  }
 
   resources :accounts, path: 'users', only: [:show], param: :username do
     resources :stream_entries, path: 'updates', only: [:show]