forked from letsencrypt/boulder
-
Notifications
You must be signed in to change notification settings - Fork 0
/
type-converter.go
119 lines (111 loc) · 3.2 KB
/
type-converter.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
package sa
import (
"encoding/json"
"errors"
"fmt"
"github.com/go-gorp/gorp/v3"
"gopkg.in/go-jose/go-jose.v2"
"github.com/letsencrypt/boulder/core"
"github.com/letsencrypt/boulder/identifier"
)
// BoulderTypeConverter is used by Gorp for storing objects in DB.
type BoulderTypeConverter struct{}
// ToDb converts a Boulder object to one suitable for the DB representation.
func (tc BoulderTypeConverter) ToDb(val interface{}) (interface{}, error) {
switch t := val.(type) {
case identifier.ACMEIdentifier, []core.Challenge, []string, [][]int:
jsonBytes, err := json.Marshal(t)
if err != nil {
return nil, err
}
return string(jsonBytes), nil
case jose.JSONWebKey:
jsonBytes, err := t.MarshalJSON()
if err != nil {
return "", err
}
return string(jsonBytes), nil
case core.AcmeStatus:
return string(t), nil
case core.OCSPStatus:
return string(t), nil
default:
return val, nil
}
}
// FromDb converts a DB representation back into a Boulder object.
func (tc BoulderTypeConverter) FromDb(target interface{}) (gorp.CustomScanner, bool) {
switch target.(type) {
case *identifier.ACMEIdentifier, *[]core.Challenge, *[]string, *[][]int:
binder := func(holder, target interface{}) error {
s, ok := holder.(*string)
if !ok {
return errors.New("FromDb: Unable to convert *string")
}
b := []byte(*s)
err := json.Unmarshal(b, target)
if err != nil {
return badJSONError(
fmt.Sprintf("binder failed to unmarshal %T", target),
b,
err)
}
return nil
}
return gorp.CustomScanner{Holder: new(string), Target: target, Binder: binder}, true
case *jose.JSONWebKey:
binder := func(holder, target interface{}) error {
s, ok := holder.(*string)
if !ok {
return fmt.Errorf("FromDb: Unable to convert %T to *string", holder)
}
if *s == "" {
return errors.New("FromDb: Empty JWK field.")
}
b := []byte(*s)
k, ok := target.(*jose.JSONWebKey)
if !ok {
return fmt.Errorf("FromDb: Unable to convert %T to *jose.JSONWebKey", target)
}
err := k.UnmarshalJSON(b)
if err != nil {
return badJSONError(
"binder failed to unmarshal JWK",
b,
err)
}
return nil
}
return gorp.CustomScanner{Holder: new(string), Target: target, Binder: binder}, true
case *core.AcmeStatus:
binder := func(holder, target interface{}) error {
s, ok := holder.(*string)
if !ok {
return fmt.Errorf("FromDb: Unable to convert %T to *string", holder)
}
st, ok := target.(*core.AcmeStatus)
if !ok {
return fmt.Errorf("FromDb: Unable to convert %T to *core.AcmeStatus", target)
}
*st = core.AcmeStatus(*s)
return nil
}
return gorp.CustomScanner{Holder: new(string), Target: target, Binder: binder}, true
case *core.OCSPStatus:
binder := func(holder, target interface{}) error {
s, ok := holder.(*string)
if !ok {
return fmt.Errorf("FromDb: Unable to convert %T to *string", holder)
}
st, ok := target.(*core.OCSPStatus)
if !ok {
return fmt.Errorf("FromDb: Unable to convert %T to *core.OCSPStatus", target)
}
*st = core.OCSPStatus(*s)
return nil
}
return gorp.CustomScanner{Holder: new(string), Target: target, Binder: binder}, true
default:
return gorp.CustomScanner{}, false
}
}