This repository has been archived by the owner on Feb 16, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 10
/
dir.go
124 lines (105 loc) · 3.58 KB
/
dir.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
120
121
122
123
124
package api
import (
"net/http"
"time"
"bitbucket.org/zombiezen/cardcpx/natsort"
"github.com/secrethub/secrethub-go/internals/api/uuid"
"github.com/secrethub/secrethub-go/internals/crypto"
)
// Errors
var (
ErrInvalidDirName = errAPI.Code("invalid_dir_name").StatusError(
"directory names must be between 2 and 32 characters long and "+
"may only contain letters, numbers, dashes (-), underscores (_), and dots (.)",
http.StatusBadRequest,
)
ErrInvalidDirBlindName = errAPI.Code("invalid_dir_blind_name").StatusErrorf("directory blind name is invalid: %s", http.StatusBadRequest, ErrInvalidBlindName)
ErrInvalidParentBlindName = errAPI.Code("invalid_parent_blind_name").StatusErrorf("directory parent blind name is invalid: %s", http.StatusBadRequest, ErrInvalidBlindName)
)
// EncryptedDir represents an encrypted Dir.
// The names are encrypted and so are the names of SubDirs and Secrets.
// The secrets contain no encrypted data, only the encrypted name.
type EncryptedDir struct {
DirID uuid.UUID `json:"dir_id"`
BlindName string `json:"blind_name"`
EncryptedName crypto.CiphertextRSA `json:"encrypted_name"`
ParentID *uuid.UUID `json:"parent_id"`
Status string `json:"status"`
CreatedAt time.Time `json:"created_at"`
LastModifiedAt time.Time `json:"last_modified_at"`
}
// Decrypt decrypts an EncryptedDir into a Dir.
func (ed *EncryptedDir) Decrypt(accountKey *crypto.RSAPrivateKey) (*Dir, error) {
name, err := accountKey.Unwrap(ed.EncryptedName)
if err != nil {
return nil, err
}
result := &Dir{
DirID: ed.DirID,
BlindName: ed.BlindName,
Name: string(name),
ParentID: ed.ParentID,
Status: ed.Status,
CreatedAt: ed.CreatedAt,
LastModifiedAt: ed.LastModifiedAt,
}
return result, nil
}
// Dir represents an directory.
// A dir belongs to a repo and contains other dirs and secrets.
type Dir struct {
DirID uuid.UUID `json:"dir_id"`
BlindName string `json:"blind_name"`
Name string `json:"name"`
ParentID *uuid.UUID `json:"parent_id"`
Status string `json:"status"`
CreatedAt time.Time `json:"created_at"`
LastModifiedAt time.Time `json:"last_modified_at"`
SubDirs []*Dir `json:"sub_dirs"`
Secrets []*Secret `json:"secrets"`
}
// CreateDirRequest contains the request fields for creating a new directory.
type CreateDirRequest struct {
BlindName string `json:"blind_name"`
ParentBlindName string `json:"parent_blind_name"`
EncryptedNames []EncryptedNameRequest `json:"encrypted_names"`
}
// Validate validates the CreateDirRequest to be valid.
func (cdr *CreateDirRequest) Validate() error {
err := ValidateBlindName(cdr.BlindName)
if err != nil {
return ErrInvalidDirBlindName
}
err = ValidateBlindName(cdr.ParentBlindName)
if err != nil {
return ErrInvalidParentBlindName
}
if len(cdr.EncryptedNames) < 1 {
return ErrNotEncryptedForAccounts
}
unique := make(map[uuid.UUID]int)
for _, encryptedName := range cdr.EncryptedNames {
err := encryptedName.Validate()
if err != nil {
return err
}
unique[encryptedName.AccountID]++
}
for _, count := range unique {
if count != 1 {
return ErrNotUniquelyEncryptedForAccounts
}
}
return nil
}
// SortDirByName makes a list of Dir sortable.
type SortDirByName []*Dir
func (d SortDirByName) Len() int {
return len(d)
}
func (d SortDirByName) Swap(i, j int) {
d[i], d[j] = d[j], d[i]
}
func (d SortDirByName) Less(i, j int) bool {
return natsort.Less(d[i].Name, d[j].Name)
}