commit
3cb1d4e730
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -21,5 +21,7 @@ tmp/
|
|||
|
||||
# Ignore config and database files (passwords)
|
||||
/config/config.yml
|
||||
/config/s3.yml
|
||||
/config/database.yml
|
||||
/config/initializers/secret_token.rb
|
||||
.env
|
1
.ruby-gemset
Normal file
1
.ruby-gemset
Normal file
|
@ -0,0 +1 @@
|
|||
members-hsl
|
1
.ruby-version
Normal file
1
.ruby-version
Normal file
|
@ -0,0 +1 @@
|
|||
ruby-1.9.3-p385
|
35
.rvmrc
35
.rvmrc
|
@ -1,35 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# This is an RVM Project .rvmrc file, used to automatically load the ruby
|
||||
# development environment upon cd'ing into the directory
|
||||
|
||||
# First we specify our desired <ruby>[@<gemset>], the @gemset name is optional,
|
||||
# Only full ruby name is supported here, for short names use:
|
||||
# echo "rvm use 1.8.7" > .rvmrc
|
||||
environment_id="ruby-1.9.3-p385@members-hsl"
|
||||
|
||||
# Uncomment the following lines if you want to verify rvm version per project
|
||||
# rvmrc_rvm_version="1.18.8 (stable)" # 1.10.1 seams as a safe start
|
||||
# eval "$(echo ${rvm_version}.${rvmrc_rvm_version} | awk -F. '{print "[[ "$1*65536+$2*256+$3" -ge "$4*65536+$5*256+$6" ]]"}' )" || {
|
||||
# echo "This .rvmrc file requires at least RVM ${rvmrc_rvm_version}, aborting loading."
|
||||
# return 1
|
||||
# }
|
||||
|
||||
# First we attempt to load the desired environment directly from the environment
|
||||
# file. This is very fast and efficient compared to running through the entire
|
||||
# CLI and selector. If you want feedback on which environment was used then
|
||||
# insert the word 'use' after --create as this triggers verbose mode.
|
||||
if [[ -d "${rvm_path:-$HOME/.rvm}/environments"
|
||||
&& -s "${rvm_path:-$HOME/.rvm}/environments/$environment_id" ]]
|
||||
then
|
||||
\. "${rvm_path:-$HOME/.rvm}/environments/$environment_id"
|
||||
[[ -s "${rvm_path:-$HOME/.rvm}/hooks/after_use" ]] &&
|
||||
\. "${rvm_path:-$HOME/.rvm}/hooks/after_use" || true
|
||||
else
|
||||
# If the environment file has not yet been created, use the RVM CLI to select.
|
||||
rvm --create "$environment_id" || {
|
||||
echo "Failed to create RVM environment '${environment_id}'."
|
||||
return 1
|
||||
}
|
||||
fi
|
||||
|
4
Gemfile
4
Gemfile
|
@ -3,6 +3,7 @@ source 'https://rubygems.org'
|
|||
ruby '1.9.3'
|
||||
|
||||
gem 'rails', '3.2.8'
|
||||
gem 'dotenv-rails'
|
||||
|
||||
# Bundle edge Rails instead:
|
||||
# gem 'rails', :git => 'git://github.com/rails/rails.git'
|
||||
|
@ -46,7 +47,8 @@ gem 'bcrypt-ruby', '~> 3.0.0'
|
|||
# To use debugger
|
||||
#gem 'debugger'
|
||||
|
||||
#gem "paperclip", "~> 3.0"
|
||||
gem "paperclip", "~> 3.0"
|
||||
gem "aws-sdk"
|
||||
gem 'gravtastic'
|
||||
|
||||
gem 'passenger'
|
||||
|
|
23
Gemfile.lock
23
Gemfile.lock
|
@ -29,9 +29,17 @@ GEM
|
|||
i18n (~> 0.6)
|
||||
multi_json (~> 1.0)
|
||||
arel (3.0.2)
|
||||
aws-sdk (1.33.0)
|
||||
json (~> 1.4)
|
||||
nokogiri (>= 1.4.4)
|
||||
uuidtools (~> 2.1)
|
||||
bcrypt-ruby (3.0.1)
|
||||
builder (3.0.4)
|
||||
cancan (1.6.10)
|
||||
climate_control (0.0.3)
|
||||
activesupport (>= 3.0)
|
||||
cocaine (0.5.3)
|
||||
climate_control (>= 0.0.3, < 1.0)
|
||||
coffee-rails (3.2.2)
|
||||
coffee-script (>= 2.2.0)
|
||||
railties (~> 3.2.0)
|
||||
|
@ -45,6 +53,9 @@ GEM
|
|||
orm_adapter (~> 0.1)
|
||||
railties (~> 3.1)
|
||||
warden (~> 1.2.1)
|
||||
dotenv (0.10.0)
|
||||
dotenv-rails (0.10.0)
|
||||
dotenv (= 0.10.0)
|
||||
erubis (2.7.0)
|
||||
execjs (2.0.2)
|
||||
gravtastic (3.2.6)
|
||||
|
@ -61,8 +72,16 @@ GEM
|
|||
mime-types (~> 1.16)
|
||||
treetop (~> 1.4.8)
|
||||
mime-types (1.25)
|
||||
mini_portile (0.5.2)
|
||||
multi_json (1.8.2)
|
||||
nokogiri (1.6.1)
|
||||
mini_portile (~> 0.5.0)
|
||||
orm_adapter (0.4.0)
|
||||
paperclip (3.5.4)
|
||||
activemodel (>= 3.0.0)
|
||||
activesupport (>= 3.0.0)
|
||||
cocaine (~> 0.5.3)
|
||||
mime-types
|
||||
passenger (4.0.19)
|
||||
daemon_controller (>= 1.1.0)
|
||||
rack
|
||||
|
@ -129,6 +148,7 @@ GEM
|
|||
uglifier (2.2.1)
|
||||
execjs (>= 0.3.0)
|
||||
multi_json (~> 1.0, >= 1.0.2)
|
||||
uuidtools (2.1.4)
|
||||
warden (1.2.3)
|
||||
rack (>= 1.0)
|
||||
|
||||
|
@ -136,13 +156,16 @@ PLATFORMS
|
|||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
aws-sdk
|
||||
bcrypt-ruby (~> 3.0.0)
|
||||
cancan
|
||||
coffee-rails (~> 3.2.1)
|
||||
devise
|
||||
dotenv-rails
|
||||
gravtastic
|
||||
jquery-rails
|
||||
json
|
||||
paperclip (~> 3.0)
|
||||
passenger
|
||||
pg
|
||||
rails (= 3.2.8)
|
||||
|
|
15
README.rdoc
15
README.rdoc
|
@ -5,17 +5,18 @@ via Ethernet ( see: https://github.com/zyphlar/Open_Access_Control_Ethernet )
|
|||
|
||||
https://github.com/zyphlar/Open-Source-Access-Control-Web-Interface
|
||||
|
||||
Copyright Will Bradley, 2012-2013
|
||||
Copyright Will Bradley, 2012-2014
|
||||
Distributed under a Creative Commons Attribution 3.0 license http://creativecommons.org/licenses/by/3.0/
|
||||
|
||||
Contributions welcome! Simply send a pull request via Github.
|
||||
|
||||
To use:
|
||||
* Install Imagemagick (for Paperclip / image uploads)
|
||||
* Install arp-scan (for LAN Mac address scanning)
|
||||
* Load into a Rails 3 environment
|
||||
* Copy config/config.yml.example to config/config.yml and edit appropriately
|
||||
* Copy config/database.yml.example to config/database.yml and edit appropriately
|
||||
* Copy env.example to .env and edit appropriately for your Amazon S3 account OR adjust the resource.rb and contract.rb model settings to use different storage for picture attachments (via Paperclip)
|
||||
* Copy config/initializers/secret_token.rb.example to config/config/initializers/secret_token.rb and edit appropriately
|
||||
* Run bundle install, rake db:migrate, etc.
|
||||
* Use the Rails console to create a new User with admin rights
|
||||
* user = User.new
|
||||
* user.password = "foobar"
|
||||
* user.admin = true
|
||||
* user.save
|
||||
* See/edit db/seeds.rb for the initial admin account info.
|
||||
* Run bundle install, rake db:migrate, rake db:seed, etc.
|
||||
|
|
0
app/assets/images/logo.png
Normal file → Executable file
0
app/assets/images/logo.png
Normal file → Executable file
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
0
app/assets/images/nil.png
Normal file → Executable file
0
app/assets/images/nil.png
Normal file → Executable file
Before Width: | Height: | Size: 95 B After Width: | Height: | Size: 95 B |
0
app/assets/javascripts/application.js
Normal file → Executable file
0
app/assets/javascripts/application.js
Normal file → Executable file
0
app/assets/javascripts/certifications.js.coffee
Normal file → Executable file
0
app/assets/javascripts/certifications.js.coffee
Normal file → Executable file
0
app/assets/javascripts/door_logs.js.coffee
Normal file → Executable file
0
app/assets/javascripts/door_logs.js.coffee
Normal file → Executable file
0
app/assets/javascripts/home.js.coffee
Normal file → Executable file
0
app/assets/javascripts/home.js.coffee
Normal file → Executable file
0
app/assets/javascripts/ipn.js.coffee
Normal file → Executable file
0
app/assets/javascripts/ipn.js.coffee
Normal file → Executable file
0
app/assets/javascripts/mac_logs.js.coffee
Normal file → Executable file
0
app/assets/javascripts/mac_logs.js.coffee
Normal file → Executable file
0
app/assets/javascripts/pamela.js.coffee
Normal file → Executable file
0
app/assets/javascripts/pamela.js.coffee
Normal file → Executable file
0
app/assets/javascripts/payments.js.coffee
Normal file → Executable file
0
app/assets/javascripts/payments.js.coffee
Normal file → Executable file
0
app/assets/javascripts/user_certifications.js.coffee
Normal file → Executable file
0
app/assets/javascripts/user_certifications.js.coffee
Normal file → Executable file
0
app/assets/javascripts/users.js.coffee
Normal file → Executable file
0
app/assets/javascripts/users.js.coffee
Normal file → Executable file
0
app/assets/stylesheets/application.css
Normal file → Executable file
0
app/assets/stylesheets/application.css
Normal file → Executable file
0
app/assets/stylesheets/certifications.css.scss
Normal file → Executable file
0
app/assets/stylesheets/certifications.css.scss
Normal file → Executable file
0
app/assets/stylesheets/door_logs.css.scss
Normal file → Executable file
0
app/assets/stylesheets/door_logs.css.scss
Normal file → Executable file
0
app/assets/stylesheets/home.css.scss
Normal file → Executable file
0
app/assets/stylesheets/home.css.scss
Normal file → Executable file
0
app/assets/stylesheets/ipn.css.scss
Normal file → Executable file
0
app/assets/stylesheets/ipn.css.scss
Normal file → Executable file
0
app/assets/stylesheets/mac_logs.css.scss
Normal file → Executable file
0
app/assets/stylesheets/mac_logs.css.scss
Normal file → Executable file
0
app/assets/stylesheets/macs.css.scss
Normal file → Executable file
0
app/assets/stylesheets/macs.css.scss
Normal file → Executable file
0
app/assets/stylesheets/payments.css.scss
Normal file → Executable file
0
app/assets/stylesheets/payments.css.scss
Normal file → Executable file
11
app/assets/stylesheets/scaffolds.css.scss
Normal file → Executable file
11
app/assets/stylesheets/scaffolds.css.scss
Normal file → Executable file
|
@ -19,17 +19,6 @@ pre {
|
|||
font-size: 11px;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #000;
|
||||
&:visited {
|
||||
color: #666;
|
||||
}
|
||||
&:hover {
|
||||
color: #fff;
|
||||
background-color: #000;
|
||||
}
|
||||
}
|
||||
|
||||
div {
|
||||
&.field, &.actions {
|
||||
margin-bottom: 10px;
|
||||
|
|
0
app/assets/stylesheets/user_certifications.css.scss
Normal file → Executable file
0
app/assets/stylesheets/user_certifications.css.scss
Normal file → Executable file
0
app/assets/stylesheets/users.css.scss
Normal file → Executable file
0
app/assets/stylesheets/users.css.scss
Normal file → Executable file
25
app/controllers/application_controller.rb
Normal file → Executable file
25
app/controllers/application_controller.rb
Normal file → Executable file
|
@ -1,6 +1,17 @@
|
|||
class ApplicationController < ActionController::Base
|
||||
protect_from_forgery
|
||||
|
||||
force_ssl if: :ssl_forced?
|
||||
|
||||
def ssl_forced?
|
||||
# Non-production environments and read-only stuff like the space API and MACs should not require SSL. (APIs hate following 301s).
|
||||
if Rails.env.development? || Rails.env.test? || ["space_api","macs"].include?(params[:controller])
|
||||
return false
|
||||
else
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
rescue_from CanCan::AccessDenied do |exception|
|
||||
if !current_user.nil? && current_user.orientation.blank? then
|
||||
flash[:alert] = "Sorry, you probably need to complete New Member Orientation before having access to this page. <br/>Please check your email and schedule a New Member Orientation with a volunteer."
|
||||
|
@ -13,6 +24,20 @@ class ApplicationController < ActionController::Base
|
|||
|
||||
@payment_methods = [[nil],["PayPal"],["Dwolla"],["Bill Pay"],["Check"],["Cash"],["Other"]]
|
||||
@payment_instructions = {nil => nil, :paypal => "Set up a monthly recurring payment to hslfinances@gmail.com", :dwolla => "Set up a monthly recurring payment to hslfinances@gmail.com", :billpay => "Have your bank send a monthly check to HeatSync Labs Treasurer, 140 W Main St, Mesa AZ 85201", :check => "Mail to HeatSync Labs Treasurer, 140 W Main St, Mesa AZ 85201 OR put in the drop safe at the Lab with a deposit slip firmly attached each month.", :cash => "Put in the drop safe at the Lab with a deposit slip firmly attached each month.", :other => "Hmm... talk to a Treasurer!"}
|
||||
|
||||
# Check authorization of a user / sign them in manually
|
||||
def check_auth(email,password)
|
||||
resource = User.find_by_email(email)
|
||||
if resource && resource.valid_password?(password)
|
||||
resource.remember_me = true
|
||||
sign_in :user, resource
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
# Add a "fit" function to sanitize inputs for mac history
|
||||
|
|
39
app/controllers/cards_controller.rb
Normal file → Executable file
39
app/controllers/cards_controller.rb
Normal file → Executable file
|
@ -1,6 +1,6 @@
|
|||
class CardsController < ApplicationController
|
||||
load_and_authorize_resource
|
||||
before_filter :authenticate_user!
|
||||
load_and_authorize_resource except: :authorize
|
||||
before_filter :authenticate_user!, except: :authorize
|
||||
|
||||
# GET /cards
|
||||
# GET /cards.json
|
||||
|
@ -111,6 +111,41 @@ class CardsController < ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
def authorize
|
||||
|
||||
# Stop unless signed in already, OR if the supplied user/pass params are good.
|
||||
unless current_user || check_auth(params['user'],params['pass'])
|
||||
@auth = "bad_user_or_pass"
|
||||
else
|
||||
# Stop unless the user can access the door system
|
||||
unless can? :authorize, Card
|
||||
@auth = "bad_user_permissions"
|
||||
Rails.logger.warn "----------\r\nWARNING: CARD AUTH ATTEMPT DENIED. USER #{current_user.inspect}\r\n----------"
|
||||
else
|
||||
|
||||
begin
|
||||
@card = Card.find(:first, :conditions => ["lower(card_number) = ?", params[:id].downcase])
|
||||
@auth = @card.inspect
|
||||
if @card && @card.user
|
||||
@auth = @card.user.has_certification?(params[:device])
|
||||
else
|
||||
@auth = false
|
||||
end
|
||||
rescue
|
||||
@auth = false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if @card && @card.user
|
||||
username = @card.user.name
|
||||
else
|
||||
username = nil
|
||||
end
|
||||
|
||||
render json: [@auth, username]
|
||||
end
|
||||
|
||||
# DELETE /cards/1
|
||||
# DELETE /cards/1.json
|
||||
def destroy
|
||||
|
|
0
app/controllers/certifications_controller.rb
Normal file → Executable file
0
app/controllers/certifications_controller.rb
Normal file → Executable file
87
app/controllers/contracts_controller.rb
Normal file
87
app/controllers/contracts_controller.rb
Normal file
|
@ -0,0 +1,87 @@
|
|||
class ContractsController < ApplicationController
|
||||
load_and_authorize_resource :contract
|
||||
before_filter :authenticate_user!, :load_users
|
||||
layout 'resources'
|
||||
|
||||
def index
|
||||
if params[:user_id].present?
|
||||
@contracts = Contract.where(user_id: params[:user_id])
|
||||
end
|
||||
respond_to do |format|
|
||||
format.html
|
||||
format.json { render :json => @contracts }
|
||||
end
|
||||
end
|
||||
|
||||
def show
|
||||
end
|
||||
|
||||
def new
|
||||
end
|
||||
|
||||
def edit
|
||||
end
|
||||
|
||||
def create
|
||||
# if @contract.first_name.blank? && @contract.last_name.blank? && @contract.cosigner.blank? # assume autodetect of filename
|
||||
# begin
|
||||
# name_split = params[:contract][:document].original_filename.sub(".jpg","").split
|
||||
# if name_split.count == 4 # we have one name
|
||||
# @contract.first_name = name_split[0]
|
||||
# @contract.last_name = name_split[1]
|
||||
# # 2 is the hyphen
|
||||
# @contract.signed_at = Date.parse(name_split[3])
|
||||
# elsif name_split.count == 7 && name_split[2] == "by" # we have two names
|
||||
# @contract.first_name = name_split[0]
|
||||
# @contract.last_name = name_split[1]
|
||||
# # 2 is "by"
|
||||
# @contract.cosigner = "#{name_split[3]} #{name_split[4]}"
|
||||
# # 5 is the hyphen
|
||||
# @contract.signed_at = Date.parse(name_split[6])
|
||||
# else
|
||||
# Rails.logger.info "Couldn't determine name from filename array: #{name_split.inspect}"
|
||||
# end
|
||||
# rescue Exception => e
|
||||
# end
|
||||
# end
|
||||
|
||||
@contract.created_by = current_user
|
||||
respond_to do |format|
|
||||
if @contract.save
|
||||
format.html { redirect_to @contract, :notice => 'Contract was successfully created.' }
|
||||
format.json { render :json => @contract, :status => :created, :location => @contract }
|
||||
else
|
||||
format.html { render :action => "new" }
|
||||
format.json { render :json => @contract.errors, :status => :unprocessable_entity }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def find_for_user
|
||||
end
|
||||
|
||||
def update
|
||||
respond_to do |format|
|
||||
if @contract.update_attributes(params[:contract])
|
||||
format.html { redirect_to @contract, :notice => 'Contract was successfully updated.' }
|
||||
format.json { head :no_content }
|
||||
else
|
||||
format.html { render :action => "edit" }
|
||||
format.json { render :json => @contract.errors, :status => :unprocessable_entity }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
@contract.destroy
|
||||
|
||||
respond_to do |format|
|
||||
format.html { redirect_to contracts_url }
|
||||
format.json { head :no_content }
|
||||
end
|
||||
end
|
||||
|
||||
def load_users
|
||||
@users = User.accessible_by(current_ability).sort_by(&:name)
|
||||
end
|
||||
end
|
30
app/controllers/door_logs_controller.rb
Normal file → Executable file
30
app/controllers/door_logs_controller.rb
Normal file → Executable file
|
@ -5,7 +5,35 @@ class DoorLogsController < ApplicationController
|
|||
# GET /door_logs
|
||||
# GET /door_logs.json
|
||||
def index
|
||||
@door_logs = DoorLog.find(:all, :order => "created_at DESC", :limit => 500)
|
||||
@door_logs = DoorLog.find(:all, :order => "created_at DESC", :limit => 100)
|
||||
|
||||
|
||||
begin
|
||||
@start_date = DateTime.parse(params[:start])
|
||||
@end_date = DateTime.parse(params[:end])
|
||||
rescue
|
||||
@start_date = DateTime.now - 2.weeks
|
||||
@end_date = DateTime.now
|
||||
end
|
||||
|
||||
@door_logs_by_hour = DoorLog.where("created_at > ? AND created_at < ? AND (key = ? OR key = ?)", @start_date, @end_date,"door_1_locked","door_2_locked").order("created_at ASC").group_by(&:key)
|
||||
@door_log_graph = [
|
||||
@door_logs_by_hour["door_1_locked"].map{|d| [d.created_at.to_time.to_i*1000, 1^d.data.to_i]}, # use XOR to invert 1 into 0 and vice versa
|
||||
@door_logs_by_hour["door_2_locked"].map{|d| [d.created_at.to_time.to_i*1000, 1^d.data.to_i]}
|
||||
]
|
||||
|
||||
# @door_logs_by_hour.each do |door_log|
|
||||
# # Add one computer for activate, subtract one for deactivate
|
||||
# if door_log.data == 1
|
||||
#
|
||||
# elsif door_log.data == 0
|
||||
# mac_running_balance -= 1
|
||||
# end
|
||||
|
||||
# @door_log_graph << [time.to_time.to_i*1000,mac_running_balance]
|
||||
# end
|
||||
|
||||
|
||||
|
||||
respond_to do |format|
|
||||
format.html # index.html.erb
|
||||
|
|
16
app/controllers/home_controller.rb
Normal file → Executable file
16
app/controllers/home_controller.rb
Normal file → Executable file
|
@ -1,6 +1,22 @@
|
|||
class HomeController < ApplicationController
|
||||
layout 'resources'
|
||||
|
||||
def index
|
||||
# Alerts
|
||||
if user_signed_in? && current_user.orientation.blank? then
|
||||
flash[:alert] = "There's a lot more to see here, but our records show you haven't completed the new member orientation yet. If that's incorrect, please contact a volunteer."
|
||||
end
|
||||
if user_signed_in? && current_user.member_status.between?(2,100) then
|
||||
flash[:alert] = "<!--
|
||||
Member: <%= current_user.member.inspect
|
||||
Level: <%= current_user.member_level.inspect
|
||||
-->
|
||||
Looks like we haven't acknowledged a recent payment for you yet. This could be because we're slow, but if in doubt please see your profile for payment instructions, consider updating your membership level to something accurate, or contact us.<br/>Thanks for supporting us!"
|
||||
end
|
||||
|
||||
# Fun Stats
|
||||
@featured_resource = Resource.where("picture_file_name IS NOT NULL").sample
|
||||
|
||||
@num_certs = UserCertification.count
|
||||
@recent_certs = UserCertification.where("created_at > ?", DateTime.now - 7.days).count
|
||||
@num_users = User.count
|
||||
|
|
0
app/controllers/ipns_controller.rb
Normal file → Executable file
0
app/controllers/ipns_controller.rb
Normal file → Executable file
4
app/controllers/mac_logs_controller.rb
Normal file → Executable file
4
app/controllers/mac_logs_controller.rb
Normal file → Executable file
|
@ -4,6 +4,10 @@ before_filter :authenticate_user!
|
|||
|
||||
def index
|
||||
@mac_logs = MacLog.desc.limit(1000)
|
||||
@macs = {}
|
||||
@mac_logs.each do |log|
|
||||
@macs.merge!({log.mac => Mac.find_by_mac(log.mac)})
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
12
app/controllers/macs_controller.rb
Normal file → Executable file
12
app/controllers/macs_controller.rb
Normal file → Executable file
|
@ -224,7 +224,7 @@ end
|
|||
|
||||
def arp_lookup
|
||||
@ip = request.env['REMOTE_ADDR']
|
||||
@arp = %x(/usr/sbin/arp -a | grep #{@ip})
|
||||
@arp = /([0-9A-F]{2}[:-]){5}([0-9A-F]{2})/i.match(%x(arp -a | grep #{@ip}))
|
||||
end
|
||||
|
||||
def scan
|
||||
|
@ -292,18 +292,22 @@ Rails.logger.info "starting scan..."
|
|||
Rails.logger.info "Running [#{command}]"
|
||||
end
|
||||
IO.popen(command) { |stdin|
|
||||
Rails.logger.info "Reading stdin: "+stdin.inspect
|
||||
stdin.each { |line|
|
||||
result = stdin.read()
|
||||
result.lines.each { |line|
|
||||
Rails.logger.info "Reading stdin: "+line.inspect
|
||||
next if line !~ /^([\d\.]+)\s+([[:xdigit:]:]+)\s/;
|
||||
macs[($2).downcase] = ($1).downcase;
|
||||
}
|
||||
Rails.logger.info "STDIN:"+result.lines.count.inspect
|
||||
@macs = macs.dup # make a copy for output in the view
|
||||
Rails.logger.info "MACS:"+@macs.inspect
|
||||
}
|
||||
|
||||
# Scan the existing macs and update each record as necessary
|
||||
Mac.find(:all).each { |entry|
|
||||
mac = entry.mac.downcase
|
||||
ip = entry.ip
|
||||
if macs.has_key?(mac)
|
||||
if macs.has_key?(mac) # if our scan shows this mac
|
||||
if ! entry.active || ! entry.since
|
||||
Rails.logger.info "Activating #{mac} at #{ip}" if options[:verbose]
|
||||
entry.since = Time.now
|
||||
|
|
3
app/controllers/payments_controller.rb
Normal file → Executable file
3
app/controllers/payments_controller.rb
Normal file → Executable file
|
@ -45,8 +45,6 @@ class PaymentsController < ApplicationController
|
|||
payment_months = @payments.sort_by(&:date).group_by{ |p| p.date.beginning_of_month }
|
||||
@payments_by_month = []
|
||||
payment_months.each do |month|
|
||||
# Only grab the last year from today
|
||||
if month.first > (Date.today - 1.year) && month.first < Date.today
|
||||
# Calculate sum of amounts for each month and store at end of month array
|
||||
@payments_by_month << [month.first.to_time.to_i*1000, month.last.sum{|p|
|
||||
amount = amount_or_level(p)
|
||||
|
@ -61,7 +59,6 @@ class PaymentsController < ApplicationController
|
|||
end
|
||||
}]
|
||||
end
|
||||
end
|
||||
|
||||
return @payments_by_month
|
||||
end
|
||||
|
|
0
app/controllers/paypal_csvs_controller.rb
Normal file → Executable file
0
app/controllers/paypal_csvs_controller.rb
Normal file → Executable file
0
app/controllers/registrations_controller.rb
Normal file → Executable file
0
app/controllers/registrations_controller.rb
Normal file → Executable file
46
app/controllers/resource_categories_controller.rb
Executable file
46
app/controllers/resource_categories_controller.rb
Executable file
|
@ -0,0 +1,46 @@
|
|||
class ResourceCategoriesController < ApplicationController
|
||||
load_and_authorize_resource
|
||||
layout 'resources'
|
||||
|
||||
def create
|
||||
authorize! :create, @resource_category
|
||||
|
||||
respond_to do |format|
|
||||
if @resource_category.save
|
||||
format.html { redirect_to resource_categories_path, :notice => "Category was successfully created." }
|
||||
format.json { head :no_content }
|
||||
else
|
||||
format.html { render :action => "new" }
|
||||
format.json { render :json => @resource_category.errors, :status => :unprocessable_entity }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def update
|
||||
authorize! :update, @resource_category
|
||||
|
||||
respond_to do |format|
|
||||
if @resource_category.update_attributes(params[:resource_category])
|
||||
format.html { redirect_to resource_categories_path, :notice => "Category was successfully updated." }
|
||||
format.json { head :no_content }
|
||||
else
|
||||
format.html { render :action => "edit" }
|
||||
format.json { render :json => @resource_category.errors, :status => :unprocessable_entity }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
|
||||
respond_to do |format|
|
||||
if @resource_category.destroy
|
||||
format.html { redirect_to resource_categories_path, :notice => "Category was deleted." }
|
||||
format.json { head :ok }
|
||||
else
|
||||
format.html { redirect_to resource_categories_path, :notice => "Category could not be deleted. #{@resource_category.errors.full_messages.first}." }
|
||||
format.json { render :json => @resource_category.errors, :status => :unprocessable_entity }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
63
app/controllers/resources_controller.rb
Executable file
63
app/controllers/resources_controller.rb
Executable file
|
@ -0,0 +1,63 @@
|
|||
class ResourcesController < ApplicationController
|
||||
load_and_authorize_resource
|
||||
before_filter :load_users
|
||||
layout 'resources'
|
||||
|
||||
def index
|
||||
@featured_resource = @resources.where("picture_file_name IS NOT NULL").sample
|
||||
end
|
||||
|
||||
def new
|
||||
# don't get too excited... for some reason this gets set to the current_user
|
||||
@resource.user_id = nil
|
||||
end
|
||||
|
||||
def create
|
||||
@resource.modified_by = current_user.id # log who modified this last
|
||||
authorize! :create, @resource
|
||||
|
||||
respond_to do |format|
|
||||
if @resource.save
|
||||
format.html { redirect_to resource_path(@resource), :notice => "Resource was successfully created." }
|
||||
format.json { head :no_content }
|
||||
else
|
||||
format.html { render :action => "new" }
|
||||
format.json { render :json => @resource.errors, :status => :unprocessable_entity }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def update
|
||||
@resource.modified_by = current_user.id # log who modified this last
|
||||
@resource.assign_attributes(params[:resource])
|
||||
authorize! :update, @resource
|
||||
|
||||
respond_to do |format|
|
||||
if @resource.update_attributes(params[:resource])
|
||||
format.html { redirect_to resource_path(@resource), :notice => "Resource was successfully updated." }
|
||||
format.json { head :no_content }
|
||||
else
|
||||
format.html { render :action => "edit" }
|
||||
format.json { render :json => @resource.errors, :status => :unprocessable_entity }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
@resource.destroy
|
||||
|
||||
respond_to do |format|
|
||||
format.html { redirect_to resources_path, :notice => "Resource was deleted." }
|
||||
format.json { head :ok }
|
||||
end
|
||||
end
|
||||
|
||||
def load_users
|
||||
if can? :assign_user, Resource then
|
||||
@users = User.accessible_by(current_ability).sort_by(&:name)
|
||||
else
|
||||
@users = [current_user]
|
||||
end
|
||||
end
|
||||
|
||||
end
|
0
app/controllers/settings_controller.rb
Normal file → Executable file
0
app/controllers/settings_controller.rb
Normal file → Executable file
33
app/controllers/space_api_controller.rb
Normal file → Executable file
33
app/controllers/space_api_controller.rb
Normal file → Executable file
|
@ -38,8 +38,19 @@ class SpaceApiController < ApplicationController
|
|||
else
|
||||
unless can? :access_doors_remotely, :door_access
|
||||
@output = "Sorry, your account isn't able to control doors remotely."
|
||||
else
|
||||
@output = "Ready to control doors. Send POST params to this URL as per the HTML form."
|
||||
end
|
||||
end
|
||||
|
||||
# Render the form again (or result)
|
||||
respond_to do |format|
|
||||
format.html
|
||||
format.json {
|
||||
response.headers["Cache-Control"] = "no-cache, no-store, max-age=0, must-revalidate"
|
||||
render :json => @output
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
def access_post
|
||||
|
@ -78,19 +89,17 @@ class SpaceApiController < ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
# Render the form again
|
||||
# Render the form again (or result)
|
||||
respond_to do |format|
|
||||
format.html {
|
||||
render :access
|
||||
end
|
||||
|
||||
def check_auth(email,password)
|
||||
resource = User.find_by_email(email)
|
||||
if resource && resource.valid_password?(password)
|
||||
resource.remember_me = true
|
||||
sign_in :user, resource
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
}
|
||||
format.json {
|
||||
response.headers["Cache-Control"] = "no-cache, no-store, max-age=0, must-revalidate"
|
||||
render :json => @output
|
||||
}
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
|
0
app/controllers/statistics_controller.rb
Normal file → Executable file
0
app/controllers/statistics_controller.rb
Normal file → Executable file
0
app/controllers/user_certifications_controller.rb
Normal file → Executable file
0
app/controllers/user_certifications_controller.rb
Normal file → Executable file
25
app/controllers/users_controller.rb
Normal file → Executable file
25
app/controllers/users_controller.rb
Normal file → Executable file
|
@ -1,6 +1,7 @@
|
|||
class UsersController < ApplicationController
|
||||
load_and_authorize_resource
|
||||
before_filter :authenticate_user!
|
||||
layout 'resources'
|
||||
|
||||
def sort_by_cert(certs,id)
|
||||
result = 0
|
||||
|
@ -15,6 +16,18 @@ class UsersController < ApplicationController
|
|||
# GET /users
|
||||
# GET /users.json
|
||||
def index
|
||||
unless params[:full] # by default, show summary
|
||||
|
||||
@users = @users.paying + @users.volunteer
|
||||
#.joins(:payments).where("payments.date > ? OR ", (DateTime.now - 60.days)).uniq
|
||||
|
||||
respond_to do |format|
|
||||
format.html { render 'summary', layout: 'resources' }
|
||||
format.json { render :json => @users }
|
||||
end
|
||||
|
||||
else # show full
|
||||
|
||||
case params[:sort]
|
||||
when "name"
|
||||
@users = @users.sort_by(&:name)
|
||||
|
@ -23,7 +36,7 @@ class UsersController < ApplicationController
|
|||
when "orientation"
|
||||
@users = @users.sort_by{ |u| [-u.orientation.to_i,u.name] }
|
||||
when "waiver"
|
||||
@users = @users.sort_by{ |u| [-u.waiver.to_i,u.name] }
|
||||
@users = @users.sort_by{ |u| [-u.contract_date.to_i,u.name] }
|
||||
when "member"
|
||||
@users = @users.sort_by{ |u| [-u.member_status.to_i,u.name] }
|
||||
when "card"
|
||||
|
@ -42,6 +55,7 @@ class UsersController < ApplicationController
|
|||
format.json { render :json => @users }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# 'Active' users who haven't paid recently
|
||||
def inactive
|
||||
|
@ -73,12 +87,10 @@ class UsersController < ApplicationController
|
|||
|
||||
def compose_email
|
||||
@user = User.find(params[:user_id])
|
||||
authorize! :read, @user
|
||||
end
|
||||
|
||||
def send_email
|
||||
@user = User.find(params[:user_id])
|
||||
authorize! :read, @user
|
||||
@subject = params[:subject]
|
||||
@body = params[:body]
|
||||
if @user.send_email(current_user,@subject,@body)
|
||||
|
@ -113,6 +125,9 @@ class UsersController < ApplicationController
|
|||
# POST /users
|
||||
# POST /users.json
|
||||
def create
|
||||
# update oriented_by only if orientation has been set
|
||||
@user.oriented_by_id = current_user.id unless @user.orientation.blank?
|
||||
|
||||
respond_to do |format|
|
||||
if @user.save
|
||||
format.html { redirect_to @user, :notice => 'User was successfully created.' }
|
||||
|
@ -127,6 +142,10 @@ class UsersController < ApplicationController
|
|||
# PUT /users/1
|
||||
# PUT /users/1.json
|
||||
def update
|
||||
# update oriented_by only if it's blank but the (new) orientation isn't blank
|
||||
# gotta test the params because they don't get applied til below.
|
||||
@user.oriented_by_id = current_user.id if @user.oriented_by.blank? && (!params[:user]["orientation(1i)"].blank?)
|
||||
|
||||
respond_to do |format|
|
||||
if @user.update_attributes(params[:user])
|
||||
format.html { redirect_to @user, :notice => 'User was successfully updated.' }
|
||||
|
|
27
app/helpers/application_helper.rb
Normal file → Executable file
27
app/helpers/application_helper.rb
Normal file → Executable file
|
@ -1,4 +1,31 @@
|
|||
module ApplicationHelper
|
||||
@payment_methods = [[nil],["PayPal"],["Dwolla"],["Bill Pay"],["Check"],["Cash"],["Other"]]
|
||||
@payment_instructions = {nil => nil, :paypal => "Set up a monthly recurring payment to hslfinances@gmail.com", :dwolla => "Set up a monthly recurring payment to hslfinances@gmail.com", :billpay => "Have your bank send a monthly check to HeatSync Labs Treasurer, 140 W Main St, Mesa AZ 85201", :check => "Mail to HeatSync Labs Treasurer, 140 W Main St, Mesa AZ 85201 OR put in the drop safe at the Lab with a deposit slip firmly attached each month.", :cash => "Put in the drop safe at the Lab with a deposit slip firmly attached each month.", :other => "Hmm... talk to a Treasurer!"}
|
||||
|
||||
def sort_link(title, column, options = {})
|
||||
condition = options[:unless] if options.has_key?(:unless)
|
||||
sort_dir = params[:dir] == 'up' ? 'down' : 'up'
|
||||
link_to_unless condition, title, request.parameters.merge( {:sort => column, :dir => sort_dir} )
|
||||
end
|
||||
|
||||
def li_link_to(name = nil, options = nil, html_options = nil, &block)
|
||||
html_options, options, name = options, name, block if block_given?
|
||||
options ||= {}
|
||||
|
||||
html_options = convert_options_to_data_attributes(options, html_options)
|
||||
|
||||
url = url_for(options)
|
||||
html_options['href'] ||= url
|
||||
|
||||
if current_page?(url)
|
||||
content_tag(:li, class: "active") do
|
||||
content_tag(:a, name || url, html_options, &block)
|
||||
end
|
||||
else
|
||||
content_tag(:li) do
|
||||
content_tag(:a, name || url, html_options, &block)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
0
app/helpers/certifications_helper.rb
Normal file → Executable file
0
app/helpers/certifications_helper.rb
Normal file → Executable file
0
app/helpers/door_logs_helper.rb
Normal file → Executable file
0
app/helpers/door_logs_helper.rb
Normal file → Executable file
0
app/helpers/home_helper.rb
Normal file → Executable file
0
app/helpers/home_helper.rb
Normal file → Executable file
0
app/helpers/ipn_helper.rb
Normal file → Executable file
0
app/helpers/ipn_helper.rb
Normal file → Executable file
0
app/helpers/mac_logs_helper.rb
Normal file → Executable file
0
app/helpers/mac_logs_helper.rb
Normal file → Executable file
0
app/helpers/pamela_helper.rb
Normal file → Executable file
0
app/helpers/pamela_helper.rb
Normal file → Executable file
0
app/helpers/payments_helper.rb
Normal file → Executable file
0
app/helpers/payments_helper.rb
Normal file → Executable file
0
app/helpers/user_certifications_helper.rb
Normal file → Executable file
0
app/helpers/user_certifications_helper.rb
Normal file → Executable file
0
app/helpers/users_helper.rb
Normal file → Executable file
0
app/helpers/users_helper.rb
Normal file → Executable file
0
app/mailers/.gitkeep
Normal file → Executable file
0
app/mailers/.gitkeep
Normal file → Executable file
0
app/mailers/user_mailer.rb
Normal file → Executable file
0
app/mailers/user_mailer.rb
Normal file → Executable file
0
app/models/.gitkeep
Normal file → Executable file
0
app/models/.gitkeep
Normal file → Executable file
14
app/models/ability.rb
Normal file → Executable file
14
app/models/ability.rb
Normal file → Executable file
|
@ -4,6 +4,8 @@ class Ability
|
|||
def initialize(user)
|
||||
can :read, Mac # Anonymous can read mac
|
||||
can :scan, Mac # Need anonymous so CRON can scan
|
||||
can :read, Resource
|
||||
can :read, ResourceCategory
|
||||
|
||||
if !user.nil?
|
||||
|
||||
|
@ -13,12 +15,16 @@ class Ability
|
|||
can :read_details, Mac
|
||||
can [:update], Mac, :user_id => nil
|
||||
can [:create,:update], Mac, :user_id => user.id
|
||||
can [:create,:update,:destroy], Resource, :user_id => user.id
|
||||
can :read, Payment, :user_id => user.id
|
||||
can [:read,:new_member_report], User, :id => user.id #TODO: why can users update themselves? Maybe because Devise doesn't check users/edit?
|
||||
can :read, UserCertification, :user_id => user.id
|
||||
can :read, User, :id => user.id #TODO: why can users update themselves? Maybe because Devise doesn't check users/edit?
|
||||
can :compose_email, User
|
||||
can :send_email, User
|
||||
|
||||
if user.card_access_enabled
|
||||
can :access_doors_remotely, :door_access
|
||||
can :authorize, Card # used for interlock card/certification auth
|
||||
end
|
||||
|
||||
# Instructors can manage certs and see users
|
||||
|
@ -30,8 +36,10 @@ class Ability
|
|||
end
|
||||
# Users can see others' stuff if they've been oriented
|
||||
unless user.orientation.blank?
|
||||
can :read, User, :hidden => [nil,false]
|
||||
can [:read,:new_member_report,:activity], User, :hidden => [nil,false]
|
||||
can :read, UserCertification
|
||||
can [:create,:update], Resource, :user_id => [nil,user.id]
|
||||
can [:create,:update,:destroy], ResourceCategory
|
||||
end
|
||||
|
||||
# Accountants can manage payments
|
||||
|
@ -46,7 +54,7 @@ class Ability
|
|||
can :manage, :all
|
||||
end
|
||||
|
||||
# Prevent all destruction for now
|
||||
# Prevent most destruction for now
|
||||
#cannot :destroy, User
|
||||
#cannot :destroy, Card
|
||||
cannot :destroy, Certification
|
||||
|
|
30
app/models/card.rb
Normal file → Executable file
30
app/models/card.rb
Normal file → Executable file
|
@ -11,21 +11,14 @@ class Card < ActiveRecord::Base
|
|||
door_access_url = APP_CONFIG['door_access_url']
|
||||
door_access_password = APP_CONFIG['door_access_password']
|
||||
|
||||
# connect to door access system
|
||||
source = open("#{door_access_url}?e=#{door_access_password}").read
|
||||
results = source.scan(/ok/)
|
||||
if(results.size > 0) then
|
||||
#only continue if we've got an OK login
|
||||
cardid = self.id.to_s.rjust(3, '0') #TODO: provide ability for
|
||||
cardid = self.id.to_s.rjust(3, '0')
|
||||
cardperm = self.card_permissions.to_s.rjust(3, '0')
|
||||
cardnum = self.card_number.rjust(8, '0')
|
||||
|
||||
source = open("#{door_access_url}?m#{cardid}&p#{cardperm}&t#{cardnum}").read
|
||||
# login and send the command all in one go (auto-logout is a feature of the arduino when used this way)
|
||||
source = open("#{door_access_url}?m#{cardid}&p#{cardperm}&t#{cardnum}&e=#{door_access_password}").read
|
||||
results = source.scan(/cur/)
|
||||
|
||||
#logout
|
||||
open("#{door_access_url}?e=0000")
|
||||
|
||||
if(results.size > 0) then
|
||||
#only return true if we got some kind of decent response
|
||||
return true
|
||||
|
@ -33,10 +26,6 @@ class Card < ActiveRecord::Base
|
|||
# We didn't get a decent response.
|
||||
return false
|
||||
end
|
||||
else
|
||||
# We didn't get an OK login.
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
def self.upload_all_to_door
|
||||
|
@ -47,16 +36,13 @@ class Card < ActiveRecord::Base
|
|||
door_access_url = APP_CONFIG['door_access_url']
|
||||
door_access_password = APP_CONFIG['door_access_password']
|
||||
|
||||
source = open("#{door_access_url}?e=#{door_access_password}").read
|
||||
results = source.scan(/ok/)
|
||||
if(results.size > 0) then
|
||||
@cards.each do |u|
|
||||
#only continue if we've got an OK login
|
||||
cardid = u.id.to_s.rjust(3, '0')
|
||||
cardperm = u.card_permissions.to_s.rjust(3, '0')
|
||||
cardnum = u.card_number.rjust(8, '0')
|
||||
|
||||
source = open("#{door_access_url}?m#{cardid}&p#{cardperm}&t#{cardnum}").read
|
||||
# login and send the command all in one go (auto-logout is a feature of the arduino when used this way)
|
||||
source = open("#{door_access_url}?m#{cardid}&p#{cardperm}&t#{cardnum}&e=#{door_access_password}").read
|
||||
results = source.scan(/cur/)
|
||||
|
||||
if(results.size > 0) then
|
||||
|
@ -67,12 +53,6 @@ class Card < ActiveRecord::Base
|
|||
end
|
||||
end
|
||||
|
||||
#logout
|
||||
open("#{door_access_url}?e=0000")
|
||||
else
|
||||
@end_results.push([cardid,"FAIL"])
|
||||
end
|
||||
|
||||
return @end_results
|
||||
end
|
||||
end
|
||||
|
|
4
app/models/certification.rb
Normal file → Executable file
4
app/models/certification.rb
Normal file → Executable file
|
@ -1,5 +1,7 @@
|
|||
class Certification < ActiveRecord::Base
|
||||
attr_accessible :description, :name
|
||||
attr_accessible :description, :name, :slug
|
||||
has_many :user_certifications
|
||||
has_many :users, :through => :user_certifications
|
||||
|
||||
validates_presence_of :name, :slug
|
||||
end
|
||||
|
|
24
app/models/contract.rb
Normal file
24
app/models/contract.rb
Normal file
|
@ -0,0 +1,24 @@
|
|||
class Contract < ActiveRecord::Base
|
||||
belongs_to :user
|
||||
belongs_to :created_by, :foreign_key => "created_by_id", :class_name => "User"
|
||||
attr_accessible :user_id, :first_name, :last_name, :cosigner,
|
||||
:signed_at, :document, :document_file_name, :document_content_type,
|
||||
:document_file_size, :document_updated_at
|
||||
# :created_by not accessible for security purposes
|
||||
|
||||
validates_presence_of :first_name, :signed_at #, :last_name
|
||||
|
||||
has_attached_file :document,
|
||||
{ :styles =>
|
||||
{
|
||||
:medium => "300x300>",
|
||||
:large => "900x900>"
|
||||
},
|
||||
:storage => :s3,
|
||||
:s3_protocol => :https,
|
||||
:s3_credentials => { :access_key_id => ENV['S3_KEY'],
|
||||
:secret_access_key => ENV['S3_SECRET'] },
|
||||
:path => ":attachment/:id/:style.:extension",
|
||||
:bucket => ENV['S3_BUCKET']
|
||||
}
|
||||
end
|
0
app/models/door_log.rb
Normal file → Executable file
0
app/models/door_log.rb
Normal file → Executable file
0
app/models/ipn.rb
Normal file → Executable file
0
app/models/ipn.rb
Normal file → Executable file
0
app/models/mac.rb
Normal file → Executable file
0
app/models/mac.rb
Normal file → Executable file
0
app/models/mac_log.rb
Normal file → Executable file
0
app/models/mac_log.rb
Normal file → Executable file
0
app/models/payment.rb
Normal file → Executable file
0
app/models/payment.rb
Normal file → Executable file
0
app/models/paypal_csv.rb
Normal file → Executable file
0
app/models/paypal_csv.rb
Normal file → Executable file
31
app/models/resource.rb
Executable file
31
app/models/resource.rb
Executable file
|
@ -0,0 +1,31 @@
|
|||
class Resource < ActiveRecord::Base
|
||||
attr_accessible :supercategory, :user_id, :resource_category_id, :name, :serial, :specs, :status, :donatable,
|
||||
:picture, :picture_file_name, :picture_content_type, :picture_file_size, :picture_updated_at,
|
||||
:picture2, :picture2_file_name, :picture2_content_type, :picture2_file_size, :picture2_updated_at,
|
||||
:picture3, :picture3_file_name, :picture3_content_type, :picture3_file_size, :picture3_updated_at,
|
||||
:picture4, :picture4_file_name, :picture4_content_type, :picture4_file_size, :picture4_updated_at,
|
||||
:notes, :estimated_value, :disposed_at, :modified_by
|
||||
|
||||
belongs_to :owner, :class_name => "ToolshareUser" #TODO: remove owner
|
||||
belongs_to :user
|
||||
belongs_to :resource_category
|
||||
|
||||
PICTURE_OPTIONS = { :styles => { :medium => "300x300>",
|
||||
:thumb => "100x100>",
|
||||
:tiny => "50x50>"},
|
||||
:storage => :s3,
|
||||
:s3_protocol => :https,
|
||||
:s3_credentials => { :access_key_id => ENV['S3_KEY'],
|
||||
:secret_access_key => ENV['S3_SECRET'] },
|
||||
:path => ":attachment/:id/:style.:extension",
|
||||
:bucket => ENV['S3_BUCKET'] }
|
||||
|
||||
has_attached_file :picture, PICTURE_OPTIONS
|
||||
has_attached_file :picture2, PICTURE_OPTIONS
|
||||
has_attached_file :picture3, PICTURE_OPTIONS
|
||||
has_attached_file :picture4, PICTURE_OPTIONS
|
||||
|
||||
def resource_category_name
|
||||
resource_category.name if resource_category
|
||||
end
|
||||
end
|
13
app/models/resource_category.rb
Executable file
13
app/models/resource_category.rb
Executable file
|
@ -0,0 +1,13 @@
|
|||
class ResourceCategory < ActiveRecord::Base
|
||||
has_many :resources
|
||||
attr_accessible :name
|
||||
|
||||
before_destroy :has_resources?
|
||||
|
||||
private
|
||||
|
||||
def has_resources?
|
||||
errors.add(:base, "Cannot delete category with associated resources") unless resources.count == 0
|
||||
errors.blank? #return false, to not destroy the element, otherwise, it will delete.
|
||||
end
|
||||
end
|
0
app/models/setting.rb
Normal file → Executable file
0
app/models/setting.rb
Normal file → Executable file
4
app/models/toolshare_user.rb
Executable file
4
app/models/toolshare_user.rb
Executable file
|
@ -0,0 +1,4 @@
|
|||
class ToolshareUser < ActiveRecord::Base
|
||||
has_many :resources, :foreign_key => "owner_id"
|
||||
attr_accessible :name, :email
|
||||
end
|
24
app/models/user.rb
Normal file → Executable file
24
app/models/user.rb
Normal file → Executable file
|
@ -1,6 +1,6 @@
|
|||
class User < ActiveRecord::Base
|
||||
include Gravtastic
|
||||
gravtastic :size => 120, :default => ""
|
||||
gravtastic :size => 150, :default => ""
|
||||
|
||||
# Include default devise modules. Others available are:
|
||||
# :token_authenticatable, :confirmable,
|
||||
|
@ -9,16 +9,24 @@ class User < ActiveRecord::Base
|
|||
:recoverable, :rememberable, :trackable, :validatable
|
||||
|
||||
# Setup accessible (or protected) attributes for your model
|
||||
attr_accessible :email, :password, :password_confirmation, :remember_me, :name, :admin, :instructor, :member, :emergency_name, :emergency_phone, :current_skills, :desired_skills, :waiver, :emergency_email, :phone, :payment_method, :orientation, :member_level, :certifications, :hidden, :marketing_source, :payee, :accountant, :exit_reason, :twitter_url, :facebook_url, :github_url, :website_url, :email_visible, :phone_visible #TODO: make admin/instructor/member/etc not accessible
|
||||
attr_accessible :email, :password, :password_confirmation, :remember_me, :name, :admin, :instructor, :member, :emergency_name, :emergency_phone, :current_skills, :desired_skills, :waiver, :emergency_email, :phone, :payment_method, :orientation, :member_level, :certifications, :hidden, :marketing_source, :payee, :accountant, :exit_reason, :twitter_url, :facebook_url, :github_url, :website_url, :email_visible, :phone_visible, :postal_code #TODO: make admin/instructor/member/etc not accessible
|
||||
|
||||
belongs_to :oriented_by, :foreign_key => "oriented_by_id", :class_name => "User"
|
||||
has_many :cards
|
||||
has_many :user_certifications
|
||||
has_many :certifications, :through => :user_certifications
|
||||
has_many :contracts
|
||||
has_many :payments
|
||||
has_many :macs
|
||||
has_many :resources
|
||||
|
||||
scope :volunteer, -> { where('member_level >= 10 AND member_level < 25') }
|
||||
scope :paying, -> { joins(:payments).where("payments.date > ?", (DateTime.now - 90.days)).uniq }
|
||||
|
||||
validates_format_of [:twitter_url, :facebook_url, :github_url, :website_url], :with => URI::regexp(%w(http https)), :allow_blank => true
|
||||
|
||||
# disable # validates_presence_of :postal_code
|
||||
|
||||
after_create :send_new_user_email
|
||||
|
||||
def absorb_user(user_to_absorb)
|
||||
|
@ -130,6 +138,18 @@ class User < ActiveRecord::Base
|
|||
Rails.logger.info UserMailer.email(self,from_user,subject,body).deliver
|
||||
end
|
||||
|
||||
def has_certification?(cert_slug)
|
||||
if self.certifications.find_by_slug(cert_slug)
|
||||
true
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
def contract_date
|
||||
self.contracts.first.signed_at unless self.contracts.blank?
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def send_new_user_email
|
||||
|
|
0
app/models/user_certification.rb
Normal file → Executable file
0
app/models/user_certification.rb
Normal file → Executable file
0
app/views/cards/_form.html.erb
Normal file → Executable file
0
app/views/cards/_form.html.erb
Normal file → Executable file
0
app/views/cards/edit.html.erb
Normal file → Executable file
0
app/views/cards/edit.html.erb
Normal file → Executable file
6
app/views/cards/index.html.erb
Normal file → Executable file
6
app/views/cards/index.html.erb
Normal file → Executable file
|
@ -6,11 +6,11 @@
|
|||
<%= link_to 'Space API', space_api_path, :class => "btn" %>
|
||||
<%= link_to 'Remote Door Access', space_api_access_path, :class => "btn" if can? :access_doors_remotely, :door_access %>
|
||||
<p>
|
||||
<b>Most Active Card Last Month:</b> <%= @most_active_card.name unless @most_active_card.blank? %> (<%= @most_active_card.accesses_this_week unless @most_active_card.blank? %> days)
|
||||
<b>Most Active Card Last Month:</b> <%= @most_active_card.user.name unless @most_active_card.user.blank? %> (<%= @most_active_card.accesses_this_week unless @most_active_card.blank? %> days)
|
||||
</p>
|
||||
<p>
|
||||
<% unless @runner_up_card.blank? %>
|
||||
<b>Runner Up:</b> <%= @runner_up_card.name %> (<%= @runner_up_card.accesses_this_week %> days)
|
||||
<% unless @runner_up_card.blank? || @runner_up_card.user.blank? %>
|
||||
<b>Runner Up:</b> <%= @runner_up_card.user.name %> (<%= @runner_up_card.accesses_this_week %> days)
|
||||
<% end %>
|
||||
</p>
|
||||
|
||||
|
|
0
app/views/cards/new.html.erb
Normal file → Executable file
0
app/views/cards/new.html.erb
Normal file → Executable file
0
app/views/cards/show.html.erb
Normal file → Executable file
0
app/views/cards/show.html.erb
Normal file → Executable file
0
app/views/cards/upload.html.erb
Normal file → Executable file
0
app/views/cards/upload.html.erb
Normal file → Executable file
0
app/views/cards/upload_all.html.erb
Normal file → Executable file
0
app/views/cards/upload_all.html.erb
Normal file → Executable file
4
app/views/certifications/_form.html.erb
Normal file → Executable file
4
app/views/certifications/_form.html.erb
Normal file → Executable file
|
@ -15,6 +15,10 @@
|
|||
<%= f.label :name %><br />
|
||||
<%= f.text_field :name %>
|
||||
</div>
|
||||
<div class="field">
|
||||
<%= f.label :slug, "Slug (lowercase, single-word identifier)" %><br />
|
||||
<%= f.text_field :slug %>
|
||||
</div>
|
||||
<div class="field">
|
||||
<%= f.label :description %><br />
|
||||
<%= f.text_area :description %>
|
||||
|
|
0
app/views/certifications/edit.html.erb
Normal file → Executable file
0
app/views/certifications/edit.html.erb
Normal file → Executable file
1
app/views/certifications/index.html.erb
Normal file → Executable file
1
app/views/certifications/index.html.erb
Normal file → Executable file
|
@ -5,6 +5,7 @@
|
|||
<ul>
|
||||
<% @certifications.each do |certification| %>
|
||||
<li><%= link_to certification.name, certification %>
|
||||
(<%= certification.slug %>)
|
||||
<% if can? :update, certification %> | <%= link_to 'Edit', edit_certification_path(certification) %><% end %>
|
||||
<% if can? :destroy, certification %> | <%= link_to 'Destroy', certification, :confirm => 'Are you sure?', :method => :delete %><% end %>
|
||||
</li>
|
||||
|
|
0
app/views/certifications/new.html.erb
Normal file → Executable file
0
app/views/certifications/new.html.erb
Normal file → Executable file
5
app/views/certifications/show.html.erb
Normal file → Executable file
5
app/views/certifications/show.html.erb
Normal file → Executable file
|
@ -3,6 +3,11 @@
|
|||
<%= @certification.name %>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b>Slug (lowercase, single-word identifier):</b>
|
||||
<%= @certification.slug %>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b>Description:</b>
|
||||
<%= simple_format @certification.description %>
|
||||
|
|
51
app/views/contracts/_form.html.erb
Normal file
51
app/views/contracts/_form.html.erb
Normal file
|
@ -0,0 +1,51 @@
|
|||
<%= form_for(@contract, html: {class: "col-sm-6"}) do |f| %>
|
||||
<% if @contract.errors.any? %>
|
||||
<div id="error_explanation">
|
||||
<h2><%= pluralize(@contract.errors.count, "error") %> prohibited this contract from being saved:</h2>
|
||||
|
||||
<ul>
|
||||
<% @contract.errors.full_messages.each do |msg| %>
|
||||
<li><%= msg %></li>
|
||||
<% end %>
|
||||
</ul>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<div class="form-group">
|
||||
<%= f.label :first_name %><br />
|
||||
<%= f.text_field :first_name, class: "form-control" %>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<%= f.label :last_name %><br />
|
||||
<%= f.text_field :last_name, class: "form-control" %>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<%= f.label :cosigner %><br />
|
||||
<%= f.text_field :cosigner, class: "form-control" %>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<%= f.label :user_id, "User" %><br />
|
||||
<%= collection_select(:contract, :user_id, @users, :id, :name, :include_blank => true) %>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<%= f.label :signed_at %><br />
|
||||
<%= f.date_select :signed_at %>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<%= f.label :document %><br />
|
||||
<%= link_to "View Existing Document", @contract.document.url, class: "btn btn-default" unless @contract.document.blank? %>
|
||||
<p>
|
||||
<%= link_to "Upload New Document", "#", class: "btn btn-default", onclick: "$('#document_upload').removeClass('hidden'); $(this).addClass('hidden')" unless @contract.document.blank? %>
|
||||
<div id="document_upload" class="<%= "hidden" unless @contract.document.blank? %>">
|
||||
<%= f.file_field :document, class: "form-control", style: "width: 100%; height: 100px; background-color: #f9f9f9;" %>
|
||||
</div>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<%= f.submit nil, class: "btn btn-primary" %>
|
||||
</div>
|
||||
<% end %>
|
4
app/views/contracts/edit.html.erb
Normal file
4
app/views/contracts/edit.html.erb
Normal file
|
@ -0,0 +1,4 @@
|
|||
<h1>Edit Contract
|
||||
<%= link_to 'Back', contracts_path, class: "btn btn-default" %>
|
||||
</h1>
|
||||
<%= render 'form' %>
|
42
app/views/contracts/index.html.erb
Normal file
42
app/views/contracts/index.html.erb
Normal file
|
@ -0,0 +1,42 @@
|
|||
<div class="row">
|
||||
<h1 class="col-md-8">Contracts
|
||||
<%= link_to 'Add Contract', new_contract_path, :class => "btn btn-success" if can? :create, Contract %>
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
<table class="table">
|
||||
<tr>
|
||||
<th>Scan?</th>
|
||||
<th>Name</th>
|
||||
<th>User</th>
|
||||
<th>Date</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
|
||||
<% @contracts.sort_by{|r| (r.last_name) || "" }.each do |contract| %>
|
||||
<tr>
|
||||
<td>
|
||||
<% unless contract.document.blank? %>
|
||||
<span class="glyphicon glyphicon-ok"></span>
|
||||
<% end %>
|
||||
</td>
|
||||
<td>
|
||||
<%= contract.last_name %>,
|
||||
<%= contract.first_name %>
|
||||
<%= "and #{contract.cosigner}" unless contract.cosigner.blank? %>
|
||||
</td>
|
||||
<td>
|
||||
<%= link_to contract.user.name, contract.user if contract.user %>
|
||||
</td>
|
||||
<td>
|
||||
<%= contract.signed_at.to_date.to_s(:long) %>
|
||||
</td>
|
||||
<td>
|
||||
<%= link_to "View", contract, class: "btn btn-primary" %>
|
||||
<%= link_to "Edit", edit_contract_path(contract), class: "btn btn-default" %>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</table>
|
||||
<br />
|
||||
|
80
app/views/contracts/new.html.erb
Normal file
80
app/views/contracts/new.html.erb
Normal file
|
@ -0,0 +1,80 @@
|
|||
<h1>New Contract
|
||||
<%= link_to 'Back', contracts_path, class: "btn btn-default" %>
|
||||
</h1>
|
||||
|
||||
<div class="col-xs-12">
|
||||
<%= render 'form' %>
|
||||
</div>
|
||||
|
||||
<div class="col-xs-12">
|
||||
<div class="alert alert-info">Note: if you name your scans in one of the below formats, this form will try to fill itself out automatically when you select the file. (The spaces, hyphen, and jpg or pdf extensions are mandatory for this to work.) <em>Double-check the names, users, and dates, though!!</em><br/>
|
||||
<strong>first last - date.[jpg|pdf]</strong><br/>
|
||||
<strong>first last by cosigner name - date.[jpg|pdf]</strong><br/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
function capitalizeIfIsntCapitalized(str){
|
||||
if(str[0].toLowerCase() == str[0] ){
|
||||
return str[0].toUpperCase() + str.slice(1);
|
||||
}
|
||||
else{
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
||||
$(function() {
|
||||
$("#contract_document").change(function (){
|
||||
doc = document.getElementById("contract_document")
|
||||
if(doc.files && doc.files.length > 0) {
|
||||
name_split = doc.files[0].name.replace(".jpg","").replace(".pdf","").split(" ");
|
||||
|
||||
$("#contract_user_alert").remove(); // clear any existing alerts
|
||||
$("#contract_user_spinner").remove(); // clear spinner
|
||||
|
||||
if(name_split.length == 4){ // we have one name
|
||||
$("#contract_first_name").val(capitalizeIfIsntCapitalized(name_split[0]));
|
||||
$("#contract_last_name").val(capitalizeIfIsntCapitalized(name_split[1]));
|
||||
// 2 is the hyphen
|
||||
signed_at = new Date(name_split[3]);
|
||||
$("#contract_signed_at_1i").val(signed_at.getUTCFullYear()).change();
|
||||
$("#contract_signed_at_2i").val(signed_at.getUTCMonth()+1).change();
|
||||
$("#contract_signed_at_3i").val(signed_at.getUTCDate()).change();
|
||||
}
|
||||
else if(name_split.length == 7 && name_split[2] == "by"){ // we have two names
|
||||
$("#contract_first_name").val(capitalizeIfIsntCapitalized(name_split[0]));
|
||||
$("#contract_last_name").val(capitalizeIfIsntCapitalized(name_split[1]));
|
||||
// 2 is "by"
|
||||
$("#contract_cosigner").val(capitalizeIfIsntCapitalized(name_split[3])+" "+capitalizeIfIsntCapitalized(name_split[4]));
|
||||
// 5 is the hyphen
|
||||
signed_at = new Date(name_split[6]);
|
||||
$("#contract_signed_at_1i").val(signed_at.getUTCFullYear());
|
||||
$("#contract_signed_at_2i").val(signed_at.getUTCMonth()+1);
|
||||
$("#contract_signed_at_3i").val(signed_at.getUTCDate());
|
||||
}
|
||||
|
||||
// Try and select the relevant user if exists
|
||||
if( $("#contract_first_name").val().length > 0 && $("#contract_last_name").val().length > 0 ) {
|
||||
user_id = $('#contract_user_id option').filter(function(){
|
||||
return $(this).text() == $("#contract_first_name").val() + " " + $("#contract_last_name").val();
|
||||
}).prop("selected", "true").val();
|
||||
|
||||
// Start a spinner before AJAX request
|
||||
$("#contract_user_id").after("<i id='contract_user_spinner' class='icon-spin icon-refresh'></i>");
|
||||
// If we found a user, check how many contracts that user already has
|
||||
$.get("/users/"+user_id+"/contracts.json",function(data){
|
||||
$("#contract_user_spinner").remove(); // clear spinner
|
||||
if(data.length > 0){
|
||||
other_contract_links = $.map(data,function(item){
|
||||
output = "<a href='/contracts/"+item["id"]+"'>"+item["id"]+"</a> ";
|
||||
return output;
|
||||
});
|
||||
$("#contract_user_id").after("<span id='contract_user_alert' class='label label-danger'>Warning: this user already has "+data.length+" other contract(s). Check the existing one(s) to avoid duplication: "+other_contract_links+"</span>");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
41
app/views/contracts/show.html.erb
Normal file
41
app/views/contracts/show.html.erb
Normal file
|
@ -0,0 +1,41 @@
|
|||
<div class="row">
|
||||
<h1 class="col-md-8">
|
||||
Contract
|
||||
<%= link_to 'Back', contracts_path, :class => "btn btn-default" %>
|
||||
<%= link_to 'New', new_contract_path, :class => "btn btn-success" %>
|
||||
<%= link_to 'Edit', edit_contract_path(@contract), :class => "btn btn-primary" %>
|
||||
<%= link_to 'Delete', contract_path(@contract), {:confirm => 'Are you sure you want to delete this forever?', :method => :delete, :class => "btn btn-danger"} if can? :destroy, @contract %>
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
|
||||
<h2>
|
||||
<%= @contract.first_name %>
|
||||
<%= @contract.last_name %>
|
||||
<%= "and #{@contract.cosigner}" unless @contract.cosigner.blank? %>
|
||||
<%= link_to "(#{@contract.user.name})", @contract.user if @contract.user %>
|
||||
<small>
|
||||
signed
|
||||
<%= @contract.signed_at.to_date.to_s(:long) %>
|
||||
</small>
|
||||
</h2>
|
||||
<% unless @contract.created_by.blank? %>
|
||||
<p>
|
||||
<em>Created by <%= @contract.created_by.name %></em>
|
||||
</p>
|
||||
<% end %>
|
||||
|
||||
<% if @contract.document.blank? %>
|
||||
<p>No document uploaded</p>
|
||||
<% else %>
|
||||
<p><%= link_to "Download Contract", @contract.document.url %>
|
||||
<div class="col-xs-12">
|
||||
<% contract_url = (@contract.document.exists?(:large) ? @contract.document.url(:large) : @contract.document.url) %>
|
||||
<iframe src="<%= contract_url %>" width="100%" height="600"></iframe>
|
||||
</div>
|
||||
</p>
|
||||
<% end %>
|
||||
|
||||
|
||||
<br />
|
||||
|
0
app/views/devise/confirmations/new.html.erb
Normal file → Executable file
0
app/views/devise/confirmations/new.html.erb
Normal file → Executable file
0
app/views/devise/mailer/confirmation_instructions.html.erb
Normal file → Executable file
0
app/views/devise/mailer/confirmation_instructions.html.erb
Normal file → Executable file
0
app/views/devise/mailer/reset_password_instructions.html.erb
Normal file → Executable file
0
app/views/devise/mailer/reset_password_instructions.html.erb
Normal file → Executable file
0
app/views/devise/mailer/unlock_instructions.html.erb
Normal file → Executable file
0
app/views/devise/mailer/unlock_instructions.html.erb
Normal file → Executable file
0
app/views/devise/passwords/edit.html.erb
Normal file → Executable file
0
app/views/devise/passwords/edit.html.erb
Normal file → Executable file
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user