device_tracker 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (113) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.rspec +2 -0
  4. data/.rubocop.yml +4 -0
  5. data/Gemfile +4 -0
  6. data/Rakefile +10 -0
  7. data/Readme.md +32 -0
  8. data/bin/console +14 -0
  9. data/bin/setup +7 -0
  10. data/device_tracker.gemspec +63 -0
  11. data/exe/device_tracker +91 -0
  12. data/lib/device_tracker/app.rb +22 -0
  13. data/lib/device_tracker/config-schema.json +111 -0
  14. data/lib/device_tracker/config.ru +9 -0
  15. data/lib/device_tracker/controllers/application_controller.rb +226 -0
  16. data/lib/device_tracker/controllers/devices_controller.rb +315 -0
  17. data/lib/device_tracker/controllers/heartbeat_controller.rb +50 -0
  18. data/lib/device_tracker/controllers/os_controller.rb +38 -0
  19. data/lib/device_tracker/controllers/transactions_controller.rb +18 -0
  20. data/lib/device_tracker/controllers/users_controller.rb +131 -0
  21. data/lib/device_tracker/db/migrate/20150521071815_create_users.rb +14 -0
  22. data/lib/device_tracker/db/migrate/20150521082155_create_devices.rb +19 -0
  23. data/lib/device_tracker/db/migrate/20150521120335_create_operating_systems.rb +9 -0
  24. data/lib/device_tracker/db/migrate/20150527162242_create_transactions.rb +12 -0
  25. data/lib/device_tracker/db/migrate/20151027073050_create_heartbeat.rb +11 -0
  26. data/lib/device_tracker/db/migrate/20151028132946_add_user_verification.rb +8 -0
  27. data/lib/device_tracker/db/migrate/20151028141328_remove_is_active_from_users.rb +6 -0
  28. data/lib/device_tracker/db/migrate/20151029085629_add_password_reset_code_to_users.rb +8 -0
  29. data/lib/device_tracker/db/migrate/20151030130341_add_missing_column_to_devices.rb +8 -0
  30. data/lib/device_tracker/db/migrate/20151102141601_add_serial_number_to_devices.rb +8 -0
  31. data/lib/device_tracker/db/schema.rb +61 -0
  32. data/lib/device_tracker/db/seeds.rb +21 -0
  33. data/lib/device_tracker/dependencies.rb +16 -0
  34. data/lib/device_tracker/device_tracker.rb +18 -0
  35. data/lib/device_tracker/helpers/application_helper.rb +116 -0
  36. data/lib/device_tracker/helpers/user_helper.rb +24 -0
  37. data/lib/device_tracker/models/device.rb +42 -0
  38. data/lib/device_tracker/models/heartbeat.rb +7 -0
  39. data/lib/device_tracker/models/operating_system.rb +7 -0
  40. data/lib/device_tracker/models/transaction.rb +62 -0
  41. data/lib/device_tracker/models/user.rb +28 -0
  42. data/lib/device_tracker/public/css/bootstrap-sortable.css +100 -0
  43. data/lib/device_tracker/public/css/bootstrap.min.css +5 -0
  44. data/lib/device_tracker/public/css/custom.css +88 -0
  45. data/lib/device_tracker/public/favicon/android-chrome-144x144.png +0 -0
  46. data/lib/device_tracker/public/favicon/android-chrome-192x192.png +0 -0
  47. data/lib/device_tracker/public/favicon/android-chrome-36x36.png +0 -0
  48. data/lib/device_tracker/public/favicon/android-chrome-48x48.png +0 -0
  49. data/lib/device_tracker/public/favicon/android-chrome-72x72.png +0 -0
  50. data/lib/device_tracker/public/favicon/android-chrome-96x96.png +0 -0
  51. data/lib/device_tracker/public/favicon/apple-touch-icon-114x114.png +0 -0
  52. data/lib/device_tracker/public/favicon/apple-touch-icon-120x120.png +0 -0
  53. data/lib/device_tracker/public/favicon/apple-touch-icon-144x144.png +0 -0
  54. data/lib/device_tracker/public/favicon/apple-touch-icon-152x152.png +0 -0
  55. data/lib/device_tracker/public/favicon/apple-touch-icon-180x180.png +0 -0
  56. data/lib/device_tracker/public/favicon/apple-touch-icon-57x57.png +0 -0
  57. data/lib/device_tracker/public/favicon/apple-touch-icon-60x60.png +0 -0
  58. data/lib/device_tracker/public/favicon/apple-touch-icon-72x72.png +0 -0
  59. data/lib/device_tracker/public/favicon/apple-touch-icon-76x76.png +0 -0
  60. data/lib/device_tracker/public/favicon/apple-touch-icon-precomposed.png +0 -0
  61. data/lib/device_tracker/public/favicon/apple-touch-icon.png +0 -0
  62. data/lib/device_tracker/public/favicon/browserconfig.xml +12 -0
  63. data/lib/device_tracker/public/favicon/favicon-16x16.png +0 -0
  64. data/lib/device_tracker/public/favicon/favicon-32x32.png +0 -0
  65. data/lib/device_tracker/public/favicon/favicon-96x96.png +0 -0
  66. data/lib/device_tracker/public/favicon/favicon.ico +0 -0
  67. data/lib/device_tracker/public/favicon/manifest.json +41 -0
  68. data/lib/device_tracker/public/favicon/mstile-144x144.png +0 -0
  69. data/lib/device_tracker/public/favicon/mstile-150x150.png +0 -0
  70. data/lib/device_tracker/public/favicon/mstile-310x150.png +0 -0
  71. data/lib/device_tracker/public/favicon/mstile-310x310.png +0 -0
  72. data/lib/device_tracker/public/favicon/mstile-70x70.png +0 -0
  73. data/lib/device_tracker/public/favicon/safari-pinned-tab.svg +21 -0
  74. data/lib/device_tracker/public/favicon.png +0 -0
  75. data/lib/device_tracker/public/fonts/glyphicons-halflings-regular.eot +0 -0
  76. data/lib/device_tracker/public/fonts/glyphicons-halflings-regular.svg +288 -0
  77. data/lib/device_tracker/public/fonts/glyphicons-halflings-regular.ttf +0 -0
  78. data/lib/device_tracker/public/fonts/glyphicons-halflings-regular.woff +0 -0
  79. data/lib/device_tracker/public/fonts/glyphicons-halflings-regular.woff2 +0 -0
  80. data/lib/device_tracker/public/js/bootstrap-sortable.js +211 -0
  81. data/lib/device_tracker/public/js/bootstrap.min.js +7 -0
  82. data/lib/device_tracker/public/js/jquery-2.1.4.min.js +4 -0
  83. data/lib/device_tracker/version.rb +4 -0
  84. data/lib/device_tracker/views/404.erb +25 -0
  85. data/lib/device_tracker/views/_alert.erb +5 -0
  86. data/lib/device_tracker/views/_device_form.erb +52 -0
  87. data/lib/device_tracker/views/_device_list.erb +47 -0
  88. data/lib/device_tracker/views/_footer.erb +3 -0
  89. data/lib/device_tracker/views/_header.erb +97 -0
  90. data/lib/device_tracker/views/_heartbeat_list.erb +25 -0
  91. data/lib/device_tracker/views/_user_form.erb +30 -0
  92. data/lib/device_tracker/views/devices/edit.erb +11 -0
  93. data/lib/device_tracker/views/devices/index.erb +12 -0
  94. data/lib/device_tracker/views/devices/new.erb +10 -0
  95. data/lib/device_tracker/views/devices/show.erb +283 -0
  96. data/lib/device_tracker/views/devices/users.erb +14 -0
  97. data/lib/device_tracker/views/emails/new_password.erb +17 -0
  98. data/lib/device_tracker/views/emails/password_reset.erb +18 -0
  99. data/lib/device_tracker/views/emails/registration.erb +16 -0
  100. data/lib/device_tracker/views/emails/reminder.erb +15 -0
  101. data/lib/device_tracker/views/emails/verification.erb +18 -0
  102. data/lib/device_tracker/views/forgot_password.erb +6 -0
  103. data/lib/device_tracker/views/index.erb +38 -0
  104. data/lib/device_tracker/views/layout.erb +8 -0
  105. data/lib/device_tracker/views/login.erb +14 -0
  106. data/lib/device_tracker/views/operating_system/operating_systems.json.jbuilder +9 -0
  107. data/lib/device_tracker/views/os/manage.erb +38 -0
  108. data/lib/device_tracker/views/transactions/_transactions_list.erb +18 -0
  109. data/lib/device_tracker/views/transactions/index.erb +3 -0
  110. data/lib/device_tracker/views/users/edit.erb +9 -0
  111. data/lib/device_tracker/views/users/manage.erb +31 -0
  112. data/lib/device_tracker/views/users/new.erb +7 -0
  113. metadata +505 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 5d723cc5a90dabf8893383431a55eadc23c59414
4
+ data.tar.gz: 7e9d8ed84ab3d673f621b1ff3af1fd21df0eed34
5
+ SHA512:
6
+ metadata.gz: 5eff08a5da86eb468b2f88698ee2abdb20c27f2577fd0223211a292121440888272bed0ec12c03af5bb4019b052695c55b846c9e4ba8ae10a41fb7145347eced
7
+ data.tar.gz: 68c74502043868dd62ccdcb41cd216d44c6e3918107fb4565f55c6f6c05516ab47c61acc0398f7a2a4a10ac24e77101be6c718dbddf787a9555e988ccaf2f7f1
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ .idea/*
2
+ *.sqlite3
3
+ *.sqlite
4
+ src/bin
5
+ backup.sql
6
+ /.bundle/
7
+ /.yardoc
8
+ /Gemfile.lock
9
+ /_yardoc/
10
+ /coverage/
11
+ /doc/
12
+ /pkg/
13
+ /spec/reports/
14
+ /tmp/
15
+ capybara-*
16
+ development.json
17
+ .byebug_history
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format NyanCatMusicFormatter
data/.rubocop.yml ADDED
@@ -0,0 +1,4 @@
1
+ AllCops:
2
+ Exclude:
3
+ - lib/db/schema.rb
4
+ - lib/device_tracker/db/**/*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in device_tracker.gemspec
4
+ gemspec
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task default: :spec
7
+
8
+ task :debug do
9
+ sh 'bundle exec exe/device_tracker'
10
+ end
data/Readme.md ADDED
@@ -0,0 +1,32 @@
1
+ [![Gem Version](https://badge.fury.io/rb/device-tracker.svg)](https://badge.fury.io/rb/device-tracker)
2
+ # Device Tracker
3
+
4
+ ## Installation
5
+
6
+ Add this line to your application's Gemfile:
7
+
8
+ ```ruby
9
+ gem 'device_tracker'
10
+ ```
11
+
12
+ And then execute:
13
+
14
+ $ bundle
15
+
16
+ Or install it yourself as:
17
+
18
+ $ gem install device_tracker
19
+
20
+ ## Usage
21
+
22
+ TODO: Write usage instructions here
23
+
24
+ ## Development
25
+
26
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
27
+
28
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
29
+
30
+ ## Contributing
31
+
32
+ Bug reports and pull requests are welcome on GitHub at https://github.com/bbc/device-tracker.
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'device_tracker'
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require 'irb'
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,63 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'device_tracker/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'device_tracker'
8
+ spec.version = DeviceTracker::VERSION
9
+ spec.authors = ['James Ruston', 'John Crossley']
10
+ spec.email = ['james.ruston@bbc.com', 'john.crossley@bbc.co.uk']
11
+
12
+ spec.required_ruby_version = '~> 2.0'
13
+
14
+ spec.summary = 'A web app for managing mobile devices'
15
+ spec.description = <<-EOF
16
+ Keep track of your devices.
17
+ Features: - User registration/login/validation
18
+ - User levels (normal/admin)
19
+ - Checkout devices
20
+ - Return devices
21
+ - Assign devices to someone (Admin only)
22
+ - Validate a user (Admin only)
23
+ - Search devices
24
+ - Keep track of number of times devices used
25
+ - Manage OS versions
26
+ - Send reminders when devices have been out for period of time
27
+ - Password reset
28
+ EOF
29
+ spec.homepage = 'https://github.com/bbc/device-tracker'
30
+
31
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
32
+ f.match(%r{^(test|spec|features)/})
33
+ end
34
+ spec.bindir = 'exe'
35
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
36
+ spec.require_paths = ['lib']
37
+
38
+ spec.add_development_dependency 'bundler', '~> 1.7'
39
+ spec.add_development_dependency 'rspec', '~> 3.4'
40
+ spec.add_development_dependency 'shotgun', '~> 0.9'
41
+ spec.add_development_dependency 'byebug', '~> 8.1'
42
+ spec.add_development_dependency 'nyan-cat-formatter'
43
+ spec.add_development_dependency 'capybara'
44
+ spec.add_development_dependency 'poltergeist'
45
+ spec.add_development_dependency 'database_cleaner'
46
+ spec.add_development_dependency 'factory_girl'
47
+
48
+ spec.add_dependency 'sinatra', '~> 1.4'
49
+ spec.add_dependency 'activerecord', '~> 4.0'
50
+ spec.add_dependency 'sinatra-activerecord', '~> 2.0'
51
+ spec.add_dependency 'bcrypt', '~> 3.1.7'
52
+ spec.add_dependency 'json', '~> 1.7'
53
+ spec.add_dependency 'sinatra-contrib', '~> 1.4'
54
+ spec.add_dependency 'sinatra-partial', '~> 0.4'
55
+ spec.add_dependency 'sinatra-flash', '~> 0.3'
56
+ spec.add_dependency 'thin', '~> 1.6'
57
+ spec.add_dependency 'rake', '~> 10.4'
58
+ spec.add_dependency 'sqlite3', '~> 1.3'
59
+ spec.add_dependency 'pony', '~> 1.11'
60
+ spec.add_dependency 'mysql2', '~> 0.3.20'
61
+ spec.add_dependency 'json-schema', '~> 2.5'
62
+ spec.add_dependency 'faker'
63
+ end
@@ -0,0 +1,91 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'device_tracker/device_tracker'
4
+ require 'optparse'
5
+ require 'json-schema'
6
+ require 'json'
7
+
8
+ config_path = './development.json'
9
+
10
+ OptionParser.new do |opts|
11
+ opts.banner = 'Usage: device_tracker [configuration]'
12
+
13
+ opts.on('-c', '--config [PATH]', String, 'Path to the config file.') do |path|
14
+ puts path
15
+ config_path = path
16
+ end
17
+
18
+ begin
19
+ opts.parse! ARGV
20
+ rescue OptionParser::InvalidOption
21
+ puts 'Invalid options supplied, use `device_tracker -h` help.'
22
+ end
23
+ end
24
+
25
+ puts config_path
26
+
27
+ unless File.exist?(config_path)
28
+ puts "File not found at #{File.expand_path(config_path)}"
29
+ exit 1
30
+ end
31
+
32
+ json = File.read(config_path)
33
+
34
+ errors = JSON::Validator.fully_validate(
35
+ File.expand_path('../../lib/device_tracker/config-schema.json', __FILE__),
36
+ json
37
+ )
38
+
39
+ unless errors.empty?
40
+ puts errors
41
+ exit 1
42
+ end
43
+
44
+ config = JSON.parse(json)
45
+
46
+ set :database, config['database']
47
+
48
+ config['email'].symbolize_keys!
49
+ pony_options = {}
50
+
51
+ # HACK: This needs cleaning at some point
52
+ config['email'].each do |key, value|
53
+ if key == :via
54
+ pony_options[key] = value.to_sym if key == :via
55
+ else
56
+ if key == :via_options
57
+ pony_options[key] = value.symbolize_keys!
58
+ pony_options[:via_options].each do |i_key, i_val|
59
+ if i_key == :authentication
60
+ pony_options[:via_options][i_key] = i_val.to_sym
61
+ else
62
+ pony_options[:via_options][i_key] = i_val
63
+ end
64
+ end
65
+ else
66
+ pony_options[key] = value
67
+ end
68
+ end
69
+ end
70
+
71
+ require_relative '../lib/device_tracker/dependencies'
72
+
73
+ Pony.options = pony_options
74
+
75
+ DeviceTracker::ApplicationController.set :session_secret,
76
+ config['session_secret']
77
+ DeviceTracker::ApplicationController.set :google_maps_api_key,
78
+ config['google_maps_api_key']
79
+ port = config['port'] || '3000'
80
+ host = config['host'] || '127.0.0.1'
81
+
82
+ ActiveRecord::Migrator.migrate(
83
+ File.expand_path('../../lib/device_tracker/db/migrate', __FILE__)
84
+ )
85
+
86
+
87
+ require_relative '../lib/device_tracker/db/seeds'
88
+
89
+ DeviceTracker::Seed.seed(config['admin'])
90
+
91
+ DeviceTracker.start(host, port)
@@ -0,0 +1,22 @@
1
+ require_relative 'dependencies'
2
+ require 'rack'
3
+
4
+ module DeviceTracker
5
+ # :nodoc:
6
+ class App
7
+ def initialize
8
+ @app = Rack::Builder.new do
9
+ map('/heartbeats') { run HeartbeatController }
10
+ map('/transactions') { run TransactionsController }
11
+ map('/users') { run UsersController }
12
+ map('/devices') { run DevicesController }
13
+ map('/os') { run OSController }
14
+ map('/') { run ApplicationController }
15
+ end
16
+ end
17
+
18
+ def call(env)
19
+ @app.call(env)
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,111 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-04/schema#",
3
+ "id": "http://jsonschema.net",
4
+ "type": "object",
5
+ "properties": {
6
+ "database": {
7
+ "id": "http://jsonschema.net/database",
8
+ "type": "object",
9
+ "properties": {
10
+ "adapter": {
11
+ "id": "http://jsonschema.net/database/adapter",
12
+ "type": "string"
13
+ }
14
+ },
15
+ "required": [
16
+ "adapter"
17
+ ]
18
+ },
19
+ "email": {
20
+ "id": "http://jsonschema.net/email",
21
+ "type": "object",
22
+ "properties": {
23
+ "from": {
24
+ "id": "http://jsonschema.net/email/from",
25
+ "type": "string"
26
+ },
27
+ "via": {
28
+ "id": "http://jsonschema.net/email/via",
29
+ "type": "string"
30
+ },
31
+ "via_options": {
32
+ "id": "http://jsonschema.net/email/via_options",
33
+ "type": "object",
34
+ "properties": {
35
+ "address": {
36
+ "id": "http://jsonschema.net/email/via_options/address",
37
+ "type": "string"
38
+ },
39
+ "port": {
40
+ "id": "http://jsonschema.net/email/via_options/port",
41
+ "type": "string"
42
+ },
43
+ "enable_starttls_auto": {
44
+ "id": "http://jsonschema.net/email/via_options/enable_starttls_auto",
45
+ "type": "boolean"
46
+ },
47
+ "user_name": {
48
+ "id": "http://jsonschema.net/email/via_options/user_name",
49
+ "type": "string"
50
+ },
51
+ "password": {
52
+ "id": "http://jsonschema.net/email/via_options/password",
53
+ "type": "string"
54
+ },
55
+ "authentication": {
56
+ "id": "http://jsonschema.net/email/via_options/authentication",
57
+ "type": "string"
58
+ },
59
+ "domain": {
60
+ "id": "http://jsonschema.net/email/via_options/domain",
61
+ "type": "string"
62
+ }
63
+ }
64
+ }
65
+ }
66
+ },
67
+ "session_secret": {
68
+ "id": "http://jsonschema.net/session_secret",
69
+ "type": "string"
70
+ },
71
+ "google_maps_api_key": {
72
+ "id": "http://jsonschema.net/google_maps_api_key",
73
+ "type": "string"
74
+ },
75
+ "host": {
76
+ "id": "http://jsonschema.net/host",
77
+ "type": "string"
78
+ },
79
+ "port": {
80
+ "id": "http://jsonschema.net/port",
81
+ "type": "string"
82
+ },
83
+ "admin": {
84
+ "id": "http://jsonschema.net/admin",
85
+ "type": "object",
86
+ "properties": {
87
+ "name": {
88
+ "id": "http://jsonschema.net/admin/name",
89
+ "type": "string"
90
+ },
91
+ "email": {
92
+ "id": "http://jsonschema.net/admin/email",
93
+ "type": "string"
94
+ },
95
+ "password": {
96
+ "id": "http://jsonschema.net/admin/password",
97
+ "type": "string"
98
+ }
99
+ }
100
+ }
101
+ },
102
+ "required": [
103
+ "database",
104
+ "email",
105
+ "session_secret",
106
+ "google_maps_api_key",
107
+ "host",
108
+ "port",
109
+ "admin"
110
+ ]
111
+ }
@@ -0,0 +1,9 @@
1
+ require './dependencies'
2
+
3
+ # map the controllers to routes
4
+ map('/heartbeats') { run HeartbeatController }
5
+ map('/transactions') { run TransactionsController }
6
+ map('/users') { run UsersController }
7
+ map('/devices') { run DevicesController }
8
+ map('/os') { run OSController }
9
+ map('/') { run ApplicationController }
@@ -0,0 +1,226 @@
1
+ module DeviceTracker
2
+ # :nodoc:
3
+ class ApplicationController < Sinatra::Base
4
+ helpers ApplicationHelper
5
+ helpers UserHelper
6
+
7
+ register Sinatra::ActiveRecordExtension
8
+ register Sinatra::Partial
9
+ register Sinatra::Flash
10
+
11
+ enable :sessions
12
+ enable :partial_underscores
13
+
14
+ set :views, File.expand_path('../../views', __FILE__)
15
+ set :public_dir, File.expand_path('../../public', __FILE__)
16
+ set :partial_template_engine, :erb
17
+
18
+ set :email_path, File.expand_path('../../views/emails/', __FILE__)
19
+
20
+ use Rack::MethodOverride
21
+
22
+ configure :development do
23
+ require 'byebug'
24
+ end
25
+
26
+ configure :test do
27
+ set database: {
28
+ adapter: 'sqlite3',
29
+ database: File.expand_path('../../db/test.sqlite', __FILE__)
30
+ }
31
+ end
32
+
33
+ configure :production, :development do
34
+ enable :logging
35
+ end
36
+
37
+ not_found do
38
+ @administrators = User.where(is_verified: true, is_admin: true)
39
+ erb :"404"
40
+ end
41
+
42
+ get '/version' do
43
+ halt 200,
44
+ error: false,
45
+ version: DeviceTracker::VERSION
46
+ end
47
+
48
+ get '/' do
49
+ @devices = Device.where(available: false)
50
+ .order(checked_out_since: :desc).limit(10)
51
+
52
+ erb :index, devices: @devices
53
+ end
54
+
55
+ get '/forgot-password' do
56
+ if !params[:user_id].nil? && !params[:password_reset].nil?
57
+
58
+ # Check to see if the user_id matches the password_reset
59
+
60
+ @user = User.where(id: params[:user_id],
61
+ reset_code: params[:password_reset]).first
62
+
63
+ if @user.nil?
64
+ create_flash 'warning',
65
+ ['Hmm, that\'s not right. Did you click a valid link?']
66
+ redirect '/'
67
+ end
68
+
69
+ # Reset that back
70
+ @user.reset_code = nil
71
+
72
+ @new_password = generate_activation_code 12
73
+
74
+ @user.password = @new_password
75
+
76
+ @user.save
77
+
78
+ body = ERB.new(
79
+ File.read(settings.email_path + '/new_password.erb')
80
+ ).result(binding)
81
+
82
+ send_email(
83
+ to: @user.email,
84
+ from: 'no-reply@device-tracker',
85
+ subject: 'New password | Device Tracker',
86
+ body: body
87
+ )
88
+
89
+ create_flash 'success',
90
+ ["Your new password has been emailed to #{@user.email}"]
91
+ redirect '/login'
92
+
93
+ else
94
+ erb :forgot_password
95
+ end
96
+ end
97
+
98
+ put '/:device_id/found' do |device_id|
99
+ if Device.exists?(device_id)
100
+
101
+ user = logged_in_user
102
+
103
+ device = Device.find(device_id)
104
+ device.missing = false
105
+ device.save
106
+
107
+ report_transaction(
108
+ "#{user[:email]} reported #{device.full_name} as found",
109
+ Transaction.found, device
110
+ )
111
+
112
+ create_flash 'success',
113
+ ['The device has been returned successfully!']
114
+ redirect back
115
+ else
116
+ fail Siatra::NotFound
117
+ end
118
+ end
119
+
120
+ put '/:device_id/missing' do |device_id|
121
+ if Device.exists?(device_id)
122
+
123
+ user = logged_in_user
124
+
125
+ device = Device.find(device_id)
126
+ device.missing = true
127
+ device.save
128
+
129
+ report_transaction(
130
+ "#{user[:email]} reported #{device.full_name} missing",
131
+ Transaction.missing,
132
+ device
133
+ )
134
+
135
+ create_flash 'success', ['The device has been reported missing!']
136
+ redirect back
137
+ else
138
+ fail Sinatra::NotFound
139
+ end
140
+ end
141
+
142
+ post '/forgot-password' do
143
+ # user = User.find(params[:email])
144
+ if User.exists?(email: params[:email])
145
+
146
+ # Generate a random string
147
+ random_string = generate_activation_code 24
148
+
149
+ @user = User.find_by_email(params[:email])
150
+ @user.reset_code = random_string
151
+ @user.save
152
+
153
+ @reset_url = request.url +
154
+ "?user_id=#{@user.id}&password_reset=" + random_string
155
+
156
+ body = ERB.new(
157
+ File.read(settings.email_path + '/password_reset.erb')
158
+ ).result(binding)
159
+
160
+ # Email that user with the link
161
+ # /password-reset?user_id=1&reset_code=MWAZ9JT9WKRP7RPTF3RHEG9J
162
+ send_email(
163
+ to: @user.email,
164
+ from: 'no-reply@device-tracker',
165
+ subject: 'Password Reset | Device Tracker',
166
+ body: body
167
+ )
168
+
169
+ # Validate the link
170
+ # Send the user a new password
171
+
172
+ create_flash 'success',
173
+ ["A password reset link has been sent to #{@user.email}"]
174
+ redirect back
175
+
176
+ else
177
+ create_flash 'warning',
178
+ ["Sorry, but the email #{params[:email]} doesn't exist."]
179
+ redirect back
180
+ end
181
+ end
182
+
183
+ get '/logout' do
184
+ session[:user] = nil
185
+ redirect to('/')
186
+ end
187
+
188
+ get '/login' do
189
+ erb :login
190
+ end
191
+
192
+ post '/login' do
193
+ # Parse the form
194
+ email = params[:user][:email]
195
+ password = params[:user][:password]
196
+
197
+ if email.empty? || password.empty?
198
+ create_flash 'warning', ['Please supply a username and or password']
199
+ redirect back
200
+ end
201
+
202
+ flash[:email] = email
203
+
204
+ user = User.find_by_email(email)
205
+
206
+ if user.nil? || !user.authenticate(password)
207
+ flash_and_go_back 'warning',
208
+ ['Invalid username and or password entered.']
209
+ end
210
+
211
+ unless user.is_verified
212
+ flash_and_go_back 'warning', ['Your account is waiting verification.']
213
+ end
214
+
215
+ session[:user] = {
216
+ id: user.id,
217
+ name: user.name,
218
+ email: user.email,
219
+ is_admin: user.is_admin,
220
+ is_verified: user.is_verified
221
+ }
222
+
223
+ redirect to("devices/users/#{session[:user][:id]}")
224
+ end
225
+ end
226
+ end