gifs/api

Paddy 2014-08-27 Child:96aac3ae74e6

0:08ec88016e2f Go to Latest

gifs/api/memstore.go

Spike out functionality and tests. Create our interfaces around storing data and retrieving it. Create an in-memory implementation of our interfaces, for testing and rapid dev purposes. Begin sketching out what our unit tests look like. Create our Google Cloud Storage datastore implementation. Sketch out an idea for a usage collection process to keep track of which users are actually using stuff.

History
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/memstore.go	Wed Aug 27 22:34:02 2014 -0400
     1.3 @@ -0,0 +1,228 @@
     1.4 +package api
     1.5 +
     1.6 +import (
     1.7 +	"time"
     1.8 +
     1.9 +	"secondbit.org/uuid"
    1.10 +)
    1.11 +
    1.12 +type Memstore struct {
    1.13 +	collections map[string]Collection
    1.14 +	domains     map[string]Domain
    1.15 +	items       map[string]Item
    1.16 +	users       map[string]User
    1.17 +	logins      map[string]Login
    1.18 +}
    1.19 +
    1.20 +func NewMemstore() Memstore {
    1.21 +	return Memstore{
    1.22 +		collections: map[string]Collection{},
    1.23 +		domains:     map[string]Domain{},
    1.24 +		items:       map[string]Item{},
    1.25 +		users:       map[string]User{},
    1.26 +		logins:      map[string]Login{},
    1.27 +	}
    1.28 +}
    1.29 +
    1.30 +func (m Memstore) CreateCollection(c Collection) error {
    1.31 +	m.collections[c.ID.String()] = c
    1.32 +	return nil
    1.33 +}
    1.34 +
    1.35 +func (m Memstore) UpdateCollection(c Collection) error {
    1.36 +	if _, ok := m.collections[c.ID.String()]; !ok {
    1.37 +		return CollectionNotFoundError
    1.38 +	}
    1.39 +	m.collections[c.ID.String()] = c
    1.40 +	return nil
    1.41 +}
    1.42 +
    1.43 +func (m Memstore) GetCollectionByDomain(domain string) (Collection, error) {
    1.44 +	d, ok := m.domains[domain]
    1.45 +	if !ok {
    1.46 +		return Collection{}, CollectionNotFoundError
    1.47 +	}
    1.48 +	return m.GetCollectionByID(d.CollectionID)
    1.49 +}
    1.50 +
    1.51 +func (m Memstore) GetCollectionByID(id uuid.ID) (Collection, error) {
    1.52 +	if c, ok := m.collections[id.String()]; ok {
    1.53 +		return c, nil
    1.54 +	}
    1.55 +	return Collection{}, CollectionNotFoundError
    1.56 +}
    1.57 +
    1.58 +func (m Memstore) GetCollectionsByUser(id uuid.ID) ([]Collection, error) {
    1.59 +	collections := []Collection{}
    1.60 +	for _, c := range m.collections {
    1.61 +		if c.Owner.Equal(id) {
    1.62 +			collections = append(collections, c)
    1.63 +		}
    1.64 +	}
    1.65 +	return collections, nil
    1.66 +}
    1.67 +
    1.68 +func (m Memstore) AddDomainToCollection(id uuid.ID, domain string) error {
    1.69 +	if _, ok := m.domains[domain]; ok {
    1.70 +		return DomainAlreadyExistsError
    1.71 +	}
    1.72 +	m.domains[domain] = Domain{
    1.73 +		Domain:       domain,
    1.74 +		CollectionID: id,
    1.75 +		Created:      time.Now(),
    1.76 +	}
    1.77 +	return nil
    1.78 +}
    1.79 +
    1.80 +func (m Memstore) RemoveDomainFromCollection(id uuid.ID, domain string) error {
    1.81 +	if _, ok := m.domains[domain]; !ok {
    1.82 +		return DomainNotFoundError
    1.83 +	}
    1.84 +	delete(m.domains, domain)
    1.85 +	return nil
    1.86 +}
    1.87 +
    1.88 +func (m Memstore) GetDomainsByCollection(id uuid.ID) ([]Domain, error) {
    1.89 +	domains := []Domain{}
    1.90 +	for _, d := range m.domains {
    1.91 +		if d.CollectionID.Equal(id) {
    1.92 +			domains = append(domains, d)
    1.93 +		}
    1.94 +	}
    1.95 +	return domains, nil
    1.96 +}
    1.97 +
    1.98 +func (m Memstore) DeleteCollection(c Collection) error {
    1.99 +	if _, ok := m.collections[c.ID.String()]; !ok {
   1.100 +		return CollectionNotFoundError
   1.101 +	}
   1.102 +	delete(m.collections, c.ID.String())
   1.103 +	return nil
   1.104 +}
   1.105 +
   1.106 +func (m Memstore) GetItemsByCollectionDomain(domain string, num, offset int) ([]Item, error) {
   1.107 +	collection, err := m.GetCollectionByDomain(domain)
   1.108 +	if err != nil {
   1.109 +		return []Item{}, err
   1.110 +	}
   1.111 +	return m.GetItemsByCollectionID(collection.ID, num, offset)
   1.112 +}
   1.113 +
   1.114 +func (m Memstore) GetItemsByCollectionID(id uuid.ID, num, offset int) ([]Item, error) {
   1.115 +	if _, ok := m.collections[id.String()]; !ok {
   1.116 +		return []Item{}, CollectionNotFoundError
   1.117 +	}
   1.118 +	items := []Item{}
   1.119 +	for _, item := range m.items {
   1.120 +		if item.CollectionID.Equal(id) {
   1.121 +			items = append(items, item)
   1.122 +		}
   1.123 +	}
   1.124 +	if len(items) < offset {
   1.125 +		return []Item{}, nil
   1.126 +	}
   1.127 +	end := offset + num
   1.128 +	if len(items) < end {
   1.129 +		end = len(items)
   1.130 +	}
   1.131 +	return items[offset:end], nil
   1.132 +}
   1.133 +
   1.134 +func (m Memstore) AddItemToCollection(id uuid.ID, item Item) error {
   1.135 +	if _, ok := m.collections[id.String()]; !ok {
   1.136 +		return CollectionNotFoundError
   1.137 +	}
   1.138 +	if _, ok := m.items[id.String()+"/"+item.Name]; ok {
   1.139 +		return ItemAlreadyExistsError
   1.140 +	}
   1.141 +	item.CollectionID = id
   1.142 +	m.items[id.String()+"/"+item.Name] = item
   1.143 +	return nil
   1.144 +}
   1.145 +
   1.146 +func (m Memstore) GetItemByName(collectionID uuid.ID, name string) (Item, error) {
   1.147 +	if _, ok := m.collections[collectionID.String()]; !ok {
   1.148 +		return Item{}, CollectionNotFoundError
   1.149 +	}
   1.150 +	if item, ok := m.items[collectionID.String()+"/"+name]; ok {
   1.151 +		return item, nil
   1.152 +	}
   1.153 +	return Item{}, ItemNotFoundError
   1.154 +}
   1.155 +
   1.156 +func (m Memstore) DeleteItem(item Item) error {
   1.157 +	if _, ok := m.items[item.CollectionID.String()+"/"+item.Name]; !ok {
   1.158 +		return ItemNotFoundError
   1.159 +	}
   1.160 +	delete(m.items, item.CollectionID.String()+"/"+item.Name)
   1.161 +	return nil
   1.162 +}
   1.163 +
   1.164 +func (m Memstore) GetUserByID(id uuid.ID) (User, error) {
   1.165 +	if u, ok := m.users[id.String()]; ok {
   1.166 +		return u, nil
   1.167 +	}
   1.168 +	return User{}, UserNotFoundError
   1.169 +}
   1.170 +
   1.171 +func (m Memstore) GetUserByLogin(loginType, value, passphrase string) (User, error) {
   1.172 +	login, ok := m.logins[loginType+":"+value]
   1.173 +	if !ok {
   1.174 +		return User{}, UserNotFoundError
   1.175 +	}
   1.176 +	user, err := m.GetUserByID(login.UserID)
   1.177 +	if err != nil {
   1.178 +		return user, err
   1.179 +	}
   1.180 +	if user.Passphrase != passphrase {
   1.181 +		return User{}, UserNotFoundError
   1.182 +	}
   1.183 +	return user, nil
   1.184 +}
   1.185 +
   1.186 +func (m Memstore) CreateUser(u User) error {
   1.187 +	m.users[u.ID.String()] = u
   1.188 +	return nil
   1.189 +}
   1.190 +
   1.191 +func (m Memstore) AddLoginToUser(login Login, user uuid.ID) error {
   1.192 +	if _, ok := m.logins[login.Type+":"+login.Value]; ok {
   1.193 +		return LoginAlreadyExistsError
   1.194 +	}
   1.195 +	m.logins[login.Type+":"+login.Value] = login
   1.196 +	return nil
   1.197 +}
   1.198 +
   1.199 +func (m Memstore) RemoveLoginFromUser(loginType, value string, user uuid.ID) error {
   1.200 +	if _, ok := m.logins[loginType+":"+value]; !ok {
   1.201 +		return LoginNotFoundError
   1.202 +	}
   1.203 +	delete(m.logins, loginType+":"+value)
   1.204 +	return nil
   1.205 +}
   1.206 +
   1.207 +func (m Memstore) GetLoginsByUser(user uuid.ID) ([]Login, error) {
   1.208 +	logins := []Login{}
   1.209 +	for _, login := range m.logins {
   1.210 +		if login.UserID.Equal(user) {
   1.211 +			logins = append(logins, login)
   1.212 +		}
   1.213 +	}
   1.214 +	return logins, nil
   1.215 +}
   1.216 +
   1.217 +func (m Memstore) UpdateUser(u User) error {
   1.218 +	if _, ok := m.users[u.ID.String()]; !ok {
   1.219 +		return UserNotFoundError
   1.220 +	}
   1.221 +	m.users[u.ID.String()] = u
   1.222 +	return nil
   1.223 +}
   1.224 +
   1.225 +func (m Memstore) DeleteUser(u User) error {
   1.226 +	if _, ok := m.users[u.ID.String()]; !ok {
   1.227 +		return UserNotFoundError
   1.228 +	}
   1.229 +	delete(m.users, u.ID.String())
   1.230 +	return nil
   1.231 +}