This repository has been archived by the owner on Jul 7, 2020. It is now read-only.
/
models.go
125 lines (107 loc) · 2.69 KB
/
models.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
125
package gonuts
import (
"appengine"
"appengine/datastore"
"appengine/user"
"crypto/rand"
"crypto/sha1"
"encoding/hex"
"fmt"
"io"
"sort"
"time"
)
type User struct {
// StringID (entity name, key name) is appengine/user.User.ID
Id string // same as StringID
Email string
FederatedIdentity string
Token string
Debug bool
Vendors []string
}
func UserKey(c appengine.Context, u *user.User) *datastore.Key {
return datastore.NewKey(c, "User", u.ID, 0, nil)
}
func (user *User) AddVendor(vendor *Vendor) {
vmap := make(map[string]bool, len(user.Vendors)+1)
for _, v := range user.Vendors {
vmap[v] = true
}
vmap[vendor.Vendor] = true
vendors := make([]string, 0, len(vmap))
for v := range vmap {
vendors = append(vendors, v)
}
sort.Strings(vendors)
user.Vendors = vendors
umap := make(map[string]bool, len(vendor.UserStringID)+1)
for _, u := range vendor.UserStringID {
umap[u] = true
}
umap[user.Id] = true
users := make([]string, 0, len(umap))
for u := range umap {
users = append(users, u)
}
sort.Strings(users)
vendor.UserStringID = users
}
func (user *User) Identifier() (id string) {
id = user.Email
if id == "" {
id = user.FederatedIdentity
}
if id == "" {
panic(fmt.Errorf("User %#v has neither email nor federated identity.", user))
}
return
}
type Vendor struct {
// StringID (entity name, key name) is "Vendor"
Vendor string
UserStringID []string // slice of User.StringID
}
func VendorKey(c appengine.Context, vendor string) *datastore.Key {
return datastore.NewKey(c, "Vendor", vendor, 0, nil)
}
type Nut struct {
// StringID (entity name, key name) is "Vendor/Name"
Vendor string
Name string
Doc string // Doc of latest published version
// TODO store total number of downloads, update by cron
}
func NutKey(c appengine.Context, vendor, nut string) *datastore.Key {
return datastore.NewKey(c, "Nut", fmt.Sprintf("%s/%s", vendor, nut), 0, nil)
}
type Version struct {
// StringID (entity name, key name) is "Vendor/Name-Version"
Vendor string
Name string
Version string
VersionNum int // for sorting
Doc string
Homepage string
BlobKey appengine.BlobKey
CreatedAt time.Time
Downloads int
}
func VersionKey(c appengine.Context, vendor, nut, version string) *datastore.Key {
return datastore.NewKey(c, "Version", fmt.Sprintf("%s/%s-%s", vendor, nut, version), 0, nil)
}
func (user *User) GenerateToken() (err error) {
const n = 4096
buf := make([]byte, n)
_, err = io.ReadAtLeast(rand.Reader, buf, n)
if err != nil {
return
}
h := sha1.New()
_, err = h.Write(buf)
if err != nil {
return
}
user.Token = hex.EncodeToString(h.Sum(nil))
return
}