diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 68470d8..3094f18 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -7,6 +7,7 @@ class ApplicationController < ActionController::Base else flash[:alert] = "Nothing to see here!" end + Rails.logger.warn "----------\r\nWARNING: AccessDenied Exception: #{exception.inspect} User: #{current_user.inspect}\r\n----------" redirect_to root_url end diff --git a/app/controllers/space_api_controller.rb b/app/controllers/space_api_controller.rb index 919de65..fca6c8e 100644 --- a/app/controllers/space_api_controller.rb +++ b/app/controllers/space_api_controller.rb @@ -1,6 +1,8 @@ class SpaceApiController < ApplicationController - authorize_resource :except => :index - before_filter :authenticate_user!, :except => :index + # Individually remove authorizing stuff since there is no SpaceApi model + authorize_resource :except => [:index, :access, :access_post] + # User auth here happens via params, instead of form. + before_filter :authenticate_user!, :except => [:index, :access, :access_post] def index @json = JSON.parse(Setting.space_api_json_template) @@ -21,11 +23,74 @@ class SpaceApiController < ApplicationController respond_to do |format| format.html format.json { - response.headers['Access-Control-Allow-Origin'] = '*' response.headers["Cache-Control"] = "no-cache, no-store, max-age=0, must-revalidate" render :json => @json } end end + def access + @status = DoorLog.show_status + + # Nothing, just render form + unless user_signed_in? + @output = "Invalid email or password. Please login with your Members DB email and password below." + else + unless can? :access_doors_remotely, :door_access + @output = "Sorry, your account isn't able to control doors remotely." + end + end + end + + def access_post + @output = "" + + #if params['cmd'] == "check-login" then + # if users[params['user']] && users[params['user']]['pass'].to_s == (Digest::SHA2.new(bitlen=512) << params['pass']).to_s then + # @output += '{ "login": "okay" }' + # else + # @output += '{ "login": "fail" }' + # end + # + # exit + #end + + # Stop unless signed in already, OR if the supplied user/pass params are good. + unless current_user || check_auth(params['user'],params['pass']) + @output += "Invalid email or password." + else + # Stop unless the user can access the door system + unless can? :access_doors_remotely, :door_access + @output += "Sorry, your account isn't able to control doors remotely. Ask an admin if this is incorrect." + Rails.logger.warn "----------\r\nWARNING: DOOR ACCESS ATTEMPT DENIED. USER #{current_user.inspect}\r\n----------" + else + # Stop unless we've got a command to run + unless params['cmd'] + @output += "No command specified." + else + # Log the access + Rails.logger.info "Door access: user #{current_user.inspect}" + DoorLog.create!({:key => "rem_"+DoorLog.parse_command(params['cmd'])[:url_param], :data => current_user.id}) + + # Execute the access + @output += DoorLog.execute_command(params['cmd']) + end + end + end + + # Render the form again + 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 + end + end diff --git a/app/models/ability.rb b/app/models/ability.rb index a887aef..4253222 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -17,6 +17,10 @@ class Ability 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 + if user.card_access_enabled + can :access_doors_remotely, :door_access + end + # Instructors can manage certs and see users if user.instructor? can :manage, Certification @@ -39,8 +43,6 @@ class Ability # Admins can manage all if user.admin? -Rails.logger.info user.inspect -Rails.logger.info "IS ADMIN" can :manage, :all end diff --git a/app/models/door_log.rb b/app/models/door_log.rb index 353b043..324e333 100644 --- a/app/models/door_log.rb +++ b/app/models/door_log.rb @@ -2,6 +2,90 @@ class DoorLog < ActiveRecord::Base attr_accessible :data, :key require 'open-uri' + def self.execute_command(command) + output = "" + # load config values + door_access_url = APP_CONFIG['door_access_url'] + door_access_password = APP_CONFIG['door_access_password'] + + #login + source = open("#{door_access_url}?e=#{door_access_password}").read + results = source.scan(/ok/) + + #only continue if we've got an OK login + if(results.size > 0) then + # Parse the command and result + parsing = parse_command(command) + output += parsing[:output] + url_param = parsing[:url_param] + + # Execute the command + open("#{door_access_url}?#{url_param}") + + self.download_status # Update the status cache + else + output += 'Failed to connect to door system.' + end + + #logout + open("#{door_access_url}?e=0000") + + return output + end + + def self.parse_command(command) + output = "" + url_param = "" + # @commands = [ + # ["Unlock all doors","unlock"], + # ["Unlock Front door","unlock-front"], + # ["Unlock Rear door","unlock-rear"], + # ["Lock all doors","lock"], + # ["Lock Front door","lock-front"], + # ["Lock Rear door","lock-rear"], + # ["Open Front door","open-front"], + # ["Open Rear door","open-rear"], + # ["Arm alarm","arm"], + # ["Disarm alarm","disarm"] + # ] + case command + when "open-front" + output += "Front door opened." + url_param = "o1" + when "open-rear" + output += "Rear door opened." + url_param = "o2" + when "u", "unlock" + output += "Doors unlocked, remember to re-lock them." + url_param = "u" + when "u1", "unlock-front" + output += "Front Door unlocked, remember to re-lock it." + url_param = "u=1" + when "u2", "unlock-rear" + output += "Rear Door unlocked, remember to re-lock it." + url_param = "u=2" + when "lock", "l" + output += "Doors locked." + url_param = "l" + when "lock-front", "l1" + output += "Front Door locked." + url_param = "l=1" + when "lock-rear", "l2" + output += "Rear Door locked." + url_param = "l=2" + when "arm" + output += "Armed." + url_param = "2" + when "disarm" + output += "Disarmed." + url_param = "1" + else + output += "Fail. Don't be a naughty user!" + url_param = "9" # Using 9 because it's just status, no harm done + end + return {:output => output, :url_param => url_param} + end + def self.show_status door_logs = DoorLog.where(key: ["door_1_locked","door_2_locked"]).order('created_at DESC').take(2) door_1_locked = parse_locked_status(door_logs, "door_1_locked") diff --git a/app/models/user.rb b/app/models/user.rb index 5d0df20..1180736 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -56,6 +56,11 @@ class User < ActiveRecord::Base user_to_absorb.destroy end + def card_access_enabled + # If the user has at least one card with permission level 1, they have access + self.cards.where(:card_permissions => 1).count > 0 + end + def name_with_email_and_visibility if hidden then "#{name} (#{email}) HIDDEN" diff --git a/app/views/cards/index.html.erb b/app/views/cards/index.html.erb index 6fc4bfc..8e4fa53 100644 --- a/app/views/cards/index.html.erb +++ b/app/views/cards/index.html.erb @@ -1,8 +1,10 @@
Most Active Card Last Month: <%= @most_active_card.name unless @most_active_card.blank? %> (<%= @most_active_card.accesses_this_week unless @most_active_card.blank? %> days)
diff --git a/app/views/door_logs/index.html.erb b/app/views/door_logs/index.html.erb index e286c70..1ac3d02 100644 --- a/app/views/door_logs/index.html.erb +++ b/app/views/door_logs/index.html.erb @@ -8,6 +8,17 @@ Guide to Card Number storage: cardnum = (R+(r*32767)), convert to hex Guide to log keys and data: + +Commands: + * rem_ = remote command issues via web UI (#=user id) +Statuses: + * armed = current status of alarm arming + * activated = current status of alarm ringing + * alarm_2 = current status of alarm sensor 2 + * alarm_3 = current status of alarm sensor 3 + * door_1_locked = status of door 1 + * door_2_locked = status of door 2 +Log Entries: * A=alarm armed (# level) * a=added user (# usernum) * C=keypad command (# command) diff --git a/app/views/home/index.html.erb b/app/views/home/index.html.erb index ccf1789..70a0ed8 100644 --- a/app/views/home/index.html.erb +++ b/app/views/home/index.html.erb @@ -47,6 +47,9 @@+ <%= raw @output %> +
+
+ <%= label_tag :user, "Email Address" %>
+ <%= text_field_tag :user %>
+
+ <%= label_tag :pass, "Password" %>
+ <%= password_field_tag :pass %>
+
+
diff --git a/config/application.rb b/config/application.rb index 4cae87d..5b119f1 100644 --- a/config/application.rb +++ b/config/application.rb @@ -37,7 +37,7 @@ module Dooraccess config.encoding = "utf-8" # Configure sensitive parameters which will be filtered from the log file. - config.filter_parameters += [:password] + config.filter_parameters += [:password, :pass] # Use SQL instead of Active Record's schema dumper when creating the database. # This is necessary if your schema can't be completely dumped by the schema dumper, diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb index 367a7da..5082246 100644 --- a/config/initializers/devise.rb +++ b/config/initializers/devise.rb @@ -103,7 +103,7 @@ Devise.setup do |config| # ==> Configuration for :rememberable # The time the user will be remembered without asking for credentials again. - # config.remember_for = 2.weeks + config.remember_for = 1.month # If true, extends the user's remember period when remembered via cookie. # config.extend_remember_period = false diff --git a/config/routes.rb b/config/routes.rb index 22050cd..7d1ca5b 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -46,6 +46,8 @@ Dooraccess::Application.routes.draw do match 'cards/:id/upload' => 'cards#upload', :as => :upload match 'space_api' => 'space_api#index', :as => :space_api + match 'space_api/access' => 'space_api#access', :via => :get, :as => :space_api_access + match 'space_api/access' => 'space_api#access_post', :via => :post match 'door_logs' => 'door_logs#index', :as => :door_logs match 'door_logs/download' => 'door_logs#download', :as => :download