Commit bb5737f4 authored by Sietse Ringers's avatar Sietse Ringers
Browse files

Fix and test scheme manager adding and automatic configuration downloading

parent 47dea744
...@@ -24,7 +24,7 @@ import ( ...@@ -24,7 +24,7 @@ import (
// at initialization. // at initialization.
// //
// - The attributes of all credentials are stored together, as they all // - The attributes of all credentials are stored together, as they all
// immediately need to be available anyway, // immediately need to be available anyway.
// //
// - The secret key (the zeroth attribute of every credential), being the same // - The secret key (the zeroth attribute of every credential), being the same
// across all credentials, is stored only once in a separate file (storing this // across all credentials, is stored only once in a separate file (storing this
......
...@@ -384,16 +384,31 @@ func TestCredentialRemoval(t *testing.T) { ...@@ -384,16 +384,31 @@ func TestCredentialRemoval(t *testing.T) {
teardown(t) teardown(t)
} }
// Test installing a new scheme manager from a qr, and do a(n issuance) session
// within this manager to test the autmatic downloading of credential definitions,
// issuers, and public keys.
func TestDownloadSchemeManager(t *testing.T) { func TestDownloadSchemeManager(t *testing.T) {
client := parseStorage(t) client := parseStorage(t)
require.NoError(t, client.Configuration.RemoveSchemeManager(irma.NewSchemeManagerIdentifier("irma-demo")))
url := "https://raw.githubusercontent.com/credentials/irma_configuration/translate/irma-demo"
sm, err := client.Configuration.DownloadSchemeManager(url)
require.NoError(t, err)
require.NotNil(t, sm)
require.NoError(t, client.Configuration.AddSchemeManager(sm)) // Remove irma-demo scheme manager as we need to test adding it
irmademo := irma.NewSchemeManagerIdentifier("irma-demo")
require.Contains(t, client.Configuration.SchemeManagers, irmademo)
require.NoError(t, client.Configuration.RemoveSchemeManager(irmademo))
require.NotContains(t, client.Configuration.SchemeManagers, irmademo)
// Do an add-scheme-manager-session
qr := &irma.Qr{
Type: irma.ActionSchemeManager,
URL: "https://raw.githubusercontent.com/credentials/irma_configuration/translate/irma-demo",
}
c := make(chan *irma.SessionError)
client.NewSession(qr, TestHandler{t, c, client})
if err := <-c; err != nil {
t.Fatal(*err)
}
require.Contains(t, client.Configuration.SchemeManagers, irmademo)
// Do a session to test downloading of cred types, issuers and keys
jwt := getIssuanceJwt("testip", irma.NewAttributeTypeIdentifier("irma-demo.RU.studentCard.studentID")) jwt := getIssuanceJwt("testip", irma.NewAttributeTypeIdentifier("irma-demo.RU.studentCard.studentID"))
sessionHelper(t, jwt, "issue", client) sessionHelper(t, jwt, "issue", client)
......
...@@ -112,6 +112,12 @@ func (client *Client) NewSession(qr *irma.Qr, handler Handler) SessionDismisser ...@@ -112,6 +112,12 @@ func (client *Client) NewSession(qr *irma.Qr, handler Handler) SessionDismisser
transport: irma.NewHTTPTransport(qr.URL), transport: irma.NewHTTPTransport(qr.URL),
client: client, client: client,
} }
if session.Action == irma.ActionSchemeManager {
go session.managerSession()
return session
}
version, err := calcVersion(qr) version, err := calcVersion(qr)
if err != nil { if err != nil {
session.fail(&irma.SessionError{ErrorType: irma.ErrorProtocolVersionNotSupported, Err: err}) session.fail(&irma.SessionError{ErrorType: irma.ErrorProtocolVersionNotSupported, Err: err})
...@@ -124,7 +130,6 @@ func (client *Client) NewSession(qr *irma.Qr, handler Handler) SessionDismisser ...@@ -124,7 +130,6 @@ func (client *Client) NewSession(qr *irma.Qr, handler Handler) SessionDismisser
case irma.ActionDisclosing: // nop case irma.ActionDisclosing: // nop
case irma.ActionSigning: // nop case irma.ActionSigning: // nop
case irma.ActionIssuing: // nop case irma.ActionIssuing: // nop
//case irmago.ActionSchemeManager: // nop
case irma.ActionUnknown: case irma.ActionUnknown:
fallthrough fallthrough
default: default:
...@@ -154,11 +159,6 @@ func (session *session) start() { ...@@ -154,11 +159,6 @@ func (session *session) start() {
session.Handler.StatusUpdate(session.Action, irma.StatusCommunicating) session.Handler.StatusUpdate(session.Action, irma.StatusCommunicating)
if session.Action == irma.ActionSchemeManager {
session.managerSession()
return
}
// Get the first IRMA protocol message and parse it // Get the first IRMA protocol message and parse it
session.info = &irma.SessionInfo{} session.info = &irma.SessionInfo{}
Err := session.transport.Get("jwt", session.info) Err := session.transport.Get("jwt", session.info)
...@@ -378,20 +378,34 @@ func (session *session) sendResponse(message interface{}) { ...@@ -378,20 +378,34 @@ func (session *session) sendResponse(message interface{}) {
} }
func (session *session) managerSession() { func (session *session) managerSession() {
defer func() {
handlePanic(func(err *irma.SessionError) {
if session.Handler != nil {
session.Handler.Failure(session.Action, err)
}
})
}()
// We have to download the scheme manager description.xml here before installing it,
// because we need to show its contents (name, description, website) to the user
// when asking installation permission.
manager, err := session.client.Configuration.DownloadSchemeManager(session.ServerURL) manager, err := session.client.Configuration.DownloadSchemeManager(session.ServerURL)
if err != nil { if err != nil {
session.Handler.Failure(session.Action, &irma.SessionError{Err: err}) // TODO session.Handler.Failure(session.Action, &irma.SessionError{ErrorType: irma.ErrorConfigurationDownload, Err: err})
return return
} }
session.Handler.RequestSchemeManagerPermission(manager, func(proceed bool) { session.Handler.RequestSchemeManagerPermission(manager, func(proceed bool) {
if !proceed { if !proceed {
session.Handler.Cancelled(session.Action) // No need to DELETE session here session.Handler.Cancelled(session.Action) // No need to DELETE session here
return return
} }
if err := session.client.Configuration.AddSchemeManager(manager); err != nil { if err := session.client.Configuration.AddSchemeManager(manager); err != nil {
session.Handler.Failure(session.Action, &irma.SessionError{}) session.Handler.Failure(session.Action, &irma.SessionError{ErrorType: irma.ErrorConfigurationDownload, Err: err})
return return
} }
// Update state and inform user of success
if manager.Distributed() { if manager.Distributed() {
session.client.UnenrolledSchemeManagers = session.client.unenrolledSchemeManagers() session.client.UnenrolledSchemeManagers = session.client.unenrolledSchemeManagers()
} }
......
...@@ -276,6 +276,8 @@ func (conf *Configuration) Copy(source string, parse bool) error { ...@@ -276,6 +276,8 @@ func (conf *Configuration) Copy(source string, parse bool) error {
return nil return nil
} }
// DownloadSchemeManager downloads and returns a scheme manager description.xml file
// from the specified URL.
func (conf *Configuration) DownloadSchemeManager(url string) (*SchemeManager, error) { func (conf *Configuration) DownloadSchemeManager(url string) (*SchemeManager, error) {
if !strings.HasPrefix(url, "http://") && !strings.HasPrefix(url, "https://") { if !strings.HasPrefix(url, "http://") && !strings.HasPrefix(url, "https://") {
url = "https://" + url url = "https://" + url
...@@ -316,6 +318,7 @@ func (conf *Configuration) RemoveSchemeManager(id SchemeManagerIdentifier) error ...@@ -316,6 +318,7 @@ func (conf *Configuration) RemoveSchemeManager(id SchemeManagerIdentifier) error
delete(conf.publicKeys, issid) delete(conf.publicKeys, issid)
} }
} }
delete(conf.SchemeManagers, id)
// Remove from storage // Remove from storage
return os.RemoveAll(fmt.Sprintf("%s/%s", conf.path, id.String())) return os.RemoveAll(fmt.Sprintf("%s/%s", conf.path, id.String()))
// or, remove above iterations and call .ParseFolder()? // or, remove above iterations and call .ParseFolder()?
...@@ -360,7 +363,7 @@ func (conf *Configuration) Download(set *IrmaIdentifierSet) (*IrmaIdentifierSet, ...@@ -360,7 +363,7 @@ func (conf *Configuration) Download(set *IrmaIdentifierSet) (*IrmaIdentifierSet,
if err = transport.GetFile(url+"/description.xml", path+"/description.xml"); err != nil { if err = transport.GetFile(url+"/description.xml", path+"/description.xml"); err != nil {
return nil, err return nil, err
} }
if transport.GetFile(url+"/logo.png", path+"/logo.png"); err != nil { if err = transport.GetFile(url+"/logo.png", path+"/logo.png"); err != nil {
return nil, err return nil, err
} }
downloaded.Issuers[issid] = struct{}{} downloaded.Issuers[issid] = struct{}{}
...@@ -376,7 +379,7 @@ func (conf *Configuration) Download(set *IrmaIdentifierSet) (*IrmaIdentifierSet, ...@@ -376,7 +379,7 @@ func (conf *Configuration) Download(set *IrmaIdentifierSet) (*IrmaIdentifierSet,
manager := issid.SchemeManagerIdentifier() manager := issid.SchemeManagerIdentifier()
suffix := fmt.Sprintf("/%s/PublicKeys/%d.xml", issid.Name(), count) suffix := fmt.Sprintf("/%s/PublicKeys/%d.xml", issid.Name(), count)
path := fmt.Sprintf("%s/%s/%s", conf.path, manager.String(), suffix) path := fmt.Sprintf("%s/%s/%s", conf.path, manager.String(), suffix)
if transport.GetFile(conf.SchemeManagers[manager].URL+suffix, path); err != nil { if err = transport.GetFile(conf.SchemeManagers[manager].URL+suffix, path); err != nil {
return nil, err return nil, err
} }
} }
...@@ -390,13 +393,16 @@ func (conf *Configuration) Download(set *IrmaIdentifierSet) (*IrmaIdentifierSet, ...@@ -390,13 +393,16 @@ func (conf *Configuration) Download(set *IrmaIdentifierSet) (*IrmaIdentifierSet,
if err := fs.EnsureDirectoryExists(local); err != nil { if err := fs.EnsureDirectoryExists(local); err != nil {
return nil, err return nil, err
} }
if transport.GetFile( if err = transport.GetFile(
fmt.Sprintf("%s/%s/Issues/%s/description.xml", fmt.Sprintf("%s/%s/Issues/%s/description.xml", conf.SchemeManagers[manager].URL, issuer.Name(), credid.Name()),
conf.SchemeManagers[manager].URL, issuer.Name(), credid.Name()),
fmt.Sprintf("%s/%s/description.xml", local, credid.Name()), fmt.Sprintf("%s/%s/description.xml", local, credid.Name()),
); err != nil { ); err != nil {
return nil, err return nil, err
} }
_ = transport.GetFile( // Get logo but ignore errors, it is optional
fmt.Sprintf("%s/%s/Issues/%s/logo.png", conf.SchemeManagers[manager].URL, issuer.Name(), credid.Name()),
fmt.Sprintf("%s/%s/logo.png", local, credid.Name()),
)
downloaded.CredentialTypes[credid] = struct{}{} downloaded.CredentialTypes[credid] = struct{}{}
} }
} }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment