mirror of
https://github.com/henrybear327/Proton-API-Bridge.git
synced 2025-12-26 08:57:42 -05:00
134 lines
2.9 KiB
Go
134 lines
2.9 KiB
Go
package proton_api_bridge
|
|
|
|
import (
|
|
"context"
|
|
"log"
|
|
"sync"
|
|
|
|
"github.com/ProtonMail/gopenpgp/v2/crypto"
|
|
"github.com/henrybear327/go-proton-api"
|
|
)
|
|
|
|
type cacheEntry struct {
|
|
link *proton.Link
|
|
kr *crypto.KeyRing
|
|
}
|
|
type cache struct {
|
|
data map[string]*cacheEntry
|
|
disableCaching bool
|
|
|
|
sync.RWMutex
|
|
}
|
|
|
|
func newLinkCache(disableCaching bool) *cache {
|
|
return &cache{
|
|
data: make(map[string]*cacheEntry),
|
|
disableCaching: disableCaching,
|
|
}
|
|
}
|
|
|
|
func (cache *cache) _get(linkID string) *cacheEntry {
|
|
if cache.disableCaching {
|
|
return nil
|
|
}
|
|
|
|
cache.RLock()
|
|
defer cache.RUnlock()
|
|
|
|
if val, ok := cache.data[linkID]; ok {
|
|
return val
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (cache *cache) _insert(link *proton.Link, kr *crypto.KeyRing) {
|
|
if cache.disableCaching {
|
|
return
|
|
}
|
|
|
|
cache.Lock()
|
|
defer cache.Unlock()
|
|
|
|
cache.data[link.LinkID] = &cacheEntry{
|
|
link: link,
|
|
kr: kr,
|
|
}
|
|
}
|
|
|
|
func (protonDrive *ProtonDrive) getLink(ctx context.Context, linkID string) (*proton.Link, error) {
|
|
// attempt to get from cache first
|
|
if data := protonDrive.cache._get(linkID); data != nil && data.link != nil {
|
|
// log.Println("From cache (Link)")
|
|
return data.link, nil
|
|
}
|
|
|
|
// log.Println("Not from cache (Link)")
|
|
// no cached data, fetch
|
|
link, err := protonDrive.c.GetLink(ctx, protonDrive.MainShare.ShareID, linkID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// populate cache
|
|
protonDrive.cache._insert(&link, nil)
|
|
|
|
return &link, nil
|
|
}
|
|
|
|
func (protonDrive *ProtonDrive) _fetchNodeKR(ctx context.Context, link *proton.Link) (*crypto.KeyRing, error) {
|
|
if link.ParentLinkID == "" {
|
|
if data := protonDrive.cache._get(link.LinkID); data != nil && data.kr != nil {
|
|
return data.kr, nil
|
|
}
|
|
nodeKR, err := link.GetKeyRing(protonDrive.MainShareKR, protonDrive.AddrKR)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
protonDrive.cache._insert(link, nodeKR)
|
|
|
|
return nodeKR, nil
|
|
}
|
|
|
|
parentLink, err := protonDrive.getLink(ctx, link.ParentLinkID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// parentNodeKR is used to decrypt the current node's KR, as each node has its keyring, which can be decrypted by its parent
|
|
parentNodeKR, err := protonDrive.getNodeKR(ctx, parentLink)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if data := protonDrive.cache._get(link.LinkID); data != nil && data.kr != nil {
|
|
return data.kr, nil
|
|
}
|
|
nodeKR, err := link.GetKeyRing(parentNodeKR, protonDrive.AddrKR)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
protonDrive.cache._insert(link, nodeKR)
|
|
|
|
return nodeKR, nil
|
|
}
|
|
|
|
func (protonDrive *ProtonDrive) getNodeKR(ctx context.Context, link *proton.Link) (*crypto.KeyRing, error) {
|
|
// attempt to get from cache first
|
|
if data := protonDrive.cache._get(link.LinkID); data != nil && data.kr != nil {
|
|
log.Println("From cache (kr)")
|
|
return data.kr, nil
|
|
}
|
|
|
|
log.Println("Not from cache (kr)")
|
|
// no cached data, fetch
|
|
kr, err := protonDrive._fetchNodeKR(ctx, link)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// populate cache
|
|
protonDrive.cache._insert(link, kr)
|
|
|
|
return kr, nil
|
|
}
|