Skip to content

Commit 97ebbb8

Browse files
authored
move the User and UserStore classes to the Auth namespace to match file hirearchy (#1187)
1 parent 24f74bd commit 97ebbb8

File tree

16 files changed

+281
-277
lines changed

16 files changed

+281
-277
lines changed

spec/api/definitions_spec.cr

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ describe LavinMQ::HTTP::Server do
2929
response = http.post("/api/definitions", body: body)
3030
response.status_code.should eq 200
3131
s.users.select("sha256", "sha512", "bcrypt", "md5").each do |_, u|
32-
u.should be_a(LavinMQ::User)
32+
u.should be_a(LavinMQ::Auth::User)
3333
ok = u.not_nil!.password.not_nil!.verify "hej"
3434
{u.name, ok}.should(eq({u.name, true}))
3535
end
@@ -646,7 +646,7 @@ describe LavinMQ::HTTP::Server do
646646
response.status_code.should eq 200
647647

648648
u = s.users[name]
649-
u.should be_a(LavinMQ::User)
649+
u.should be_a(LavinMQ::Auth::User)
650650
ok = u.not_nil!.password.not_nil!.verify "hej"
651651
{u.name, ok}.should eq({name, true})
652652

@@ -661,7 +661,7 @@ describe LavinMQ::HTTP::Server do
661661
response.status_code.should eq 200
662662

663663
u = s.users[name]
664-
u.should be_a(LavinMQ::User)
664+
u.should be_a(LavinMQ::Auth::User)
665665
ok = u.not_nil!.password.not_nil!.verify "test"
666666
{u.name, ok}.should eq({name, true})
667667
end

spec/users_spec.cr

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
require "./spec_helper"
22

3-
describe LavinMQ::User do
3+
describe LavinMQ::Auth::User do
44
describe "#update_password" do
55
it "should not update password hash when given same password as current" do
6-
u = LavinMQ::User.create("username", "password", "sha256", [] of LavinMQ::Tag)
6+
u = LavinMQ::Auth::User.create("username", "password", "sha256", [] of LavinMQ::Tag)
77
password_hash_before = u.password
88
u.update_password("password")
99
u.password.should eq password_hash_before
1010
end
1111

1212
it "should update password hash when given other password than current" do
13-
u = LavinMQ::User.create("username", "password", "sha256", [] of LavinMQ::Tag)
13+
u = LavinMQ::Auth::User.create("username", "password", "sha256", [] of LavinMQ::Tag)
1414
password_hash_before = u.password
1515
u.update_password("other")
1616
u.password.should_not eq password_hash_before
@@ -276,26 +276,26 @@ describe LavinMQ::Server do
276276

277277
it "allows changing default user" do
278278
LavinMQ::Config.instance.default_user = "spec"
279-
LavinMQ::Config.instance.default_password = LavinMQ::User.hash_password("spec", "SHA256").to_s
279+
LavinMQ::Config.instance.default_password = LavinMQ::Auth::User.hash_password("spec", "SHA256").to_s
280280
with_amqp_server do |s|
281281
with_channel(s, user: "spec", password: "spec") { }
282282
end
283283
ensure
284284
LavinMQ::Config.instance.default_user = "guest"
285-
LavinMQ::Config.instance.default_password = LavinMQ::User.hash_password("guest", "SHA256").to_s
285+
LavinMQ::Config.instance.default_password = LavinMQ::Auth::User.hash_password("guest", "SHA256").to_s
286286
end
287287

288288
it "disallows 'guest' if default user is changed" do
289289
LavinMQ::Config.instance.default_user = "spec"
290-
LavinMQ::Config.instance.default_password = LavinMQ::User.hash_password("spec", "SHA256").to_s
290+
LavinMQ::Config.instance.default_password = LavinMQ::Auth::User.hash_password("spec", "SHA256").to_s
291291
with_amqp_server do |s|
292292
expect_raises(AMQP::Client::Connection::ClosedException) do
293293
with_channel(s, user: "guest", password: "guest") { }
294294
end
295295
end
296296
ensure
297297
LavinMQ::Config.instance.default_user = "guest"
298-
LavinMQ::Config.instance.default_password = LavinMQ::User.hash_password("guest", "SHA256").to_s
298+
LavinMQ::Config.instance.default_password = LavinMQ::Auth::User.hash_password("guest", "SHA256").to_s
299299
end
300300
end
301301

src/lavinmq/amqp/client.cr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ module LavinMQ
4040
def initialize(@socket : IO,
4141
@connection_info : ConnectionInfo,
4242
@vhost : VHost,
43-
@user : User,
43+
@user : Auth::User,
4444
tune_ok,
4545
start_ok)
4646
@max_frame_size = tune_ok.frame_max

src/lavinmq/auth/user.cr

Lines changed: 136 additions & 134 deletions
Original file line numberDiff line numberDiff line change
@@ -4,169 +4,171 @@ require "../sortable_json"
44
require "../tag"
55

66
module LavinMQ
7-
class User
8-
include SortableJSON
9-
getter name, password, permissions
10-
property tags, plain_text_password
11-
alias Permissions = NamedTuple(config: Regex, read: Regex, write: Regex)
12-
13-
@name : String
14-
@permissions = Hash(String, Permissions).new
15-
@password : Auth::Password? = nil
16-
@plain_text_password : String?
17-
@tags = Array(Tag).new
18-
19-
def initialize(pull : JSON::PullParser)
20-
loc = pull.location
21-
name = hash = hash_algo = nil
22-
pull.read_object do |key|
23-
case key
24-
when "name"
25-
name = pull.read_string
26-
when "password_hash"
27-
hash = pull.read_string
28-
when "hashing_algorithm"
29-
hash_algo = pull.read_string
30-
when "permissions"
31-
parse_permissions(pull)
32-
when "tags"
33-
@tags = Tag.parse_list(pull.read_string)
34-
else nil
7+
module Auth
8+
class User
9+
include SortableJSON
10+
getter name, password, permissions
11+
property tags, plain_text_password
12+
alias Permissions = NamedTuple(config: Regex, read: Regex, write: Regex)
13+
14+
@name : String
15+
@permissions = Hash(String, Permissions).new
16+
@password : Auth::Password? = nil
17+
@plain_text_password : String?
18+
@tags = Array(Tag).new
19+
20+
def initialize(pull : JSON::PullParser)
21+
loc = pull.location
22+
name = hash = hash_algo = nil
23+
pull.read_object do |key|
24+
case key
25+
when "name"
26+
name = pull.read_string
27+
when "password_hash"
28+
hash = pull.read_string
29+
when "hashing_algorithm"
30+
hash_algo = pull.read_string
31+
when "permissions"
32+
parse_permissions(pull)
33+
when "tags"
34+
@tags = Tag.parse_list(pull.read_string)
35+
else nil
36+
end
3537
end
38+
raise JSON::ParseException.new("Missing json attribute: name", *loc) if name.nil?
39+
raise JSON::ParseException.new("Missing json attribute: password_hash", *loc) if hash.nil?
40+
@name = name
41+
@password = parse_password(hash, hash_algo, loc)
3642
end
37-
raise JSON::ParseException.new("Missing json attribute: name", *loc) if name.nil?
38-
raise JSON::ParseException.new("Missing json attribute: password_hash", *loc) if hash.nil?
39-
@name = name
40-
@password = parse_password(hash, hash_algo, loc)
41-
end
4243

43-
def self.create(name : String, password : String, hash_algorithm : String, tags : Array(Tag))
44-
pwd = hash_password(password, hash_algorithm)
45-
self.new(name, pwd, tags)
46-
end
44+
def self.create(name : String, password : String, hash_algorithm : String, tags : Array(Tag))
45+
pwd = hash_password(password, hash_algorithm)
46+
self.new(name, pwd, tags)
47+
end
4748

48-
def self.hash_password(password, hash_algorithm)
49-
case hash_algorithm
50-
when /bcrypt$/i then Auth::Password::BcryptPassword.create(password, cost: 4)
51-
when /sha256$/i then Auth::Password::SHA256Password.create(password)
52-
when /sha512$/i then Auth::Password::SHA512Password.create(password)
53-
when /md5$/i then Auth::Password::MD5Password.create(password)
54-
else raise UnknownHashAlgoritm.new(hash_algorithm)
49+
def self.hash_password(password, hash_algorithm)
50+
case hash_algorithm
51+
when /bcrypt$/i then Auth::Password::BcryptPassword.create(password, cost: 4)
52+
when /sha256$/i then Auth::Password::SHA256Password.create(password)
53+
when /sha512$/i then Auth::Password::SHA512Password.create(password)
54+
when /md5$/i then Auth::Password::MD5Password.create(password)
55+
else raise UnknownHashAlgoritm.new(hash_algorithm)
56+
end
5557
end
56-
end
5758

58-
private def parse_password(hash, hash_algorithm, loc = nil)
59-
case hash_algorithm
60-
when /bcrypt$/i then Auth::Password::BcryptPassword.new(hash)
61-
when /sha256$/i then Auth::Password::SHA256Password.new(hash)
62-
when /sha512$/i then Auth::Password::SHA512Password.new(hash)
63-
when /md5$/i, nil then Auth::Password::MD5Password.new(hash)
64-
else
65-
if loc
66-
raise JSON::ParseException.new("Unsupported hash algorithm", *loc)
59+
private def parse_password(hash, hash_algorithm, loc = nil)
60+
case hash_algorithm
61+
when /bcrypt$/i then Auth::Password::BcryptPassword.new(hash)
62+
when /sha256$/i then Auth::Password::SHA256Password.new(hash)
63+
when /sha512$/i then Auth::Password::SHA512Password.new(hash)
64+
when /md5$/i, nil then Auth::Password::MD5Password.new(hash)
6765
else
68-
raise UnknownHashAlgoritm.new(hash_algorithm)
66+
if loc
67+
raise JSON::ParseException.new("Unsupported hash algorithm", *loc)
68+
else
69+
raise UnknownHashAlgoritm.new(hash_algorithm)
70+
end
6971
end
7072
end
71-
end
7273

73-
def self.create_hidden_user(name)
74-
password = Random::Secure.urlsafe_base64(32)
75-
password_hash = hash_password(password, "sha256")
76-
user = self.new(name, password_hash, [Tag::Administrator])
77-
user.plain_text_password = password
78-
user
79-
end
74+
def self.create_hidden_user(name)
75+
password = Random::Secure.urlsafe_base64(32)
76+
password_hash = hash_password(password, "sha256")
77+
user = self.new(name, password_hash, [Tag::Administrator])
78+
user.plain_text_password = password
79+
user
80+
end
8081

81-
def initialize(@name, password_hash, hash_algorithm, @tags)
82-
update_password_hash(password_hash, hash_algorithm)
83-
end
82+
def initialize(@name, password_hash, hash_algorithm, @tags)
83+
update_password_hash(password_hash, hash_algorithm)
84+
end
8485

85-
def initialize(@name, @password, @tags)
86-
end
86+
def initialize(@name, @password, @tags)
87+
end
8788

88-
def hidden?
89-
UserStore.hidden?(@name)
90-
end
89+
def hidden?
90+
UserStore.hidden?(@name)
91+
end
9192

92-
def update_password_hash(password_hash, hash_algorithm)
93-
if password_hash.empty?
94-
@password = nil
95-
return
93+
def update_password_hash(password_hash, hash_algorithm)
94+
if password_hash.empty?
95+
@password = nil
96+
return
97+
end
98+
@password = parse_password(password_hash, hash_algorithm)
9699
end
97-
@password = parse_password(password_hash, hash_algorithm)
98-
end
99100

100-
def update_password(password, hash_algorithm = "sha256")
101-
return if @password.try &.verify(password)
102-
@password = User.hash_password(password, hash_algorithm)
103-
end
101+
def update_password(password, hash_algorithm = "sha256")
102+
return if @password.try &.verify(password)
103+
@password = User.hash_password(password, hash_algorithm)
104+
end
104105

105-
def details_tuple
106-
user_details.merge(permissions: @permissions)
107-
end
106+
def details_tuple
107+
user_details.merge(permissions: @permissions)
108+
end
108109

109-
def user_details
110-
{
111-
name: @name,
112-
password_hash: @password,
113-
hashing_algorithm: @password.try &.hash_algorithm,
114-
tags: @tags.map(&.to_s.downcase).join(","),
115-
}
116-
end
110+
def user_details
111+
{
112+
name: @name,
113+
password_hash: @password,
114+
hashing_algorithm: @password.try &.hash_algorithm,
115+
tags: @tags.map(&.to_s.downcase).join(","),
116+
}
117+
end
117118

118-
def permissions_details
119-
@permissions.map { |k, p| permissions_details(k, p) }
120-
end
119+
def permissions_details
120+
@permissions.map { |k, p| permissions_details(k, p) }
121+
end
121122

122-
def permissions_details(vhost, p)
123-
{
124-
user: @name,
125-
vhost: vhost,
126-
configure: p[:config],
127-
read: p[:read],
128-
write: p[:write],
129-
}
130-
end
123+
def permissions_details(vhost, p)
124+
{
125+
user: @name,
126+
vhost: vhost,
127+
configure: p[:config],
128+
read: p[:read],
129+
write: p[:write],
130+
}
131+
end
131132

132-
def can_write?(vhost, name) : Bool
133-
perm = permissions[vhost]?
134-
perm ? perm_match?(perm[:write], name) : false
135-
end
133+
def can_write?(vhost, name) : Bool
134+
perm = permissions[vhost]?
135+
perm ? perm_match?(perm[:write], name) : false
136+
end
136137

137-
def can_read?(vhost, name) : Bool
138-
perm = permissions[vhost]?
139-
perm ? perm_match?(perm[:read], name) : false
140-
end
138+
def can_read?(vhost, name) : Bool
139+
perm = permissions[vhost]?
140+
perm ? perm_match?(perm[:read], name) : false
141+
end
141142

142-
def can_config?(vhost, name) : Bool
143-
perm = permissions[vhost]?
144-
perm ? perm_match?(perm[:config], name) : false
145-
end
143+
def can_config?(vhost, name) : Bool
144+
perm = permissions[vhost]?
145+
perm ? perm_match?(perm[:config], name) : false
146+
end
146147

147-
def can_impersonate?
148-
@tags.includes? Tag::Impersonator
149-
end
148+
def can_impersonate?
149+
@tags.includes? Tag::Impersonator
150+
end
150151

151-
private def parse_permissions(pull)
152-
pull.read_object do |vhost|
153-
config = read = write = /^$/
154-
pull.read_object do |ikey|
155-
case ikey
156-
when "config" then config = Regex.from_json(pull)
157-
when "read" then read = Regex.from_json(pull)
158-
when "write" then write = Regex.from_json(pull)
159-
else nil
152+
private def parse_permissions(pull)
153+
pull.read_object do |vhost|
154+
config = read = write = /^$/
155+
pull.read_object do |ikey|
156+
case ikey
157+
when "config" then config = Regex.from_json(pull)
158+
when "read" then read = Regex.from_json(pull)
159+
when "write" then write = Regex.from_json(pull)
160+
else nil
161+
end
160162
end
163+
@permissions[vhost] = {config: config, read: read, write: write}
161164
end
162-
@permissions[vhost] = {config: config, read: read, write: write}
163165
end
164-
end
165166

166-
private def perm_match?(perm, name)
167-
perm != /^$/ && perm != // && perm.matches? name
168-
end
167+
private def perm_match?(perm, name)
168+
perm != /^$/ && perm != // && perm.matches? name
169+
end
169170

170-
class UnknownHashAlgoritm < Exception; end
171+
class UnknownHashAlgoritm < Exception; end
172+
end
171173
end
172174
end

0 commit comments

Comments
 (0)