Documentation
¶
Index ¶
- Constants
- Variables
- func IsValidPermission(p string) bool
- func MeasureDiskSpaceAvailable(path string) (int64, error)
- func Migrations(log logs.Log) []migration.Migrator
- func NormalizeUsername(username string) string
- func RestartNeeded(c1, c2 *ConfigJSON) bool
- func ValidateConfig(c *ConfigJSON) error
- func ValidateRecordingConfig(isDefaults bool, c *RecordingJSON) error
- type AuthResult
- type BaseModel
- type Camera
- type ConfigDB
- func (c *ConfigDB) Authorize(r *http.Request, allowSpecial SpecialAuthMethods) AuthResult
- func (c *ConfigDB) DBFilename() string
- func (c *ConfigDB) GenerateNewID(tx *gorm.DB, key string) (int64, error)
- func (c *ConfigDB) GetAccountsNonce() int64
- func (c *ConfigDB) GetAccountsToken() string
- func (c *ConfigDB) GetCameraFromID(id int64) (*Camera, error)
- func (c *ConfigDB) GetConfig() ConfigJSON
- func (c *ConfigDB) GetUser(r *http.Request, allowSpecial SpecialAuthMethods) (user *User, deviceId string)
- func (c *ConfigDB) GetUserFromID(id int64) (*User, error)
- func (c *ConfigDB) IsCallerOnLAN(r *http.Request) bool
- func (c *ConfigDB) Login(w http.ResponseWriter, r *http.Request)
- func (c *ConfigDB) LoginInternal(w http.ResponseWriter, userID int64, expiresAt time.Time, mode string, ...)
- func (c *ConfigDB) Logout(w http.ResponseWriter, r *http.Request)
- func (c *ConfigDB) NumAdminUsers() (int, error)
- func (c *ConfigDB) NumVerifiedIdentities() (int, error)
- func (c *ConfigDB) PurgeExpiredSessions()
- func (c *ConfigDB) SetAccountsToken(token string) error
- func (c *ConfigDB) SetConfig(cfg ConfigJSON) (bool, error)
- func (c *ConfigDB) VerifyIdentityAndBindToServer(token string) (*VerifiedIdentity, error)
- type ConfigJSON
- type DetectionZone
- type Key
- type RecordInstruction
- type RecordMode
- type RecordingJSON
- type Session
- type SpecialAuthMethods
- type SystemConfig
- type User
- type UserPermissions
- type Variable
- type VerifiedIdentity
Constants ¶
const ( LoginModeCookie = "Cookie" LoginModeBearerToken = "BearerToken" LoginModeCookieAndBearerToken = "CookieAndBearerToken" )
const ( SpecialAuthMethodBASIC = 1 << iota // BASIC (username/password) SpecialAuthMethodIdentityToken // Identity Token (validated by accounts.cyclopcam.org) )
const AccountsUrl = "https://accounts.cyclopcam.org"
const KeyAccountsNonce = "accountsNonce" // Monotonically increasing nonce used to authenticate ourselves to accounts.cyclopcam.org
const KeyAccountsToken = "accountsToken" // Token used to authenticate to accounts.cyclopcam.org
const KeyMain = "main" // Private X25519 key
Keys stored in our 'key' table
const SessionCookie = "session"
SYNC-CYCLOPS-SESSION-COOKIE
Variables ¶
var ErrDetectionZoneDecode = errors.New("DetectionZone decode error")
Functions ¶
func IsValidPermission ¶
func MeasureDiskSpaceAvailable ¶ added in v1.0.4
Measure the space available at the given path, or the first parent directory that exists. Returns the amount of space available in bytes.
func NormalizeUsername ¶
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 (*Camera) EqualsConnection ¶
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 (*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 (*ConfigDB) GenerateNewID ¶
Generate a new ID from the 'next_id' table in the database
func (*ConfigDB) GetAccountsNonce ¶ added in v1.0.4
Get our accounts nonce, and increment it.
func (*ConfigDB) GetAccountsToken ¶ added in v1.0.4
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 (*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 (*ConfigDB) IsCallerOnLAN ¶
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) LoginInternal ¶
func (*ConfigDB) NumAdminUsers ¶
func (*ConfigDB) NumVerifiedIdentities ¶ added in v1.0.4
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
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 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 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 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).