configdb

package
v1.0.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 16, 2025 License: MIT Imports: 26 Imported by: 0

Documentation

Index

Constants

View Source
const (
	LoginModeCookie               = "Cookie"
	LoginModeBearerToken          = "BearerToken"
	LoginModeCookieAndBearerToken = "CookieAndBearerToken"
)
View Source
const (
	SpecialAuthMethodBASIC         = 1 << iota // BASIC (username/password)
	SpecialAuthMethodIdentityToken             // Identity Token (validated by accounts.cyclopcam.org)
)
View Source
const AccountsUrl = "https://accounts.cyclopcam.org"
View Source
const KeyAccountsNonce = "accountsNonce" // Monotonically increasing nonce used to authenticate ourselves to accounts.cyclopcam.org
View Source
const KeyAccountsToken = "accountsToken" // Token used to authenticate to accounts.cyclopcam.org
View Source
const KeyMain = "main" // Private X25519 key

Keys stored in our 'key' table

View Source
const SessionCookie = "session"

SYNC-CYCLOPS-SESSION-COOKIE

Variables

View Source
var ErrDetectionZoneDecode = errors.New("DetectionZone decode error")

Functions

func IsValidPermission

func IsValidPermission(p string) bool

func MeasureDiskSpaceAvailable added in v1.0.4

func MeasureDiskSpaceAvailable(path string) (int64, error)

Measure the space available at the given path, or the first parent directory that exists. Returns the amount of space available in bytes.

func Migrations

func Migrations(log logs.Log) []migration.Migrator

func NormalizeUsername

func NormalizeUsername(username string) string

func RestartNeeded

func RestartNeeded(c1, c2 *ConfigJSON) bool

func ValidateConfig

func ValidateConfig(c *ConfigJSON) error

Returns an error if there is anything invalid about the config, or nil if everything is OK

func ValidateRecordingConfig

func ValidateRecordingConfig(isDefaults bool, c *RecordingJSON) error

If isDefaults is true, then this is the default recording config for the whole system. If isDefaults is false, then this is the recording config for a specific camera.

Types

type AuthResult added in v1.0.4

type AuthResult struct {
	UserID   int64  // If zero, then no valid user credentials
	DeviceID string // Can be empty if no device ID was provided when the session was created. Comes from the session table.
}

Result of authorization

type BaseModel

type BaseModel struct {
	ID int64 `gorm:"primaryKey" json:"id"`
}

BaseModel is our base class for a GORM model. The default GORM Model uses int, but we prefer int64

type Camera

type Camera struct {
	BaseModel
	Model            string      `json:"model"`                                // eg HikVision (actually CameraModels enum, so should be called "Brand" instead of "Model")
	Name             string      `json:"name"`                                 // Friendly name
	Host             string      `json:"host"`                                 // Hostname such as 192.168.1.33
	Port             int         `json:"port" gorm:"default:null"`             // if 0, then default is 554
	Username         string      `json:"username"`                             // RTSP username
	Password         string      `json:"password"`                             // RTSP password
	HighResURLSuffix string      `json:"highResURLSuffix" gorm:"default:null"` // eg Streaming/Channels/101 for HikVision. Can leave blank if Model is a known type.
	LowResURLSuffix  string      `json:"lowResURLSuffix" gorm:"default:null"`  // eg Streaming/Channels/102 for HikVision. Can leave blank if Model is a known type.
	CreatedAt        dbh.IntTime `json:"createdAt" gorm:"autoCreateTime:milli"`
	UpdatedAt        dbh.IntTime `json:"updatedAt" gorm:"autoUpdateTime:milli"`
	DetectionZone    string      `json:"detectionZone" gorm:"default:null"` // See DetectionZone.EncodeBase64()
	EnableAlarm      bool        `json:"enableAlarm"`                       // If this camera sees a person when armed, then trigger the alarm

	// The long lived name is used to identify the camera in the storage archive.
	// If necessary, we can make this configurable.
	// At present, it is equal to the camera ID. But in future, we could allow
	// the user to override this. For example, if their system goes down, but their
	// archive is on another disk, and they want to restore all the cameras, and
	// still have the history intact, and matching up to the new (but same) cameras.
	// Or perhaps you have to replace a camera, but want to retain the logical identify.
	LongLivedName string `json:"longLivedName"`
}

SYNC-RECORD-CAMERA

func (*Camera) DeepEquals

func (c *Camera) DeepEquals(x *Camera) bool

func (*Camera) EqualsConnection

func (c *Camera) EqualsConnection(newCam *Camera) bool

Compare the current camera config against the new camera config, and return true if the connection details refer to the exact same camera host and config.

type ConfigDB

type ConfigDB struct {
	Log        logs.Log
	DB         *gorm.DB
	PrivateKey wgtypes.Key
	PublicKey  wgtypes.Key

	// Addresses allowed from VPN network. Used to detect if user is connecting from LAN or VPN.
	// Injected by VPN system after it has connected. There can be two: an IPv4 and an IPv6.
	VpnAllowedIP net.IPNet
	// contains filtered or unexported fields
}

func NewConfigDB

func NewConfigDB(logger logs.Log, dbFilename, explicitPrivateKey string) (*ConfigDB, error)

func (*ConfigDB) Authorize added in v1.0.4

func (c *ConfigDB) Authorize(r *http.Request, allowSpecial SpecialAuthMethods) AuthResult

Returns the auth result (which contains zeros on failure)

func (*ConfigDB) DBFilename added in v1.0.4

func (c *ConfigDB) DBFilename() string

func (*ConfigDB) GenerateNewID

func (c *ConfigDB) GenerateNewID(tx *gorm.DB, key string) (int64, error)

Generate a new ID from the 'next_id' table in the database

func (*ConfigDB) GetAccountsNonce added in v1.0.4

func (c *ConfigDB) GetAccountsNonce() int64

Get our accounts nonce, and increment it.

func (*ConfigDB) GetAccountsToken added in v1.0.4

func (c *ConfigDB) GetAccountsToken() string

Get our token that we use to authenticate to accounts.cyclopcam.org, or an empty string if none.

func (*ConfigDB) GetCameraFromID added in v1.0.4

func (c *ConfigDB) GetCameraFromID(id int64) (*Camera, error)

func (*ConfigDB) GetConfig

func (c *ConfigDB) GetConfig() ConfigJSON

func (*ConfigDB) GetUser

func (c *ConfigDB) GetUser(r *http.Request, allowSpecial SpecialAuthMethods) (user *User, deviceId string)

Returns the user and deviceId, or (nil, "") if the user is not authenticated.

func (*ConfigDB) GetUserFromID added in v1.0.4

func (c *ConfigDB) GetUserFromID(id int64) (*User, error)

func (*ConfigDB) IsCallerOnLAN

func (c *ConfigDB) IsCallerOnLAN(r *http.Request) bool

Returns true if: 1. We are not using a VPN 2. We are using a VPN, but the caller is not reaching us from it

func (*ConfigDB) Login

func (c *ConfigDB) Login(w http.ResponseWriter, r *http.Request)

func (*ConfigDB) LoginInternal

func (c *ConfigDB) LoginInternal(w http.ResponseWriter, userID int64, expiresAt time.Time, mode string, needRestart bool, deviceId string)

func (*ConfigDB) Logout

func (c *ConfigDB) Logout(w http.ResponseWriter, r *http.Request)

func (*ConfigDB) NumAdminUsers

func (c *ConfigDB) NumAdminUsers() (int, error)

func (*ConfigDB) NumVerifiedIdentities added in v1.0.4

func (c *ConfigDB) NumVerifiedIdentities() (int, error)

Return the number of users on the system that have an external ID (which is given by accounts.cyclopcam.org).

func (*ConfigDB) PurgeExpiredSessions

func (c *ConfigDB) PurgeExpiredSessions()

func (*ConfigDB) SetAccountsToken added in v1.0.4

func (c *ConfigDB) SetAccountsToken(token string) error

Set the token that we use to authenticate to accounts.cyclopcam.org.

func (*ConfigDB) SetConfig

func (c *ConfigDB) SetConfig(cfg ConfigJSON) (bool, error)

Return true if the system needs to be restarted for the config changes to take effect

func (*ConfigDB) VerifyIdentityAndBindToServer

func (c *ConfigDB) VerifyIdentityAndBindToServer(token string) (*VerifiedIdentity, error)

Do the same thing as GetVerifiedIdentityFromToken, but also bind the identity to the server. This unlocks the ability to use the VPN.

type ConfigJSON

type ConfigJSON struct {
	Recording    RecordingJSON `json:"recording"`    // Recording settings. We aim to make some settings overridable per-camera, such as recording mode.
	TempFilePath string        `json:"tempFilePath"` // Temporary file path
	ArcServer    string        `json:"arcServer"`    // Arc server URL
	ArcApiKey    string        `json:"arcApiKey"`    // Arc API key
}

Root system config SYNC-SYSTEM-CONFIG-JSON

type DetectionZone

type DetectionZone struct {
	Width  int // Must be a multiple of 8
	Height int
	Active []byte // Bitmap of Width * Height bits. If bit is 1, then objects in that area are important. If bit is 0, then objects in that area are ignored.
}

Bitmap of camera detection zone (i.e. which areas of the image are important when the system is armed) We make sure that the width is a multiple of 8, so that it's easy to manipulate bits on a row-by-row basis.

func DecodeDetectionZoneBase64

func DecodeDetectionZoneBase64(dzBase64 string) (*DetectionZone, error)

func DecodeDetectionZoneBytes

func DecodeDetectionZoneBytes(raw []byte) (*DetectionZone, error)

func NewDetectionZone

func NewDetectionZone(width, height int) *DetectionZone

func (*DetectionZone) EncodeBase64

func (d *DetectionZone) EncodeBase64() string

func (*DetectionZone) EncodeBytes

func (d *DetectionZone) EncodeBytes() []byte

type Key

type Key struct {
	Name  string `gorm:"primaryKey"`
	Value string // normal (not URL-safe) base64 encoded (same as Wireguard)
}

Generic key/value pairs in our database. For example, KeyMain, etc.

type RecordInstruction

type RecordInstruction struct {
	BaseModel
	StartAt    dbh.IntTime `json:"startAt"`
	FinishAt   dbh.IntTime `json:"finishAt"`
	Resolution string      `json:"resolution" gorm:"default:null"` // One of defs.Resolution (LD or HD)
}

type RecordMode

type RecordMode string

What causes us to record video

const (
	RecordModeAlways      RecordMode = "always"
	RecordModeOnMovement  RecordMode = "movement"
	RecordModeOnDetection RecordMode = "detection"
)

type RecordingJSON

type RecordingJSON struct {
	Mode              RecordMode `json:"mode,omitempty"`
	Path              string     `json:"path,omitempty"`              // Root directory of fsv archive
	MaxStorageSize    string     `json:"maxStorageSize,omitempty"`    // Maximum storage with optional "gb", "mb", "tb" suffix. If no suffix, then bytes.
	RecordBeforeEvent int        `json:"recordBeforeEvent,omitempty"` // Record this many seconds before an event
	RecordAfterEvent  int        `json:"recordAfterEvent,omitempty"`  // Record this many seconds after an event
}

Recording config SYNC-SYSTEM-RECORDING-CONFIG-JSON

func (*RecordingJSON) RecordAfterEventDuration

func (r *RecordingJSON) RecordAfterEventDuration() time.Duration

func (*RecordingJSON) RecordBeforeEventDuration

func (r *RecordingJSON) RecordBeforeEventDuration() time.Duration

type Session

type Session struct {
	BaseModel
	Key       []byte
	UserID    int64
	CreatedAt dbh.IntTime `gorm:"autoCreateTime:milli"`
	ExpiresAt dbh.IntTime `gorm:"default:null"`
	DeviceID  string      `json:"deviceId" gorm:"default:null"`
}

type SpecialAuthMethods

type SpecialAuthMethods int

Special authentication methods, which take computation time on our side, or internet bandwidth. We want to rate limit these methods, or disallow them from the internet.

type SystemConfig

type SystemConfig struct {
	Key   string `gorm:"primaryKey"`
	Value *dbh.JSONField[ConfigJSON]
}

type User

type User struct {
	BaseModel
	Username           string      `json:"username" gorm:"default:null"`           // Can be null if ExternalID is set
	UsernameNormalized string      `json:"usernameNormalized" gorm:"default:null"` // Can be null if ExternalID is set
	Permissions        string      `json:"permissions"`
	Name               string      `json:"name" gorm:"default:null"`
	Password           string      `json:"-" gorm:"default:null"`
	ExternalID         string      `json:"externalId" gorm:"default:null"` // ID on accounts.cyclopcam.org
	Email              string      `json:"email" gorm:"default:null"`      // Email on accounts.cyclopcam.org (can be blank, but either Name, Username or Email should not be blank)
	CreatedAt          dbh.IntTime `json:"createdAt" gorm:"autoCreateTime:milli"`
}

SYNC-RECORD-USER

func (*User) HasPermission

func (u *User) HasPermission(p UserPermissions) bool

type UserPermissions

type UserPermissions string

UserPermissions are single characters that are present in the user's Permissions field

const (
	UserPermissionAdmin  UserPermissions = "a"
	UserPermissionViewer UserPermissions = "v"
)

type Variable

type Variable struct {
	Key   string `gorm:"primaryKey" json:"key"`
	Value string `json:"value"`
}

type VerifiedIdentity

type VerifiedIdentity struct {
	ID          string `json:"id"`
	Email       string `json:"email"`
	DisplayName string `json:"displayName"`
}

VerifiedIdentity is an identity that accounts.cyclopcam.org has verified

func GetVerifiedIdentityFromToken

func GetVerifiedIdentityFromToken(token string) (*VerifiedIdentity, error)

Ask accounts.cyclopcam.org for information about this token. These tokens are generated by a user to prove that they are who they claim to be. These tokens have a short expiration time (eg 3 minutes).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL