api.go 2.96 KB
Newer Older
Sietse Ringers's avatar
Sietse Ringers committed
1
package server
2
3

import (
4
	"encoding/json"
5
	"errors"
6
7
8
	"net/http"
	"runtime/debug"

9
10
11
12
13
	"github.com/Sirupsen/logrus"
	"github.com/mhe/gabi"
	"github.com/privacybydesign/irmago"
)

14
15
var Logger *logrus.Logger = logrus.StandardLogger()

16
17
type Configuration struct {
	IrmaConfigurationPath string
18
	IssuerPrivateKeysPath string
19

20
	Logger *logrus.Logger `json:"-"`
21

22
23
	IssuerPrivateKeys map[irma.IssuerIdentifier]*gabi.PrivateKey `json:"-"`
	IrmaConfiguration *irma.Configuration                        `json:"-"`
24
25
26
}

type SessionResult struct {
Sietse Ringers's avatar
Sietse Ringers committed
27
28
	Token       string
	Status      Status
29
	Type        irma.Action
Sietse Ringers's avatar
Sietse Ringers committed
30
31
32
33
	ProofStatus irma.ProofStatus
	Disclosed   []*irma.DisclosedAttribute
	Signature   *irma.SignedMessage
	Err         *irma.RemoteError
34
35
}

Sietse Ringers's avatar
Sietse Ringers committed
36
// Status is the status of an IRMA session.
37
38
39
type Status string

const (
Sietse Ringers's avatar
Sietse Ringers committed
40
41
42
43
44
	StatusInitialized Status = "INITIALIZED" // The session has been started and is waiting for the client
	StatusConnected   Status = "CONNECTED"   // The client has retrieved the session request, we wait for its response
	StatusCancelled   Status = "CANCELLED"   // The session is cancelled, possibly due to an error
	StatusDone        Status = "DONE"        // The session has completed successfully
	StatusTimeout     Status = "TIMEOUT"     // Session timed out
45
)
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72

func RemoteError(err Error, message string) *irma.RemoteError {
	stack := string(debug.Stack())
	Logger.Errorf("Error: %d %s %s\n%s", err.Status, err.Type, message, stack)
	return &irma.RemoteError{
		Status:      err.Status,
		Description: err.Description,
		ErrorName:   string(err.Type),
		Message:     message,
		Stacktrace:  stack,
	}
}

func JsonResponse(v interface{}, err *irma.RemoteError) (int, []byte) {
	msg := v
	status := http.StatusOK
	if err != nil {
		msg = err
		status = err.Status
	}
	b, e := json.Marshal(msg)
	if e != nil {
		Logger.Error("Failed to serialize response:", e.Error())
		return http.StatusInternalServerError, nil
	}
	return status, b
}
73
74

func WriteError(w http.ResponseWriter, err Error, msg string) {
75
	WriteResponse(w, nil, RemoteError(err, msg))
76
77
78
}

func WriteJson(w http.ResponseWriter, object interface{}) {
79
80
81
82
83
	WriteResponse(w, object, nil)
}

func WriteResponse(w http.ResponseWriter, object interface{}, rerr *irma.RemoteError) {
	status, bts := JsonResponse(object, rerr)
84
85
86
87
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(status)
	w.Write(bts)
}
88
89
90
91
92
93

func WriteString(w http.ResponseWriter, str string) {
	w.Header().Set("Content-Type", "text/plain")
	w.WriteHeader(http.StatusOK)
	w.Write([]byte(str))
}
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109

func ParseSessionRequest(bts []byte) (request irma.SessionRequest, err error) {
	request = &irma.DisclosureRequest{}
	if err = irma.UnmarshalValidate(bts, request); err == nil {
		return request, nil
	}
	request = &irma.SignatureRequest{}
	if err = irma.UnmarshalValidate(bts, request); err == nil {
		return request, nil
	}
	request = &irma.IssuanceRequest{}
	if err = irma.UnmarshalValidate(bts, request); err == nil {
		return request, nil
	}
	return nil, errors.New("Invalid or disabled session type")
}