Documentation
¶
Index ¶
- Constants
- Variables
- func ComparePasswords(hashed, plaintext string) bool
- func ConsoleDebug(message string, args ...interface{})
- func CopyFile(src string, dst string, mode os.FileMode) error
- func CountryCodeAndPhone(phoneNumber string) (int32, string, error)
- func EncryptPassword(password string) (string, error)
- func ExpandTilde(filePath string) (string, error)
- func FileExists(path string) bool
- func Hash(plaintext string) string
- func InterfaceList(items []string) []interface{}
- func IsEmptyString(str string) bool
- func IsTrueString(s string) bool
- func ListIsEmpty(list []string) bool
- func LoadRelativeFile(relpath string) ([]byte, error)
- func LooksEncrypted(s string) bool
- func LooksLikeUUID(uuid string) bool
- func NewOTP() (string, error)
- func PasswordMeetsRequirements(pwd string) bool
- func PrintAndExit(message string)
- func ProjectRoot() string
- func RandomToken() string
- func SanitizeIdentifier(str string) string
- func SplitCamelCase(str string, max int) []string
- func TestsAreRunning() bool
- func ToHumanSize(size, unit int64) string
- type APTContext
- type Config
- type CookieConfig
- type DBConfig
- type EmailConfig
- type LoggingConfig
- type Pager
- type QueryLogger
- type RedisConfig
- type RetentionMinimum
- type TwoFactorConfig
- type ValidationError
Constants ¶
const Cost = 10
Cost is the cost of the bcrypt digest. This is hard-coded at 10 to match the value that Rails/Devise uses. We're porting a Rails database and we want to be able to use existing passwords instead of forcing users to reset them.
const EncryptedTokenPrefix = "$2a$10$"
EncryptedTokenPrefix is the prefix that should appear on all our encrypted passwords and tokens in the database. Note that it depends on common.Cost being set to 10.
Variables ¶
var ErrAccountDeactivated = errors.New("account deactivated")
ErrAccountDeactivated means the user logged in to a deactivated account.
var ErrActiveFiles = errors.New("cannot delete object with active files")
ErrActiveFiles occurs when we try to delete an IntellectualObject that has active files. All of the object's files should first be deleted (set to State = "D").
var ErrAlreadyHasAuthyID = errors.New("user is already registered with authy")
ErrAlreadyHasAuthyID occurs when we try to register a user with Authy and they already have an Authy ID.
var ErrCountTypeNotSupported = errors.New("type is not supported for view count")
ErrCountTypeNotSupported indicates that we cannot get counts for the given type from the *_counts views. Use a regular SQL count() instead.
var ErrCrossOriginReferer = errors.New("csrf error: cross origin request forbidden")
ErrMissingReferer means we got a cross-site request on an unsafe methods such as POST, PUT, DELETE. See the CSRF middleware.
var ErrDecodeCookie = errors.New("error decoding cookie")
ErrDecodeCookie occurs when we get a bad authentication cookie. We consider it a 400/Bad Request because we don't set bad cookies.
var ErrIDMismatch = errors.New("resource or institution id mismatch")
ErrIDMismatch can indicate that the specified resource does not belong to the specified institition, or (more likely) that resource/institution IDs in a URL do not match resource/institution IDs submitted in the PUT/POST body of an HTML request.
var ErrIdentifierChange = errors.New("identifier cannot change")
ErrIdentifierChange occurs when someone tries to change the identifier of a resource.
var ErrInstIDChange = errors.New("institution id cannot change")
ErrInstIDChange occurs when someone tries to change the institution id of a resource.
var ErrInternal = errors.New("internal server error")
ErrInternal is a runtime error that is not the user's fault, hence probably the programmer's fault.
var ErrInvalidAPICredentials = errors.New("invalid api credentials")
ErrInvalidAPICredentials means the user supplied the wrong email or API token while trying to access a REST API endpoint.
var ErrInvalidCSRFToken = errors.New("invalid csrf token")
ErrInvalidCSRFToken is specifically for POST/PUT/DELETE where we have a missing or invalid CSRF token.
var ErrInvalidLogin = errors.New("invalid login or password")
ErrInvalidLogin means the user supplied the wrong login name or password while trying to sign in.
var ErrInvalidObjectID = errors.New("one or more object ids is invalid")
ErrInvalidObjectID occurs when requesting a batch deletion that contains one or more invalid object ids.
var ErrInvalidParam = errors.New("invalid parameter")
ErrInvalidParam means the HTTP request contained an invalid parameter.
var ErrInvalidRequestorID = errors.New("invalid requestor id")
ErrInvalidRequestorID occurs when APTrust admin submits batch delete request on behalf of a user who is not allowed to initiate a batch deletion.
var ErrInvalidToken = errors.New("invalid token")
ErrInvalidToken means that the token presented for an action like password reset or deletion confirmation does not match the encrypted token in the database. When this error occurs, the user may not proceed with the requested action.
var ErrMissingReferer = errors.New("csrf error: missing http referer")
ErrMissingReferer means the request had no http referer header, so we can't tell where it came from. We can't tell for sure if it's a cross-origin attack, so we throw an error. This happens only on unsafe methods (POST, PUT, DELETE). See the CSRF middleware.
var ErrMustCompleteReset = errors.New("you must complete your own password reset")
ErrMustCompleteReset occurs when a user is supposed to be resetting their own password but tries instead to reset someone else's. SysAdmin and Inst admins can legitimately reset others' passwords, but they shouldn't be doing it in this context.
var ErrNoAuthyID = errors.New("user does not have an authy id")
ErrNoAuthyID occurs when a user requests two-factor login via Authy but does not have an Authy ID.
var ErrNotSignedIn = errors.New("user is not signed in")
ErrNotSignedIn means user has not signed in.
var ErrNotSupported = errors.New("operation not supported")
ErrNotSupported is an internal error that occurs, for example, when we try to delete an object that does not support deletion. This represents a programmer error and should not occur.
var ErrParentRecordNotFound = errors.New("parent record not found")
ErrParentRecordNotFound occurs when we cannot find the parent record required to check a user's permission. For example, when a user requests a Checksum, we first need to know if the user is allowed to access the Checksum's parent, which is a Generic File. If that record is missing, we get this error.
var ErrPasswordReqs = errors.New("password does not meet minimum requirements")
ErrPasswordReqs indicates that the password the user is trying to set does not meet minimum requirements.
var ErrPendingWorkItems = errors.New("task cannot be completed because this object has pending work items")
ErrPendingWorkItems occurs when a user wants to restore or delete an object or file but the WorkItems list shows other operations are pending on that item. For example, we can't delete or restore an object or file while another version of that object/file is pending ingest. Doing so would cause newly ingested files to be deleted as soon as they're sent to preservation, or would cause a restoration to contain a mix of new and old versions of a bag's files.
var ErrPermissionDenied = errors.New("permission denied")
ErrPermissionDenied means the user tried to access a resource withouth sufficient permission.
var ErrRequestAlreadyApproved = errors.New("this request has already been approved")
ErrRequestAlreadyApproved occurs when someone tries to approve or cancel a request that was previously approved.
var ErrRequestAlreadyCancelled = errors.New("this request has already been cancelled")
ErrRequestAlreadyCancelled occurs when someone tries to approve or cancel a request that was previously cancelled.
var ErrResourcePermission = errors.New("cannot determine permission type for requested requested resource")
ErrResourcePermission occurs when Authorization middleware cannot determine which permission is required to access the specified resoruce.
var ErrStorageOptionChange = errors.New("cannot change storage option on active object")
ErrStorageOptionChange indicates someone tried to change the storage option on an active object. (It's OK to change storage option on a deleted object that you are re-depositing.)
var ErrSubclassMustImplement = errors.New("subclass must implement this method")
ErrSubclassMustImplement indicates that a subclass has not implemented a method inherited from a base class.
var ErrWrongAPI = errors.New("non-admins must use the member api")
ErrWrongAPI occurs when a non-admin user tries to access the admin API. While the member and admin APIs share some common handlers, and members do technically have access to a number of read-only operations in both APIs, we don't want members to get in the habit of accessing the wrong endpoints.
var ErrWrongDataType = errors.New("wrong data type")
ErrWrongDataType occurs when the user submits data of the wrong type, such string data that cannot be converted to a number, bool, date, or whatever type the application is expecting.
var TextTemplates map[string]*template.Template
Functions ¶
func ComparePasswords ¶
ComparePasswords compares a plaintext password against a hashed password, returning true if they match, false otherwise.
func ConsoleDebug ¶
func ConsoleDebug(message string, args ...interface{})
ConsoleDebug prints a message to the console if the following we are running in the dev or test environment and we are not running automated tests. We want to see these messages in the console when we're doing interactive testing in the dev or test environments, but NOT when running automated tests because they clutter the test output.
We also don't want these messages to appear in production, which is why we have a hard-coded list of safe environment names.
func CopyFile ¶
CopyFile copies the file at src path to dst path. It applies the permissions specified in mode to the destination file. Mode values are 0644, 0755, etc.
func CountryCodeAndPhone ¶
CountryCodeAndPhone returns the country code and phone number for a phoneNumber in format that begins with plus country code, e.g. "+12125551212"
func EncryptPassword ¶
EncryptPassword returns the password run through bcrypt 2a with the specified salt and cost.
func ExpandTilde ¶
Expands the tilde in a directory path to the current user's home directory. For example, on Linux, ~/data would expand to something like /home/josie/data
func FileExists ¶
Returns true if the file at path exists, false if not.
func Hash ¶
Hash returns an encrypted version of plaintext that cannot be decrypted. This is suitable for encrypting passwords, reset-tokens, etc. The combined use of md5 plus plaintext salt plus sha256 provides some protection against rainbow tables.
TODO: Delete this if we're not using it. Looks like we're actually using bcrypt in common/password.go
func InterfaceList ¶
func InterfaceList(items []string) []interface{}
InterfaceList converts a list of strings to a list of interfaces.
func IsEmptyString ¶
IsEmptyString returns true if str, stripped of leading and trailing whitespace, is empty.
func IsTrueString ¶
IsTrueString returns true if param s is "true", "yes", or "1". The test is case-insensitive. Use this for parsing query string params.
func ListIsEmpty ¶
ListIsEmpty returns true if the slice contains no elements, or if all the elements are empty strings.
func LoadRelativeFile ¶
LoadRelativeFile loads the file at the specified path relative to ProjectRoot() and returns the contents as a byte array.
Example:
bytes, err := LoadRelativeFile("db/fixtures/work_items.csv")
func LooksEncrypted ¶
LooksEncrypted returns true if string s looks like it's been through our EncryptePassword fuction. We use LooksEncrypted on some pgmodels to ensure we're not saving unencrypted passwords or tokens.
func LooksLikeUUID ¶
LooksLikeUUID returns true if uuid looks like a valid UUID.
func NewOTP ¶
NewOTP returns a six-digit code suitable for use as a one-time password. We return this as a string because we need to store a hashed version in the DB and then send a copy to the user.
func PasswordMeetsRequirements ¶
PasswordMeetsRequirements returns true if param pwd meets our minimum password requirements.
func PrintAndExit ¶
func PrintAndExit(message string)
PrintAndExit prints a message to STDERR and exits
func RandomToken ¶
func RandomToken() string
RandomToken returns a string of random hex digits suitable for use as a secure token.
func SanitizeIdentifier ¶
SanitizeIdentifier strips everything but letters, numbers, underscores periods and double quotes from str. This is used primarily to sanitize SQL column names in queries. Column names may include things like "email", "user"."email", etc.
func SplitCamelCase ¶
SplitCamelCase splits camel-case identifiers into multiple words. Note that it does not split on multiple consecutive caps, so param CurrencyUSD would return ["Currency", "USD"].
If max is less than zero, this will split into all words. If max is > 0, this will split into max words.
func TestsAreRunning ¶
func TestsAreRunning() bool
TestsAreRunning returns true when code is running under "go test"
func ToHumanSize ¶
ToHumanSize converts a raw byte count (size) to a human-friendly representation.
Types ¶
type APTContext ¶
type APTContext struct { // Config contains config information for the entire app. Config *Config // DB is our connection to the Postgres/RDS database. DB *pg.DB // Log is our logger. Log zerolog.Logger // AuthyClient sends push notifications to users who have enabled // two-factor auth via push. AuthyClient network.AuthyClientInterface // NSQClient lets registry queue work items for preservation services // and lets us view NSQ admin stats. NSQClient *network.NSQClient // RedisClient talks to Redis/Elasticache to retrieve info about // WorkItems in progress. RedisClient *network.RedisClient // SESClient is for sending emails from behind a NAT gateway SESClient *network.SESClient // SNSClient sends two-factor auth codes via Text/SMS message // to user phones. SNSClient *network.SNSClient // SMTPClient is for sending emails from a private subnet that // is not using a NAT gateway. SMTPClient *network.SMTPClient }
func Context ¶
func Context() *APTContext
Context returns an APTContext object, which includes global config settings and a connection to the postgres database. It requires the environment variable APT_ENV to be set to something valid, such as "test", "dev", "integration", "demo", "staging" or "production". It loads the .env file that corresponds to that setting. If APT_ENV is not set to a valid setting, the app dies immediately.
This will also exit if the app cannot connect to the database. If that happens, ensure the database is running and accepting connections at the specified location, and ensure that the db credentials are correct.
func (*APTContext) SendEmail ¶
func (c *APTContext) SendEmail(recipientEmail, subject, message string) error
type Config ¶
type Config struct { Cookies *CookieConfig DB *DBConfig EnvName string Logging *LoggingConfig NsqUrl string TwoFactor *TwoFactorConfig Email *EmailConfig Redis *RedisConfig RetentionMinimum *RetentionMinimum // BatchDeletionKey is a secret loaded from parameter store. // Batch deletion requests must include this as an extra security token. BatchDeletionKey string // MaintenanceMode indicates whether we're currently doing maintenance // on the system. If this is true, all requests will be redirected to // the /maintenance page, which will render HTML or JSON as necessary. // Also, when this is true, the cron jobs in application/cron.go will // not be initialized, so that the DB will receive no writes from Registry // and will be free to run migrations. MaintenanceMode bool // EmailServiceType describes which email service to use in the current // environment. This should be "SMTP" if we're running on a private // subnet with no NAT gateway. Otherwise, it should be "SES". If this is // not set, or if it's set to an invalid value, it defaults to SMTP. EmailServiceType string }
func (*Config) BucketQualifier ¶
BucketQualifier returns the S3 bucket qualifier for the current config. We could set this in the .env file, but we want to avoid the possibility of a config pointing to the wrong buckets. (For example, by someone carelessly copying and pasting config settings.) Our restrictive IAM permissions prevent the wrong environments from accessing the wrong buckets, but this is an extra layer of protection. This defaults to ".test", so if anything is misconfigured, we'll be reading from and writing to buckets in which we explicitly guarantee no permanance.
func (*Config) HTTPScheme ¶
HTTPScheme returns "http" for the dev, test, ci, and travis environments. It returns "https" for all other environments.
func (*Config) IsTestOrDevEnv ¶
Returns true if we're in a test or dev environment.
type CookieConfig ¶
type CookieConfig struct { Secure *securecookie.SecureCookie Domain string HTTPSOnly bool MaxAge int SessionCookie string FlashCookie string PrefsCookie string }
type DBConfig ¶
type DBConfig struct { Host string Name string User string Password string Port int Driver string UseSSL bool }
DBConfig contains info for connecting to the Postgres database.
type EmailConfig ¶
type EmailConfig struct { AWSRegion string Enabled bool FromAddress string SesUser string SesPassword string SesEndpoint string }
EmailConfig describes how to connect to Amazon SES or another SMTP service. If SesEndpoint is empty, we'll use the default public SES endpoint for the specified region. If non-empty, we'll use the explicit SesEndpoint. Should be non-empty if we're on a private subnet without a NAT gateway.
type LoggingConfig ¶
type Pager ¶
type QueryLogger ¶
type QueryLogger struct {
// contains filtered or unexported fields
}
func NewQueryLogger ¶
func NewQueryLogger(logger zerolog.Logger) *QueryLogger
func (*QueryLogger) AfterQuery ¶
func (l *QueryLogger) AfterQuery(c context.Context, qe *pg.QueryEvent) error
func (*QueryLogger) BeforeQuery ¶
type RedisConfig ¶
type RetentionMinimum ¶
RetentionMinimum describes the minimum number of days items must remain in preservation storage before they can be deleted. For S3 and APTrust Standard storage, this is zero. We can delete those items at any time. All other storage types have restrictions. We prevent depositors from deleting items that have not met the minimum retention period because we have to pay for the minimum retention period no matter what, and we need to pass those costs through to depositors.
func (*RetentionMinimum) For ¶
func (rm *RetentionMinimum) For(storageOption string) int
For returns the minimum number of days an object or file must be stored in the specified storage option. (RetentionMinimum.For(option) makes for readable code.)
type TwoFactorConfig ¶
type TwoFactorConfig struct { AuthyEnabled bool AuthyAPIKey string AWSRegion string SMSEnabled bool OTPExpiration time.Duration SNSUser string SNSPassword string SNSEndpoint string }
TwoFactorConfig contains info for sending push messages through Authy and SMS text messages through AWS SNS. If SNSEndpoint is empty, we'll use the default public SNS endpoint for the specified region. If non-empty, we'll use the explicit SNSEndpoint. Should be non-empty if we're on a private subnet without a NAT gateway.
type ValidationError ¶
func NewValidationError ¶
func NewValidationError() *ValidationError
func (*ValidationError) Error ¶
func (v *ValidationError) Error() string