Require valid invitation to start sign-up process
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
69b99711e5
commit
7aadb5cb51
@ -9,6 +9,12 @@ class ApplicationController < ActionController::Base
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def require_user_signed_out
|
||||||
|
if user_signed_in?
|
||||||
|
redirect_to root_path and return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def authorize_admin
|
def authorize_admin
|
||||||
http_status :forbidden unless current_user.is_admin?
|
http_status :forbidden unless current_user.is_admin?
|
||||||
end
|
end
|
||||||
|
@ -1,11 +1,26 @@
|
|||||||
class InvitationsController < ApplicationController
|
class InvitationsController < ApplicationController
|
||||||
before_action :require_user_signed_in
|
before_action :require_user_signed_in, except: ["show"]
|
||||||
|
before_action :require_user_signed_out, only: ["show"]
|
||||||
|
|
||||||
|
layout "signup", only: ["show"]
|
||||||
|
|
||||||
# GET /invitations
|
# GET /invitations
|
||||||
def index
|
def index
|
||||||
@invitations = current_user.invitations
|
@invitations = current_user.invitations
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# GET /invitations/a-random-invitation-token
|
||||||
|
def show
|
||||||
|
token = session[:invitation_token] = params[:id]
|
||||||
|
|
||||||
|
if Invitation.where(token: token, used_at: nil).exists?
|
||||||
|
redirect_to signup_path and return
|
||||||
|
else
|
||||||
|
flash.now[:alert] = "This invitation either doesn't exist or has already been used."
|
||||||
|
http_status :unauthorized
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# POST /invitations
|
# POST /invitations
|
||||||
def create
|
def create
|
||||||
@invitation = Invitation.new(user: current_user)
|
@invitation = Invitation.new(user: current_user)
|
||||||
|
33
app/controllers/signup_controller.rb
Normal file
33
app/controllers/signup_controller.rb
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
class SignupController < ApplicationController
|
||||||
|
before_action :require_user_signed_out
|
||||||
|
before_action :require_invitation
|
||||||
|
before_action :set_invitation
|
||||||
|
|
||||||
|
layout "signup"
|
||||||
|
|
||||||
|
def index
|
||||||
|
@invited_by_name = @invitation.user.address
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def require_invitation
|
||||||
|
if session[:invitation_token].blank?
|
||||||
|
flash.now[:alert] = "You need an invitation to sign up for an account."
|
||||||
|
http_status :unauthorized
|
||||||
|
elsif !valid_invitation?(session[:invitation_token])
|
||||||
|
flash.now[:alert] = "This invitation either doesn't exist or has already been used."
|
||||||
|
http_status :unauthorized
|
||||||
|
end
|
||||||
|
|
||||||
|
@invitation = Invitation.find_by(token: session[:invitation_token])
|
||||||
|
end
|
||||||
|
|
||||||
|
def valid_invitation?(token)
|
||||||
|
Invitation.where(token: session[:invitation_token], used_at: nil).exists?
|
||||||
|
end
|
||||||
|
|
||||||
|
def set_invitation
|
||||||
|
@invitation = Invitation.find_by(token: session[:invitation_token])
|
||||||
|
end
|
||||||
|
end
|
2
app/helpers/signup_helper.rb
Normal file
2
app/helpers/signup_helper.rb
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
module SignupHelper
|
||||||
|
end
|
@ -36,4 +36,8 @@ class User < ApplicationRecord
|
|||||||
false
|
false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def address
|
||||||
|
"#{self.cn}@#{self.ou}"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
41
app/views/layouts/signup.html.erb
Normal file
41
app/views/layouts/signup.html.erb
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Sign up | Kosmos Accounts</title>
|
||||||
|
<%= csrf_meta_tags %>
|
||||||
|
<%= csp_meta_tag %>
|
||||||
|
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
|
||||||
|
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
|
||||||
|
<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="wrapper">
|
||||||
|
<header>
|
||||||
|
<h1>
|
||||||
|
<span class ="project-name">Kosmos</span>
|
||||||
|
<span class ="site-name">Sign Up</span>
|
||||||
|
<!-- <span class="beta"><span class="bolt">⚡</span> beta</span> -->
|
||||||
|
</h1>
|
||||||
|
<% if user_signed_in? %>
|
||||||
|
<p class="current-user">
|
||||||
|
Signed in as <strong><%= current_user.cn %>@kosmos.org</strong>.
|
||||||
|
<%= link_to "Log out", destroy_user_session_path, method: :delete %>
|
||||||
|
</p>
|
||||||
|
<% end %>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<% flash.each do |type, msg| %>
|
||||||
|
<div class="flash-msg <%= type %>">
|
||||||
|
<p><%= msg %></p>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<main>
|
||||||
|
<%= yield %>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -1,2 +1,2 @@
|
|||||||
<h2>Access forbidden</h2>
|
<h2>Access forbidden</h2>
|
||||||
<p>Not with those shoes, buddy.</p>
|
<p>Sorry, you're not allowed to access this page.</p>
|
||||||
|
0
app/views/shared/status_unauthorized.html.erb
Normal file
0
app/views/shared/status_unauthorized.html.erb
Normal file
12
app/views/signup/index.html.erb
Normal file
12
app/views/signup/index.html.erb
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<h2>Welcome</h2>
|
||||||
|
<p>
|
||||||
|
Hey there! You were invited to sign up for a Kosmos account by
|
||||||
|
<strong><%= @invited_by_name %></strong>.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
This invitation can only be used once, and sign-up is currently only possible
|
||||||
|
by invitation. Seems like you have good friends!
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<%= link_to "Get started", signup_path, class: "next-step" %>
|
||||||
|
</p>
|
@ -4,10 +4,12 @@ Rails.application.routes.draw do
|
|||||||
get 'welcome', to: 'welcome#index'
|
get 'welcome', to: 'welcome#index'
|
||||||
get 'check_your_email', to: 'welcome#check_your_email'
|
get 'check_your_email', to: 'welcome#check_your_email'
|
||||||
|
|
||||||
|
get 'signup', to: 'signup#index'
|
||||||
|
|
||||||
get 'settings', to: 'settings#index'
|
get 'settings', to: 'settings#index'
|
||||||
post 'settings_reset_password', to: 'settings#reset_password'
|
post 'settings_reset_password', to: 'settings#reset_password'
|
||||||
|
|
||||||
resources :invitations, only: ['index', 'create', 'destroy']
|
resources :invitations, only: ['index', 'show', 'create', 'destroy']
|
||||||
|
|
||||||
namespace :admin do
|
namespace :admin do
|
||||||
root to: 'dashboard#index'
|
root to: 'dashboard#index'
|
||||||
|
7
spec/factories/invitations.rb
Normal file
7
spec/factories/invitations.rb
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
FactoryBot.define do
|
||||||
|
factory :invitation do
|
||||||
|
id { 1 }
|
||||||
|
token { "abcdef123456" }
|
||||||
|
user
|
||||||
|
end
|
||||||
|
end
|
39
spec/features/signup_spec.rb
Normal file
39
spec/features/signup_spec.rb
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
require "rails_helper"
|
||||||
|
|
||||||
|
RSpec.describe "Signup", type: :feature do
|
||||||
|
let(:user) { create :user }
|
||||||
|
|
||||||
|
before do
|
||||||
|
@unused_invitation = Invitation.create(user: user)
|
||||||
|
@used_invitation = Invitation.create(user: user)
|
||||||
|
@used_invitation.update_attribute :used_at, DateTime.now - 1.day
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario "Follow link for non-existing invitation" do
|
||||||
|
visit invitation_url(id: "123")
|
||||||
|
|
||||||
|
within ".flash-msg.alert" do
|
||||||
|
expect(page).to have_content("doesn't exist")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario "Follow link for used invitation" do
|
||||||
|
visit invitation_url(id: @used_invitation.token)
|
||||||
|
|
||||||
|
within ".flash-msg.alert" do
|
||||||
|
expect(page).to have_content("has already been used")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario "Follow link for unused invitation" do
|
||||||
|
visit invitation_url(id: @unused_invitation.token)
|
||||||
|
|
||||||
|
expect(current_url).to eq(signup_url)
|
||||||
|
expect(page).to have_content("Welcome")
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario "Successful signup" do
|
||||||
|
visit invitation_url(id: @unused_invitation.token)
|
||||||
|
click_link "Get started"
|
||||||
|
end
|
||||||
|
end
|
15
spec/helpers/signup_helper_spec.rb
Normal file
15
spec/helpers/signup_helper_spec.rb
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
# Specs in this file have access to a helper object that includes
|
||||||
|
# the SignupHelper. For example:
|
||||||
|
#
|
||||||
|
# describe SignupHelper do
|
||||||
|
# describe "string concat" do
|
||||||
|
# it "concats two strings with spaces" do
|
||||||
|
# expect(helper.concat_strings("this","that")).to eq("this that")
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
RSpec.describe SignupHelper, type: :helper do
|
||||||
|
pending "add some examples to (or delete) #{__FILE__}"
|
||||||
|
end
|
@ -20,4 +20,12 @@ RSpec.describe User, type: :model do
|
|||||||
expect(user.is_admin?).to be false
|
expect(user.is_admin?).to be false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "#address" do
|
||||||
|
let(:user) { build :user, cn: "jimmy", ou: "kosmos.org" }
|
||||||
|
|
||||||
|
it "returns the user address" do
|
||||||
|
expect(user.address).to eq("jimmy@kosmos.org")
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
14
spec/requests/signup_request_spec.rb
Normal file
14
spec/requests/signup_request_spec.rb
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
RSpec.describe "Signups", type: :request do
|
||||||
|
|
||||||
|
describe "GET /index" do
|
||||||
|
context "without invitation" do
|
||||||
|
it "returns http unauthorized" do
|
||||||
|
get "/signup"
|
||||||
|
expect(response).to have_http_status(:unauthorized)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
Loading…
x
Reference in New Issue
Block a user