visor-auth 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/visor-admin +282 -0
- data/bin/visor-auth +8 -0
- data/lib/auth/backends/base.rb +167 -0
- data/lib/auth/backends/mongo_db.rb +165 -0
- data/lib/auth/backends/mysql_db.rb +186 -0
- data/lib/auth/cli.rb +333 -0
- data/lib/auth/client.rb +149 -0
- data/lib/auth/server.rb +215 -0
- data/lib/auth/version.rb +5 -0
- data/lib/visor-auth.rb +12 -0
- data/spec/lib/server_spec.rb +189 -0
- metadata +203 -0
data/bin/visor-admin
ADDED
@@ -0,0 +1,282 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'optparse'
|
4
|
+
require 'uri'
|
5
|
+
require 'visor-common'
|
6
|
+
$:.unshift File.expand_path('../../lib', __FILE__)
|
7
|
+
require 'auth/version'
|
8
|
+
require 'auth/client'
|
9
|
+
|
10
|
+
# VISoR administration command line interface script.
|
11
|
+
#
|
12
|
+
# Commands:
|
13
|
+
#
|
14
|
+
#list Show all registered users
|
15
|
+
#get Show a specific user
|
16
|
+
#add Register a new user
|
17
|
+
#update Update an user
|
18
|
+
#delete Delete an user
|
19
|
+
#clean Delete all users
|
20
|
+
#help <cmd> Show help message for one of the above commands
|
21
|
+
#
|
22
|
+
# Run <visor -h> to get more usage help.
|
23
|
+
#
|
24
|
+
class VisorAdminCLI
|
25
|
+
include Visor::Common::Exception
|
26
|
+
include Visor::Common::Config
|
27
|
+
|
28
|
+
# VISoR Admin CLI version
|
29
|
+
VERSION = '0.0.1'
|
30
|
+
|
31
|
+
attr_reader :argv, :options, :parser, :command
|
32
|
+
|
33
|
+
# Initialize a new CLI
|
34
|
+
def initialize(argv=ARGV)
|
35
|
+
@argv = argv
|
36
|
+
@options = load_conf_file
|
37
|
+
@parser = parser
|
38
|
+
@command = parse!
|
39
|
+
end
|
40
|
+
|
41
|
+
# OptionParser parser
|
42
|
+
def parser
|
43
|
+
OptionParser.new do |opts|
|
44
|
+
opts.banner = "Usage: visor-admin <command> [options]"
|
45
|
+
|
46
|
+
opts.separator ""
|
47
|
+
opts.separator "Commands:"
|
48
|
+
opts.separator " list Show all registered users"
|
49
|
+
opts.separator " get Show a specific user"
|
50
|
+
opts.separator " add Register a new user"
|
51
|
+
opts.separator " update Update an user"
|
52
|
+
opts.separator " delete Delete an user"
|
53
|
+
opts.separator " clean Delete all users"
|
54
|
+
opts.separator " help <cmd> Show help message for one of the above commands"
|
55
|
+
|
56
|
+
opts.separator ""
|
57
|
+
opts.separator "Options:"
|
58
|
+
opts.on("-a", "--access KEY", "The user access key (username)") { |key| options[:access_key] = key }
|
59
|
+
opts.on("-e", "--email ADDRESS", "The user email address") { |addr| options[:email] = addr }
|
60
|
+
opts.on("-q", "--query QUERY", "HTTP query like string to filter results") do |query|
|
61
|
+
(options[:query] = URI.decode_www_form(query)) rescue abort "The provided query string is not valid."
|
62
|
+
end
|
63
|
+
|
64
|
+
opts.separator ""
|
65
|
+
opts.separator "Common options:"
|
66
|
+
opts.on_tail("-D", "--dry-run", "Don't persist results, just print what would it do") { options[:dry] = true }
|
67
|
+
opts.on_tail('-v', '--verbose', "Enable verbose") { options[:verbose] = true }
|
68
|
+
opts.on_tail("-h", "--help", "Show this help message") { puts opts; exit 0 }
|
69
|
+
opts.on_tail('-V', '--version', "Show version") { puts "VISoR Admin CLI v#{VERSION}"; exit 0 }
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
# Parse argv arguments
|
74
|
+
def parse!
|
75
|
+
parser.parse! ARGV
|
76
|
+
ARGV.shift
|
77
|
+
end
|
78
|
+
|
79
|
+
# Parse the current shell arguments and run the command
|
80
|
+
def run!
|
81
|
+
abort parser.to_s if command.nil?
|
82
|
+
start = Time.now
|
83
|
+
case command
|
84
|
+
when 'list' then
|
85
|
+
list
|
86
|
+
when 'get' then
|
87
|
+
get
|
88
|
+
when 'add' then
|
89
|
+
add
|
90
|
+
when 'update' then
|
91
|
+
update
|
92
|
+
when 'delete' then
|
93
|
+
delete
|
94
|
+
when 'help' then
|
95
|
+
help
|
96
|
+
else
|
97
|
+
abort "Unknown command '#{command}'"
|
98
|
+
end
|
99
|
+
finish = Time.now
|
100
|
+
printf("Done in %-0.4f seconds", finish - start) if verbose?
|
101
|
+
exit 0
|
102
|
+
end
|
103
|
+
|
104
|
+
# Show all registered users
|
105
|
+
def list
|
106
|
+
users = client.get_users(options[:query])
|
107
|
+
puts "Found #{users.size} users..."
|
108
|
+
print_users(users)
|
109
|
+
rescue NotFound => e
|
110
|
+
puts e.message
|
111
|
+
rescue => e
|
112
|
+
abort "Failure while executing 'list':\n#{e.message}"
|
113
|
+
end
|
114
|
+
|
115
|
+
# Retrieve an user
|
116
|
+
def get
|
117
|
+
access_key = argv.shift
|
118
|
+
abort "No user access key provided as first argument, please provide it." unless access_key
|
119
|
+
user = client.get_user(access_key)
|
120
|
+
print_users(user)
|
121
|
+
rescue NotFound => e
|
122
|
+
puts e.message
|
123
|
+
rescue => e
|
124
|
+
abort "Failure while executing 'get':\n#{e.message}"
|
125
|
+
end
|
126
|
+
|
127
|
+
# Add a new user
|
128
|
+
def add
|
129
|
+
begin
|
130
|
+
info = parse_info_from_args
|
131
|
+
user = client.post_user(info)
|
132
|
+
puts "Successfully added new user with access key '#{user[:access_key]}'."
|
133
|
+
print_users(user)
|
134
|
+
rescue NotFound => e
|
135
|
+
puts e.message
|
136
|
+
rescue => e
|
137
|
+
abort "Failure while executing 'add':\n#{e.message}"
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
# Update an user
|
142
|
+
def update
|
143
|
+
access_key = argv.shift
|
144
|
+
abort "No user access key provided as first argument, please provide it." unless access_key
|
145
|
+
begin
|
146
|
+
info = parse_info_from_args
|
147
|
+
user = client.put_user(access_key, info)
|
148
|
+
puts "Successfully updated the user #{access_key}."
|
149
|
+
print_users(user) if verbose?
|
150
|
+
rescue NotFound => e
|
151
|
+
puts e.message
|
152
|
+
rescue => e
|
153
|
+
abort "Failure while executing 'update':\n#{e.message}"
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
# Delete an user
|
158
|
+
def delete
|
159
|
+
begin
|
160
|
+
argv.each do |access_key|
|
161
|
+
abort "No user access key provided as first argument, please provide it." unless access_key
|
162
|
+
user = client.delete_user(access_key)
|
163
|
+
puts "Successfully deleted user #{access_key}."
|
164
|
+
print_users(user) if verbose?
|
165
|
+
end
|
166
|
+
end
|
167
|
+
rescue NotFound => e
|
168
|
+
puts e.message
|
169
|
+
rescue => e
|
170
|
+
abort "Failure while executing 'delete':\n#{e.message}"
|
171
|
+
end
|
172
|
+
|
173
|
+
# Show help message for one of the above commands
|
174
|
+
def help
|
175
|
+
cmd = argv[0]
|
176
|
+
abort "Please provide a command name as argument (example: visor-admin help list)." unless cmd
|
177
|
+
|
178
|
+
case cmd.to_sym
|
179
|
+
when :list
|
180
|
+
puts %q[Usage: visor-admin list [options]
|
181
|
+
|
182
|
+
Returns a list of all registered users.
|
183
|
+
|
184
|
+
You can filter results based on a query using the --query (-q) option.
|
185
|
+
|
186
|
+
Examples:
|
187
|
+
$ visor-admin list
|
188
|
+
$ visor-admin list --query email=foo@bar.com]
|
189
|
+
when :get
|
190
|
+
puts %q[Usage: visor-admin get <ACCESS KEY> [options]
|
191
|
+
|
192
|
+
Returns the account information of the user with the given access key.
|
193
|
+
|
194
|
+
Examples:
|
195
|
+
$ visor get foo]
|
196
|
+
when :add
|
197
|
+
puts %q[Usage: visor-admin add <ATTRIBUTES> [options]
|
198
|
+
|
199
|
+
Add a new user, providing its attributes.
|
200
|
+
|
201
|
+
The following attributes can be specified as key/value pairs:
|
202
|
+
|
203
|
+
access_key: The wanted user access key (username)
|
204
|
+
email: The user email address
|
205
|
+
|
206
|
+
Examples:
|
207
|
+
$ visor-admin add access_key=foo email=foo@bar.com]
|
208
|
+
when :update
|
209
|
+
puts %q[Usage: visor-admin update <ACCESS KEY> [options]
|
210
|
+
|
211
|
+
Updates the account information of the user with the given access key.
|
212
|
+
|
213
|
+
The following attributes can be specified as key/value pairs:
|
214
|
+
|
215
|
+
access_key: The wanted user access key (username)
|
216
|
+
email: The user email address
|
217
|
+
|
218
|
+
Examples:
|
219
|
+
$ visor update foo email=bar@foo.com]
|
220
|
+
when :delete
|
221
|
+
puts %q[Usage: visor-admin delete <ACCESS KEY> [options]
|
222
|
+
|
223
|
+
Deletes the account of the user with the given access key.
|
224
|
+
|
225
|
+
Examples:
|
226
|
+
$ visor delete foo]
|
227
|
+
else
|
228
|
+
abort "Unknown command '#{cmd}'"
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
private
|
233
|
+
|
234
|
+
# Pretty print users
|
235
|
+
def print_users(user)
|
236
|
+
str = "%-37s %-18s %-41s %-27s %-24s %-24s\n"
|
237
|
+
printf(str, 'ID', 'ACCESS KEY', 'SECRET KEY', 'EMAIL', 'CREATED AT', 'UPDATED AT')
|
238
|
+
puts "#{'-'*36+" "+'-'*17+" "+'-'*40+" "+'-'*26+" "+'-'*23+" "+'-'*23}"
|
239
|
+
|
240
|
+
if user.is_a?(Array)
|
241
|
+
user.each { |u| printf(str, u[:_id], u[:access_key], u[:secret_key], u[:email] || '-', u[:created_at] || '-', u[:updated_at] || '-') }
|
242
|
+
else
|
243
|
+
printf(str, user[:_id], user[:access_key], user[:secret_key], user[:email] || '-', user[:created_at] || '-', user[:updated_at] || '-')
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
# Load configuration file options
|
248
|
+
def load_conf_file
|
249
|
+
config = Visor::Common::Config.load_config(:visor_auth)
|
250
|
+
{host: config[:bind_host], port: config[:bind_port]}
|
251
|
+
rescue => e
|
252
|
+
raise "There was an error loading the configuration file: #{e.message}"
|
253
|
+
end
|
254
|
+
|
255
|
+
# Get a new VISoR Auth Client instance
|
256
|
+
def client
|
257
|
+
Visor::Auth::Client.new(options)
|
258
|
+
end
|
259
|
+
|
260
|
+
# Find if verbose mode is active
|
261
|
+
def verbose?
|
262
|
+
options[:verbose]
|
263
|
+
end
|
264
|
+
|
265
|
+
# Parse key/value pair arguments to a valid hash
|
266
|
+
def parse_info_from_args
|
267
|
+
info = {}
|
268
|
+
raise "You should provide at least one key=value pair." if argv.empty?
|
269
|
+
argv.each do |arg|
|
270
|
+
k, v = arg.split('=')
|
271
|
+
raise "Arguments should be in the form of key=value pairs." unless k && v
|
272
|
+
info[k.downcase.sub('-', '_')] = v
|
273
|
+
end
|
274
|
+
info
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
# Execute if file is called
|
279
|
+
#if __FILE__ == $0
|
280
|
+
VisorAdminCLI.new.run!
|
281
|
+
#end
|
282
|
+
|
data/bin/visor-auth
ADDED
@@ -0,0 +1,167 @@
|
|
1
|
+
require 'securerandom'
|
2
|
+
|
3
|
+
module Visor
|
4
|
+
module Auth
|
5
|
+
module Backends
|
6
|
+
|
7
|
+
# This is the Base super class for all Backends. Each new backend inherits from Base,
|
8
|
+
# which contains the model and all validations for the users metadata.
|
9
|
+
#
|
10
|
+
# Implementing a new backend is as simple as create a new backend class which inherits
|
11
|
+
# from Base and them implement the specific methods for querying the underlying database.
|
12
|
+
#
|
13
|
+
class Base
|
14
|
+
|
15
|
+
# Keys validation
|
16
|
+
#
|
17
|
+
# Mandatory attributes
|
18
|
+
MANDATORY = [:access_key, :email]
|
19
|
+
# Read-only attributes
|
20
|
+
READONLY = [:_id, :secret_key, :created_at, :updated_at]
|
21
|
+
# All attributes
|
22
|
+
ALL = MANDATORY + READONLY
|
23
|
+
|
24
|
+
attr_reader :db, :host, :port, :user, :password, :conn
|
25
|
+
|
26
|
+
# Initializes a Backend instance.
|
27
|
+
#
|
28
|
+
# @option [Hash] opts Any of the available options can be passed.
|
29
|
+
#
|
30
|
+
# @option opts [String] :host The host address.
|
31
|
+
# @option opts [Integer] :port The port to be used.
|
32
|
+
# @option opts [String] :db The wanted database.
|
33
|
+
# @option opts [String] :user The username to be authenticate db access.
|
34
|
+
# @option opts [String] :password The password to be authenticate db access.
|
35
|
+
# @option opts [Object] :conn The connection pool to access database.
|
36
|
+
#
|
37
|
+
def initialize(opts)
|
38
|
+
@host = opts[:host]
|
39
|
+
@port = opts[:port]
|
40
|
+
@db = opts[:db]
|
41
|
+
@user = opts[:user]
|
42
|
+
@password = opts[:password]
|
43
|
+
@conn = opts[:conn]
|
44
|
+
end
|
45
|
+
|
46
|
+
# Validates the user information for a post operation, based on possible keys and values.
|
47
|
+
#
|
48
|
+
# @param [Hash] info The user information.
|
49
|
+
#
|
50
|
+
# @raise[ArgumentError] If some of the information fields do not respect the
|
51
|
+
# possible values, contains any read-only or misses any mandatory field.
|
52
|
+
#
|
53
|
+
def validate_data_post(info)
|
54
|
+
info.assert_exclusion_keys(READONLY)
|
55
|
+
info.assert_inclusion_keys(MANDATORY)
|
56
|
+
validate_email(info[:email])
|
57
|
+
end
|
58
|
+
|
59
|
+
# Validates the user information for a put operation, based on possible keys and values.
|
60
|
+
#
|
61
|
+
# @param [Hash] info The user information.
|
62
|
+
#
|
63
|
+
# @raise[ArgumentError] If some of the metadata fields do not respect the
|
64
|
+
# possible values, contains any read-only or misses any mandatory field.
|
65
|
+
#
|
66
|
+
def validate_data_put(info)
|
67
|
+
info.assert_exclusion_keys(READONLY)
|
68
|
+
validate_email(info[:email]) if info[:email]
|
69
|
+
end
|
70
|
+
|
71
|
+
# Set protected fields value from a post operation.
|
72
|
+
# Being them the _id and created_at.
|
73
|
+
#
|
74
|
+
# @param [Hash] info The user information.
|
75
|
+
#
|
76
|
+
# @option [Hash] opts Any of the available options can be passed.
|
77
|
+
#
|
78
|
+
# @return [Hash] The updated user information.
|
79
|
+
#
|
80
|
+
def set_protected_post(info)
|
81
|
+
info.merge!(_id: SecureRandom.uuid, secret_key: SecureRandom.base64(30), created_at: Time.now)
|
82
|
+
end
|
83
|
+
|
84
|
+
# Set protected field value from a get operation.
|
85
|
+
# Being it the updated_at.
|
86
|
+
#
|
87
|
+
# @param [Hash] info The user information update.
|
88
|
+
#
|
89
|
+
# @return [Hash] The updated user information.
|
90
|
+
#
|
91
|
+
def set_protected_put(info)
|
92
|
+
info.merge!(updated_at: Time.now)
|
93
|
+
end
|
94
|
+
|
95
|
+
# Generates a compatible SQL WHERE string from a hash.
|
96
|
+
#
|
97
|
+
# @param [Hash] h The input hash.
|
98
|
+
#
|
99
|
+
# @return [String] A string as "k='v' AND k1='v1'",
|
100
|
+
# only Strings Times or Hashes values are surrounded with '<value>'.
|
101
|
+
#
|
102
|
+
def to_sql_where(h)
|
103
|
+
h.map { |k, v| string_time_or_hash?(v) ? "#{k}='#{v}'" : "#{k}=#{v}" }.join(' AND ')
|
104
|
+
end
|
105
|
+
|
106
|
+
# Generates a compatible SQL UPDATE string from a hash.
|
107
|
+
#
|
108
|
+
# @param [Hash] h The input hash.
|
109
|
+
#
|
110
|
+
# @return [String] A string as "k='v', k1='v1'",
|
111
|
+
# only Strings Times or Hashes values are surrounded with '<value>'.
|
112
|
+
#
|
113
|
+
def to_sql_update(h)
|
114
|
+
h.map { |k, v| string_time_or_hash?(v) ? "#{k}='#{v}'" : "#{k}=#{v}" }.join(', ')
|
115
|
+
end
|
116
|
+
|
117
|
+
# Generates a compatible SQL INSERT string from a hash.
|
118
|
+
#
|
119
|
+
# @param [Hash] h The input hash.
|
120
|
+
#
|
121
|
+
# @return [String] A string as "(k, k1) VALUES ('v', 'v1')",
|
122
|
+
# only Strings Times or Hashes values are surrounded with '<value>'.
|
123
|
+
#
|
124
|
+
def to_sql_insert(h)
|
125
|
+
surround = h.values.map { |v| string_time_or_hash?(v) ? "'#{v}'" : v }
|
126
|
+
%W{(#{h.keys.join(', ')}) (#{surround.join(', ')})}
|
127
|
+
end
|
128
|
+
|
129
|
+
# Validates that incoming query filters fields are valid.
|
130
|
+
#
|
131
|
+
# @param [Hash] filters The image metadata filters coming from a GET request.
|
132
|
+
#
|
133
|
+
# @raise[ArgumentError] If some of the query filter fields do not respect the
|
134
|
+
# possible values.
|
135
|
+
#
|
136
|
+
def validate_query_filters(filters)
|
137
|
+
filters.symbolize_keys!
|
138
|
+
filters.assert_valid_keys(ALL)
|
139
|
+
end
|
140
|
+
|
141
|
+
private
|
142
|
+
|
143
|
+
# Verifies if a given object is a String, a Time or a Hash.
|
144
|
+
#
|
145
|
+
# @param [Object] v The input value.
|
146
|
+
#
|
147
|
+
# @return [true, false] If the provided value is or not a String, a Time or a Hash.
|
148
|
+
#
|
149
|
+
def string_time_or_hash?(v)
|
150
|
+
v.is_a?(String) or v.is_a?(Time) or v.is_a?(Hash)
|
151
|
+
end
|
152
|
+
|
153
|
+
# Verifies if a given email string is a valid email.
|
154
|
+
#
|
155
|
+
# @param [String] s The input value.
|
156
|
+
#
|
157
|
+
# @raise [ArgumentError] If the email address is invalid.
|
158
|
+
#
|
159
|
+
def validate_email(s)
|
160
|
+
valid = s.match(/([^@\s*]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})/i)
|
161
|
+
raise ArgumentError, "The email address seems to be invalid." unless valid
|
162
|
+
end
|
163
|
+
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
@@ -0,0 +1,165 @@
|
|
1
|
+
require 'mongo'
|
2
|
+
require 'uri'
|
3
|
+
|
4
|
+
module Visor
|
5
|
+
module Auth
|
6
|
+
module Backends
|
7
|
+
|
8
|
+
# The MongoDB Backend for the VISoR Auth.
|
9
|
+
#
|
10
|
+
class MongoDB < Base
|
11
|
+
|
12
|
+
include Visor::Common::Exception
|
13
|
+
|
14
|
+
# Connection constants
|
15
|
+
#
|
16
|
+
# Default MongoDB database
|
17
|
+
DEFAULT_DB = 'visor'
|
18
|
+
# Default MongoDB host address
|
19
|
+
DEFAULT_HOST = '127.0.0.1'
|
20
|
+
# Default MongoDB host port
|
21
|
+
DEFAULT_PORT = 27017
|
22
|
+
# Default MongoDB user
|
23
|
+
DEFAULT_USER = nil
|
24
|
+
# Default MongoDB password
|
25
|
+
DEFAULT_PASSWORD = nil
|
26
|
+
|
27
|
+
# Initializes a MongoDB Backend instance.
|
28
|
+
#
|
29
|
+
# @option [Hash] opts Any of the available options can be passed.
|
30
|
+
#
|
31
|
+
# @option opts [String] :uri The connection uri, if provided, no other option needs to be setted.
|
32
|
+
# @option opts [String] :db (DEFAULT_DB) The wanted database.
|
33
|
+
# @option opts [String] :host (DEFAULT_HOST) The host address.
|
34
|
+
# @option opts [Integer] :port (DEFAULT_PORT) The port to be used.
|
35
|
+
# @option opts [String] :user (DEFAULT_USER) The user to be used.
|
36
|
+
# @option opts [String] :password (DEFAULT_PASSWORD) The password to be used.
|
37
|
+
# @option opts [Object] :conn The connection pool to access database.
|
38
|
+
#
|
39
|
+
def self.connect(opts = {})
|
40
|
+
opts[:uri] ||= ''
|
41
|
+
uri = URI.parse(opts[:uri])
|
42
|
+
opts[:db] = uri.path ? uri.path.gsub('/', '') : DEFAULT_DB
|
43
|
+
opts[:host] = uri.host || DEFAULT_HOST
|
44
|
+
opts[:port] = uri.port || DEFAULT_PORT
|
45
|
+
opts[:user] = uri.user || DEFAULT_USER
|
46
|
+
opts[:password] = uri.password || DEFAULT_PASSWORD
|
47
|
+
|
48
|
+
self.new opts
|
49
|
+
end
|
50
|
+
|
51
|
+
def initialize(opts)
|
52
|
+
super opts
|
53
|
+
@conn = connection
|
54
|
+
end
|
55
|
+
|
56
|
+
# Establishes and returns a MongoDB database connection.
|
57
|
+
#
|
58
|
+
# @return [Mongo::Collection] A MongoDB collection object.
|
59
|
+
#
|
60
|
+
def connection
|
61
|
+
db = Mongo::Connection.new(@host, @port, :pool_size => 10, :pool_timeout => 5).db(@db)
|
62
|
+
db.authenticate(@user, @password) unless @user.empty? && @password.empty?
|
63
|
+
db.collection('users')
|
64
|
+
end
|
65
|
+
|
66
|
+
# Returns an array with the registered users.
|
67
|
+
#
|
68
|
+
# @option [Hash] filters Users attributes for filtering the returned results.
|
69
|
+
# Besides common attributes filters, the following options can be passed to.
|
70
|
+
#
|
71
|
+
# @return [Array] The users information.
|
72
|
+
#
|
73
|
+
# @raise [NotFound] If there are no registered users.
|
74
|
+
#
|
75
|
+
def get_users(filters = {})
|
76
|
+
validate_query_filters filters unless filters.empty?
|
77
|
+
users = @conn.find(filters).to_a
|
78
|
+
raise NotFound, "No users found." if users.empty? && filters.empty?
|
79
|
+
raise NotFound, "No users found with given parameters." if users.empty?
|
80
|
+
users
|
81
|
+
end
|
82
|
+
|
83
|
+
# Returns an user information.
|
84
|
+
#
|
85
|
+
# @param [String] access_key The user access_key.
|
86
|
+
#
|
87
|
+
# @return [BSON::OrderedHash] The requested user information.
|
88
|
+
#
|
89
|
+
# @raise [NotFound] If user was not found.
|
90
|
+
#
|
91
|
+
def get_user(access_key)
|
92
|
+
user = @conn.find_one(access_key: access_key)
|
93
|
+
raise NotFound, "No user found with Access Key '#{access_key}'." unless user
|
94
|
+
user
|
95
|
+
end
|
96
|
+
|
97
|
+
# Delete a registered user.
|
98
|
+
#
|
99
|
+
# @param [String] access_key The user access_key.
|
100
|
+
#
|
101
|
+
# @return [BSON::OrderedHash] The deleted image metadata.
|
102
|
+
#
|
103
|
+
# @raise [NotFound] If user was not found.
|
104
|
+
#
|
105
|
+
def delete_user(access_key)
|
106
|
+
user = @conn.find_one(access_key: access_key)
|
107
|
+
raise NotFound, "No user found with Access Key '#{access_key}'." unless user
|
108
|
+
@conn.remove(access_key: access_key)
|
109
|
+
user
|
110
|
+
end
|
111
|
+
|
112
|
+
# Delete all registered users.
|
113
|
+
#
|
114
|
+
def delete_all!
|
115
|
+
@conn.remove
|
116
|
+
end
|
117
|
+
|
118
|
+
# Create a new user record for the given information.
|
119
|
+
#
|
120
|
+
# @param [Hash] user The user information.
|
121
|
+
#
|
122
|
+
# @return [BSON::OrderedHash] The already added user information.
|
123
|
+
#
|
124
|
+
# @raise [Invalid] If user information validation fails.
|
125
|
+
# @raise [ConflictError] If an access_key was already taken.
|
126
|
+
#
|
127
|
+
def post_user(user)
|
128
|
+
validate_data_post user
|
129
|
+
exists = @conn.find_one(access_key: user[:access_key])
|
130
|
+
raise ConflictError, "The Access Key '#{user[:access_key]}' was already taken." if exists
|
131
|
+
set_protected_post user
|
132
|
+
@conn.insert(user)
|
133
|
+
self.get_user(user[:access_key])
|
134
|
+
end
|
135
|
+
|
136
|
+
# Update an user information.
|
137
|
+
#
|
138
|
+
# @param [String] access_key The user access_key.
|
139
|
+
# @param [Hash] update The user information update.
|
140
|
+
#
|
141
|
+
# @return [BSON::OrderedHash] The updated user information.
|
142
|
+
#
|
143
|
+
# @raise [Invalid] If user information validation fails.
|
144
|
+
# @raise [ConflictError] If an access_key was already taken.
|
145
|
+
# @raise [NotFound] If user was not found.
|
146
|
+
#
|
147
|
+
def put_user(access_key, update)
|
148
|
+
validate_data_put update
|
149
|
+
user = @conn.find_one(access_key: access_key)
|
150
|
+
raise NotFound, "No user found with Access Key '#{access_key}'." unless user
|
151
|
+
if update[:access_key]
|
152
|
+
exists = @conn.find_one(access_key: update[:access_key])
|
153
|
+
raise ConflictError, "The Access Key '#{update[:access_key]}' was already taken." if exists
|
154
|
+
end
|
155
|
+
set_protected_put update
|
156
|
+
@conn.update({access_key: access_key}, :$set => update)
|
157
|
+
self.get_user(update[:access_key] || access_key)
|
158
|
+
end
|
159
|
+
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
|