github.com/aleksi/gonuts.io@v0.0.0-20130622121132-3b0f2d1999fb/app/gonuts/models.go (about) 1 package gonuts 2 3 import ( 4 "appengine" 5 "appengine/datastore" 6 "appengine/user" 7 "crypto/rand" 8 "crypto/sha1" 9 "encoding/hex" 10 "fmt" 11 "io" 12 "sort" 13 "time" 14 ) 15 16 type User struct { 17 // StringID (entity name, key name) is appengine/user.User.ID 18 Id string // same as StringID 19 Email string 20 FederatedIdentity string 21 Token string 22 Debug bool 23 Vendors []string 24 } 25 26 func UserKey(c appengine.Context, u *user.User) *datastore.Key { 27 return datastore.NewKey(c, "User", u.ID, 0, nil) 28 } 29 30 func (user *User) AddVendor(vendor *Vendor) { 31 vmap := make(map[string]bool, len(user.Vendors)+1) 32 for _, v := range user.Vendors { 33 vmap[v] = true 34 } 35 vmap[vendor.Vendor] = true 36 37 vendors := make([]string, 0, len(vmap)) 38 for v := range vmap { 39 vendors = append(vendors, v) 40 } 41 sort.Strings(vendors) 42 user.Vendors = vendors 43 44 umap := make(map[string]bool, len(vendor.UserStringID)+1) 45 for _, u := range vendor.UserStringID { 46 umap[u] = true 47 } 48 umap[user.Id] = true 49 50 users := make([]string, 0, len(umap)) 51 for u := range umap { 52 users = append(users, u) 53 } 54 sort.Strings(users) 55 vendor.UserStringID = users 56 } 57 58 func (user *User) Identifier() (id string) { 59 id = user.Email 60 if id == "" { 61 id = user.FederatedIdentity 62 } 63 if id == "" { 64 panic(fmt.Errorf("User %#v has neither email nor federated identity.", user)) 65 } 66 return 67 } 68 69 type Vendor struct { 70 // StringID (entity name, key name) is "Vendor" 71 Vendor string 72 UserStringID []string // slice of User.StringID 73 } 74 75 func VendorKey(c appengine.Context, vendor string) *datastore.Key { 76 return datastore.NewKey(c, "Vendor", vendor, 0, nil) 77 } 78 79 type Nut struct { 80 // StringID (entity name, key name) is "Vendor/Name" 81 Vendor string 82 Name string 83 Doc string // Doc of latest published version 84 // TODO store total number of downloads, update by cron 85 } 86 87 func NutKey(c appengine.Context, vendor, nut string) *datastore.Key { 88 return datastore.NewKey(c, "Nut", fmt.Sprintf("%s/%s", vendor, nut), 0, nil) 89 } 90 91 type Version struct { 92 // StringID (entity name, key name) is "Vendor/Name-Version" 93 Vendor string 94 Name string 95 Version string 96 VersionNum int // for sorting 97 Doc string 98 Homepage string 99 BlobKey appengine.BlobKey 100 CreatedAt time.Time 101 Downloads int 102 } 103 104 func VersionKey(c appengine.Context, vendor, nut, version string) *datastore.Key { 105 return datastore.NewKey(c, "Version", fmt.Sprintf("%s/%s-%s", vendor, nut, version), 0, nil) 106 } 107 108 func (user *User) GenerateToken() (err error) { 109 const n = 4096 110 111 buf := make([]byte, n) 112 _, err = io.ReadAtLeast(rand.Reader, buf, n) 113 if err != nil { 114 return 115 } 116 117 h := sha1.New() 118 _, err = h.Write(buf) 119 if err != nil { 120 return 121 } 122 123 user.Token = hex.EncodeToString(h.Sum(nil)) 124 return 125 }