Files
play-with-docker/storage/file.go
2021-09-07 08:02:29 -03:00

452 lines
11 KiB
Go

package storage
import (
"encoding/json"
"fmt"
"os"
"sync"
"github.com/play-with-docker/play-with-docker/pwd/types"
)
type storage struct {
rw sync.Mutex
path string
db *DB
}
type DB struct {
Sessions map[string]*types.Session `json:"sessions"`
Instances map[string]*types.Instance `json:"instances"`
Clients map[string]*types.Client `json:"clients"`
WindowsInstances map[string]*types.WindowsInstance `json:"windows_instances"`
LoginRequests map[string]*types.LoginRequest `json:"login_requests"`
Users map[string]*types.User `json:"user"`
Playgrounds map[string]*types.Playground `json:"playgrounds"`
WindowsInstancesBySessionId map[string][]string `json:"windows_instances_by_session_id"`
InstancesBySessionId map[string][]string `json:"instances_by_session_id"`
ClientsBySessionId map[string][]string `json:"clients_by_session_id"`
UsersByProvider map[string]string `json:"users_by_providers"`
}
func (store *storage) SessionGet(id string) (*types.Session, error) {
store.rw.Lock()
defer store.rw.Unlock()
s, found := store.db.Sessions[id]
if !found {
return nil, NotFoundError
}
return s, nil
}
func (store *storage) SessionGetAll() ([]*types.Session, error) {
store.rw.Lock()
defer store.rw.Unlock()
sessions := make([]*types.Session, len(store.db.Sessions))
i := 0
for _, s := range store.db.Sessions {
sessions[i] = s
i++
}
return sessions, nil
}
func (store *storage) SessionPut(session *types.Session) error {
store.rw.Lock()
defer store.rw.Unlock()
store.db.Sessions[session.Id] = session
return store.save()
}
func (store *storage) SessionDelete(id string) error {
store.rw.Lock()
defer store.rw.Unlock()
_, found := store.db.Sessions[id]
if !found {
return nil
}
for _, i := range store.db.WindowsInstancesBySessionId[id] {
delete(store.db.WindowsInstances, i)
}
store.db.WindowsInstancesBySessionId[id] = []string{}
for _, i := range store.db.InstancesBySessionId[id] {
delete(store.db.Instances, i)
}
store.db.InstancesBySessionId[id] = []string{}
for _, i := range store.db.ClientsBySessionId[id] {
delete(store.db.Clients, i)
}
store.db.ClientsBySessionId[id] = []string{}
delete(store.db.Sessions, id)
return store.save()
}
func (store *storage) SessionCount() (int, error) {
store.rw.Lock()
defer store.rw.Unlock()
return len(store.db.Sessions), nil
}
func (store *storage) InstanceGet(name string) (*types.Instance, error) {
store.rw.Lock()
defer store.rw.Unlock()
i := store.db.Instances[name]
if i == nil {
return nil, NotFoundError
}
return i, nil
}
func (store *storage) InstancePut(instance *types.Instance) error {
store.rw.Lock()
defer store.rw.Unlock()
_, found := store.db.Sessions[string(instance.SessionId)]
if !found {
return NotFoundError
}
store.db.Instances[instance.Name] = instance
found = false
for _, i := range store.db.InstancesBySessionId[string(instance.SessionId)] {
if i == instance.Name {
found = true
break
}
}
if !found {
store.db.InstancesBySessionId[string(instance.SessionId)] = append(store.db.InstancesBySessionId[string(instance.SessionId)], instance.Name)
}
return store.save()
}
func (store *storage) InstanceDelete(name string) error {
store.rw.Lock()
defer store.rw.Unlock()
instance, found := store.db.Instances[name]
if !found {
return nil
}
instances := store.db.InstancesBySessionId[string(instance.SessionId)]
for n, i := range instances {
if i == name {
instances = append(instances[:n], instances[n+1:]...)
break
}
}
store.db.InstancesBySessionId[string(instance.SessionId)] = instances
delete(store.db.Instances, name)
return store.save()
}
func (store *storage) InstanceCount() (int, error) {
store.rw.Lock()
defer store.rw.Unlock()
return len(store.db.Instances), nil
}
func (store *storage) InstanceFindBySessionId(sessionId string) ([]*types.Instance, error) {
store.rw.Lock()
defer store.rw.Unlock()
instanceIds := store.db.InstancesBySessionId[sessionId]
instances := make([]*types.Instance, len(instanceIds))
for i, id := range instanceIds {
instances[i] = store.db.Instances[id]
}
return instances, nil
}
func (store *storage) WindowsInstanceGetAll() ([]*types.WindowsInstance, error) {
store.rw.Lock()
defer store.rw.Unlock()
instances := []*types.WindowsInstance{}
for _, s := range store.db.WindowsInstances {
instances = append(instances, s)
}
return instances, nil
}
func (store *storage) WindowsInstancePut(instance *types.WindowsInstance) error {
store.rw.Lock()
defer store.rw.Unlock()
_, found := store.db.Sessions[string(instance.SessionId)]
if !found {
return NotFoundError
}
store.db.WindowsInstances[instance.Id] = instance
found = false
for _, i := range store.db.WindowsInstancesBySessionId[string(instance.SessionId)] {
if i == instance.Id {
found = true
break
}
}
if !found {
store.db.WindowsInstancesBySessionId[string(instance.SessionId)] = append(store.db.WindowsInstancesBySessionId[string(instance.SessionId)], instance.Id)
}
return store.save()
}
func (store *storage) WindowsInstanceDelete(id string) error {
store.rw.Lock()
defer store.rw.Unlock()
instance, found := store.db.WindowsInstances[id]
if !found {
return nil
}
instances := store.db.WindowsInstancesBySessionId[string(instance.SessionId)]
for n, i := range instances {
if i == id {
instances = append(instances[:n], instances[n+1:]...)
break
}
}
store.db.WindowsInstancesBySessionId[string(instance.SessionId)] = instances
delete(store.db.WindowsInstances, id)
return store.save()
}
func (store *storage) ClientGet(id string) (*types.Client, error) {
store.rw.Lock()
defer store.rw.Unlock()
i := store.db.Clients[id]
if i == nil {
return nil, NotFoundError
}
return i, nil
}
func (store *storage) ClientPut(client *types.Client) error {
store.rw.Lock()
defer store.rw.Unlock()
_, found := store.db.Sessions[string(client.SessionId)]
if !found {
return NotFoundError
}
store.db.Clients[client.Id] = client
found = false
for _, i := range store.db.ClientsBySessionId[string(client.SessionId)] {
if i == client.Id {
found = true
break
}
}
if !found {
store.db.ClientsBySessionId[string(client.SessionId)] = append(store.db.ClientsBySessionId[string(client.SessionId)], client.Id)
}
return store.save()
}
func (store *storage) ClientDelete(id string) error {
store.rw.Lock()
defer store.rw.Unlock()
client, found := store.db.Clients[id]
if !found {
return nil
}
clients := store.db.ClientsBySessionId[string(client.SessionId)]
for n, i := range clients {
if i == client.Id {
clients = append(clients[:n], clients[n+1:]...)
break
}
}
store.db.ClientsBySessionId[string(client.SessionId)] = clients
delete(store.db.Clients, id)
return store.save()
}
func (store *storage) ClientCount() (int, error) {
store.rw.Lock()
defer store.rw.Unlock()
return len(store.db.Clients), nil
}
func (store *storage) ClientFindBySessionId(sessionId string) ([]*types.Client, error) {
store.rw.Lock()
defer store.rw.Unlock()
clientIds := store.db.ClientsBySessionId[sessionId]
clients := make([]*types.Client, len(clientIds))
for i, id := range clientIds {
clients[i] = store.db.Clients[id]
}
return clients, nil
}
func (store *storage) LoginRequestPut(loginRequest *types.LoginRequest) error {
store.rw.Lock()
defer store.rw.Unlock()
store.db.LoginRequests[loginRequest.Id] = loginRequest
return nil
}
func (store *storage) LoginRequestGet(id string) (*types.LoginRequest, error) {
store.rw.Lock()
defer store.rw.Unlock()
if lr, found := store.db.LoginRequests[id]; !found {
return nil, NotFoundError
} else {
return lr, nil
}
}
func (store *storage) LoginRequestDelete(id string) error {
store.rw.Lock()
defer store.rw.Unlock()
delete(store.db.LoginRequests, id)
return nil
}
func (store *storage) UserFindByProvider(providerName, providerUserId string) (*types.User, error) {
store.rw.Lock()
defer store.rw.Unlock()
if userId, found := store.db.UsersByProvider[fmt.Sprintf("%s_%s", providerName, providerUserId)]; !found {
return nil, NotFoundError
} else {
if user, found := store.db.Users[userId]; !found {
return nil, NotFoundError
} else {
return user, nil
}
}
}
func (store *storage) UserPut(user *types.User) error {
store.rw.Lock()
defer store.rw.Unlock()
store.db.UsersByProvider[fmt.Sprintf("%s_%s", user.Provider, user.ProviderUserId)] = user.Id
store.db.Users[user.Id] = user
return store.save()
}
func (store *storage) UserGet(id string) (*types.User, error) {
store.rw.Lock()
defer store.rw.Unlock()
if user, found := store.db.Users[id]; !found {
return nil, NotFoundError
} else {
return user, nil
}
}
func (store *storage) PlaygroundPut(playground *types.Playground) error {
store.rw.Lock()
defer store.rw.Unlock()
store.db.Playgrounds[playground.Id] = playground
return store.save()
}
func (store *storage) PlaygroundGet(id string) (*types.Playground, error) {
store.rw.Lock()
defer store.rw.Unlock()
playground, found := store.db.Playgrounds[id]
if !found {
return nil, NotFoundError
}
return playground, nil
}
func (store *storage) load() error {
file, err := os.Open(store.path)
if err == nil {
decoder := json.NewDecoder(file)
err = decoder.Decode(&store.db)
if err != nil {
return err
}
} else {
store.db = &DB{
Sessions: map[string]*types.Session{},
Instances: map[string]*types.Instance{},
Clients: map[string]*types.Client{},
WindowsInstances: map[string]*types.WindowsInstance{},
LoginRequests: map[string]*types.LoginRequest{},
Users: map[string]*types.User{},
Playgrounds: map[string]*types.Playground{},
WindowsInstancesBySessionId: map[string][]string{},
InstancesBySessionId: map[string][]string{},
ClientsBySessionId: map[string][]string{},
UsersByProvider: map[string]string{},
}
}
file.Close()
return nil
}
func (store *storage) PlaygroundGetAll() ([]*types.Playground, error) {
store.rw.Lock()
defer store.rw.Unlock()
playgrounds := make([]*types.Playground, len(store.db.Playgrounds))
i := 0
for _, p := range store.db.Playgrounds {
playgrounds[i] = p
i++
}
return playgrounds, nil
}
func (store *storage) save() error {
file, err := os.Create(store.path)
if err != nil {
return err
}
defer file.Close()
encoder := json.NewEncoder(file)
err = encoder.Encode(&store.db)
return err
}
func NewFileStorage(path string) (StorageApi, error) {
s := &storage{path: path}
err := s.load()
if err != nil {
return nil, err
}
return s, nil
}