diff --git a/src/Model/registrar.jl b/src/Model/registrar.jl index 0e5ce9e..d5f2343 100644 --- a/src/Model/registrar.jl +++ b/src/Model/registrar.jl @@ -209,6 +209,8 @@ end Base.:(==)(x::Invite, y::Invite) = x.demehash == y.demehash && x.token == y.token && x.hasher == y.hasher && x.route == y.route +Base.show(io::IO, invite::Invite) = print(io, string(invite)) + # This gives a nasty error for some reason when CryptoGroups are imported. #@batteries Invite diff --git a/src/Utils/Parser.jl b/src/Utils/Parser.jl index 86c21b1..a232a4f 100644 --- a/src/Utils/Parser.jl +++ b/src/Utils/Parser.jl @@ -154,18 +154,53 @@ StructTypes.StructType(::Type{BraidReceipt}) = StructTypes.Struct() StructTypes.omitempties(::Type{BraidReceipt}) = (:approval,) -StructTypes.StructType(::Type{Invite}) = StructTypes.CustomStruct() +### Special stroing scheme for the invite -StructTypes.lower(invite::Invite) = Dict(:demehash => base64encode(bytes(invite.demehash)), :token => base64encode(invite.token), :hasher => invite.hasher, :route => string(invite.route)) +StructTypes.StructType(::Type{Invite}) = StructTypes.StringType() -function StructTypes.construct(::Type{Invite}, data::Dict) +function base64encode_url(bytes::Vector{UInt8}) + str = base64encode(bytes) + newstr = replace(str, '+'=>'-', '/'=>'_') + return rstrip(newstr, '=') +end + +function base64decode_url(str::AbstractString) + newstr = replace(str, '-'=>'+', '_'=>'/') + return base64decode(newstr) +end + +function Base.string(invite::Invite) + + hash_str = bytes(invite.demehash) |> base64encode_url + token_str = invite.token |> base64encode_url + + hash_spec = string(invite.hasher) + + if invite.route == URI() + return "deme:?xt=$hash_spec:$hash_str&tk=$token_str" + else + return "deme:?xt=$hash_spec:$hash_str&sr=$(invite.route)&tk=$token_str" + end +end + +function StructTypes.construct(::Type{Invite}, invite_str::AbstractString) + + uri = URI(invite_str) + @assert uri.scheme == "deme" + + parameters = Dict() - #demehash = StructTypes.constructfrom(Digest, data["demehash"]) - demehash = Digest(base64decode(data["demehash"])) - token = base64decode(data["token"]) - hasher = StructTypes.constructfrom(Hash, data["hasher"]) - route = URI(data["route"]) + for pair in split(uri.query, '&') + (key, value) = split(pair, '=') + parameters[key] = value + end + route = haskey(parameters, "sr") ? URI(parameters["sr"]) : URI() + token = base64decode_url(parameters["tk"]) + xt = URI(parameters["xt"]) + hasher = Hash(xt.scheme) + demehash = Digest(base64decode_url(xt.path)) + return Invite(demehash, token, hasher, route) end diff --git a/test/mapper.jl b/test/mapper.jl index f99f914..b926289 100644 --- a/test/mapper.jl +++ b/test/mapper.jl @@ -34,7 +34,6 @@ DEMESPEC = Mapper.BRAID_CHAIN[].spec function enroll(signer, invite::Invite) # Authorization is done in the service layer now! - # auth_code = auth(id(signer), invite.token, hasher(invite)) _tokenid = tokenid(invite.token, invite.hasher) ticket = Mapper.get_ticket(_tokenid) # This is done at the service layer diff --git a/test/parser.jl b/test/parser.jl index 5147464..fa77e86 100644 --- a/test/parser.jl +++ b/test/parser.jl @@ -1,8 +1,9 @@ using Test import PeaceFounder: Model, Parser -import .Model: TicketID, Digest, Pseudonym, Admission, Seal, DemeSpec, CryptoSpec, Membership, Signature, Generator, id +import .Model: TicketID, Digest, Pseudonym, Admission, Seal, DemeSpec, CryptoSpec, Membership, Signature, Generator, id, Hash, Invite import .Parser: marshal, unmarshal import Dates: DateTime, now +import URIs: URI isconsistent(event::T) where T = unmarshal(marshal(event), T) == event @@ -47,3 +48,9 @@ event = Membership(admission, Generator(UInt8[1, 2, 3, 4]), Pseudonym(UInt8[1, 2 event = Pseudonym(UInt8[1, 2, 3, 4]) @test isconsistent(event) + +invite = Invite(Digest(rand(UInt8, 32)), rand(UInt8, 8), Hash("sha256"), URI("http://peacefounder.org")) +@test isconsistent(invite) + +invite = Invite(Digest(rand(UInt8, 32)), rand(UInt8, 8), Hash("sha256"), URI()) +@test isconsistent(invite)