diff --git a/app/assets/images/background-photo.jpg b/app/assets/images/background-photo.jpg new file mode 100644 index 000000000..3f2eeb121 Binary files /dev/null and b/app/assets/images/background-photo.jpg differ diff --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 { - font-family: 'Noto Sans', sans-serif; - background: $background-color image-url('background-pattern.png'); + 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: '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; - .mastodon-link { - color: $quaternary-color; - text-decoration: none; - font-weight: bold; + 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%); + } + + &: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 @@ +
Hello <%= @resource.email %>!
+ +We're contacting you to notify you that your password has been changed.
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 @@ +Hello <%= @resource.email %>!
+ +Someone has requested a link to change your password. You can do this through the link below.
+ +<%= link_to 'Change my password', edit_password_url(@resource, reset_password_token: @token) %>
+ +If you didn't request this, please ignore this email.
+Your password won't change until you access the link above and create a new one.
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 @@ +