login con imap

This commit is contained in:
f 2018-01-29 15:09:30 -03:00
parent 3bc2bfed3c
commit 6a1240308d
No known key found for this signature in database
GPG key ID: F3FDAB97B5F9F7E7
18 changed files with 290 additions and 70 deletions

12
Gemfile
View file

@ -29,9 +29,14 @@ gem 'jbuilder', '~> 2.5'
# Use Capistrano for deployment
# gem 'capistrano-rails', group: :development
gem 'email_address'
gem 'rails_warden'
gem 'haml-rails'
gem 'bootstrap', '~> 4.0.0.beta3'
gem 'jekyll'
group :development, :test do
# Call 'byebug' anywhere in the code to stop execution and get a debugger console
gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
gem 'pry'
# Adds support for Capybara system testing and selenium driver
gem 'capybara', '~> 2.13'
gem 'selenium-webdriver'
@ -45,6 +50,3 @@ group :development do
gem 'spring'
gem 'spring-watcher-listen', '~> 2.0.0'
end
# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]

View file

@ -41,9 +41,14 @@ GEM
addressable (2.5.2)
public_suffix (>= 2.0.2, < 4.0)
arel (8.0.0)
autoprefixer-rails (7.2.4)
execjs
bindex (0.5.0)
bootstrap (4.0.0.beta3)
autoprefixer-rails (>= 6.0.3)
popper_js (>= 1.12.3, < 2)
sass (>= 3.5.2)
builder (3.2.3)
byebug (9.1.0)
capybara (2.16.1)
addressable
mini_mime (>= 0.1.3)
@ -53,18 +58,63 @@ GEM
xpath (~> 2.0)
childprocess (0.8.0)
ffi (~> 1.0, >= 1.0.11)
coderay (1.1.2)
colorator (1.1.0)
concurrent-ruby (1.0.5)
crass (1.0.3)
em-websocket (0.5.1)
eventmachine (>= 0.12.9)
http_parser.rb (~> 0.6.0)
email_address (0.1.6)
netaddr
simpleidn
erubi (1.7.0)
erubis (2.7.0)
eventmachine (1.2.5)
execjs (2.7.0)
ffi (1.9.18)
forwardable-extended (2.6.0)
globalid (0.4.1)
activesupport (>= 4.2.0)
haml (5.0.4)
temple (>= 0.8.0)
tilt
haml-rails (1.0.0)
actionpack (>= 4.0.1)
activesupport (>= 4.0.1)
haml (>= 4.0.6, < 6.0)
html2haml (>= 1.0.1)
railties (>= 4.0.1)
html2haml (2.2.0)
erubis (~> 2.7.0)
haml (>= 4.0, < 6)
nokogiri (>= 1.6.0)
ruby_parser (~> 3.5)
http_parser.rb (0.6.0)
i18n (0.9.1)
concurrent-ruby (~> 1.0)
jbuilder (2.7.0)
activesupport (>= 4.2.0)
multi_json (>= 1.2)
jekyll (3.7.0)
addressable (~> 2.4)
colorator (~> 1.0)
em-websocket (~> 0.5)
i18n (~> 0.7)
jekyll-sass-converter (~> 1.0)
jekyll-watch (~> 2.0)
kramdown (~> 1.14)
liquid (~> 4.0)
mercenary (~> 0.3.3)
pathutil (~> 0.9)
rouge (>= 1.7, < 4)
safe_yaml (~> 1.0)
jekyll-sass-converter (1.5.1)
sass (~> 3.4)
jekyll-watch (2.0.0)
listen (~> 3.0)
kramdown (1.16.2)
liquid (4.0.0)
listen (3.1.5)
rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7)
@ -74,14 +124,22 @@ GEM
nokogiri (>= 1.5.9)
mail (2.7.0)
mini_mime (>= 0.1.1)
mercenary (0.3.6)
method_source (0.9.0)
mini_mime (1.0.0)
mini_portile2 (2.3.0)
minitest (5.10.3)
multi_json (1.12.2)
netaddr (1.5.1)
nio4r (2.1.0)
nokogiri (1.8.1)
mini_portile2 (~> 2.3.0)
pathutil (0.16.1)
forwardable-extended (~> 2.6)
popper_js (1.12.9)
pry (0.11.3)
coderay (~> 1.1.0)
method_source (~> 0.9.0)
public_suffix (3.0.1)
puma (3.11.0)
rack (2.0.3)
@ -104,6 +162,8 @@ GEM
nokogiri (>= 1.6)
rails-html-sanitizer (1.0.3)
loofah (~> 2.0)
rails_warden (0.5.8)
warden (>= 1.0.0)
railties (5.1.4)
actionpack (= 5.1.4)
activesupport (= 5.1.4)
@ -114,8 +174,12 @@ GEM
rb-fsevent (0.10.2)
rb-inotify (0.9.10)
ffi (>= 0.5.0, < 2)
rouge (3.1.0)
ruby_dep (1.5.0)
ruby_parser (3.10.1)
sexp_processor (~> 4.9)
rubyzip (1.2.1)
safe_yaml (1.0.4)
sass (3.5.4)
sass-listen (~> 4.0.0)
sass-listen (4.0.0)
@ -130,6 +194,8 @@ GEM
selenium-webdriver (3.8.0)
childprocess (~> 0.5)
rubyzip (~> 1.0)
sexp_processor (4.10.0)
simpleidn (0.0.9)
spring (2.0.2)
activesupport (>= 4.2)
spring-watcher-listen (2.0.1)
@ -143,6 +209,7 @@ GEM
activesupport (>= 4.0)
sprockets (>= 3.0.0)
sqlite3 (1.3.13)
temple (0.8.0)
thor (0.20.0)
thread_safe (0.3.6)
tilt (2.0.8)
@ -153,6 +220,8 @@ GEM
thread_safe (~> 0.1)
uglifier (4.1.2)
execjs (>= 0.3.0, < 3)
warden (1.2.7)
rack (>= 1.0)
web-console (3.5.1)
actionview (>= 5.0)
activemodel (>= 5.0)
@ -168,19 +237,23 @@ PLATFORMS
ruby
DEPENDENCIES
byebug
bootstrap (~> 4.0.0.beta3)
capybara (~> 2.13)
email_address
haml-rails
jbuilder (~> 2.5)
jekyll
listen (>= 3.0.5, < 3.2)
pry
puma (~> 3.7)
rails (~> 5.1.4)
rails_warden
sass-rails (~> 5.0)
selenium-webdriver
spring
spring-watcher-listen (~> 2.0.0)
sqlite3
turbolinks (~> 5)
tzinfo-data
uglifier (>= 1.3.0)
web-console (>= 3.3.0)

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

View file

@ -1,15 +0,0 @@
/*
* This is a manifest file that'll be compiled into application.css, which will include all the files
* listed below.
*
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, or any plugin's
* vendor/assets/stylesheets directory can be referenced here using a relative path.
*
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
* compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
* files in this directory. Styles in this file should be added after the last require_* statement.
* It is generally better to create a new file per style scope.
*
*= require_tree .
*= require_self
*/

View file

@ -0,0 +1,38 @@
@import "bootstrap";
$footer-height: 60px;
.background-cover {
background: image-url("background.jpg") no-repeat center center fixed;
-webkit-background-size: cover;
-moz-background-size: cover;
-o-background-size: cover;
background-size: cover;
}
.full-height {
height: calc(100vh - #{$footer-height});
}
html {
position: relative;
min-height: 100%;
}
body {
margin-bottom: $footer-height;
}
.footer {
position: absolute;
bottom: 0;
width: 100%;
height: $footer-height;
line-height: $footer-height;
text-align: center;
}
textarea.post-content {
min-height: 80vh;
font-family: monospace;
}

View file

@ -1,3 +1,7 @@
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
def index
redirect_to sites_path
end
end

View file

@ -0,0 +1,21 @@
class LoginController < ApplicationController
protect_from_forgery with: :exception
def index
redirect_to new_login_path
end
def new
@has_cover = true
render 'login/new'
end
def create
authenticate
if authenticated?
# TODO enviar a la URL de donde vinimos
redirect_to sites_path
end
end
end

View file

@ -0,0 +1,6 @@
class SitesController < ApplicationController
before_action :authenticate!
def index
end
end

18
app/models/usuaria.rb Normal file
View file

@ -0,0 +1,18 @@
# Un modelo para la usuaria que no se corresponde con una base de datos
# porque vienen de IMAP
#
# Una usuaria puede tener muchos sitios, pero no podemos establecer
# relaciones estilo has_many porque no estamos usando ActiveRecord, que
# requeriría que guardemos todo en una base de datos.
class Usuaria < OpenStruct
# Crear una usuaria ad hoc, porque la base de datos de usuarias está
# en otro lado.
def self.find(username)
Usuaria.new(username: username)
end
# Obtener todos los sitios de esta usuaria
def sites
@sites ||= Site.all_for(self)
end
end

View file

@ -1,14 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title>Sutty</title>
<%= csrf_meta_tags %>
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
</head>
<body>
<%= yield %>
</body>
</html>

View file

@ -0,0 +1,15 @@
!!!
%html
%head
%meta{content: "text/html; charset=UTF-8", 'http-equiv': "Content-Type"}/
%title Sutty
= csrf_meta_tags
= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload'
%body{class: @has_cover ? 'background-cover' : ''}
.container-fluid
= yield
%footer.footer
%p{style: @has_cover ? 'color: white' : ''}
%a{href: 'https://0xacab.org/itacate-kefir/sutty'} Sutty
es desarrollada por
%a{href: 'https://kefir.red'} Kéfir

14
app/views/login/new.haml Normal file
View file

@ -0,0 +1,14 @@
.row.align-items-center.justify-content-center.full-height
.col-md-6.align-self-center
- if flash[:error]
.alert.alert-danger{role: 'alert'}
= flash[:error]
= form_tag login_path do
.form-group
%input{type: 'email', name: 'username', class: 'form-control', placeholder: t('login.email')}
.form-group
%input{type: 'password', name: 'password', class: 'form-control', placeholder: t('login.password')}
.form-group
%input{type: 'submit', value: t('login.submit', class: 'btn btn-lg btn-primary btn-block'}

View file

@ -0,0 +1 @@
%h1= t('sites.title')

View file

@ -0,0 +1,18 @@
require 'warden/imap'
Rails.configuration.middleware.use RailsWarden::Manager do |manager|
manager.default_strategies :imap
manager.failure_app = -> (env) { LoginController.action(:new).call(env) }
end
class Warden::SessionSerializer
def serialize(record)
[record.username]
end
def deserialize(keys)
Usuaria.find(keys.first)
end
end
Warden::Strategies.add(:imap, Warden::IMAP::Strategy)

View file

@ -1,33 +1,7 @@
# Files in the config/locales directory are used for internationalization
# and are automatically loaded by Rails. If you want to use locales other
# than English, add the necessary files in this directory.
#
# To use the locales, use `I18n.t`:
#
# I18n.t 'hello'
#
# In views, this is aliased to just `t`:
#
# <%= t('hello') %>
#
# To use a different locale, set it with `I18n.locale`:
#
# I18n.locale = :es
#
# This would use the information in config/locales/es.yml.
#
# The following keys must be escaped otherwise they will not be retrieved by
# the default I18n backend:
#
# true, false, on, off, yes, no
#
# Instead, surround them with single quotes.
#
# en:
# 'true': 'foo'
#
# To learn more, please read the Rails Internationalization guide
# available at http://guides.rubyonrails.org/i18n.html.
en:
hello: "Hello world"
login:
email: 'E-mail'
password: 'Password'
submit: 'Log in'
sites:
title: 'Sites'

7
config/locales/es.yml Normal file
View file

@ -0,0 +1,7 @@
es:
login:
email: 'Dirección de correo'
password: 'Contraseña'
submit: 'Ingresar'
sites:
title: 'Sitios'

View file

@ -1,3 +1,10 @@
Rails.application.routes.draw do
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
root 'application#index'
get 'login/new', to: 'login#new'
post 'login', to: 'login#create'
resources :sites do
resources :posts
end
end

51
lib/warden/imap.rb Normal file
View file

@ -0,0 +1,51 @@
# frozen_string_literal: true
require 'net/imap'
require 'warden'
require 'email_address'
module Warden
module IMAP
# Una estrategia de autenticación por IMAP
class Strategy < Warden::Strategies::Base
def valid?
return false unless params.include? 'username'
return false unless params.include? 'password'
@email = EmailAddress.new(params['username'])
@email.valid?
end
def authenticate!
imap_connect
imap_login
end
private
def imap_connect
# No vamos a enviar la contraseña en texto plano a ningún lado
@imap = Net::IMAP.new(@email.host_name, ssl: true)
# Errores más comunes según
# https://ruby-doc.org/stdlib-2.0.0/libdoc/net/imap/rdoc/Net/IMAP.html
rescue Errno::ECONNREFUSED, Errno::ETIMEDOUT, Errno::ENETUNREACH,
SocketError, Net::IMAP::ByeResponseError => e
@imap.disconnect
fail! e.to_s
end
def imap_login
@imap.login(@email.normal, params['password'])
@imap.disconnect
success! Usuaria.find(@email.normal)
rescue EOFError => e
@imap.disconnect
fail! e.to_s
end
end
end
end