Skip to content

Commit f4ccaa3

Browse files
committed
Updated
1 parent 8c3482f commit f4ccaa3

File tree

5 files changed

+176
-7
lines changed

5 files changed

+176
-7
lines changed

pkg/cert/certmanager.go

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@ package cert
22

33
import (
44
"context"
5-
"log"
65

76
// Packages
87
pg "github.com/djthorpe/go-pg"
98
schema "github.com/mutablelogic/go-server/pkg/cert/schema"
109
httpresponse "github.com/mutablelogic/go-server/pkg/httpresponse"
10+
"github.com/mutablelogic/go-server/pkg/types"
1111
)
1212

1313
////////////////////////////////////////////////////////////////////////////////
@@ -52,7 +52,7 @@ func NewCertManager(ctx context.Context, conn pg.PoolConn, opt ...Opt) (*CertMan
5252
if name, err := self.RegisterName(ctx, self.root.SubjectMeta()); err != nil {
5353
return err
5454
} else {
55-
log.Println(name)
55+
self.root.Subject = types.Uint64Ptr(name.Id)
5656
}
5757
return nil
5858
}); err != nil {
@@ -66,6 +66,14 @@ func NewCertManager(ctx context.Context, conn pg.PoolConn, opt ...Opt) (*CertMan
6666
////////////////////////////////////////////////////////////////////////////////
6767
// PUBLIC METHODS
6868

69+
// Return the root certificate
70+
func (certmanager *CertManager) Root() *Cert {
71+
return certmanager.root
72+
}
73+
74+
////////////////////////////////////////////////////////////////////////////////
75+
// PUBLIC METHODS
76+
6977
func (certmanager *CertManager) RegisterName(ctx context.Context, meta schema.NameMeta) (*schema.Name, error) {
7078
var name schema.Name
7179
if err := certmanager.conn.Insert(ctx, &name, meta); err != nil {
@@ -95,9 +103,21 @@ func (certmanager *CertManager) UpdateName(ctx context.Context, id uint64, meta
95103

96104
func (certmanager *CertManager) DeleteName(ctx context.Context, id uint64) (*schema.Name, error) {
97105
var name schema.Name
98-
if err := certmanager.conn.Delete(ctx, &name, schema.NameId(id)); err != nil {
106+
// Don't allow the root certificate to be deleted
107+
if id == types.PtrUint64(certmanager.root.Subject) {
108+
return nil, httpresponse.ErrConflict.With("cannot delete root certificate")
109+
} else if err := certmanager.conn.Delete(ctx, &name, schema.NameId(id)); err != nil {
99110
return nil, err
100111
} else {
101112
return &name, nil
102113
}
103114
}
115+
116+
func (certmanager *CertManager) ListNames(ctx context.Context) (*schema.NameList, error) {
117+
var list schema.NameList
118+
if err := certmanager.conn.List(ctx, &list, schema.NameListRequest{}); err != nil {
119+
return nil, err
120+
} else {
121+
return &list, nil
122+
}
123+
}

pkg/cert/certmanager_test.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ import (
88
// Packages
99
test "github.com/djthorpe/go-pg/pkg/test"
1010
cert "github.com/mutablelogic/go-server/pkg/cert"
11+
schema "github.com/mutablelogic/go-server/pkg/cert/schema"
12+
"github.com/mutablelogic/go-server/pkg/types"
13+
"github.com/mutablelogic/go-service/pkg/httpresponse"
1114
assert "github.com/stretchr/testify/assert"
1215
)
1316

@@ -38,4 +41,44 @@ func Test_CertManager_001(t *testing.T) {
3841
t.FailNow()
3942
}
4043
assert.NotNil(certmanager)
44+
45+
// Get the root name
46+
t.Run("GetName", func(t *testing.T) {
47+
name, err := certmanager.GetName(context.TODO(), types.PtrUint64(certmanager.Root().Subject))
48+
if !assert.NoError(err) {
49+
t.FailNow()
50+
}
51+
assert.NotNil(name)
52+
assert.Equal(name.CommonName, "root")
53+
})
54+
55+
// List names
56+
t.Run("ListName", func(t *testing.T) {
57+
names, err := certmanager.ListNames(context.TODO())
58+
if !assert.NoError(err) {
59+
t.FailNow()
60+
}
61+
assert.NotNil(names)
62+
assert.Equal(names.Count, uint64(1))
63+
assert.Len(names.Body, 1)
64+
})
65+
66+
// Update name
67+
t.Run("UpdateName", func(t *testing.T) {
68+
name, err := certmanager.UpdateName(context.TODO(), types.PtrUint64(certmanager.Root().Subject), schema.NameMeta{
69+
CommonName: "root_2",
70+
Org: types.StringPtr("mutablelogic"),
71+
})
72+
if !assert.NoError(err) {
73+
t.FailNow()
74+
}
75+
assert.Equal("root_2", name.CommonName)
76+
assert.Equal("mutablelogic", types.PtrString(name.Org))
77+
})
78+
79+
// Delete name - don't allow the deletion of the root certificate
80+
t.Run("DeleteName", func(t *testing.T) {
81+
_, err := certmanager.DeleteName(context.TODO(), types.PtrUint64(certmanager.Root().Subject))
82+
assert.ErrorIs(err, httpresponse.ErrConflict)
83+
})
4184
}

pkg/cert/schema/name.go

Lines changed: 92 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ import (
88

99
// Packages
1010
pg "github.com/djthorpe/go-pg"
11-
httpresponse "github.com/mutablelogic/go-service/pkg/httpresponse"
11+
httpresponse "github.com/mutablelogic/go-server/pkg/httpresponse"
12+
"github.com/mutablelogic/go-server/pkg/types"
1213
)
1314

1415
////////////////////////////////////////////////////////////////////////////////
@@ -34,6 +35,15 @@ type Name struct {
3435
Subject *string `json:"subject,omitempty"`
3536
}
3637

38+
type NameList struct {
39+
Count uint64 `json:"count"`
40+
Body []Name `json:"body,omitempty"`
41+
}
42+
43+
type NameListRequest struct {
44+
pg.OffsetLimit
45+
}
46+
3747
////////////////////////////////////////////////////////////////////////////////
3848
// STRINGIFY
3949

@@ -53,6 +63,14 @@ func (n Name) String() string {
5363
return string(data)
5464
}
5565

66+
func (n NameList) String() string {
67+
data, err := json.MarshalIndent(n, "", " ")
68+
if err != nil {
69+
return err.Error()
70+
}
71+
return string(data)
72+
}
73+
5674
////////////////////////////////////////////////////////////////////////////////
5775
// SELECT
5876

@@ -65,11 +83,33 @@ func (n NameId) Select(bind *pg.Bind, op pg.Op) (string, error) {
6583

6684
// Return query
6785
switch op {
86+
case pg.Get:
87+
return nameGet, nil
88+
case pg.Update:
89+
return namePatch, nil
90+
case pg.Delete:
91+
return nameDelete, nil
6892
default:
6993
return "", httpresponse.ErrInternalError.Withf("unsupported NameId operation %q", op)
7094
}
7195
}
7296

97+
func (n NameListRequest) Select(bind *pg.Bind, op pg.Op) (string, error) {
98+
// Set empty where
99+
bind.Set("where", "")
100+
101+
// Bind offset and limit
102+
n.OffsetLimit.Bind(bind, NameListLimit)
103+
104+
// Return query
105+
switch op {
106+
case pg.List:
107+
return nameList, nil
108+
default:
109+
return "", httpresponse.ErrInternalError.Withf("unsupported NameListRequest operation %q", op)
110+
}
111+
}
112+
73113
////////////////////////////////////////////////////////////////////////////////
74114
// WRITER
75115

@@ -79,13 +119,48 @@ func (n NameMeta) Insert(bind *pg.Bind) (string, error) {
79119
} else {
80120
bind.Set("commonName", commonName)
81121
}
122+
// TODO
82123

83124
// Return insert or replace
84125
return nameReplace, nil
85126
}
86127

87128
func (n NameMeta) Update(bind *pg.Bind) error {
88-
return httpresponse.ErrNotImplemented.With("NameMeta.Update")
129+
bind.Del("patch")
130+
if name := strings.TrimSpace(n.CommonName); name != "" {
131+
bind.Append("patch", `"commonName" = `+bind.Set("commonName", name))
132+
}
133+
if n.Org != nil {
134+
bind.Append("patch", `"organizationName" = `+bind.Set("organizationName", types.TrimStringPtr(*n.Org)))
135+
}
136+
if n.Unit != nil {
137+
bind.Append("patch", `"organizationalUnit" = `+bind.Set("organizationalUnit", types.TrimStringPtr(*n.Unit)))
138+
}
139+
if n.Country != nil {
140+
bind.Append("patch", `"countryName" = `+bind.Set("countryName", types.TrimStringPtr(*n.Country)))
141+
}
142+
if n.City != nil {
143+
bind.Append("patch", `"localityName" = `+bind.Set("localityName", types.TrimStringPtr(*n.City)))
144+
}
145+
if n.State != nil {
146+
bind.Append("patch", `"stateOrProvinceName" = `+bind.Set("stateOrProvinceName", types.TrimStringPtr(*n.State)))
147+
}
148+
if n.StreetAddress != nil {
149+
bind.Append("patch", `"streetAddress" = `+bind.Set("streetAddress", types.TrimStringPtr(*n.StreetAddress)))
150+
}
151+
if n.PostalCode != nil {
152+
bind.Append("patch", `"postalCode" = `+bind.Set("postalCode", types.TrimStringPtr(*n.PostalCode)))
153+
}
154+
155+
// Join the patch fields
156+
if patch := bind.Join("patch", ", "); patch == "" {
157+
return httpresponse.ErrBadRequest.With("nothing to update")
158+
} else {
159+
bind.Set("patch", patch)
160+
}
161+
162+
// Return success
163+
return nil
89164
}
90165

91166
////////////////////////////////////////////////////////////////////////////////
@@ -95,6 +170,20 @@ func (n *Name) Scan(row pg.Row) error {
95170
return row.Scan(&n.Id, &n.CommonName, &n.Org, &n.Unit, &n.Country, &n.City, &n.State, &n.StreetAddress, &n.PostalCode, &n.Ts)
96171
}
97172

173+
func (n *NameList) Scan(row pg.Row) error {
174+
var name Name
175+
if err := name.Scan(row); err != nil {
176+
return err
177+
} else {
178+
n.Body = append(n.Body, name)
179+
}
180+
return nil
181+
}
182+
183+
func (n *NameList) ScanCount(row pg.Row) error {
184+
return row.Scan(&n.Count)
185+
}
186+
98187
////////////////////////////////////////////////////////////////////////////////
99188
// SQL
100189

@@ -165,5 +254,5 @@ const (
165254
${"schema"}."name"
166255
`
167256
nameGet = nameSelect + ` WHERE "id" = @id`
168-
nameList = `WITH q AS (` + nameSelect + `) SELECT * FROM q ${where} ${offsetlimit}`
257+
nameList = `WITH q AS (` + nameSelect + `) SELECT * FROM q ${where}`
169258
)

pkg/cert/schema/schema.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@ const (
1414
SchemaName = "cert"
1515
)
1616

17+
const (
18+
// Maximum number of names to return in a list query
19+
NameListLimit = 100
20+
)
21+
1722
////////////////////////////////////////////////////////////////////////////////
1823
// PUBLIC METHODS
1924

pkg/types/ptr.go

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,24 @@
11
package types
22

3-
import "time"
3+
import (
4+
"strings"
5+
"time"
6+
)
47

58
// StringPtr returns a pointer to a string
69
func StringPtr(s string) *string {
710
return &s
811
}
912

13+
// TrimStringPtr returns a pointer to a white-space trimmed string, or nil
14+
// if the string is empty
15+
func TrimStringPtr(s string) *string {
16+
if s = strings.TrimSpace(s); s == "" {
17+
return nil
18+
}
19+
return &s
20+
}
21+
1022
// PtrString returns a string from a pointer
1123
func PtrString(s *string) string {
1224
if s == nil {

0 commit comments

Comments
 (0)