2023-06-19 17:42:47 -04:00
|
|
|
// SPDX-FileCopyrightText: Copyright The Miniflux Authors. All rights reserved.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0
|
2021-01-29 21:44:40 -05:00
|
|
|
|
2023-08-10 22:46:45 -04:00
|
|
|
package storage // import "miniflux.app/v2/internal/storage"
|
2021-01-29 21:44:40 -05:00
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"database/sql"
|
|
|
|
|
|
|
|
"golang.org/x/crypto/acme/autocert"
|
|
|
|
)
|
|
|
|
|
|
|
|
// Making sure that we're adhering to the autocert.Cache interface.
|
2021-02-13 17:07:39 -05:00
|
|
|
var _ autocert.Cache = (*CertificateCache)(nil)
|
2021-01-29 21:44:40 -05:00
|
|
|
|
2021-02-13 17:07:39 -05:00
|
|
|
// CertificateCache provides a SQL backend to the autocert cache.
|
|
|
|
type CertificateCache struct {
|
2021-01-29 21:44:40 -05:00
|
|
|
storage *Storage
|
|
|
|
}
|
|
|
|
|
2021-02-13 17:07:39 -05:00
|
|
|
// NewCertificateCache creates an cache instance that can be used with autocert.Cache.
|
2021-01-29 21:44:40 -05:00
|
|
|
// It returns any errors that could happen while connecting to SQL.
|
2021-02-13 17:07:39 -05:00
|
|
|
func NewCertificateCache(storage *Storage) *CertificateCache {
|
|
|
|
return &CertificateCache{
|
2021-01-29 21:44:40 -05:00
|
|
|
storage: storage,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get returns a certificate data for the specified key.
|
|
|
|
// If there's no such key, Get returns ErrCacheMiss.
|
2021-02-13 17:07:39 -05:00
|
|
|
func (c *CertificateCache) Get(ctx context.Context, key string) ([]byte, error) {
|
2021-01-29 21:44:40 -05:00
|
|
|
query := `SELECT data::bytea FROM acme_cache WHERE key = $1`
|
|
|
|
var data []byte
|
|
|
|
err := c.storage.db.QueryRowContext(ctx, query, key).Scan(&data)
|
|
|
|
if err == sql.ErrNoRows {
|
|
|
|
return nil, autocert.ErrCacheMiss
|
|
|
|
}
|
|
|
|
|
|
|
|
return data, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Put stores the data in the cache under the specified key.
|
2021-02-13 17:07:39 -05:00
|
|
|
func (c *CertificateCache) Put(ctx context.Context, key string, data []byte) error {
|
2021-01-29 21:44:40 -05:00
|
|
|
query := `INSERT INTO acme_cache (key, data, updated_at) VALUES($1, $2::bytea, now())
|
|
|
|
ON CONFLICT (key) DO UPDATE SET data = $2::bytea, updated_at = now()`
|
|
|
|
_, err := c.storage.db.ExecContext(ctx, query, key, data)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Delete removes a certificate data from the cache under the specified key.
|
|
|
|
// If there's no such key in the cache, Delete returns nil.
|
2021-02-13 17:07:39 -05:00
|
|
|
func (c *CertificateCache) Delete(ctx context.Context, key string) error {
|
2021-01-29 21:44:40 -05:00
|
|
|
query := `DELETE FROM acme_cache WHERE key = $1`
|
|
|
|
_, err := c.storage.db.ExecContext(ctx, query, key)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|