using MD5 using HTTP using JSON2 const users = JlSonic.User[] function getlogin(app, req) query = HTTP.URIs.queryparams(req[:query]) username = string(get(query, "u", "")) token = get(query, "t", "") salt = get(query, "s", "") password = get(query, "p", "") req[:login] = Dict(:name => username, :token => token, :salt => salt, :password => password, :login => false) return app(req) end function checkpassword(app, req) global users usern = findfirst(u -> u.name == req[:login][:name], users) usern === nothing && return app(req) user = users[usern] req[:login][:user] = user if !isempty(req[:login][:salt]) if bytes2hex(MD5.md5(string(user.password, req[:login][:salt]))) == req[:login][:token] req[:login][:login] = true end elseif !isempty(req[:login][:password]) if startswith(req[:login][:password], "enc:") req[:login][:login] = String(hex2bytes(split(req[:login][:password], ":")[2])) == user.password else req[:login][:login] = user.password == req[:login][:password] end end return app(req) end function saveusers(file = expanduser("~/.config/beets/users.jsonl")) global users open(file, "w") do f write(f, join(JSON2.write.(users), "\n")) end end function loadusers(; file = expanduser("~/.config/beets/users.jsonl")) global users isfile(file) || touch(file) ps = JSON2.readlines(file) p = JSON2.read.(ps, JlSonic.User) empty!(users) append!(users, p) end sonic_login = stack(getlogin, checkpassword)