diff --git a/Gemfile b/Gemfile index 8a7b258c..2e785cf0 100644 --- a/Gemfile +++ b/Gemfile @@ -1,6 +1,7 @@ source 'https://rubygems.org' gem 'rails', '3.2.8' +gem 'rack-cors', :require => 'rack/cors' # Bundle edge Rails instead: # gem 'rails', :git => 'git://github.com/rails/rails.git' diff --git a/Gemfile.lock b/Gemfile.lock index f866280a..86f54d20 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -50,7 +50,7 @@ GEM ansi (1.4.3) arel (3.0.2) bcrypt-ruby (3.0.1) - builder (3.0.0) + builder (3.0.3) capybara (1.1.2) mime-types (>= 1.16) nokogiri (>= 1.3.3) @@ -90,37 +90,36 @@ GEM devise diff-lcs (1.1.3) erubis (2.7.0) - eventmachine (0.12.10) + eventmachine (1.0.0) execjs (1.4.0) multi_json (~> 1.0) - factory_girl (4.0.0) + factory_girl (4.1.0) activesupport (>= 3.0.0) - factory_girl_rails (4.0.0) - factory_girl (~> 4.0.0) + factory_girl_rails (4.1.0) + factory_girl (~> 4.1.0) railties (>= 3.0.0) ffi (1.1.5) fssm (0.2.9) haml (3.1.7) - haml-rails (0.3.4) - actionpack (~> 3.0) - activesupport (~> 3.0) - haml (~> 3.0) - railties (~> 3.0) + haml-rails (0.3.5) + actionpack (>= 3.1, < 4.1) + activesupport (>= 3.1, < 4.1) + haml (~> 3.1) + railties (>= 3.1, < 4.1) hike (1.2.1) i18n (0.6.1) journey (1.0.4) - jquery-rails (2.1.1) + jquery-rails (2.1.2) railties (>= 3.1.0, < 5.0) thor (~> 0.14) json (1.6.7) - kaminari (0.13.0) + kaminari (0.14.1) actionpack (>= 3.0.0) activesupport (>= 3.0.0) - railties (>= 3.0.0) - kaminari-bootstrap (0.1.2) - kaminari + kaminari-bootstrap (0.1.3) + kaminari (>= 0.13.0) rails - less (2.2.1) + less (2.2.2) commonjs (~> 0.2.6) less-rails (2.2.3) actionpack (>= 3.1) @@ -147,6 +146,8 @@ GEM rack (1.4.1) rack-cache (1.2) rack (>= 0.4) + rack-cors (0.2.7) + rack rack-ssl (1.3.2) rack rack-test (0.6.1) @@ -177,7 +178,7 @@ GEM rspec-expectations (~> 2.11.0) rspec-mocks (~> 2.11.0) rspec-core (2.11.1) - rspec-expectations (2.11.2) + rspec-expectations (2.11.3) diff-lcs (~> 1.1.3) rspec-mocks (2.11.2) rspec-rails (2.11.0) @@ -196,8 +197,8 @@ GEM libwebsocket (~> 0.1.3) multi_json (~> 1.0) rubyzip - slim (1.2.2) - temple (~> 0.4.0) + slim (1.3.0) + temple (~> 0.4.1) tilt (~> 1.3.3) slim-rails (1.0.3) actionpack (~> 3.0) @@ -210,7 +211,7 @@ GEM rack (~> 1.0) tilt (~> 1.1, != 1.3.0) subexec (0.2.2) - temple (0.4.0) + temple (0.4.1) therubyracer (0.10.2) libv8 (~> 3.3.10) thin (1.4.1) @@ -230,9 +231,9 @@ GEM railties (>= 3.1) therubyracer (~> 0.10.2) tzinfo (0.3.33) - uglifier (1.2.7) + uglifier (1.3.0) execjs (>= 0.3.0) - multi_json (~> 1.3) + multi_json (~> 1.0, >= 1.0.2) warden (1.1.1) rack (>= 1.0) xpath (0.1.4) @@ -254,6 +255,7 @@ DEPENDENCIES kaminari-bootstrap mini_magick pry + rack-cors rails (= 3.2.8) rqrcode rspec-rails diff --git a/app/assets/javascripts/qwaiter.js.coffee b/app/assets/javascripts/qwaiter.js.coffee index b8b663ed..f21fd9d0 100644 --- a/app/assets/javascripts/qwaiter.js.coffee +++ b/app/assets/javascripts/qwaiter.js.coffee @@ -1,5 +1,4 @@ -root = exports ? this -root.Qwaiter= +window.Qwaiter= alert: (msg) -> alert(msg) confirm: (options) -> diff --git a/app/assets/javascripts/user/application.js b/app/assets/javascripts/user/application.js index cc75048e..957aa310 100644 --- a/app/assets/javascripts/user/application.js +++ b/app/assets/javascripts/user/application.js @@ -33,7 +33,9 @@ var path_mapping = { user_root: '/user/home', join_occupied_table: '/user/join_occupied_table', list_products_for_table: '/user/list_products_for_table', - list_products: '/user/list_products' + list_products: '/user/list_products', + active_list: '/user/active_list', + history_list: '/user/history_list' } var translations = { confirmations: { @@ -67,7 +69,7 @@ function redirect_to(mapping, variables){ for(var name in variables){ vars.push(name + '=' +variables[name]) } - window.location = root_url + path_mapping[mapping] + '.html?' + vars.join('&') + window.location = QMobile.root_url() + path_mapping[mapping] + '.html?' + vars.join('&') } function currency(num) { return Qwaiter.currency(num); diff --git a/app/assets/javascripts/user/base64.js b/app/assets/javascripts/user/base64.js new file mode 100644 index 00000000..e6ed5788 --- /dev/null +++ b/app/assets/javascripts/user/base64.js @@ -0,0 +1,136 @@ +var Base64 = { + +// private property +_keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=", + +// public method for encoding +encode : function (input) { + var output = ""; + var chr1, chr2, chr3, enc1, enc2, enc3, enc4; + var i = 0; + + input = Base64._utf8_encode(input); + + while (i < input.length) { + + chr1 = input.charCodeAt(i++); + chr2 = input.charCodeAt(i++); + chr3 = input.charCodeAt(i++); + + enc1 = chr1 >> 2; + enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); + enc3 = ((chr2 & 15) << 2) | (chr3 >> 6); + enc4 = chr3 & 63; + + if (isNaN(chr2)) { + enc3 = enc4 = 64; + } else if (isNaN(chr3)) { + enc4 = 64; + } + + output = output + + this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) + + this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4); + + } + + return output; +}, + +// public method for decoding +decode : function (input) { + var output = ""; + var chr1, chr2, chr3; + var enc1, enc2, enc3, enc4; + var i = 0; + + input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ""); + + while (i < input.length) { + + enc1 = this._keyStr.indexOf(input.charAt(i++)); + enc2 = this._keyStr.indexOf(input.charAt(i++)); + enc3 = this._keyStr.indexOf(input.charAt(i++)); + enc4 = this._keyStr.indexOf(input.charAt(i++)); + + chr1 = (enc1 << 2) | (enc2 >> 4); + chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); + chr3 = ((enc3 & 3) << 6) | enc4; + + output = output + String.fromCharCode(chr1); + + if (enc3 != 64) { + output = output + String.fromCharCode(chr2); + } + if (enc4 != 64) { + output = output + String.fromCharCode(chr3); + } + + } + + output = Base64._utf8_decode(output); + + return output; + +}, + +// private method for UTF-8 encoding +_utf8_encode : function (string) { + string = string.replace(/\r\n/g,"\n"); + var utftext = ""; + + for (var n = 0; n < string.length; n++) { + + var c = string.charCodeAt(n); + + if (c < 128) { + utftext += String.fromCharCode(c); + } + else if((c > 127) && (c < 2048)) { + utftext += String.fromCharCode((c >> 6) | 192); + utftext += String.fromCharCode((c & 63) | 128); + } + else { + utftext += String.fromCharCode((c >> 12) | 224); + utftext += String.fromCharCode(((c >> 6) & 63) | 128); + utftext += String.fromCharCode((c & 63) | 128); + } + + } + + return utftext; +}, + +// private method for UTF-8 decoding +_utf8_decode : function (utftext) { + var string = ""; + var i = 0; + var c = c1 = c2 = 0; + + while ( i < utftext.length ) { + + c = utftext.charCodeAt(i); + + if (c < 128) { + string += String.fromCharCode(c); + i++; + } + else if((c > 191) && (c < 224)) { + c2 = utftext.charCodeAt(i+1); + string += String.fromCharCode(((c & 31) << 6) | (c2 & 63)); + i += 2; + } + else { + c2 = utftext.charCodeAt(i+1); + c3 = utftext.charCodeAt(i+2); + string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63)); + i += 3; + } + + } + + return string; +} + +} + diff --git a/app/assets/javascripts/user/quser.js.coffee b/app/assets/javascripts/user/quser.js.coffee index d24d1083..23580b47 100644 --- a/app/assets/javascripts/user/quser.js.coffee +++ b/app/assets/javascripts/user/quser.js.coffee @@ -1,5 +1,7 @@ data_host = window.data_host -root_url = window.root_url +root_url = QMobile.root_url() +authentication_string = QMobile.authentication_string() +authentication_object = $.parseJSON(QMobile.authentication_object()) window.Quser= format_date: (utc) -> formatted = '' @@ -8,9 +10,9 @@ window.Quser= formatted += utc.substr(11, 5) formatted home_loader: -> - $.getJSON(data_host + '/user/list_info.json', (res) -> Quser.handle_active_list_default_actions(res)) + $.getJSON(data_host + '/user/list_info.json?' + authentication_string, (res) -> Quser.handle_active_list_default_actions(res)) handle_active_list: (callback) -> - $.getJSON(data_host + '/user/list_info.json', (res) -> + $.getJSON(data_host + '/user/list_info.json?' + authentication_string, (res) -> if !res.list_active redirect_to 'user_root', {list_closed: 'true'} return @@ -38,11 +40,11 @@ window.Quser= wrapper = $('
') join_callback = ( (request)-> -> - $.post(data_host + '/user/approve_join_request', {user_id: request.user_id}, -> window.join_request_active = false; wrapper.modal('hide') ) + $.post(data_host + '/user/approve_join_request', $.extend({user_id: request.user_id}, authentication_object), -> window.join_request_active = false; wrapper.modal('hide') ) )(join_request) reject_callback = ( (request)-> -> - $.post(data_host + '/user/reject_join_request', {user_id: request.user_id}, -> window.join_request_active = false; wrapper.modal('hide' )) + $.post(data_host + '/user/reject_join_request', $.extend({user_id: request.user_id}, authentication_object), -> window.join_request_active = false; wrapper.modal('hide' )) )(join_request) header = $('') .append('') @@ -84,7 +86,7 @@ window.Quser= needs_help_container.data('click-initialized', true) list_needs_help: -> return unless window.active_list && !window.active_list.needs_help - $.post(data_host + '/user/needs_help.json', (res) -> window.active_list = res; Quser.list_needs_help_default_action(res)) + $.post(data_host + '/user/needs_help.json', authentication_object, (res) -> window.active_list = res; Quser.list_needs_help_default_action(res)) list_needs_payment_default_action: (response)-> response ||= window.active_list needs_payment_container = $('#list-needs-payment-button') @@ -109,12 +111,12 @@ window.Quser= needs_payment_container.data('click-initialized', true) list_needs_payment: -> return unless window.active_list && !window.active_list.needs_payment - $.post(data_host + '/user/list_needs_payment.json', (res) -> window.active_list = res; Quser.list_needs_payment_default_action(res)) + $.post(data_host + '/user/list_needs_payment.json', authentication_object, (res) -> window.active_list = res; Quser.list_needs_payment_default_action(res)) load_active_list: () -> - $.getJSON(data_host + '/user/active_list.json', (res) -> + $.getJSON(data_host + '/user/active_list.json?'+authentication_string, (res) -> window.active_list = res unless res.list_active - window.location = root_url + '/user/list_history/'+res._id + '.html?list_closed=true' + redirect_to 'history_list', {list_id: res._id, list_closed: true} return Quser.handle_active_list_default_actions(res) body = $('#active-list-table tbody') @@ -122,12 +124,12 @@ window.Quser= Quser.build_list_table(body, foot, res) ) load_history_list: () -> - match = window.document.URL.toString().match('([0-9a-zA-Z]+)(.html)?(\\?|$)') + match = window.document.URL.toString().match('list_id=([0-9a-zA-Z]+)') if match list_id = match[1] else return - $.getJSON(data_host + '/user/list_history/'+list_id+'.json', (res) -> + $.getJSON(data_host + '/user/history_list.json?list_id='+list_id+'&'+ authentication_string, (res) -> body = $('#history-list-table tbody') foot = $('#history-list-table tfoot') Quser.build_list_table(body, foot, res) @@ -140,13 +142,13 @@ window.Quser= page = match[1] else page = 1 - $.getJSON(data_host + '/user/list_history.json?page='+page, (res) -> + $.getJSON(data_host + '/user/list_history.json?'+authentication_string+'&page='+page, (res) -> Quser.paginate(res, '/user/list_history.html') container = $('#list-history-container') for list in res.lists li = $('').appendTo(container) link = $('').appendTo(li) - link.attr('href', '/user/list_history/'+list._id + '.html') + link.attr('href', root_url + '/user/history_list.html?list_id='+list._id) txt = list.supplier_name txt += ' - ' txt += Quser.format_date(list.created_at) @@ -165,7 +167,7 @@ window.Quser= li.addClass('active') link.attr('href', 'javascript:void(0)') else - link.attr('href', src + '?page='+i) + link.attr('href', root_url + src + '?'+authentication_string+'&page='+i) li.append(link) list.append(li) build_list_table: (body, foot, res) -> @@ -193,7 +195,7 @@ window.Quser= h['table_id'] = match[1] if match for product_id, info of window.active_products_list h['products['+product_id+']'] = info.number - $.post(data_host + '/user/order_selected_products', h, ((res) -> Quser.handle_response(res)), 'json') + $.post(data_host + '/user/order_selected_products', $.extend(h, authentication_object), ((res) -> Quser.handle_response(res)), 'json') handle_response: (res) -> if(typeof(res) == 'string') return unless res.length @@ -206,7 +208,7 @@ window.Quser= if res['message'] && !res['ok'] redirect_to 'user_root', {message: res['message']} else - redirect_to 'list_products' if res['ok'] + redirect_to res.location || 'list_products' if res['ok'] build_product_list: -> table = $('#active-order-table') tbody = table.find('tbody') @@ -225,7 +227,7 @@ window.Quser= table.show() load_active_list_products: -> - Quser.populate_products_table('/user/list_products.json') + Quser.populate_products_table('/user/list_products.json?'+authentication_string) load_table_products: -> match = window.document.URL.toString().match('table_id=([0-9a-zA-Z]+)') if match @@ -233,7 +235,7 @@ window.Quser= else redirect_to 'user_root', {message: 'cannot_identify_table'} return - Quser.populate_products_table('/user/list_products_for_table.json?table_id='+table_id) + Quser.populate_products_table('/user/list_products_for_table.json?'+authentication_string+'&table_id='+table_id) populate_products_table: (src)-> $.getJSON(data_host + src, (res) -> if res.has_occupied_info @@ -285,7 +287,7 @@ window.Quser= ) actions_for_table: (table)-> table = JSON.parse(table) if typeof(table) == 'string' - $.getJSON(data_host + '/user/table_info.json?table_id='+table.table_id, (res)-> + $.getJSON(data_host + '/user/table_info.json?'+authentication_string+'&table_id='+table.table_id, (res)-> if res.current_table_id if res.other_supplier redirect_to 'user_root', {message: 'table_is_from_other_supplier'} @@ -305,7 +307,7 @@ window.Quser= #TODO Offer to move table Qwaiter.confirm( ok: -> - $.post(data_host + '/user/move_table', {table_id: table.table_id}, (res2)-> + $.post(data_host + '/user/move_table', $.extend({table_id: table.table_id}, authentication_object), (res2)-> if res2.occupied alert('Cannot move to occupied table') else @@ -338,10 +340,10 @@ window.Quser= cont.html('') cont.append $('
')
cont.append $('Waiting for approval of the person on this table
') - $.post(data_host + '/user/join_occupied_table', {table_id: table_id}) + $.post(data_host + '/user/join_occupied_table', $.extend({table_id: table_id}, authentication_object)) setInterval('Quser.check_if_can_join_occupied_table("'+table_id+'")', 7500) check_if_can_join_occupied_table: (table_id)-> - $.post(data_host + '/user/check_table_join_status', {table_id: table_id}, (res) -> + $.post(data_host + '/user/check_table_join_status', $.extend({table_id: table_id}, authentication_object), (res) -> res ||= {} if res.approved redirect_to 'list_products' diff --git a/app/controllers/user_controller.rb b/app/controllers/user_controller.rb index 51c2fdce..aad400b6 100644 --- a/app/controllers/user_controller.rb +++ b/app/controllers/user_controller.rb @@ -7,6 +7,7 @@ class UserController < ApplicationController def allow_mobile headers['Access-Control-Allow-Origin'] = '*' headers['Access-Control-Request-Method'] = '*' + headers['Access-Control-Allow-Headers'] = '*' end def home @@ -261,7 +262,7 @@ class UserController < ApplicationController format.js do render js: js_alert(t('messages.cannot_order_on_non_active_list')) and return unless @list.active? @list.place_order current_user, params[:products] - render js: js_notice( t('messages.order_is_placed'), location: user_active_list_path ) + render js: js_notice( t('messages.order_is_placed'), location: :active_list) end end end diff --git a/app/views/layouts/phone.html.slim b/app/views/layouts/phone.html.slim index 24639b2c..7a388872 100644 --- a/app/views/layouts/phone.html.slim +++ b/app/views/layouts/phone.html.slim @@ -17,15 +17,22 @@ html lang="en" link href="/images/apple-touch-icon.png" rel="apple-touch-icon-precomposed" link href="/favicon.ico" rel="shortcut icon" javascript: - var QMobile; - var data_host = 'http://localhost:3000'; - var root_url = 'file:///Users/bterkuile/Documents/workspace/Qwaiter/assets'; + var data_host = 'http://data.qwaiter.com'; // Dummy holder when Qmobile object is not supplied by the mobile phone + var QMobile, Qwaiter, Quser; QMobile || (QMobile = { scanQr: function(){window.location = '/select_qrcode'}, activateRotation: function(){}, - mobile: function(){return false} + mobile: function(){return false}, + authentication_string: function(){return this.authentication_string_storage}, + authentication_object: function(){return this.authentication_object_storage}, + setAuthToken: function(token){ + this.authentication_string_storage = 'auth_token='+token; + this.authentication_object_storage = '{"auth_token": "'+token+'"}' + }, + root_url: function(){return ''} }); + QMobile.setAuthToken('i5brDZ1HS1okoEq3pMyh'); body class=action_name .navbar.navbar-fixed-top diff --git a/config/application.rb b/config/application.rb index fd1d1330..418e7b30 100644 --- a/config/application.rb +++ b/config/application.rb @@ -75,6 +75,13 @@ module Qrammer config.assets.precompile += ['supplier/application.css', 'user/application.css', 'qr_sheet/application.css'] config.default_url_options = {format: 'html'} + #config.middleware.use Rack::Cors do + # allow do + # origins '*' + # resource '/user/*', :headers => '*,auth_token', :methods => '*' #[:get, :post, :options] + # end + #end + # Version of your assets, change this if you want to expire all your assets config.assets.version = '1.0' end diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb index 9a867866..c9a65e1d 100644 --- a/config/initializers/devise.rb +++ b/config/initializers/devise.rb @@ -55,10 +55,10 @@ Devise.setup do |config| # It can be set to an array that will enable http authentication only for the # given strategies, for example, `config.http_authenticatable = [:token]` will # enable it only for token authentication. - config.http_authenticatable = [:token] + # config.http_authenticatable = [:token] # If http headers should be returned for AJAX requests. True by default. - config.http_authenticatable_on_xhr = true + # config.http_authenticatable_on_xhr = true # The realm used in Http Basic Authentication. "Application" by default. # config.http_authentication_realm = "Application" diff --git a/config/routes.rb b/config/routes.rb index 97bb6d82..bfe684d4 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -48,7 +48,7 @@ Qrammer::Application.routes.draw do get '/user/list_products' => 'user#list_products', as: :user_list_products get '/user/list_products_for_table' => 'user#list_products_for_table', as: :user_list_products_for_table match '/user/list_history' => 'user#list_history', as: :user_list_history - match '/user/list_history/:list_id' => 'user#history_list', as: :user_history_list + match '/user/history_list' => 'user#history_list', as: :user_history_list post '/user/order_selected_products' => 'user#order_selected_products', as: :user_order_selected_products post '/user/move_table' => 'user#move_table', as: :user_move_table get '/user/table_info' => 'user#table_info', as: :user_table_info diff --git a/make_android b/make_android index a59c2c22..523836de 100755 --- a/make_android +++ b/make_android @@ -1,4 +1,4 @@ -#!/usr/bin/bash +#!/usr/bin/env bash rm -rf public/assets; RAILS_ENV=production rake assets:precompile; RAILS_ENV=production rails runner script/build_mobile_app.rb diff --git a/script/build_mobile_app.rb b/script/build_mobile_app.rb index b2f6eb23..e55486ff 100644 --- a/script/build_mobile_app.rb +++ b/script/build_mobile_app.rb @@ -4,9 +4,11 @@ include FileUtils #`rake assets:precompile` android_root = '/Users/bterkuile/Documents/workspace/Qwaiter/assets' root_url = "file:///Users/bterkuile/Documents/workspace/Qwaiter/assets" +root_url = 'file:///android_asset' mkdir_p File.join(android_root, 'user') rm_rf File.join(android_root, 'assets') -cp_r Rails.root.join('public', 'assets'), File.join(android_root, 'assets') +Dir.glob(File.join('public', 'assets', '**', '*.gz')).each{|f| rm_f f} +move Rails.root.join('public', 'assets'), File.join(android_root, 'assets') for css in Dir.glob(File.join(android_root, "**", "*.css")) contents = File.read(css) contents.gsub!(/url\("/, %|url("#{root_url}|)