Password Recovery.
This commit is contained in:
parent
3ce1d78a50
commit
bd68148924
55
src/authd.cr
55
src/authd.cr
@ -99,6 +99,18 @@ class AuthD::Response
|
||||
initialize :user, :service, :resource, :permission
|
||||
end
|
||||
|
||||
class PasswordRecoverySent < Response
|
||||
property user : ::AuthD::User::Public
|
||||
|
||||
initialize :user
|
||||
end
|
||||
|
||||
class PasswordRecovered < Response
|
||||
property user : ::AuthD::User::Public
|
||||
|
||||
initialize :user
|
||||
end
|
||||
|
||||
# This creates a Request::Type enumeration. One entry for each request type.
|
||||
{% begin %}
|
||||
enum Type
|
||||
@ -273,6 +285,21 @@ class AuthD::Request
|
||||
initialize :shared_key, :user, :service, :resource, :permission
|
||||
end
|
||||
|
||||
class PasswordRecovery < Request
|
||||
property shared_key : String
|
||||
property user : Int32 | String
|
||||
property password_renew_key : String
|
||||
property new_password : String
|
||||
|
||||
initialize :shared_key, :user, :password_renew_key, :new_password
|
||||
end
|
||||
|
||||
class AskPasswordRecovery < Request
|
||||
property user : Int32 | String
|
||||
|
||||
initialize :user
|
||||
end
|
||||
|
||||
# This creates a Request::Type enumeration. One entry for each request type.
|
||||
{% begin %}
|
||||
enum Type
|
||||
@ -309,7 +336,7 @@ class AuthD::Request
|
||||
|
||||
requests.find(&.type.==(type)).try &.from_json(payload)
|
||||
rescue e : JSON::ParseException
|
||||
raise Exception.new "malformed request"
|
||||
raise Exception.new "malformed request: #{e}"
|
||||
end
|
||||
end
|
||||
|
||||
@ -419,6 +446,32 @@ module AuthD
|
||||
end
|
||||
end
|
||||
|
||||
def ask_password_recovery(uid_or_login : String | Int32)
|
||||
send Request::AskPasswordRecovery.new uid_or_login
|
||||
response = Response.from_ipc read
|
||||
|
||||
case response
|
||||
when Response::PasswordRecoverySent
|
||||
when Response::Error
|
||||
raise Exception.new response.reason
|
||||
else
|
||||
Exception.new
|
||||
end
|
||||
end
|
||||
|
||||
def change_password(uid_or_login : String | Int32, new_pass : String, renew_key : String)
|
||||
send Request::PasswordRecovery.new @key, uid_or_login, renew_key, new_pass
|
||||
response = Response.from_ipc read
|
||||
|
||||
case response
|
||||
when Response::PasswordRecovered
|
||||
when Response::Error
|
||||
raise Exception.new response.reason
|
||||
else
|
||||
Exception.new
|
||||
end
|
||||
end
|
||||
|
||||
def register(login : String,
|
||||
password : String,
|
||||
email : String?,
|
||||
|
57
src/main.cr
57
src/main.cr
@ -209,6 +209,7 @@ class AuthD::Service
|
||||
user.profile = profile
|
||||
end
|
||||
|
||||
|
||||
@users << user
|
||||
|
||||
# Once the user is created and stored, we try to contact him
|
||||
@ -309,6 +310,62 @@ class AuthD::Service
|
||||
@users_per_uid.update user.uid.to_s, user
|
||||
|
||||
Response::PermissionSet.new user.uid, service, request.resource, request.permission
|
||||
when Request::AskPasswordRecovery
|
||||
|
||||
uid_or_login = request.user
|
||||
user = if uid_or_login.is_a? Int32
|
||||
@users_per_uid.get? uid_or_login.to_s
|
||||
else
|
||||
@users_per_login.get? uid_or_login
|
||||
end
|
||||
|
||||
if user.nil?
|
||||
return Response::Error.new "user not found"
|
||||
end
|
||||
|
||||
user.password_renew_key = UUID.random.to_s
|
||||
|
||||
@users_per_uid.update user.uid.to_s, user
|
||||
|
||||
# Once the user is created and stored, we try to contact him
|
||||
unless Process.run("password-recovery-mailer", [
|
||||
"-l", user.login,
|
||||
"-e", user.contact.email.not_nil!,
|
||||
"-t", "Password recovery email",
|
||||
"-f", "karchnu@localhost",
|
||||
"-a", user.password_renew_key.not_nil!
|
||||
]).success?
|
||||
return Response::Error.new "cannot contact the user for password recovery"
|
||||
end
|
||||
|
||||
Response::PasswordRecoverySent.new user.to_public
|
||||
when Request::PasswordRecovery
|
||||
if request.shared_key != @jwt_key
|
||||
return Response::Error.new "invalid authentication key"
|
||||
end
|
||||
|
||||
uid_or_login = request.user
|
||||
user = if uid_or_login.is_a? Int32
|
||||
@users_per_uid.get? uid_or_login.to_s
|
||||
else
|
||||
@users_per_login.get? uid_or_login
|
||||
end
|
||||
|
||||
if user.nil?
|
||||
return Response::Error.new "user not found"
|
||||
end
|
||||
|
||||
if user.password_renew_key == request.password_renew_key
|
||||
user.password_hash = hash_password request.new_password
|
||||
else
|
||||
return Response::Error.new "renew key not valid"
|
||||
end
|
||||
|
||||
user.password_renew_key = nil
|
||||
|
||||
@users_per_uid.update user.uid.to_s, user
|
||||
|
||||
Response::PasswordRecoverySent.new user.to_public
|
||||
else
|
||||
Response::Error.new "unhandled request type"
|
||||
end
|
||||
|
@ -39,6 +39,7 @@ class AuthD::User
|
||||
# Private.
|
||||
property contact : Contact
|
||||
property password_hash : String
|
||||
property password_renew_key : String?
|
||||
# service => resource => permission level
|
||||
property permissions : Hash(String, Hash(String, PermissionLevel))
|
||||
property configuration : Hash(String, Hash(String, JSON::Any))
|
||||
|
45
utils/authd-user-ask-for-new-password.cr
Normal file
45
utils/authd-user-ask-for-new-password.cr
Normal file
@ -0,0 +1,45 @@
|
||||
require "option_parser"
|
||||
|
||||
require "../src/authd.cr"
|
||||
|
||||
key_file : String? = nil
|
||||
cli_login : String? = nil
|
||||
|
||||
OptionParser.parse do |parser|
|
||||
parser.unknown_args do |args|
|
||||
if args.size != 1
|
||||
puts "usage: #{PROGRAM_NAME} <login> [options]"
|
||||
puts parser
|
||||
exit 1
|
||||
end
|
||||
|
||||
cli_login = args[0]
|
||||
end
|
||||
|
||||
parser.on "-K file", "--key-file file", "Read the authd shared key from a file." do |file|
|
||||
key_file = file
|
||||
end
|
||||
|
||||
parser.on "-h", "--help", "Prints this help message." do
|
||||
puts "usage: #{PROGRAM_NAME} <login> [options]"
|
||||
puts parser
|
||||
exit 0
|
||||
end
|
||||
end
|
||||
|
||||
begin
|
||||
authd = IPC::Connection.new "auth"
|
||||
|
||||
authd = AuthD::Client.new
|
||||
authd.key = File.read(key_file.not_nil!).chomp
|
||||
|
||||
login = cli_login.not_nil!
|
||||
|
||||
# AskPasswordRecovery => PasswordRecoverySent
|
||||
# PasswordRecovery =>
|
||||
|
||||
pp! authd.ask_password_recovery login
|
||||
rescue e
|
||||
puts "Error: #{e}"
|
||||
exit 1
|
||||
end
|
Loading…
Reference in New Issue
Block a user