diff --git a/app/assets/stylesheets/forms.scss b/app/assets/stylesheets/forms.scss new file mode 100644 index 0000000..64fcb0b --- /dev/null +++ b/app/assets/stylesheets/forms.scss @@ -0,0 +1,28 @@ +form { + .field_with_errors { + display: inline-block; + } +} + +.layout-signup { + label { + display: none; + } + + input[type=text], input[type=email], input[type=password] { + font-size: 1.25rem; + padding: 0.5rem 1rem; + } + + span.at-sign, span.domain { + font-size: 1.25rem; + } + + .error-msg { + color: #bc0101; + } + + .actions { + margin-top: 2rem; + } +} diff --git a/app/controllers/signup_controller.rb b/app/controllers/signup_controller.rb index 21dd7b3..237b77e 100644 --- a/app/controllers/signup_controller.rb +++ b/app/controllers/signup_controller.rb @@ -2,6 +2,7 @@ class SignupController < ApplicationController before_action :require_user_signed_out before_action :require_invitation before_action :set_invitation + before_action :set_new_user, only: ["steps", "validate"] layout "signup" @@ -9,8 +10,61 @@ class SignupController < ApplicationController @invited_by_name = @invitation.user.address end + def steps + @step = params[:step].to_i + http_status :not_found unless [1,2,3].include?(@step) + @validation_error = session[:validation_error] + end + + def validate + session[:validation_error] = nil + + case user_params.keys.first + when "cn" + @user.cn = user_params[:cn] + @user.valid? + session[:new_user] = @user + + if @user.errors[:cn].present? + session[:validation_error] = @user.errors[:cn].first # Store user including validation errors + redirect_to signup_steps_path(1) and return + else + redirect_to signup_steps_path(2) and return + end + when "email" + @user.email = user_params[:email] + @user.valid? + session[:new_user] = @user + + if @user.errors[:email].present? + session[:validation_error] = @user.errors[:email].first # Store user including validation errors + redirect_to signup_steps_path(2) and return + else + redirect_to signup_steps_path(3) and return + end + when "password" + @user.password = user_params[:password] + @user.password_confirmation = user_params[:password] + @user.valid? + session[:new_user] = @user + + if @user.errors[:password].present? + session[:validation_error] = @user.errors[:password].first # Store user including validation errors + redirect_to signup_steps_path(3) and return + else + complete_signup + msg = "Almost done! We have sent you an email to confirm your address." + redirect_to(check_your_email_path, notice: msg) and return + end + end + end + private + def user_params + params.require(:user).permit(:cn, :email, :password) + end + def require_invitation if session[:invitation_token].blank? flash.now[:alert] = "You need an invitation to sign up for an account." @@ -30,4 +84,27 @@ class SignupController < ApplicationController def set_invitation @invitation = Invitation.find_by(token: session[:invitation_token]) end + + def set_new_user + if session[:new_user].present? + @user = User.new(session[:new_user]) + else + @user = User.new(ou: "kosmos.org") + end + end + + def complete_signup + @user.save! + session[:new_user] = nil + session[:validation_error] = nil + + CreateAccount.call( + username: @user.cn, + email: @user.email, + password: @user.password + ) + + @invitation.update_attributes invited_user_id: @user.id, + used_at: DateTime.now + end end diff --git a/app/models/user.rb b/app/models/user.rb index e6f80f0..b2f3693 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -2,6 +2,10 @@ class User < ApplicationRecord # Relations has_many :invitations, dependent: :destroy + validates_uniqueness_of :cn + validates_uniqueness_of :email + validates_length_of :cn, :minimum => 3 + # Include default devise modules. Others available are: # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable devise :ldap_authenticatable, @@ -40,4 +44,9 @@ class User < ApplicationRecord def address "#{self.cn}@#{self.ou}" end + + def valid_attribute?(attribute_name) + self.valid? + self.errors[attribute_name].blank? + end end diff --git a/app/views/layouts/signup.html.erb b/app/views/layouts/signup.html.erb index 05fbf73..1a49165 100644 --- a/app/views/layouts/signup.html.erb +++ b/app/views/layouts/signup.html.erb @@ -11,7 +11,7 @@ <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %> - +

diff --git a/app/views/shared/status_not_found.html.erb b/app/views/shared/status_not_found.html.erb new file mode 100644 index 0000000..c31810c --- /dev/null +++ b/app/views/shared/status_not_found.html.erb @@ -0,0 +1,2 @@ +

Not found

+

Sorry, this page does not exist.

diff --git a/app/views/signup/index.html.erb b/app/views/signup/index.html.erb index f3782fa..f3d8b80 100644 --- a/app/views/signup/index.html.erb +++ b/app/views/signup/index.html.erb @@ -8,5 +8,5 @@ by invitation. Seems like you have good friends!

- <%= link_to "Get started", signup_path, class: "next-step" %> + <%= link_to "Get started", signup_steps_path(1), class: "next-step" %>

diff --git a/app/views/signup/steps.html.erb b/app/views/signup/steps.html.erb new file mode 100644 index 0000000..107ed5a --- /dev/null +++ b/app/views/signup/steps.html.erb @@ -0,0 +1,55 @@ +<% case @step %> +<% when 1 %> +

Choose a username

+ <%= form_for @user, :url => signup_validate_url do |f| %> +
+

+ <%= f.label :cn, 'Username' %>
+ <%= f.text_field :cn, autofocus: true, autocomplete: "username" %> + @ + kosmos.org +

+ <% if @validation_error.present? %> +

Username <%= @validation_error %>

+ <% end %> +
+
+

<%= f.submit "Continue" %>

+
+ <% end %> + +<% when 2 %> +

What's your email?

+ <%= form_for @user, :url => signup_validate_url do |f| %> +
+

+ <%= f.label :email, 'Email address' %>
+ <%= f.email_field :email, autofocus: true, autocomplete: "email" %> +

+ <% if @validation_error.present? %> +

Email <%= @validation_error %>

+ <% end %> +
+
+

<%= f.submit "Continue" %>

+
+ <% end %> + +<% when 3 %> +

Choose a password

+ + <%= form_for @user, :url => signup_validate_url do |f| %> +
+

+ <%= f.label :password, 'Password' %>
+ <%= f.password_field :password, autofocus: true %> +

+ <% if @validation_error.present? %> +

Password <%= @validation_error %>

+ <% end %> +
+
+

<%= f.submit "Continue" %>

+
+ <% end %> +<% end %> diff --git a/config/routes.rb b/config/routes.rb index f6aa90c..bdefef0 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -5,6 +5,8 @@ Rails.application.routes.draw do get 'check_your_email', to: 'welcome#check_your_email' get 'signup', to: 'signup#index' + match 'signup/:step', to: 'signup#steps', as: :signup_steps, via: [:get, :post] + post 'signup_validate', to: 'signup#validate' get 'settings', to: 'settings#index' post 'settings_reset_password', to: 'settings#reset_password'