Skip to content
This repository has been archived by the owner on Dec 9, 2020. It is now read-only.

Commit

Permalink
Initial commit of nopassword project
Browse files Browse the repository at this point in the history
  • Loading branch information
alsmola committed Apr 23, 2012
0 parents commit 7863b2b
Show file tree
Hide file tree
Showing 58 changed files with 996 additions and 0 deletions.
38 changes: 38 additions & 0 deletions Gemfile
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,38 @@
source 'https://rubygems.org'

gem 'rails', '3.2.0'

# Bundle edge Rails instead:
# gem 'rails', :git => 'git://github.com/rails/rails.git'

gem 'sqlite3'


# Gems used only for assets and not required
# in production environments by default.
group :assets do
gem 'sass-rails', '~> 3.2.3'
gem 'coffee-rails', '~> 3.2.1'

# See https://github.com/sstephenson/execjs#readme for more supported runtimes
# gem 'therubyracer'

gem 'uglifier', '>= 1.0.3'
end

gem 'jquery-rails'

gem 'bcrypt-ruby', '~> 3.0.0'
gem 'browser'
gem 'less-rails-bootstrap'
# To use Jbuilder templates for JSON
# gem 'jbuilder'

# Use unicorn as the web server
# gem 'unicorn'

# Deploy with Capistrano
# gem 'capistrano'

# To use debugger
# gem 'ruby-debug19', :require => 'ruby-debug'
128 changes: 128 additions & 0 deletions Gemfile.lock
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,128 @@
GEM
remote: https://rubygems.org/
specs:
actionmailer (3.2.0)
actionpack (= 3.2.0)
mail (~> 2.4.0)
actionpack (3.2.0)
activemodel (= 3.2.0)
activesupport (= 3.2.0)
builder (~> 3.0.0)
erubis (~> 2.7.0)
journey (~> 1.0.0)
rack (~> 1.4.0)
rack-cache (~> 1.1)
rack-test (~> 0.6.1)
sprockets (~> 2.1.2)
activemodel (3.2.0)
activesupport (= 3.2.0)
builder (~> 3.0.0)
activerecord (3.2.0)
activemodel (= 3.2.0)
activesupport (= 3.2.0)
arel (~> 3.0.0)
tzinfo (~> 0.3.29)
activeresource (3.2.0)
activemodel (= 3.2.0)
activesupport (= 3.2.0)
activesupport (3.2.0)
i18n (~> 0.6)
multi_json (~> 1.0)
arel (3.0.2)
bcrypt-ruby (3.0.1)
browser (0.1.3)
builder (3.0.0)
coffee-rails (3.2.2)
coffee-script (>= 2.2.0)
railties (~> 3.2.0)
coffee-script (2.2.0)
coffee-script-source
execjs
coffee-script-source (1.3.1)
commonjs (0.2.5)
erubis (2.7.0)
execjs (1.3.0)
multi_json (~> 1.0)
hike (1.2.1)
i18n (0.6.0)
journey (1.0.3)
jquery-rails (2.0.2)
railties (>= 3.2.0, < 5.0)
thor (~> 0.14)
json (1.6.6)
less (2.1.0)
commonjs (~> 0.2.0)
therubyracer (~> 0.10.0)
less-rails (2.2.1)
actionpack (>= 3.1)
less (~> 2.1.0)
less-rails-bootstrap (2.0.10)
less-rails (~> 2.2.0)
libv8 (3.3.10.4)
mail (2.4.4)
i18n (>= 0.4.0)
mime-types (~> 1.16)
treetop (~> 1.4.8)
mime-types (1.18)
multi_json (1.3.2)
polyglot (0.3.3)
rack (1.4.1)
rack-cache (1.2)
rack (>= 0.4)
rack-ssl (1.3.2)
rack
rack-test (0.6.1)
rack (>= 1.0)
rails (3.2.0)
actionmailer (= 3.2.0)
actionpack (= 3.2.0)
activerecord (= 3.2.0)
activeresource (= 3.2.0)
activesupport (= 3.2.0)
bundler (~> 1.0)
railties (= 3.2.0)
railties (3.2.0)
actionpack (= 3.2.0)
activesupport (= 3.2.0)
rack-ssl (~> 1.3.2)
rake (>= 0.8.7)
rdoc (~> 3.4)
thor (~> 0.14.6)
rake (0.9.2.2)
rdoc (3.12)
json (~> 1.4)
sass (3.1.16)
sass-rails (3.2.5)
railties (~> 3.2.0)
sass (>= 3.1.10)
tilt (~> 1.3)
sprockets (2.1.2)
hike (~> 1.2)
rack (~> 1.0)
tilt (~> 1.1, != 1.3.0)
sqlite3 (1.3.6)
therubyracer (0.10.1)
libv8 (~> 3.3.10)
thor (0.14.6)
tilt (1.3.3)
treetop (1.4.10)
polyglot
polyglot (>= 0.3.1)
tzinfo (0.3.33)
uglifier (1.2.4)
execjs (>= 0.3.0)
multi_json (>= 1.0.2)

PLATFORMS
ruby

DEPENDENCIES
bcrypt-ruby (~> 3.0.0)
browser
coffee-rails (~> 3.2.1)
jquery-rails
less-rails-bootstrap
rails (= 3.2.0)
sass-rails (~> 3.2.3)
sqlite3
uglifier (>= 1.0.3)
4 changes: 4 additions & 0 deletions README.md
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,4 @@
NoPassword is a simple authentication and session engine that removes
the need for passwords. Instead, it uses tokens sent to an email
address, similar to most forgot password functionality. These tokens
created long-lived sessions that can be tracked and revoked easily.
7 changes: 7 additions & 0 deletions Rakefile
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/usr/bin/env rake
# Add your own tasks in files placed in lib/tasks ending in .rake,
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.

require File.expand_path('../config/application', __FILE__)

Nopassword::Application.load_tasks
Binary file added app/assets/images/rails.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 16 additions & 0 deletions app/assets/javascripts/application.js
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,16 @@
// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// the compiled file.
//
// WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
// GO AFTER THE REQUIRES BELOW.
//
//= require jquery
//= require jquery_ujs
//= require_tree .
//= require twitter/bootstrap
8 changes: 8 additions & 0 deletions app/assets/javascripts/main.js
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,8 @@
$(document).ready(function(){
$('.revoke').click(function(e) {
id = $(this).siblings("input").val();
$.post('revoke/' + id, function(data) {
$(this).parent("tr").fadeOut();
});
});
});
13 changes: 13 additions & 0 deletions app/assets/stylesheets/application.css
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,13 @@
/*
* 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, vendor/assets/stylesheets,
* or vendor/assets/stylesheets of plugins, if any, 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 top of the
* compiled file, but it's generally better to create a new file per style scope.
*
*= require_self
*= require_tree .
*/
9 changes: 9 additions & 0 deletions app/assets/stylesheets/main.css.scss
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,9 @@
// Place all the styles related to the Main controller here.
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: http://sass-lang.com/

@import "twitter/bootstrap";

.navbar-inner {
border-radius: 0;
}
3 changes: 3 additions & 0 deletions app/controllers/application_controller.rb
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,3 @@
class ApplicationController < ActionController::Base
protect_from_forgery
end
59 changes: 59 additions & 0 deletions app/controllers/main_controller.rb
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,59 @@
class MainController < ApplicationController

before_filter :check_valid_session

def check_valid_session
session[:login_session] = nil if session[:login_session] && LoginSession.find(session[:login_session]).terminated
end

def send_login_email
email = request[:email]
remote_ip = request.remote_ip
user_agent = request.env["HTTP_USER_AGENT"]
session = LoginSession.new(:email => email, :requesting_ip => remote_ip, :requesting_user_agent => user_agent)
code = session.generate_code
session.save
NoPasswordEmails.login_email(email, session.id, session.created_at, remote_ip, user_agent, code).deliver
flash[:notice] = "We sent an email to %{email}" % { :email => email }
redirect_to '/'
end

def login
id = request[:id]
code = request[:code]
login_session = LoginSession.lookup_code(id, code)
if !login_session
flash[:notice] = "That code sucked."
elsif login_session.activated? || login_session.terminated?
flash[:notice] = "That code is already used."
elsif login_session.expired?
flash[:notice] = "That code is old as shit."
else
session[:login_session] = login_session.id
login_session.activated_at = DateTime.now
login_session.activating_ip = request.remote_ip
login_session.activating_user_agent = request.env["HTTP_USER_AGENT"]
login_session.activated = true
login_session.save
end
redirect_to '/'
end

def logout
login_session = LoginSession.find(session[:login_session])
login_session.terminated_at = DateTime.now
login_session.terminated = true
login_session.save
session[:login_session] = nil
redirect_to '/'
end

def revoke
id = request[:id]
login_session = LoginSession.find(id)
login_session.terminated_at = DateTime.now
login_session.terminated = true
login_session.save
render :json => { :success => :true }
end
end
9 changes: 9 additions & 0 deletions app/helpers/application_helper.rb
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,9 @@
module ApplicationHelper
def friendly_time(time)
time.strftime("%d-%m-%Y %H:%M")
end

def browser_name(ua)
Browser.new(:ua => ua).to_s.split(' ')[0].capitalize
end
end
15 changes: 15 additions & 0 deletions app/helpers/main_helper.rb
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,15 @@
require 'browser'
module MainHelper
def logged_in_user
LoginSession.find(session[:login_session])
end

def other_active_sessions
LoginSession.where("email == :email AND activated == 't' AND terminated == 'f' AND id != :current_id", { :email => logged_in_user.email, :current_id => session[:login_session]})
end

def inactive_sessions
LoginSession.find_all_by_email_and_terminated(logged_in_user.email, true)
end

end
14 changes: 14 additions & 0 deletions app/mailers/no_password_emails.rb
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,14 @@
class NoPasswordEmails < ActionMailer::Base
default :from => 'nopassword@alexsmolen.com',
:return_path => 'nopassword@alexsmolen.com'

def login_email(email, id, time, remote_ip, user_agent, code)
@id = id
@time = time.strftime("%e %b %Y %H:%m%p")
@remote_ip = remote_ip
@user_agent = user_agent
@code = code
mail(:to => email,
:subject => "Login request for nopassword.com")
end
end
20 changes: 20 additions & 0 deletions app/models/login_session.rb
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,20 @@
require 'bcrypt'

class LoginSession < ActiveRecord::Base
EXPIRY = 60 * 60 # 1 hour

def generate_code
code = SecureRandom.hex(32).to_s
self.hashed_code = BCrypt::Password.create(code)
code
end

def self.lookup_code(id, code)
login_session = self.find(id)
BCrypt::Password.new(login_session.hashed_code) == code ? login_session : nil
end

def expired?
DateTime.current.to_i - self.created_at.to_i > EXPIRY
end
end
24 changes: 24 additions & 0 deletions app/views/layouts/application.html.erb
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,24 @@
<!DOCTYPE html>
<html>
<head>
<title>NoPassword</title>
<%= stylesheet_link_tag "application", :media => "all" %>
<%= javascript_include_tag "application" %>
<%= csrf_meta_tags %>
</head>
<body>
<div class="navbar">
<div class="navbar-inner">
<div class="container">
<a class="brand" href="/">NoPassword</a>
</div>
</div>
</div>
<div class="container">
<% if flash[:notice] %>
<p class="notice"><%= flash[:notice] %></p>
<% end %>
<%= yield %>
</div>
</body>
</html>
Loading

0 comments on commit 7863b2b

Please sign in to comment.