db

package
v2.1.4 Latest Latest
Warning

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

Go to latest
Published: Oct 15, 2023 License: MIT Imports: 17 Imported by: 0

Documentation

Overview

Package db provides functions to interact with a sql database.

This package does not handle db connection. For that, refer to the 3rd part sqldb package. This package handles higher-level stuff specific to this app, not low level db configuration or connection.

Other files in this package declare the schema for each table. Each table should be in its own file named as close as possible to the table name. While table names are spaced with underscores these files are named with camelcase. Each file defines the struct that is used to interface with that table's data. Struct names should be similar to table names except in camelcase and in singular form (tables are plural). The fields in each struct should match exactly to column names. Fields are grouped into three main sections: table columns, calculated fields (stuff calculated from other columns or other data), and JOINed fields (columns aliased from other tables in JOIN queries).

Each file should declare a "create" query that deployes the schema for this table. There can also be additional queries to be run after the table is created that creates indexes and/or inserts initial data into the database. These queries should all be capable of rerunning safely (i.e. not creating duplicate tables, duplicate indexes, or inserting default data multiple times).

Each file may have an "update" query that adds new columns to the table. Any new columns should be added to the "create" and "update" funcs to handle times when user is installing app fresh or upgrading an existing install with existing data in the database.

Index

Constants

View Source
const (
	CustomFieldTypeInteger     = customFieldType("Integer")
	CustomFieldTypeDecimal     = customFieldType("Decimal")
	CustomFieldTypeText        = customFieldType("Text")
	CustomFieldTypeBoolean     = customFieldType("Boolean")
	CustomFieldTypeMultiChoice = customFieldType("Multi-Choice")
	CustomFieldTypeDate        = customFieldType("Date")
)
View Source
const Enable2FAForAll int64 = -132674

Enable2FAForAll is a random value that allows the use of the Enable2FA func to turn 2FA on/off for all users. This random value is used so that someone can't just code in a value easily when using this func and mistakenly turn 2FA on/off for all users.

View Source
const (
	InitialUserUsername = "admin@example.com"
)

default stuff to insert upon creating table

View Source
const TableAPIKeys = "api_keys"

TableAPIKeys is the name of the table

View Source
const TableActivityLog = "activity_log"

TableActivityLog is the name of the table

View Source
const TableAppSettings = "app_settings"

TableAppSettings is the name of the table

View Source
const TableApps = "apps"

TableApps is the name of the table.

View Source
const TableAuthorizedBrowsers = "user_authorized_browsers"

TableAuthorizedBrowsers is the name of the table

View Source
const TableCustomFieldDefined = "custom_fields_defined"

TableCustomFieldDefined is the name of the table.

View Source
const TableCustomFieldResults = "custom_field_results"

TableCustomFieldResults is the name of the table.

View Source
const TableDownloadHistory = "download_history"

TableDownloadHistory is the name of the table.

View Source
const TableKeyPairs = "key_pairs"

TableKeyPairs is the name of the table.

View Source
const TableKeyValue = "key_value"

TableKeyValue is the name of the table

View Source
const TableLicenseNotes = "license_notes"

TableLicenseNotes is the name of the table.

View Source
const TableLicenses = "licenses"

TableLicenses is the name of the table.

View Source
const TableRenewalRelationships = "renewal_relationships"

TableRenewalRelationships is the name of the table.

View Source
const TableUserLogins = "user_logins"

TableUserLogins is the name of the table

View Source
const TableUsers = "users"

TableUsers is the name of the table

Variables

View Source
var (
	//ErrAppSettingDisabled is the generic error used when an app setting is turned of
	//A more detailed or specific err can be defined for certain use cases.
	ErrAppSettingDisabled = errors.New("app setting is turned off")

	//ErrNoUser2FAEnabled is returned when a user tries to force turning on 2fa but no admin user has 2fa set up yet
	//You can't force the requirement of 2fa if no user has 2fa set up yet otherwise you will be locked out of the app.
	ErrNoUser2FAEnabled = errors.New("no user has 2 factor auth enabled")
)

errors specific to app settings

View Source
var (
	//ErrInputInvalid is returned when doing validation before INSERT or UPDATE
	//queries and some input value is not valid.
	ErrInputInvalid = errors.New("db: input invalid")

	//ErrCouldNotFindMatchingField is returned when validating the list of defined
	//versus result fields and a match could not be found. This means that the
	//user somehow provided an incorrect result.
	ErrCouldNotFindMatchingField = errors.New("could not find matching result for defined field")
)

errors

View Source
var DeployFuncs = []sqldb.DeployFunc{
	insertInitialUser,
	insertInitialAppSettings,

	setLicenseIDStartingValue,
}
View Source
var DeployQueries = []string{
	createTableKeyValue,

	createTableUsers,
	createTableAuthorizedBrowsers,
	createTableUserLogins,

	createTableAPIKeys,
	createTableActivityLog,
	createTableAppSettings,

	createTableApps,
	createTableKeyPairs,
	createTableCustomFieldsDefined,
	createTableCustomFieldResults,
	createTableLicenses,
	createTableDownloadHistory,
	createTableLicenseNotes,
	createTableRenewalRelationships,
}

DeployQueries is the list of queries to deploy the database schema. This only includes CREATE TABLE queries. - Inserting of initial data is handled via DeployFuncs (see below). - Queries to create indexes are located in createIndexes (see db--indexes.go).

View Source
var UpdateQueries = []string{

	updateKeyValueDatetimeModified,
	updateActivityLogReferrer,
}

Functions

func ClearActivityLog

func ClearActivityLog(ctx context.Context, date string) (rowsDeleted int64, err error)

ClearActivityLog deletes rows from the activity log table prior to a given date

func ClearAuthorizedBrowsers added in v2.1.0

func ClearAuthorizedBrowsers(ctx context.Context, date string) (rowsDeleted int64, err error)

ClearAuthorizedBrowsers deletes rows from the authorized browsers table prior to a given date. This is used as part of the admin tool to delete user login history.

func ClearUserLogins added in v2.1.0

func ClearUserLogins(ctx context.Context, date string) (rowsDeleted int64, err error)

ClearUserLogins deletes rows from the user logins table prior to a given date.

func DisableAllAuthorizedBrowsers

func DisableAllAuthorizedBrowsers(ctx context.Context, userID int64) (err error)

DisableAllAuthorizedBrowsers disabled all saved authorized browsers for a user. Authorized browsers are saved when 2FA is enabled. This func is used to "unremember" all authorized browsers so user has to provide 2FA token again. This func is called in db-users.go ForceUserLogout().

func DisableLicense

func DisableLicense(ctx context.Context, licenseID int64, tx *sqlx.Tx) (err error)

DisableLicense marks a license as inactive. We use a transaction for this since we typically will add a note about why the license as disabled as well.

func DisableLoginsForUser

func DisableLoginsForUser(ctx context.Context, userID int64) (err error)

DisableLoginsForUser disables all sessions for a user that are active and not currently expired. This is used upon logging in when single sessions is enabled to mark all other currently active and non-expired sessions as inactive to enforce the single session policy. UserID is required to prevent us from mistakenly disabled all sessions for all users.

func Enable2FA

func Enable2FA(ctx context.Context, userID int64, turnOn bool) (err error)

Enable2FA sets 2fa on or off for a user.

This also works for all users, but only if userID is set to Enable2FAForAll. Be careful! This was added to support turning 2fa on/off in development and testing.

func GetDateInConfigTimezone

func GetDateInConfigTimezone(input string) (output string)

GetDateInConfigTimezone is similar to GetDatetimeInConfigTimezone but for dates only.

func GetDatetimeInConfigTimezone

func GetDatetimeInConfigTimezone(input string) (output string)

GetDatetimeInConfigTimezone is used to convert a datetime from the database as UTC into the timezone specified in the config file. This cleans up and removes duplicate code to do this elsewhere. This is mostly used for DatetimeCreated and DatetimeModified fields. Although we use time.Parse that can return an error, we simply log the error and return the input value instead. Typically when this func is used, the original datetime value is stored in "fieldNameUTC" such as DatetimeCreatedUTC for clarification and/or diagnostics.

func GetPublicKeyByID

func GetPublicKeyByID(ctx context.Context, id int64) (publicKey string, err error)

GetPublicKeyByID returns the public key for a key pair. This is used to display the public key for copying.

func RevokeAPIKey

func RevokeAPIKey(ctx context.Context, id int64) error

RevokeAPIKey marks an API key as inactive. It cannot be reactivated.

func Save2FASecret

func Save2FASecret(ctx context.Context, userID int64, secret string) (err error)

Save2FASecret saves the secret shared secret for 2fa to the database for a user. This does not enable 2fa since the user still needs to verify a 2fa token the first time a secret/qr code is shown to them.

func Set2FABadAttempts

func Set2FABadAttempts(ctx context.Context, userID int64, badValue uint8) error

Set2FABadAttempts sets the value for 2fa bad login attempts for a user. This is used to either (a) reset the value upon a good login or (b) increment the value (up to the max) for bad logins. The new badValue should have already been calculated and validated.

func SetNewPassword

func SetNewPassword(ctx context.Context, userID int64, passwordHash string) (err error)

SetNewPassword sets a new password for a given user ID. The password should already be hashed.

func SetPasswordBadAttempts

func SetPasswordBadAttempts(ctx context.Context, userID int64, badValue uint8) error

SetPasswordBadAttempts sets the value for the bad password attempts for a user. This is used to either (a) reset the value upon a good password or (b) increment the value (up to the max) for bad passwords. The new badValue should have already been calculated and validated.

Types

type APIKey

type APIKey struct {
	ID               int64
	DatetimeCreated  string
	DatetimeModified string
	Active           bool
	CreatedByUserID  int64
	Description      string //so user can identify what the api key is used for
	K                string //the actual api key

	//JOINed fields
	CreatedByUsername string

	//Calculated fields
	DatetimeCreatedTZ string //DatetimeCreated converted to timezone per config file.
	Timezone          string //extra data for above fields for displaying in GUI.
}

APIKey is used to interact with the table

func GetAPIKeyByDescription

func GetAPIKeyByDescription(ctx context.Context, desc string) (a APIKey, err error)

GetAPIKeyByDescription looks up an API key by its Description. This is used when adding a new API key to verify a key with the same description doesn't already exist and is active.

func GetAPIKeyByKey

func GetAPIKeyByKey(ctx context.Context, key string, columns sqldb.Columns) (a APIKey, err error)

GetAPIKeyByKey looks up an API key's data by its Key.

func GetAPIKeys

func GetAPIKeys(ctx context.Context, activeOnly bool, columns sqldb.Columns) (aa []APIKey, err error)

GetAPIKeys looks up a list of API keys.

func (*APIKey) Insert

func (a *APIKey) Insert(ctx context.Context) (err error)

Insert saves a new API key to the database.

type ActivityLog

type ActivityLog struct {
	ID               int64
	DatetimeCreated  string //no default in CREATE TABLE so that we can set value using golang since we will also set TimestampCreated using golang.
	TimestampCreated int64  //nanoseconds, for sorting, no default in CREATE TABLE since handling nanoseconds with DEFAULT and SQLite is a pain/impossible.
	Method           string //GET, POST, etc.
	URL              string //the endpoint accessed
	RemoteIP         string
	UserAgent        string
	TimeDuration     int64  //milliseconds it took for server to complete the request
	PostFormValues   string //json encoded form values passed in request
	Referrer         string //page the user is on that caused this request to be made.

	//either CreatedByUserID or CreatedByAPIKeyID is provided, never both
	CreatedByUserID   null.Int
	CreatedByAPIKeyID null.Int

	//JOINed fields
	Username          string
	APIKeyDescription string
	APIKeyK           string //the actual api key

	//Calculated fields
	DatetimeCreatedTZ string //DatetimeCreated converted to timezone per config file.
	Timezone          string //extra data for above fields for displaying in GUI.
}

ActivityLog is used to interact with the table

func GetActivityLog

func GetActivityLog(ctx context.Context, userID, apiKeyID int64, endpoint, searchFor, startDate, endDate string, numRows uint16) (aa []ActivityLog, err error)

GetActivityLog looks up the latest activites in the activity log. The results can be filter by a specific user, a specific API key, an endpoint, and/or a string in the form values sent in a request (GET or POST) via a wildcard LIKE. The results can be limited by a date range or a limit, with the latest 200 rows being returned by default if a date range nor a limit is provided.

func (*ActivityLog) Insert

func (a *ActivityLog) Insert(ctx context.Context) (err error)

Insert saves a log entry to the database for an action performed by a user or via an api key. you should have already performed validation.

type App

type App struct {
	ID               int64
	DatetimeCreated  string
	DatetimeModified string
	CreatedByUserID  int64
	Active           bool

	Name             string
	DaysToExpiration int                    //the number of days to add on to "today" to calculate a default expiration date of a license
	FileFormat       licensefile.FileFormat //yaml, json, etc. the format of the data stored in the text file.
	ShowLicenseID    bool                   //if the ID field of a created license file will be populated/non-zero.
	ShowAppName      bool                   //if the Application field of a created license file will be populated/non-blank.

	//DownloadFilename is the name of the license file when downloaded. This defaults to
	//"appname-license.txt" but can be customized using {{}} placeholders.
	//Placeholders:
	// - {ext} is replaced with the file format's extension prepended by a period (ex: .json);
	// - {appName} is replaced with the app's name, in lowercase and with spaces replaced by underscores.
	// - {licenseID} is replaced with the license's ID.
	DownloadFilename string
}

App is used to interact with the table.

func GetAppByID

func GetAppByID(ctx context.Context, id int64) (a App, err error)

GetAppByID looks up an app by its ID.

func GetAppByName

func GetAppByName(ctx context.Context, name string) (a App, err error)

GetAppByName looks up an app by its name.

func GetApps

func GetApps(ctx context.Context, activeOnly bool) (aa []App, err error)

GetApps returns the list of apps optionally filtered by active apps only.

func (*App) Insert

func (a *App) Insert(ctx context.Context) (err error)

Insert saves an app. You should have already called Validate().

func (*App) Update

func (a *App) Update(ctx context.Context) (err error)

Update saves changes to an app. You should have already called Validate().

func (*App) Validate

func (a *App) Validate(ctx context.Context) (errMsg string, err error)

Validate is used to validate a struct's data before adding or saving changes. This also handles sanitizing.

type AppSettings

type AppSettings struct {
	ID               int64
	DatetimeModified string

	EnableActivityLogging bool //whether or not the app tracks user activity (page views, endpoints, etc.)
	AllowAPIAccess        bool //whether or not external access to this app is allowed
	Allow2FactorAuth      bool //if 2 factor authentication can be used
	Force2FactorAuth      bool //if all users are required to have 2 factor auth enabled prior to logging in (check if at least one user has 2fa enabled first to prevent lock out!)
	ForceSingleSession    bool //user can only be logged into the app in one browser at a time. used as a security tool.
}

AppSettings is used to interact with the table

func GetAppSettings

func GetAppSettings(ctx context.Context) (a AppSettings, err error)

GetAppSettings looks up the current app settings used for this app.

func (*AppSettings) Update

func (a *AppSettings) Update(ctx context.Context) (err error)

Update updates the saved app settings to the given values

type AuthorizedBrowser

type AuthorizedBrowser struct {
	ID              int64
	DatetimeCreated string
	UserID          int64
	RemoteIP        string
	UserAgent       string
	Cookie          string //a token saved to user's cookie so that if user resets browser we reprompt for 2fa token
	Timestamp       int64  //so we can force asking for a 2fa code after so much time regardless if browser is trusted
	Active          bool
}

AuthorizedBrowser is used to interact with the table

func LookUpAuthorizedBrowser

func LookUpAuthorizedBrowser(ctx context.Context, userID int64, ip, cookie string, activeOnly bool) (a AuthorizedBrowser, err error)

LookUpAuthorizedBrowser looks up if a browser identified by ip, and cookie has already been authorized via 2fa.

func (*AuthorizedBrowser) Insert

func (a *AuthorizedBrowser) Insert(ctx context.Context) (err error)

Insert saves a row to the database. you should have already performed validation.

type CustomFieldDefined

type CustomFieldDefined struct {
	ID               int64
	DatetimeCreated  string
	DatetimeModified string
	CreatedByUserID  int64
	Active           bool

	AppID        int64           //what app this field is for.
	Type         customFieldType //field type
	Name         string          //
	Instructions string          //what field is for and expected value

	//defaults to populate GUI when user is creating a new key
	IntegerDefaultValue     null.Int
	DecimalDefaultValue     null.Float
	TextDefaultValue        null.String
	BoolDefaultValue        null.Bool
	MultiChoiceDefaultValue null.String
	DateDefaultIncrement    null.Int //number of days incremented from "today", date license is being created

	//validation for value chosen/given in gui
	NumberMinValue     null.Float  //for integers and decimals
	NumberMaxValue     null.Float  //""
	MultiChoiceOptions null.String //semicolon separated list of options

	//When saving a license, we retrieve the defined fields for an app
	//and set the value for each field using the same list of objects
	//returned just for ease of use and not changing types. Therefore,
	//we need fields in this struct to store the chosen/provided
	//values for each field. Only one of these fields is populated per
	//the Type field. These are only populated when saving/creating a
	//new license.
	IntegerValue     int64   `json:",omitempty"`
	Decimalvalue     float64 `json:",omitempty"`
	TextValue        string  `json:",omitempty"`
	BoolValue        bool    `json:",omitempty"`
	MultiChoiceValue string  `json:",omitempty"`
	DateValue        string  `json:",omitempty"`
}

CustomFieldDefined is used to interact with the table.

func GetCustomFieldsDefined

func GetCustomFieldsDefined(ctx context.Context, appID int64, activeOnly bool) (cc []CustomFieldDefined, err error)

GetCustomFieldsDefined returns the list of fields for an app optionally filtered by active fields only.

func GetFieldByName

func GetFieldByName(ctx context.Context, appID int64, name string) (cfd CustomFieldDefined, err error)

GetFieldByName looks up a field by its name for a given app. We filter by app since multiple apps can have the same fields names.

func (*CustomFieldDefined) Delete

func (cfd *CustomFieldDefined) Delete(ctx context.Context) (err error)

Delete marks a defined custom field as deleted.

func (*CustomFieldDefined) Insert

func (cfd *CustomFieldDefined) Insert(ctx context.Context) (err error)

Insert saves a defined field. You should have already called Validate().

func (*CustomFieldDefined) Update

func (cfd *CustomFieldDefined) Update(ctx context.Context) (err error)

Update saves changes to a defined field. You should have already called Validate().

func (*CustomFieldDefined) Validate

func (cfd *CustomFieldDefined) Validate(ctx context.Context) (errMsg string, err error)

Validate is used to validate a struct's data before adding or saving changes. This also handles sanitizing.

type CustomFieldResult

type CustomFieldResult struct {
	ID              int64
	DatetimeCreated string

	//a license can be created by a user or via an api call.
	CreatedByUserID   null.Int
	CreatedByAPIKeyID null.Int

	LicenseID            int64           //what license this result was set for
	CustomFieldDefinedID int64           //what field this result is related to
	CustomFieldType      customFieldType //field type, since type could be changed on defined field
	CustomFieldName      string          //name of field when result was set, since name could be changed on defined field

	IntegerValue     null.Int    //provided result value for an integer field
	DecimalValue     null.Float  //provided result value for a decminal field.
	TextValue        null.String //provided result value for a text field
	BoolValue        null.Bool   //provided result for a boolean field
	MultiChoiceValue null.String //chosen result for a multi choice field
	DateValue        null.String //provided result for a date field
}

CustomFieldResult is used to interact with the table.

func GetCustomFieldResults

func GetCustomFieldResults(ctx context.Context, licenseID int64) (ff []CustomFieldResult, err error)

GetCustomFieldResults looks up the list of saved values for a license.

func (*CustomFieldResult) Insert

func (f *CustomFieldResult) Insert(ctx context.Context, tx *sqlx.Tx) (err error)

Insert saves an app. You should have already called Validate().

type DownloadHistory

type DownloadHistory struct {
	ID               int64
	DatetimeCreated  string //no default in CREATE TABLE so that we can set value using golang since we will also set TimestampCreated using golang.
	TimestampCreated int64  //nanoseconds, for sorting, no default in CREATE TABLE since handling nanoseconds with DEFAULT and SQLite is a pain/impossible.
	LicenseID        int64

	//a license can be creatd by a user or via an api call.
	CreatedByUserID   null.Int
	CreatedByAPIKeyID null.Int

	//Calculated fields
	DatetimeCreatedTZ string //DatetimeCreated converted to timezone per config file.
	Timezone          string //extra data for above fields for displaying in GUI.

	//JOINed fields
	CreatedByUsername          null.String
	CreatedByAPIKeyDescription null.String
}

DownloadHistory is used to interact with the table.

func GetHistory

func GetHistory(ctx context.Context, licenseID int64, orderBy string) (hh []DownloadHistory, err error)

GetHistory returns the download history for a license.

func (*DownloadHistory) Insert

func (h *DownloadHistory) Insert(ctx context.Context) (err error)

Insert saves the record of a license being downloaded.

type KeyPair

type KeyPair struct {
	ID               int64
	DatetimeCreated  string
	DatetimeModified string
	CreatedByUserID  int64
	Active           bool

	AppID               int64                       //what app this key pair is for
	Name                string                      //something descriptive for times when you have multiple key pairs for an app.
	PrivateKey          string                      `json:"-"` //should never leave this app
	PublicKey           string                      //embedded in your application you want to verify the licenses on.
	AlgorithmType       licensefile.KeyPairAlgoType //what algorithm was used to generate the key pair. ex: ecdsa.
	PrivateKeyEncrypted bool                        //true when private key is encrypted with config file encryption key

	//Default sets whether or not this keypair is the default key
	//to use when creating a new license for this app. This keypair
	//will be selected in the select menu automatically when the
	//parent app is chosen for a new license. Only one keypair for
	//an app can be set as default, obviously. If the default keypair
	//is deleted another is not set automatically.
	IsDefault bool
}

KeyPair is used to interact with the table.

func GetDefaultKeyPair

func GetDefaultKeyPair(ctx context.Context, appID int64) (k KeyPair, err error)

GetDefaultKeyPair retuns the default key pair for an app.

func GetKeyPairByID

func GetKeyPairByID(ctx context.Context, id int64) (k KeyPair, err error)

GetKeyPairByID looks up a key pair by its ID.

func GetKeyPairByName

func GetKeyPairByName(ctx context.Context, name string) (k KeyPair, err error)

GetKeyPairByName looks up a key pair by its name.

func GetKeyPairs

func GetKeyPairs(ctx context.Context, appID int64, activeOnly bool) (kk []KeyPair, err error)

GetKeyPairs returns the list of key pairs for an app optionally filtered by active keypairs only.

func (*KeyPair) Delete

func (k *KeyPair) Delete(ctx context.Context) (err error)

Delete marks a defined custom field as deleted.

func (*KeyPair) Insert

func (k *KeyPair) Insert(ctx context.Context) (err error)

Insert saves a key pair. You should have already called Validate().

func (*KeyPair) SetIsDefault

func (k *KeyPair) SetIsDefault(ctx context.Context) (err error)

SetIsDefault marks the keypair as the default keypair for the respective app. This also marks any other keypairs as non-default for the app to ensure only one keypair is marked as default as a time.

func (*KeyPair) Validate

func (k *KeyPair) Validate(ctx context.Context) (errMsg string, err error)

Validate handles validation of a key pair before saving.

type KeyValue

type KeyValue struct {
	ID               int64
	DatetimeCreated  string
	DatetimeModified string
	Active           bool

	//The actual data being stored
	K          string //key name
	V          string //value
	Type       string //string, float, bool, int, etc. Something to help when converting to datatype for usage. Matches golang type.
	Expiration int64  //a unix timestamp of when key and value should no longer be used, a TTL value. set to 0 for no expiration
}

KeyValue is used to interact with the table

func GetValueByKey

func GetValueByKey(ctx context.Context, keyName string) (k KeyValue, err error)

GetValueByKey looks up key/value pair by the key name. This will skip keys that are inactive or expired.

This will skip keys that are inactive or expired. This will return the newest key if multiple keys with the same name exist.

func (*KeyValue) Insert

func (k *KeyValue) Insert(ctx context.Context, tx *sqlx.Tx) (err error)

Insert saves a key/value to the database. you should have already performed validation.

func (*KeyValue) Update

func (k *KeyValue) Update(ctx context.Context, tx *sqlx.Tx) (err error)

Update saves changes to a key/value. Updating is done by key (name), not by ID. Don't forget to update expiration if needed!

type License

type License struct {
	ID               int64
	DatetimeCreated  string
	DatetimeModified string
	Active           bool

	//a license can be created by a user or via an api call.
	CreatedByUserID   null.Int
	CreatedByAPIKeyID null.Int

	//details chosen/provided in gui by user
	KeyPairID      int64  //the keypair used to sign the license
	CompanyName    string //company this license is for
	ContactName    string //who requested this license
	PhoneNumber    string //contact info
	Email          string //contact info
	IssueDate      string //yyyy-mm-dd format
	IssueTimestamp int64  //unix timestamp in seconds
	ExpireDate     string //yyyy-mm-dd format

	//The signature generated using the private key from the keypair. This is
	//generated once when the license is first created using the the common
	//license details and the common field results stored in the app's file
	//format. This is set to "" when license data is saved so we can get a
	//license ID before the license data is signed since some licenses contain
	//the license ID.
	Signature string

	//This is set to true ONLY after a license's data is saved, the signature
	//is created, and we reread the signed license file and check the signature
	//with the public key. This is used to ensure that a license can actually
	//be verified as authentic with the respective public key.
	Verified bool

	//These fields are copied from the app's details when the license
	//is created.
	AppName       string
	FileFormat    licensefile.FileFormat
	ShowLicenseID bool
	ShowAppName   bool

	//Calculated fields
	Expired           bool   //true if Expire date is greater than current date
	DatetimeCreatedTZ string //DatetimeCreated converted to timezone per config file.
	IssueDateTZ       string // " " " "
	Timezone          string //extra data for above fields for displaying in GUI.

	//JOINed fields
	KeyPairAlgoType            licensefile.KeyPairAlgoType
	CreatedByUsername          null.String
	CreatedByAPIKeyDescription null.String
	AppID                      int64
	AppFileFormat              licensefile.FileFormat
	AppDownloadFilename        string
	RenewedFromLicenseID       null.Int
	RenewedToLicenseID         null.Int
}

License is used to interact with the table.

func GetLicense

func GetLicense(ctx context.Context, licenseID int64, columns sqldb.Columns) (l License, err error)

GetLicense looks up a single license's data.

func GetLicenses

func GetLicenses(ctx context.Context, appID, limit int64, activeOnly bool, columns sqldb.Columns) (ll []License, err error)

GetLicenses looks up a list of licenses optionally filtered by app and active licenses only.

func (*License) Insert

func (l *License) Insert(ctx context.Context, tx *sqlx.Tx) (err error)

Insert saves a license. You should have already called Validate(). You need to validate the license and update the Signature and Verified fields.

func (*License) MarkVerified

func (l *License) MarkVerified(ctx context.Context) (err error)

MarkVerified updates a saved license by marking it as valid.

func (*License) SaveSignature

func (l *License) SaveSignature(ctx context.Context, tx *sqlx.Tx) (err error)

SaveSignature updates a saved license by saving the generated signature.

func (*License) Validate

func (l *License) Validate(ctx context.Context) (errMsg string, err error)

Validate handle sanitizing and validation of the license data. This only handle the common fields, not custom fields.

viaAPI alters the validation based on if this function is being called due to a license being created by an API request. We have to handle validation slightly different due to how the data will be provided in this request.

type LicenseNote

type LicenseNote struct {
	ID               int64
	DatetimeCreated  string
	DatetimeModified string
	Active           bool

	//a note can be added by a user or via an api call.
	CreatedByUserID   null.Int
	CreatedByAPIKeyID null.Int

	LicenseID int64
	Note      string

	//Calculated fields
	DatetimeCreatedTZ string //DatetimeCreated converted to timezone per config file.
	Timezone          string //extra data for above fields for displaying in GUI.

	//JOINed fields
	CreatedByUsername          null.String
	CreatedByAPIKeyDescription null.String
}

LicenseNote is used to interact with the table.

func GetNotes

func GetNotes(ctx context.Context, licenseID int64, orderBy string) (nn []LicenseNote, err error)

GetNotes looks up the notes for a license.

func (*LicenseNote) Insert

func (n *LicenseNote) Insert(ctx context.Context, tx *sqlx.Tx) (err error)

Insert saves a note. A transaction is optional, pass nil if you don't have one. A transaction is used when we are performing an action to a license, for example disabling, and we also want to save a note.

func (*LicenseNote) Validate

func (n *LicenseNote) Validate() (errMsg string)

Validate handles sanitizing and validation before a note is saved.

type MultiCustomFieldResult

type MultiCustomFieldResult []CustomFieldResult

MultiCustomFieldResult is used so that we can defined a method on a slice type. You cannot do func (c []CustomField) FuncName...

func (MultiCustomFieldResult) Validate

func (results MultiCustomFieldResult) Validate(ctx context.Context, appID int64, viaAPI bool) (errMsg string, err error)

Validate handles validating results for each custom field provided when creating a new license.

An error can be returned as a string, errMsg, or an error, err. This is done because if an input validation error occurs we will not have an error type value to pass back, but we will have a human-readable message to display to the user.

The input provided results are modified with data from the defined field to use when saving the results to the database.

type RenewalRelationship

type RenewalRelationship struct {
	ID               int64
	DatetimeCreated  string
	DatetimeModified string
	Active           bool

	//a license can be created by a user or via an api call.
	CreatedByUserID   null.Int
	CreatedByAPIKeyID null.Int

	FromLicenseID int64
	ToLicenseID   int64
}

RenewalRelationship is used to interact with the table.

func GetRenewalRelationshipByFromID

func GetRenewalRelationshipByFromID(ctx context.Context, fromLicenseID int64) (r RenewalRelationship, err error)

GetRenewalRelationshipByFromID looks up a renewal relationship's data by the from license's ID.

func (*RenewalRelationship) Insert

func (r *RenewalRelationship) Insert(ctx context.Context, tx *sqlx.Tx) (err error)

Insert saves a new renewal relationship.

type User

type User struct {
	//Basics.
	ID               int64
	DatetimeCreated  string
	DatetimeModified string
	CreatedByUserID  int64
	Active           bool

	Username            string
	Password            string `json:"-"`
	BadPasswordAttempts uint8  `json:"-"`

	//Access control permissions.
	Administrator  bool //can user create other users, apps, signing details, etc.
	CreateLicenses bool //can user create licenses.
	ViewLicenses   bool //can user view and download licenses.

	//2 factor auth stuff
	//Using "Two" not "2" since golang struct fields must start with letter.
	TwoFactorAuthEnabled     bool   //does the user use 2 factor auth
	TwoFactorAuthSecret      string `json:"-"` //the shared secret used to validate 2fa tokens
	TwoFactorAuthBadAttempts uint8  `json:"-"` //the number of bad 2fa tokens provides, increases the time taken to verify tokens to reduce impact of brute forcing 2fa tokens

	//Have to use different field names since struct tags block using Password field.
	//Only used when sending data into app; adding user or updating password.
	PasswordInput1 string
	PasswordInput2 string
}

User is used to interact with the table

func GetUserByID

func GetUserByID(ctx context.Context, id int64, columns sqldb.Columns) (u User, err error)

GetUserByID looks up a user's data by their ID.

func GetUserByUsername

func GetUserByUsername(ctx context.Context, username string, columns sqldb.Columns) (u User, err error)

GetUserByUsername looks up a user's by their username.

func GetUsers

func GetUsers(ctx context.Context, activeOnly bool) (uu []User, err error)

GetUsers looks up a list of users.

func (*User) Insert

func (u *User) Insert(ctx context.Context) (err error)

Insert saves a user to the database.

func (*User) Update

func (u *User) Update(ctx context.Context) (err error)

Update saves changes to a user

func (*User) Validate

func (u *User) Validate(ctx context.Context) (errMsg string, err error)

Validate handles validating and sanitizing of data prior to saving or updating a user.

type UserLogin

type UserLogin struct {
	ID                 int64 //not stored in cookie because it is easily guessed & incremented to find "next" session
	UserID             int64
	DatetimeCreated    string
	DatetimeModified   string
	RemoteIP           string
	UserAgent          string
	TwoFATokenProvided bool //whether or not a 2FA token was provided upon logging in.

	//This is a random, long value that will be stored in a cookie set for the user to
	//identify the login. This is used, over the ID field, since the ID field can easily
	//be guessed and incremented to find the "next" session. We will use this value,
	//from the cookie, to look up the logged in user's data when needed.
	CookieValue string

	//This is used to force a user to log out, force a users session to be marked as
	//invalid, prior to hitting the expiration. This is useful for forcing users to
	//log out for diagnostics, low level fixing of database, security, etc. This is
	//also used, by setting to false, when a user's password is changed so that all
	//currently logged in sessions need to re-provide the password, again for security.
	Active bool

	//When a user's session will expire. This is reset, extended, each time the user
	//visits a new page on the app.
	Expiration int64

	//JOINed fields
	Username string

	//Calculated fields
	DatetimeCreatedTZ string //DatetimeCreated converted to timezone per config file.
	Timezone          string //extra data for above fields for displaying in GUI.
}

UserLogin is used to interact with the table

func GetLoginByCookieValue

func GetLoginByCookieValue(ctx context.Context, cv string) (l UserLogin, err error)

GetLoginByCookieValue looks up login/session data by the cookie stored value.

func GetUserLogins

func GetUserLogins(ctx context.Context, userID int64, numRows uint16) (uu []UserLogin, err error)

GetUserLogins looks up successful logins. This defaults to looking up the last 200 rows if not limit is provided. You can optionally filter by userID or get logins for all users if userID is 0.

func (*UserLogin) ExtendLoginExpiration

func (u *UserLogin) ExtendLoginExpiration(ctx context.Context, newExpiration int64) (err error)

ExtendLoginExpiration updates the expiration timestamp for a user's login. This is used to reset the time a session will expire to keep users logged in if they are active within the app.

func (*UserLogin) Insert

func (u *UserLogin) Insert(ctx context.Context) (err error)

Insert saves an entry to the database for a user logging in to the app.

Jump to

Keyboard shortcuts

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