Remove previous login impl
parent
45c1de59b6
commit
2c91357182
@ -1,27 +0,0 @@
|
||||
class LoginsController < ApplicationController
|
||||
|
||||
def new; end
|
||||
|
||||
def create
|
||||
email = params[:email].strip
|
||||
|
||||
if login_service.login(email)
|
||||
redirect_to sent_login_path, flash: { email_recipient: email }
|
||||
else
|
||||
@invalid_email = true
|
||||
render :new
|
||||
end
|
||||
end
|
||||
|
||||
def sent
|
||||
@email_recipient = flash[:email_recipient]
|
||||
redirect_to new_login_path unless @email_recipient
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def login_service
|
||||
EmailLoginService.new
|
||||
end
|
||||
|
||||
end
|
@ -1,44 +1,8 @@
|
||||
class SessionsController < ApplicationController
|
||||
|
||||
def new
|
||||
end
|
||||
|
||||
def create
|
||||
user = login_service.validate(params[:token].to_s.strip)
|
||||
|
||||
if user
|
||||
self.current_user = user
|
||||
redirect_to_profile(user)
|
||||
else
|
||||
render :error
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
self.current_user = nil
|
||||
redirect_to root_path, notice: "See you later!"
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def login_service
|
||||
EmailLoginService.new
|
||||
end
|
||||
|
||||
def redirect_to_profile(user)
|
||||
if user.username
|
||||
redirect_back_or_to profile_path(user), notice: login_notice(user)
|
||||
else
|
||||
redirect_to new_username_path, notice: login_notice(user)
|
||||
end
|
||||
end
|
||||
|
||||
def login_notice(user)
|
||||
if user.first_login?
|
||||
"Welcome to asciinema!"
|
||||
else
|
||||
"Welcome back!"
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -1,14 +0,0 @@
|
||||
class Notifications < ActionMailer::Base
|
||||
default from: CFG.smtp_from_address
|
||||
|
||||
def self.delay_login_request(user_id, token)
|
||||
delay.login_request(user_id, token)
|
||||
end
|
||||
|
||||
def login_request(user_id, token)
|
||||
user = User.find(user_id)
|
||||
@login_url = login_token_url(token)
|
||||
|
||||
mail to: user.email
|
||||
end
|
||||
end
|
@ -1,21 +0,0 @@
|
||||
class EmailLoginService
|
||||
|
||||
def login(email)
|
||||
user = User.for_email!(email)
|
||||
expiring_token = ExpiringToken.create_for_user(user)
|
||||
Notifications.delay_login_request(expiring_token.user_id, expiring_token.token)
|
||||
true
|
||||
rescue User::InvalidEmailError
|
||||
false
|
||||
end
|
||||
|
||||
def validate(token)
|
||||
expiring_token = ExpiringToken.active_for_token(token)
|
||||
|
||||
if expiring_token
|
||||
expiring_token.use!
|
||||
expiring_token.user
|
||||
end
|
||||
end
|
||||
|
||||
end
|
@ -1,33 +0,0 @@
|
||||
.container
|
||||
.row
|
||||
.col-md-6
|
||||
h1
|
||||
span class="glyphicon glyphicon-user"
|
||||
| Log in
|
||||
|
||||
br
|
||||
|
||||
p Log in to asciinema.org using your email address:
|
||||
|
||||
= form_tag login_path, class: "form-inline login-form" do
|
||||
.form-group
|
||||
input.form-control.email name="email" type="email" placeholder="Enter email" data-behavior="focus"
|
||||
button.btn.btn-primary type="submit" Log in
|
||||
|
||||
- if @invalid_email
|
||||
br
|
||||
p.text-danger This email address doesn't seem to be correct.
|
||||
|
||||
.col-md-6
|
||||
h1
|
||||
span class="glyphicon glyphicon-info-sign"
|
||||
| First time here?
|
||||
|
||||
br
|
||||
|
||||
p
|
||||
| asciinema.org uses email-based, passwordless login process.
|
||||
Whether you're here for the first time or you're coming back,
|
||||
just enter your email address and you'll get sent a login link.
|
||||
If you're doing this for the first time then your user account will
|
||||
automatically get created.
|
@ -1,14 +0,0 @@
|
||||
.container
|
||||
.row
|
||||
.col-md-12
|
||||
h1 You're almost there!
|
||||
|
||||
br
|
||||
|
||||
p
|
||||
| We sent a login link to
|
||||
strong = @email_recipient
|
||||
' . Please click on the link to login to your account.
|
||||
' The link is valid for next 15 minutes.
|
||||
|
||||
p If it doesn't arrive, check your spam folder, or #{link_to 'enter your email again', new_login_path} to get another login link.
|
@ -1,7 +0,0 @@
|
||||
Hello,
|
||||
|
||||
Click the following link to log in to asciinema.org:
|
||||
|
||||
<%= @login_url %>
|
||||
|
||||
If you did not initiate this request, just ignore this email. The request will expire shortly.
|
@ -1,15 +0,0 @@
|
||||
.container
|
||||
.row
|
||||
.col-md-12
|
||||
h1 Invalid login link
|
||||
|
||||
br
|
||||
|
||||
p Your login link is either invalid or has expired.
|
||||
|
||||
p
|
||||
' Login links are valid for 15 minutes. If you think yours might have expired then
|
||||
a href=new_login_path request a new login link
|
||||
| .
|
||||
|
||||
p If you're copy-pasting the link check if the link hasn't been corrupted by your email client's message formatting.
|
@ -1,13 +0,0 @@
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<h1>Welcome.</h1>
|
||||
<br>
|
||||
<p>Click the button and you're in!</p>
|
||||
<br>
|
||||
<%= form_tag method: :post do %>
|
||||
<input type="submit" value="Log in" class="btn btn-primary">
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -1,65 +0,0 @@
|
||||
require 'rails_helper'
|
||||
|
||||
describe LoginsController do
|
||||
|
||||
describe "#new" do
|
||||
subject { get :new }
|
||||
|
||||
it "renders 'new' template" do
|
||||
should render_template('new')
|
||||
end
|
||||
end
|
||||
|
||||
describe "#create" do
|
||||
subject { post :create, email: "foo@example.com" }
|
||||
|
||||
let(:login_service) { double(:login_service) }
|
||||
|
||||
before do
|
||||
allow(controller).to receive(:login_service) { login_service }
|
||||
allow(login_service).to receive(:login).with("foo@example.com") { login_success }
|
||||
end
|
||||
|
||||
context "when login succeeds" do
|
||||
let(:login_success) { true }
|
||||
|
||||
it "sets email_recipient in flash" do
|
||||
subject
|
||||
expect(flash[:email_recipient]).to eq("foo@example.com")
|
||||
end
|
||||
|
||||
it "redirects to 'sent' page" do
|
||||
should redirect_to(sent_login_path)
|
||||
end
|
||||
end
|
||||
|
||||
context "when login fails" do
|
||||
let(:login_success) { false }
|
||||
|
||||
it "renders 'new' template" do
|
||||
should render_template('new')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#sent" do
|
||||
subject { get :sent, {}, {}, { email_recipient: email_recipient } }
|
||||
|
||||
context "when email_recipient is set in flash" do
|
||||
let(:email_recipient) { "foo@example.com" }
|
||||
|
||||
it "renders 'sent' template" do
|
||||
should render_template('sent')
|
||||
end
|
||||
end
|
||||
|
||||
context "when email_recipient is not set in flash" do
|
||||
let(:email_recipient) { nil }
|
||||
|
||||
it "redirects to login page" do
|
||||
should redirect_to(new_login_path)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
@ -1,38 +0,0 @@
|
||||
require 'rails_helper'
|
||||
|
||||
feature "Recorder tokens management" do
|
||||
|
||||
let!(:user) { create(:user) }
|
||||
|
||||
scenario 'Listing tokens when user has none' do
|
||||
login_as user
|
||||
visit edit_user_path
|
||||
|
||||
expect(page).to have_content('asciinema auth')
|
||||
end
|
||||
|
||||
scenario 'Listing tokens when user has some' do
|
||||
api_token = create(:api_token, user: user)
|
||||
|
||||
login_as user
|
||||
visit edit_user_path
|
||||
|
||||
expect(page).to have_content(api_token.token)
|
||||
expect(page).to have_link('Revoke')
|
||||
expect(page).to have_no_content('asciinema auth')
|
||||
end
|
||||
|
||||
scenario 'Revoking a token' do
|
||||
api_token = create(:api_token, user: user)
|
||||
|
||||
login_as user
|
||||
visit edit_user_path
|
||||
|
||||
click_on "Revoke"
|
||||
|
||||
expect(page).to have_content(api_token.token)
|
||||
expect(page).to have_no_link('Revoke')
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -1,20 +0,0 @@
|
||||
require "rails_helper"
|
||||
|
||||
RSpec.describe Notifications, :type => :mailer do
|
||||
describe "login_request" do
|
||||
let(:mail) { Notifications.login_request(user.id, "the-to-ken") }
|
||||
let(:user) { create(:user, email: "foo@example.com") }
|
||||
|
||||
it "renders the headers" do
|
||||
expect(mail.subject).to eq("Login request")
|
||||
expect(mail.to).to eq(["foo@example.com"])
|
||||
expect(mail.from).to eq(["hello@localhost"])
|
||||
end
|
||||
|
||||
it "renders the body" do
|
||||
expect(mail.body.encoded).to match("Click")
|
||||
expect(mail.body.encoded).to match(login_token_path("the-to-ken"))
|
||||
end
|
||||
end
|
||||
|
||||
end
|
@ -1,99 +0,0 @@
|
||||
require 'rails_helper'
|
||||
|
||||
describe EmailLoginService do
|
||||
|
||||
let(:creator) { described_class.new }
|
||||
|
||||
describe "#login" do
|
||||
subject { creator.login(email) }
|
||||
|
||||
let(:email) { "me@example.com" }
|
||||
|
||||
context "when given email is blank" do
|
||||
let(:email) { nil }
|
||||
|
||||
it "returns false" do
|
||||
expect(subject).to be(false)
|
||||
end
|
||||
end
|
||||
|
||||
context "when given email is invalid" do
|
||||
let(:email) { "oops" }
|
||||
|
||||
it "returns false" do
|
||||
expect(subject).to be(false)
|
||||
end
|
||||
end
|
||||
|
||||
context "when there's no user with given email" do
|
||||
it "creates a user with given email" do
|
||||
expect { subject }.to change(User, :count).by(1)
|
||||
expect(User.last.email).to eq("me@example.com")
|
||||
end
|
||||
|
||||
it "creates an expiring token for new user" do
|
||||
expect { subject }.to change(ExpiringToken, :count).by(1)
|
||||
expect(ExpiringToken.last.user).to eq(User.last)
|
||||
end
|
||||
|
||||
it "sends login email" do
|
||||
expect(Notifications).to receive(:delay_login_request)
|
||||
subject
|
||||
end
|
||||
|
||||
it "returns true" do
|
||||
expect(subject).to be(true)
|
||||
end
|
||||
end
|
||||
|
||||
context "when there's a user with given email" do
|
||||
let!(:user) { create(:user, email: "me@example.com") }
|
||||
|
||||
it "creates an expiring token this user" do
|
||||
expect { subject }.to change(ExpiringToken, :count).by(1)
|
||||
expect(ExpiringToken.last.user).to eq(user)
|
||||
end
|
||||
|
||||
it "sends login email" do
|
||||
expect(Notifications).to receive(:delay_login_request)
|
||||
subject
|
||||
end
|
||||
|
||||
it "returns true" do
|
||||
expect(subject).to be(true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#validate" do
|
||||
subject { creator.validate(token) }
|
||||
|
||||
let(:token) { "the-to-ken" }
|
||||
|
||||
context "when given token is valid" do
|
||||
let!(:expiring_token) { create(:expiring_token, user: user, token: token) }
|
||||
let(:user) { create(:user) }
|
||||
|
||||
it "marks token as used" do
|
||||
now = Time.now
|
||||
|
||||
Timecop.freeze(now) do
|
||||
subject
|
||||
end
|
||||
|
||||
expect(expiring_token.reload.used_at.to_i).to eq(now.to_i)
|
||||
end
|
||||
|
||||
it "returns user associated with the token" do
|
||||
expect(subject).to eq(user)
|
||||
end
|
||||
end
|
||||
|
||||
context "when given token is invalid" do
|
||||
it "returns nil" do
|
||||
expect(subject).to be(nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
Loading…
Reference in New Issue