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
|
||||
|
||||
def require_user_signed_out
|
||||
if user_signed_in?
|
||||
redirect_to root_path and return
|
||||
end
|
||||
end
|
||||
|
||||
def authorize_admin
|
||||
http_status :forbidden unless current_user.is_admin?
|
||||
end
|
||||
|
@ -1,11 +1,26 @@
|
||||
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
|
||||
def index
|
||||
@invitations = current_user.invitations
|
||||
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
|
||||
def create
|
||||
@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
|
||||
end
|
||||
end
|
||||
|
||||
def address
|
||||
"#{self.cn}@#{self.ou}"
|
||||
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>
|
||||
<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 'check_your_email', to: 'welcome#check_your_email'
|
||||
|
||||
get 'signup', to: 'signup#index'
|
||||
|
||||
get 'settings', to: 'settings#index'
|
||||
post 'settings_reset_password', to: 'settings#reset_password'
|
||||
|
||||
resources :invitations, only: ['index', 'create', 'destroy']
|
||||
resources :invitations, only: ['index', 'show', 'create', 'destroy']
|
||||
|
||||
namespace :admin do
|
||||
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
|
||||
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
|
||||
|
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