Class ::nsmcp::FileCredentials (public)

 ::nx::Class ::nsmcp::FileCredentials[i]

Defined in /usr/local/ns/tcl/nsmcp/lib/credentials.tcl

Testcases:
No testcase defined.
Source code:
    :property authenticator:required
    :property section:required
    :property store:required
    :variable mutex
    :method init {} {set :mutex [ns_mutex create]}
    :method names {} {
        set names [ns_config ${:section} credentials {}]
        if {[llength $names] != [llength [lsort -unique $names]]} {error "duplicate credential names"}
        foreach name $names {
            if {![regexp {^[A-Za-z0-9][A-Za-z0-9_.-]*$} $name]} {error "invalid symbolic credential name"}
        }
        return $names
    }
    :method prepare {name} {
        set section ${:section}/credential/$name
        set path [ns_config $section tokenFile {}]
        if {[file pathtype $path] ne "absolute" || ![file isfile $path] || ![file readable $path]} {
            error "credential $name requires a readable absolute tokenFile"
        }
        set principal [ns_config $section principal $name]
        set permissions [ns_config $section permissions {}]
        if {$principal eq ""} {error "credential $name requires a principal"}
        llength $permissions
        set expires [ns_config $section expires 0]
        if {![string is wideinteger -strict $expires] || ($expires != 0 && $expires <= [clock seconds])} {
            error "credential $name has an invalid or expired expiry"
        }
        set f [open $path rb]
        try {set raw [read $f 4097]} finally {close $f}
        if {[string length $raw] > 4096} {error "credential $name has an oversized token file"}
        set token [string trim $raw "\r\n"]
        if {[string length $token] < 32 || [string length $token] > 4096 ||
            ![regexp {^[A-Za-z0-9._~+/-]+=*$} $token]} {
            error "credential $name has an invalid token file"
        }
        set digest [ns_crypto::md string -digest sha256 -- $token]
        return [dict create token $token digest $digest tokenFile $path principal $principal  permissions $permissions targets [list [ns_info server]] expires $expires]
    }
    :method publish {name prepared} {
        ${:authenticator} grant [dict get $prepared token] [dict get $prepared principal]  [dict get $prepared permissions] [dict get $prepared targets] [dict get $prepared expires]
        dict unset prepared token
        nsv_set ${:store} $name $prepared
        return $prepared
    }
    :public method loadAll {} {
        ns_mutex lock ${:mutex}
        try {
            # Validate every file/policy before changing any existing binding.
            set staged {}; set digests {}
            foreach name [:names] {
                set prepared [:prepare $name]
                set digest [dict get $prepared digest]
                if {[dict exists $digests $digest]} {error "configured credentials must use distinct tokens"}
                dict set digests $digest $name
                dict set staged $name $prepared
            }
            foreach name [nsv_array names ${:store}] {
                ${:authenticator} revoke [dict get [nsv_get ${:store} $name] digest]
                nsv_unset ${:store} $name
            }
            dict for {name prepared} $staged {:publish $name $prepared}
            return [:describeUnlocked]
        } finally {ns_mutex unlock ${:mutex}}
    }
    :public method load {name} {
        ns_mutex lock ${:mutex}
        try {
            if {$name ni [:names]} {error "unknown configured credential name"}
            set prepared [:prepare $name]
            foreach other [nsv_array names ${:store}] {
                if {$other ne $name && [dict get [nsv_get ${:store} $other] digest] eq [dict get $prepared digest]} {
                    error "configured credentials must use distinct tokens"
                }
            }
            set previous {}
            if {[nsv_exists ${:store} $name]} {set previous [dict get [nsv_get ${:store} $name] digest]}
            set metadata [:publish $name $prepared]
            if {$previous ne "" && $previous ne [dict get $prepared digest]} {${:authenticator} revoke $previous}
            return $metadata
        } finally {ns_mutex unlock ${:mutex}}
    }
    :public method revoke {name} {
        ns_mutex lock ${:mutex}
        try {
            if {![nsv_exists ${:store} $name]} {error "unknown loaded credential name"}
            ${:authenticator} revoke [dict get [nsv_get ${:store} $name] digest]
        } finally {ns_mutex unlock ${:mutex}}
    }
    :method describeUnlocked {} {
        set result {}
        foreach name [lsort [nsv_array names ${:store}]] {
            set metadata [nsv_get ${:store} $name]
            set current [${:authenticator} credentialInfo [dict get $metadata digest]]
            set status revoked
            if {$current ne ""} {
                set status active
                if {[dict get $current expires] != 0 && [dict get $current expires] <= [clock seconds]} {set status expired}
            }
            dict set metadata status $status
            dict set result $name $metadata
        }
        return $result
    }
    :public method describe {} {
        ns_mutex lock ${:mutex}
        try {return [:describeUnlocked]} finally {ns_mutex unlock ${:mutex}}
    }
XQL Not present:
Generic, PostgreSQL, Oracle
[ hide source ] | [ make this the default ]
Show another procedure: