updates.go 3.08 KB
Newer Older
1
package irmaclient
Sietse Ringers's avatar
Sietse Ringers committed
2
3

import (
4
	"os"
5
	"time"
Sietse Ringers's avatar
Sietse Ringers committed
6

7
8
	"github.com/privacybydesign/irmago"
	"github.com/privacybydesign/irmago/internal/fs"
Sietse Ringers's avatar
Sietse Ringers committed
9
10
)

11
// This file contains the update mechanism for Client
Sietse Ringers's avatar
Sietse Ringers committed
12
13
// as well as updates themselves.

14
type update struct {
15
	When    irma.Timestamp
16
17
18
	Number  int
	Success bool
	Error   *string
19
20
}

21
var clientUpdates = []func(client *Client) error{
22
	// 0: Convert old cardemu.xml Android storage to our own storage format
23
	nil, // No longer necessary as the Android app was deprecated long ago
24

25
	// 1: Adding scheme manager index, signature and public key
26
27
	// Check the signatures of all scheme managers, if any is not ok,
	// copy the entire irma_configuration folder from assets
28
	nil, // made irrelevant by irma_configuration-autocopying
29

30
	// 2: Rename config -> preferences
31
32
33
34
35
	func(client *Client) (err error) {
		exists, err := fs.PathExists(client.storage.path("config"))
		if !exists || err != nil {
			return
		}
36
37
38
39
		oldStruct := &struct {
			SendCrashReports bool
		}{}
		// Load old file, convert to new struct, and save
40
		err = client.storage.load(oldStruct, "config")
41
42
43
44
45
46
47
48
		if err != nil {
			return err
		}
		client.Preferences = Preferences{
			EnableCrashReporting: oldStruct.SendCrashReports,
		}
		return client.storage.StorePreferences(client.Preferences)
	},
49

50
	// 3: Copy new irma_configuration out of assets
51
	nil, // made irrelevant by irma_configuration-autocopying
52

53
	// 4: For each keyshare server, include in its struct the identifier of its scheme manager
54
	func(client *Client) (err error) {
55
56
57
58
59
		keyshareServers, err := client.storage.LoadKeyshareServers()
		if err != nil {
			return err
		}
		for smi, kss := range keyshareServers {
60
61
			kss.SchemeManagerIdentifier = smi
		}
62
		return client.storage.StoreKeyshareServers(keyshareServers)
63
	},
64

65
	// 5: Remove the test scheme manager which was erroneously included in a production build
66
	nil, // No longer necessary, also broke many unit tests
Tomas's avatar
Tomas committed
67

68
69
	// 6: Guess and include version protocol in issuance logs, and convert log entry structure
	// from Response to either IssueCommitment or ProofList
Tomas's avatar
Tomas committed
70
	func(client *Client) (err error) {
71
72
73
		// TODO: this has been temporarily removed and should be restored
		os.Remove(client.storage.path(logsFile))
		return nil
Tomas's avatar
Tomas committed
74
	},
75
}
76

77
// update performs any function from clientUpdates that has not
78
79
// already been executed in the past, keeping track of previously executed updates
// in the file at updatesFile.
80
func (client *Client) update() error {
81
82
	// Load and parse file containing info about already performed updates
	var err error
83
	if client.updates, err = client.storage.LoadUpdates(); err != nil {
84
85
86
87
		return err
	}

	// Perform all new updates
88
	for i := len(client.updates); i < len(clientUpdates); i++ {
89
90
91
		err = nil
		if clientUpdates[i] != nil {
			err = clientUpdates[i](client)
92
		}
Sietse Ringers's avatar
Sietse Ringers committed
93
		u := update{
94
			When:    irma.Timestamp(time.Now()),
95
96
97
98
99
			Number:  i,
			Success: err == nil,
		}
		if err != nil {
			str := err.Error()
Sietse Ringers's avatar
Sietse Ringers committed
100
			u.Error = &str
101
		}
102
		client.updates = append(client.updates, u)
103
104
105
		if err != nil {
			break
		}
106
107
	}

108
109
110
111
112
	storeErr := client.storage.StoreUpdates(client.updates)
	if storeErr != nil {
		return storeErr
	}
	return err
113
}