Define API and implement an in-memory store.

This commit is contained in:
Mariano Uvalle 2023-11-06 01:48:10 +00:00
parent b8a4ad02d7
commit b01c6fb05e
4 changed files with 150 additions and 0 deletions

View file

@ -0,0 +1,8 @@
package config
type Config struct {
PublicKeyPath string
PrivateKeyPath string
}
var Default = Config{}

19
internal/db/db.go Normal file
View file

@ -0,0 +1,19 @@
package db
import "github.com/AYM1607/ccclip/pkg/api"
type DB interface {
// Users.
PutUser(id string, passwordHash string) error
GetUser(id string) (*api.User, error)
// Devices.
PutDevice(pubKey, userId string) (string, error)
GetDevice(id string) (*api.Device, error)
GetUserDevices(userId string) ([]*api.Device, error)
GetDeviceUser(deviceId string) (*api.User, error)
// Clipboard.
PutClipboard(userId string, clipboard *api.Clipboard) error
GetClipboard(userId string) (*api.Clipboard, error)
}

106
internal/db/local.go Normal file
View file

@ -0,0 +1,106 @@
package db
import (
"errors"
"fmt"
ulid "github.com/oklog/ulid/v2"
"github.com/AYM1607/ccclip/pkg/api"
)
type localDB struct {
users map[string]*api.User
devices map[string]*api.Device
usersDevices map[string]map[string]struct{}
clipboards map[string]*api.Clipboard
}
var _ DB = (*localDB)(nil)
func NewLocalDB() DB {
return &localDB{
users: make(map[string]*api.User),
devices: make(map[string]*api.Device),
usersDevices: make(map[string]map[string]struct{}),
clipboards: make(map[string]*api.Clipboard),
}
}
func (d *localDB) PutUser(id, passwordHash string) error {
if _, ok := d.users[id]; ok {
return errors.New("user exists")
}
d.users[id] = &api.User{ID: id, PasswordHash: passwordHash}
return nil
}
func (d *localDB) GetUser(id string) (*api.User, error) {
u, ok := d.users[id]
if !ok {
return nil, errors.New("user does not exist")
}
return u, nil
}
func (d *localDB) PutDevice(pubKey, userId string) (string, error) {
id := ulid.Make().String()
if _, ok := d.users[userId]; !ok {
return "", errors.New("user does not exist")
}
d.devices[id] = &api.Device{
ID: id,
PublicKey: pubKey,
}
if d.usersDevices[userId] == nil {
d.usersDevices[userId] = map[string]struct{}{}
}
d.usersDevices[userId][id] = struct{}{}
return id, nil
}
func (d *localDB) GetDevice(id string) (*api.Device, error) {
device, ok := d.devices[id]
if !ok {
return nil, errors.New("requested device does no exist")
}
return device, nil
}
func (d *localDB) GetUserDevices(userId string) ([]*api.Device, error) {
ids := d.usersDevices[userId]
res := []*api.Device{}
for id := range ids {
d, ok := d.devices[id]
if !ok {
return nil, fmt.Errorf("device %s is associated to user but it does not exist", id)
}
res = append(res, d)
}
return res, nil
}
func (d *localDB) GetDeviceUser(deviceId string) (*api.User, error) {
// Foreign keys can make this better.
for uId, u := range d.users {
if _, ok := d.usersDevices[uId]; ok {
return u, nil
}
}
return nil, errors.New("device is not associated to any user")
}
func (d *localDB) PutClipboard(userId string, clipboard *api.Clipboard) error {
d.clipboards[userId] = clipboard
return nil
}
func (d *localDB) GetClipboard(userId string) (*api.Clipboard, error) {
c, ok := d.clipboards[userId]
if !ok {
return nil, errors.New("user does not have a current clipboard")
}
return c, nil
}

17
pkg/api/api.go Normal file
View file

@ -0,0 +1,17 @@
package api
type User struct {
ID string
PasswordHash string
}
type Device struct {
ID string
PublicKey []byte
}
type Clipboard struct {
SenderDeviceID string
// Payloads maps DeviceIDs to base64 encoded data.
Payloads map[string]string
}