Commit 24ff0a65 authored by Sietse Ringers's avatar Sietse Ringers
Browse files

Add download command to schememgr executable

parent a397ab12
......@@ -167,6 +167,10 @@ func (id *Issuer) SchemeManagerIdentifier() SchemeManagerIdentifier {
return NewSchemeManagerIdentifier(id.SchemeManagerID)
}
func NewSchemeManager(name string) *SchemeManager {
return &SchemeManager{ID: name, Status: SchemeManagerStatusUnprocessed, Valid: false}
}
// Identifier returns the identifier of the specified scheme manager.
func (sm *SchemeManager) Identifier() SchemeManagerIdentifier {
return NewSchemeManagerIdentifier(sm.ID)
......
......@@ -501,7 +501,7 @@ func (session *session) managerSession() {
// 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 := irma.DownloadSchemeManager(session.ServerURL)
if err != nil {
session.Handler.Failure(session.Action, &irma.SessionError{ErrorType: irma.ErrorConfigurationDownload, Err: err})
return
......@@ -512,7 +512,7 @@ func (session *session) managerSession() {
session.Handler.Cancelled(session.Action) // No need to DELETE session here
return
}
if err := session.client.Configuration.AddSchemeManager(manager); err != nil {
if err := session.client.Configuration.InstallSchemeManager(manager); err != nil {
session.Handler.Failure(session.Action, &irma.SessionError{ErrorType: irma.ErrorConfigurationDownload, Err: err})
return
}
......
......@@ -103,24 +103,31 @@ func NewConfiguration(path string, assets string) (conf *Configuration, err erro
}
}
// Init all maps
conf.clear()
return
}
// ParseFolder populates the current Configuration by parsing the storage path,
// listing the containing scheme managers, issuers and credential types.
func (conf *Configuration) ParseFolder() (err error) {
// Init all maps
func (conf *Configuration) clear() {
conf.SchemeManagers = make(map[SchemeManagerIdentifier]*SchemeManager)
conf.Issuers = make(map[IssuerIdentifier]*Issuer)
conf.CredentialTypes = make(map[CredentialTypeIdentifier]*CredentialType)
conf.DisabledSchemeManagers = make(map[SchemeManagerIdentifier]*SchemeManagerError)
conf.publicKeys = make(map[IssuerIdentifier]map[int]*gabi.PublicKey)
conf.reverseHashes = make(map[string]CredentialTypeIdentifier)
}
// ParseFolder populates the current Configuration by parsing the storage path,
// listing the containing scheme managers, issuers and credential types.
func (conf *Configuration) ParseFolder() (err error) {
// Init all maps
conf.clear()
var mgrerr *SchemeManagerError
err = iterateSubfolders(conf.Path, func(dir string) error {
manager := &SchemeManager{ID: filepath.Base(dir), Status: SchemeManagerStatusUnprocessed, Valid: false}
err := conf.parseSchemeManagerFolder(dir, manager)
manager := NewSchemeManager(filepath.Base(dir))
err := conf.ParseSchemeManagerFolder(dir, manager)
if err == nil {
return nil // OK, do next scheme manager folder
}
......@@ -155,9 +162,9 @@ func (conf *Configuration) ParseOrRestoreFolder() error {
return err
}
// parseSchemeManagerFolder parses the entire tree of the specified scheme manager
// ParseSchemeManagerFolder parses the entire tree of the specified scheme manager
// If err != nil then a problem occured
func (conf *Configuration) parseSchemeManagerFolder(dir string, manager *SchemeManager) (err error) {
func (conf *Configuration) ParseSchemeManagerFolder(dir string, manager *SchemeManager) (err error) {
// From this point, keep it in our map even if it has an error. The user must check either:
// - manager.Status == SchemeManagerStatusValid, aka "VALID"
// - or equivalently, manager.Valid == true
......@@ -450,7 +457,7 @@ func (conf *Configuration) CopyManagerFromAssets(managerID SchemeManagerIdentifi
// DownloadSchemeManager downloads and returns a scheme manager description.xml file
// from the specified URL.
func (conf *Configuration) DownloadSchemeManager(url string) (*SchemeManager, error) {
func DownloadSchemeManager(url string) (*SchemeManager, error) {
if !strings.HasPrefix(url, "http://") && !strings.HasPrefix(url, "https://") {
url = "https://" + url
}
......@@ -464,7 +471,7 @@ func (conf *Configuration) DownloadSchemeManager(url string) (*SchemeManager, er
if err != nil {
return nil, err
}
manager := &SchemeManager{Status: SchemeManagerStatusUnprocessed, Valid: false}
manager := NewSchemeManager("")
if err = xml.Unmarshal(b, manager); err != nil {
return nil, err
}
......@@ -500,11 +507,11 @@ func (conf *Configuration) RemoveSchemeManager(id SchemeManagerIdentifier, fromS
return nil
}
// AddSchemeManager adds the specified scheme manager to this Configuration,
// InstallSchemeManager downloads and adds the specified scheme manager to this Configuration,
// provided its signature is valid.
func (conf *Configuration) AddSchemeManager(manager *SchemeManager) error {
func (conf *Configuration) InstallSchemeManager(manager *SchemeManager) error {
name := manager.ID
if err := fs.EnsureDirectoryExists(fmt.Sprintf("%s/%s", conf.Path, name)); err != nil {
if err := fs.EnsureDirectoryExists(filepath.Join(conf.Path, name)); err != nil {
return err
}
......@@ -519,8 +526,12 @@ func (conf *Configuration) AddSchemeManager(manager *SchemeManager) error {
if err := conf.DownloadSchemeManagerSignature(manager); err != nil {
return err
}
conf.SchemeManagers[manager.Identifier()] = manager
if err := conf.UpdateSchemeManager(manager.Identifier(), nil); err != nil {
return err
}
return conf.parseSchemeManagerFolder(filepath.Join(conf.Path, name), manager)
return conf.ParseSchemeManagerFolder(filepath.Join(conf.Path, name), manager)
}
// DownloadSchemeManagerSignature downloads, stores and verifies the latest version
......@@ -815,12 +826,17 @@ func (conf *Configuration) UpdateSchemeManager(id SchemeManagerIdentifier, downl
// TODO: how to recover/fix local copy if err != nil below?
for filename, newHash := range newIndex {
path := filepath.Join(conf.Path, filename)
oldHash, known := manager.index[filename]
if known && oldHash.Equal(newHash) {
var have bool
have, err = fs.PathExists(path)
if err != nil {
return err
}
if known && have && oldHash.Equal(newHash) {
continue // nothing to do, we already have this file
}
// Ensure that the folder in which to write the file exists
path := filepath.Join(conf.Path, filename)
if err = os.MkdirAll(filepath.Dir(path), 0700); err != nil {
return err
}
......
package cmd
import (
"net/url"
"path/filepath"
"strings"
"github.com/go-errors/errors"
"github.com/privacybydesign/irmago"
"github.com/privacybydesign/irmago/internal/fs"
"github.com/spf13/cobra"
)
// TODO: add flag to update timestamp of irma_configuration folder
var downloadCmd = &cobra.Command{
Use: "download path url...",
Short: "[Experimental] Download a scheme manager",
Long: `The download command downloads and saves a scheme manager given its URL, saving it in path (i.e., an irma_configuration folder).`,
Args: cobra.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string) error {
return downloadSchemeManager(args[0], args[1:])
},
}
func init() {
RootCmd.AddCommand(downloadCmd)
}
func downloadSchemeManager(dest string, urls []string) error {
exists, err := fs.PathExists(dest)
if err != nil {
return errors.Errorf("Could not check path existence: %s", err.Error())
}
if !exists {
return errors.New("Destination does not exist")
}
var normalizedUrls []string
for _, u := range urls {
_, err := url.ParseRequestURI(u)
if err != nil {
return errors.Errorf("%s is not a valid URL: %s", u, err.Error())
}
// Calculate normalized scheme manager url
if strings.HasSuffix(u, "description.xml") {
u = strings.TrimRight(u, "description.xml")
}
if strings.HasSuffix(u, "/") {
u = strings.TrimRight(u, "/")
}
normalizedUrls = append(normalizedUrls, u)
urlparts := strings.Split(u, "/")
managerName := urlparts[len(urlparts)-1]
if err = fs.AssertPathNotExists(filepath.Join(dest, managerName)); err != nil {
return errors.Errorf("Scheme manager %s already exists", managerName)
}
}
conf, err := irma.NewConfiguration(dest, "")
for _, u := range normalizedUrls {
urlparts := strings.Split(u, "/")
managerName := urlparts[len(urlparts)-1]
manager := irma.NewSchemeManager(managerName)
manager.URL = u
conf.InstallSchemeManager(manager)
}
return nil
}
......@@ -11,6 +11,7 @@ import (
"github.com/spf13/cobra"
)
// TODO: add flag to update timestamp of irma_configuration folder
var updateCmd = &cobra.Command{
Use: "update path...",
Short: "[Experimental] Update a scheme manager",
......
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