device-tracker 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +14 -0
  3. data/Gemfile +4 -0
  4. data/Rakefile +6 -0
  5. data/Readme.md +32 -0
  6. data/bin/console +14 -0
  7. data/bin/setup +7 -0
  8. data/device-tracker.gemspec +54 -0
  9. data/exe/device-tracker +50 -0
  10. data/lib/device/tracker.rb +19 -0
  11. data/lib/device/tracker/app.rb +25 -0
  12. data/lib/device/tracker/config-schema.json +53 -0
  13. data/lib/device/tracker/config.ru +9 -0
  14. data/lib/device/tracker/controllers/application_controller.rb +215 -0
  15. data/lib/device/tracker/controllers/devices_controller.rb +315 -0
  16. data/lib/device/tracker/controllers/heartbeat_controller.rb +55 -0
  17. data/lib/device/tracker/controllers/os_controller.rb +43 -0
  18. data/lib/device/tracker/controllers/transactions_controller.rb +21 -0
  19. data/lib/device/tracker/controllers/users_controller.rb +193 -0
  20. data/lib/device/tracker/db/data/devices.xlsx +0 -0
  21. data/lib/device/tracker/db/migrate/20150521071815_create_users.rb +13 -0
  22. data/lib/device/tracker/db/migrate/20150521082155_create_devices.rb +23 -0
  23. data/lib/device/tracker/db/migrate/20150521120335_create_operating_systems.rb +8 -0
  24. data/lib/device/tracker/db/migrate/20150527162242_create_transactions.rb +13 -0
  25. data/lib/device/tracker/db/migrate/20151027073050_create_heartbeat.rb +10 -0
  26. data/lib/device/tracker/db/migrate/20151028132946_add_user_verification.rb +7 -0
  27. data/lib/device/tracker/db/migrate/20151028141328_remove_is_active_from_users.rb +5 -0
  28. data/lib/device/tracker/db/migrate/20151029085629_add_password_reset_code_to_users.rb +7 -0
  29. data/lib/device/tracker/db/migrate/20151030130341_add_missing_column_to_devices.rb +7 -0
  30. data/lib/device/tracker/db/migrate/20151102141601_add_serial_number_to_devices.rb +7 -0
  31. data/lib/device/tracker/db/schema.rb +74 -0
  32. data/lib/device/tracker/db/seeds.rb +18 -0
  33. data/lib/device/tracker/dependencies.rb +15 -0
  34. data/lib/device/tracker/helpers/application_helper.rb +84 -0
  35. data/lib/device/tracker/models/device.rb +39 -0
  36. data/lib/device/tracker/models/heartbeat.rb +9 -0
  37. data/lib/device/tracker/models/operating_system.rb +8 -0
  38. data/lib/device/tracker/models/transaction.rb +56 -0
  39. data/lib/device/tracker/models/user.rb +22 -0
  40. data/lib/device/tracker/public/css/bootstrap-sortable.css +100 -0
  41. data/lib/device/tracker/public/css/bootstrap.min.css +5 -0
  42. data/lib/device/tracker/public/css/custom.css +88 -0
  43. data/lib/device/tracker/public/favicon.png +0 -0
  44. data/lib/device/tracker/public/favicon/android-chrome-144x144.png +0 -0
  45. data/lib/device/tracker/public/favicon/android-chrome-192x192.png +0 -0
  46. data/lib/device/tracker/public/favicon/android-chrome-36x36.png +0 -0
  47. data/lib/device/tracker/public/favicon/android-chrome-48x48.png +0 -0
  48. data/lib/device/tracker/public/favicon/android-chrome-72x72.png +0 -0
  49. data/lib/device/tracker/public/favicon/android-chrome-96x96.png +0 -0
  50. data/lib/device/tracker/public/favicon/apple-touch-icon-114x114.png +0 -0
  51. data/lib/device/tracker/public/favicon/apple-touch-icon-120x120.png +0 -0
  52. data/lib/device/tracker/public/favicon/apple-touch-icon-144x144.png +0 -0
  53. data/lib/device/tracker/public/favicon/apple-touch-icon-152x152.png +0 -0
  54. data/lib/device/tracker/public/favicon/apple-touch-icon-180x180.png +0 -0
  55. data/lib/device/tracker/public/favicon/apple-touch-icon-57x57.png +0 -0
  56. data/lib/device/tracker/public/favicon/apple-touch-icon-60x60.png +0 -0
  57. data/lib/device/tracker/public/favicon/apple-touch-icon-72x72.png +0 -0
  58. data/lib/device/tracker/public/favicon/apple-touch-icon-76x76.png +0 -0
  59. data/lib/device/tracker/public/favicon/apple-touch-icon-precomposed.png +0 -0
  60. data/lib/device/tracker/public/favicon/apple-touch-icon.png +0 -0
  61. data/lib/device/tracker/public/favicon/browserconfig.xml +12 -0
  62. data/lib/device/tracker/public/favicon/favicon-16x16.png +0 -0
  63. data/lib/device/tracker/public/favicon/favicon-32x32.png +0 -0
  64. data/lib/device/tracker/public/favicon/favicon-96x96.png +0 -0
  65. data/lib/device/tracker/public/favicon/favicon.ico +0 -0
  66. data/lib/device/tracker/public/favicon/manifest.json +41 -0
  67. data/lib/device/tracker/public/favicon/mstile-144x144.png +0 -0
  68. data/lib/device/tracker/public/favicon/mstile-150x150.png +0 -0
  69. data/lib/device/tracker/public/favicon/mstile-310x150.png +0 -0
  70. data/lib/device/tracker/public/favicon/mstile-310x310.png +0 -0
  71. data/lib/device/tracker/public/favicon/mstile-70x70.png +0 -0
  72. data/lib/device/tracker/public/favicon/safari-pinned-tab.svg +21 -0
  73. data/lib/device/tracker/public/fonts/glyphicons-halflings-regular.eot +0 -0
  74. data/lib/device/tracker/public/fonts/glyphicons-halflings-regular.svg +288 -0
  75. data/lib/device/tracker/public/fonts/glyphicons-halflings-regular.ttf +0 -0
  76. data/lib/device/tracker/public/fonts/glyphicons-halflings-regular.woff +0 -0
  77. data/lib/device/tracker/public/fonts/glyphicons-halflings-regular.woff2 +0 -0
  78. data/lib/device/tracker/public/js/bootstrap-sortable.js +211 -0
  79. data/lib/device/tracker/public/js/bootstrap.min.js +7 -0
  80. data/lib/device/tracker/public/js/jquery-2.1.4.min.js +4 -0
  81. data/lib/device/tracker/version.rb +5 -0
  82. data/lib/device/tracker/views/404.erb +25 -0
  83. data/lib/device/tracker/views/_alert.erb +5 -0
  84. data/lib/device/tracker/views/_device_form.erb +52 -0
  85. data/lib/device/tracker/views/_device_list.erb +47 -0
  86. data/lib/device/tracker/views/_footer.erb +3 -0
  87. data/lib/device/tracker/views/_header.erb +97 -0
  88. data/lib/device/tracker/views/_heartbeat_list.erb +25 -0
  89. data/lib/device/tracker/views/_user_form.erb +30 -0
  90. data/lib/device/tracker/views/devices/edit.erb +11 -0
  91. data/lib/device/tracker/views/devices/index.erb +12 -0
  92. data/lib/device/tracker/views/devices/new.erb +10 -0
  93. data/lib/device/tracker/views/devices/show.erb +283 -0
  94. data/lib/device/tracker/views/devices/users.erb +14 -0
  95. data/lib/device/tracker/views/emails/new_password.erb +17 -0
  96. data/lib/device/tracker/views/emails/password_reset.erb +18 -0
  97. data/lib/device/tracker/views/emails/registration.erb +16 -0
  98. data/lib/device/tracker/views/emails/reminder.erb +15 -0
  99. data/lib/device/tracker/views/emails/verification.erb +18 -0
  100. data/lib/device/tracker/views/forgot_password.erb +6 -0
  101. data/lib/device/tracker/views/index.erb +38 -0
  102. data/lib/device/tracker/views/layout.erb +8 -0
  103. data/lib/device/tracker/views/login.erb +14 -0
  104. data/lib/device/tracker/views/operating_system/operating_systems.json.jbuilder +9 -0
  105. data/lib/device/tracker/views/os/manage.erb +38 -0
  106. data/lib/device/tracker/views/transactions/_transactions_list.erb +18 -0
  107. data/lib/device/tracker/views/transactions/index.erb +3 -0
  108. data/lib/device/tracker/views/users/edit.erb +9 -0
  109. data/lib/device/tracker/views/users/manage.erb +31 -0
  110. data/lib/device/tracker/views/users/new.erb +7 -0
  111. metadata +427 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f30ce100bb30574c2c19fce33c2377c1c9d8e8e5
4
+ data.tar.gz: 3ccec9a1c68b47a6faeff309452231be5d8cf01d
5
+ SHA512:
6
+ metadata.gz: 2ea463439dd5676bc17b9c109792f68f493d1ad85ec9379ad50881cca2f178da63d25e528e9e2e9ca9a418584cff8d0f8defca06fce7089456b3ba12f5e95e6e
7
+ data.tar.gz: de3001994b8f48c01fd735c17594e466285948d08147082125de5026396f13b643fcd667eb6ea0d99bf3e7042c8e6a1190f61373d34c41c888a85c367cac9c8c
@@ -0,0 +1,14 @@
1
+ .idea/*
2
+ *.sqlite3
3
+ src/bin
4
+ backup.sql
5
+ /.bundle/
6
+ /.yardoc
7
+ /Gemfile.lock
8
+ /_yardoc/
9
+ /coverage/
10
+ /doc/
11
+ /pkg/
12
+ /spec/reports/
13
+ /tmp/
14
+
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
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,32 @@
1
+ # Device Tracker
2
+
3
+ ## Installation
4
+
5
+ Add this line to your application's Gemfile:
6
+
7
+ ```ruby
8
+ gem 'device-tracker'
9
+ ```
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install device-tracker
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Development
24
+
25
+ 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.
26
+
27
+ 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).
28
+
29
+ ## Contributing
30
+
31
+ Bug reports and pull requests are welcome on GitHub at https://github.com/bbc/device-tracker.
32
+
@@ -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
@@ -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,54 @@
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 = Device::Tracker::VERSION
9
+ spec.authors = ["James Ruston", "John Crossley"]
10
+ spec.email = ["james.ruston@bbc.com", "john.crossley@bbc.co.uk"]
11
+
12
+ spec.summary = %q{A web app for managing mobile devices}
13
+ spec.description = %q{
14
+ Keep track of your devices.
15
+ Features: - User registration/login/validation
16
+ - User levels (normal/admin)
17
+ - Checkout devices
18
+ - Return devices
19
+ - Assign devices to someone (Admin only)
20
+ - Validate a user (Admin only)
21
+ - Search devices
22
+ - Keep track of number of times devices used
23
+ - Manage OS versions
24
+ - Send reminders to someone who has had a device checked out for a long time
25
+ - Password reset
26
+ }
27
+ spec.homepage = "https://github.com/bbc/device-tracker"
28
+
29
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
30
+ spec.bindir = "exe"
31
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
32
+ spec.require_paths = ["lib"]
33
+
34
+ spec.add_development_dependency "bundler", "~> 1.7"
35
+ spec.add_development_dependency "rspec", "~> 3.4"
36
+ spec.add_development_dependency "tux", "~> 0.3"
37
+ spec.add_development_dependency "shotgun", "~> 0.9"
38
+ spec.add_development_dependency "byebug", "~> 8.1"
39
+
40
+ spec.add_dependency "sinatra", "~> 1.4"
41
+ spec.add_dependency "activerecord", "~> 4.0"
42
+ spec.add_dependency "sinatra-activerecord", "~> 2.0"
43
+ spec.add_dependency "bcrypt", "~> 3.1.7"
44
+ spec.add_dependency "json", "~> 1.7"
45
+ spec.add_dependency "sinatra-contrib", "~> 1.4"
46
+ spec.add_dependency "sinatra-partial", "~> 0.4"
47
+ spec.add_dependency "sinatra-flash", "~> 0.3"
48
+ spec.add_dependency "thin", "~> 1.6"
49
+ spec.add_dependency "rake", "~> 10.4"
50
+ spec.add_dependency "sqlite3", "~> 1.3"
51
+ spec.add_dependency "pony", "~> 1.11"
52
+ spec.add_dependency "mysql2", "~> 0.3.20"
53
+ spec.add_dependency "json-schema", "~> 2.5"
54
+ end
@@ -0,0 +1,50 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "device/tracker"
4
+ require "optparse"
5
+ require "json-schema"
6
+ require "json"
7
+
8
+ config_path = "./development.json"
9
+
10
+ opts = OptionParser.new do |opts|
11
+ opts.banner = "Usage: device-tracker [configuration]"
12
+
13
+ opts.separator ""
14
+
15
+ opts.on("-c", "--config" "path to config file") do |path|
16
+ config_path = path
17
+ end
18
+
19
+ opts.parse! ARGV
20
+ end
21
+
22
+ puts config_path
23
+
24
+ unless File.exists?(config_path)
25
+ puts "File not found at #{File.expand_path(config_path)}"
26
+ exit 1
27
+ end
28
+
29
+ json = File.read(config_path)
30
+
31
+ errors = JSON::Validator.fully_validate('./lib/device/tracker/config-schema.json', json)
32
+
33
+ unless errors.empty?
34
+ puts errors
35
+ exit 1
36
+ end
37
+
38
+ config = JSON.parse(json)
39
+
40
+ set :database, config["database"]
41
+ Pony.options = config["email"]
42
+ set :google_maps_api_key, config["google_maps_api_key"]
43
+
44
+ ActiveRecord::Migrator.migrate('./lib/device/tracker/db/migrate')
45
+
46
+ require './lib/device/tracker/dependencies'
47
+ require './lib/device/tracker/db/seeds'
48
+
49
+ Device::Tracker::Seed.seed(name: 'James Ruston', password: 'password', email: 'james.ruston@bbc.co.uk')
50
+ Device::Tracker.start
@@ -0,0 +1,19 @@
1
+ require "device/tracker/version"
2
+ require "device/tracker/dependencies"
3
+ require "device/tracker/app"
4
+ require "rack"
5
+
6
+ module Device
7
+ module Tracker
8
+ def self.start
9
+ options = {
10
+ :Host => '127.0.0.1',
11
+ :Port => '3000'
12
+ }
13
+
14
+ Rack::Handler::Thin.run(App.new, options) do |server|
15
+ [:INT, :TERM].each { |sig| trap(sig) { server.stop } }
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,25 @@
1
+ require_relative 'dependencies'
2
+ require 'rack'
3
+
4
+ module Device
5
+ module Tracker
6
+
7
+ class App
8
+ def initialize
9
+ @app = Rack::Builder.new do
10
+ map('/heartbeats') { run HeartbeatController }
11
+ map('/transactions') { run TransactionsController }
12
+ map('/users') { run UsersController }
13
+ map('/devices') { run DevicesController }
14
+ map('/os') { run OSController }
15
+ map('/') { run ApplicationController }
16
+ end
17
+ end
18
+
19
+ def call(env)
20
+ @app.call(env)
21
+ end
22
+ end
23
+
24
+ end
25
+ end
@@ -0,0 +1,53 @@
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
+ "database": {
15
+ "id": "http://jsonschema.net/database/database",
16
+ "type": "any"
17
+ }
18
+ },
19
+ "required": [
20
+ "adapter",
21
+ "database"
22
+ ]
23
+ },
24
+ "email": {
25
+ "id": "http://jsonschema.net/email",
26
+ "type": "object",
27
+ "properties": {
28
+ "from": {
29
+ "id": "http://jsonschema.net/email/from",
30
+ "type": "string"
31
+ },
32
+ "via": {
33
+ "id": "http://jsonschema.net/email/via",
34
+ "type": "string"
35
+ },
36
+ "via_options": {
37
+ "id": "http://jsonschema.net/email/via_options",
38
+ "type": "object",
39
+ "properties": {}
40
+ }
41
+ }
42
+ },
43
+ "google_maps_api_key": {
44
+ "id": "http://jsonschema.net/google_maps_api_key",
45
+ "type": "string"
46
+ }
47
+ },
48
+ "required": [
49
+ "database",
50
+ "email",
51
+ "google_maps_api_key"
52
+ ]
53
+ }
@@ -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,215 @@
1
+ module Device
2
+ module Tracker
3
+ class ApplicationController < Sinatra::Base
4
+ helpers ApplicationHelper
5
+
6
+ register Sinatra::ActiveRecordExtension
7
+ register Sinatra::Partial
8
+ register Sinatra::Flash
9
+
10
+ enable :sessions
11
+ enable :partial_underscores
12
+
13
+ set :views, File.expand_path('../../views', __FILE__)
14
+ set :public_dir, File.expand_path('../../public', __FILE__)
15
+ set :partial_template_engine, :erb
16
+ set :session_secret, SECRET
17
+
18
+ use Rack::MethodOverride
19
+
20
+ EMAILS_PATH = File.expand_path('../../views/emails/', __FILE__)
21
+
22
+ configure :development do
23
+ require 'byebug'
24
+ end
25
+
26
+ configure :production, :development do
27
+ enable :logging
28
+ end
29
+
30
+ not_found do
31
+ @administrators = User.where(is_verified: true, is_admin: true)
32
+ erb :"404"
33
+ end
34
+
35
+ get "/version" do
36
+ halt 200, {
37
+ error: false,
38
+ version: $version
39
+ }
40
+ end
41
+
42
+ get "/" do
43
+ @devices = Device.where(available: false).order(checked_out_since: :desc).limit(10)
44
+ erb :index, devices: @devices
45
+ end
46
+
47
+ get "/forgot-password" do
48
+
49
+ if !params[:user_id].nil? and !params[:password_reset].nil?
50
+
51
+ # Check to see if the user_id matches the password_reset
52
+
53
+ @user = User.where(id: params[:user_id], reset_code: params[:password_reset]).first
54
+
55
+ if @user.nil?
56
+ create_flash "warning", ["Sorry, but something went wrong. Did you click on the correct link?"]
57
+ redirect "/"
58
+ end
59
+
60
+ # Reset that back
61
+ @user.reset_code = nil
62
+
63
+ @new_password = generate_activation_code 12
64
+
65
+ @user.password = @new_password
66
+
67
+ @user.save
68
+
69
+ body = ERB.new(File.read(EMAILS_PATH + "/new_password.erb")).result(binding)
70
+
71
+ begin
72
+ Pony.mail(
73
+ :to => @user.email,
74
+ :from => 'no-reply@device-tracker',
75
+ :subject => 'New password | Device Tracker',
76
+ :html_body => body
77
+ )
78
+ rescue Net::OpenTimeout => e
79
+ puts "ERROR: Error sending email"
80
+ end
81
+
82
+ create_flash "success", ["Your new password has been emailed to #{@user.email}"]
83
+ redirect "/login"
84
+
85
+ else
86
+ erb :"forgot_password"
87
+ end
88
+ end
89
+
90
+ put "/:device_id/found" do |device_id|
91
+
92
+ if Device.exists?(device_id)
93
+
94
+ user = get_logged_in_user
95
+
96
+ device = Device.find(device_id)
97
+ device.missing = false
98
+ device.save
99
+
100
+ report_transaction("#{user[:email]} reported #{device.full_name} as found", Transaction.found, device)
101
+
102
+ create_flash "success", ["Yay.. The device has been returned successfully!"]
103
+ redirect back
104
+ else
105
+ raise Siatra::NotFound
106
+ end
107
+ end
108
+
109
+ put "/:device_id/missing" do |device_id|
110
+ if Device.exists?(device_id)
111
+
112
+ user = get_logged_in_user
113
+
114
+ device = Device.find(device_id)
115
+ device.missing = true
116
+ device.save
117
+
118
+ report_transaction("#{user[:email]} reported #{device.full_name} missing", Transaction.missing, device)
119
+
120
+ create_flash "success", ["Oh no, the device has been reported missing!"]
121
+ redirect back
122
+ else
123
+ raise Sinatra::NotFound
124
+ end
125
+ end
126
+
127
+ post "/forgot-password" do
128
+ # user = User.find(params[:email])
129
+ if User.exists?(email: params[:email])
130
+
131
+ # Generate a random string
132
+ random_string = generate_activation_code 24
133
+
134
+ @user = User.find_by_email(params[:email])
135
+ @user.reset_code = random_string
136
+ @user.save
137
+
138
+ @password_reset_url = request.url + "?user_id=#{@user.id}&password_reset=#{random_string}"
139
+
140
+ body = ERB.new(File.read(EMAILS_PATH + "/password_reset.erb")).result(binding)
141
+
142
+ # Email that user with the link
143
+ # /password-reset?user_id=1&reset_code=MWAZ9JT9WKRP7RPTF3RHEG9J
144
+ begin
145
+ Pony.mail(
146
+ :to => @user.email,
147
+ :subject => 'Password Reset | Device Tracker',
148
+ :html_body => body
149
+ )
150
+ rescue Net::OpenTimeout => e
151
+ puts "ERROR: Error sending email"
152
+ end
153
+
154
+ # Validate the link
155
+ # Send the user a new password
156
+
157
+ create_flash "success", ["We have sent you a password reset link to #{@user.email}"]
158
+ redirect back
159
+
160
+ else
161
+ create_flash "warning", ["Sorry, but the email #{params[:email]} doesn't exist."]
162
+ redirect back
163
+ end
164
+ end
165
+
166
+ get "/logout" do
167
+ session[:user] = nil
168
+ redirect to("/")
169
+ end
170
+
171
+ get "/login" do
172
+ erb :login
173
+ end
174
+
175
+ post "/login" do
176
+
177
+ # Parse the form
178
+ email = params[:user][:email]
179
+ password = params[:user][:password]
180
+
181
+ if email.empty? or password.empty?
182
+ create_flash "warning", ["Please supply a username and or password"]
183
+ redirect back
184
+ end
185
+
186
+ flash[:email] = email
187
+
188
+ user = User.find_by_email(email)
189
+
190
+ unless user.is_verified
191
+ create_flash "warning", ["Your account is waiting verification."]
192
+ redirect back
193
+ end
194
+
195
+ if user.nil? or !user.authenticate(password)
196
+ create_flash "warning", ["You entered an invalid username and or password, please try again."]
197
+ redirect back
198
+ end
199
+
200
+
201
+ session[:user] = {
202
+ id: user.id,
203
+ name: user.name,
204
+ email: user.email,
205
+ is_admin: user.is_admin,
206
+ is_verified: user.is_verified
207
+ }
208
+
209
+ redirect to("devices/users/#{session[:user][:id]}")
210
+
211
+ end
212
+
213
+ end
214
+ end
215
+ end