// Package config holds some (mostly static) configuration for the app. package config import ( "regexp" "time" ) // Branding const ( Title = "nonshy" Subtitle = "A social network for nudists and exhibitionists." ) // Paths and layouts const ( TemplatePath = "./web/templates" StaticPath = "./web/static" SettingsPath = "./settings.json" // Web path where photos are kept. Photos in DB store only their filenames, this // is the base URL that goes in front. TODO: support setting a CDN URL prefix. JpegQuality = 90 PhotoWebPath = "/static/photos" PhotoDiskPath = "./web/static/photos" ) // Security const ( BcryptCost = 14 SessionCookieName = "session_id" CSRFCookieName = "xsrf_token" CSRFInputName = "_csrf" // html input name SessionCookieMaxAge = 60 * 60 * 24 * 30 SessionRedisKeyFormat = "session/%s" MaxBodySize = 1024 * 1024 * 8 // max upload file (e.g., 8 MB gifs) MultipartMaxMemory = 1024 * 1024 * 1024 * 20 // 20 MB TwoFactorBackupCodeCount = 12 TwoFactorBackupCodeLength = 8 // characters a-z0-9 ) // Authentication const ( // Skip the email verification step. The signup page will directly ask for // email+username+password rather than only email and needing verification. SkipEmailVerification = false SignupTokenRedisKey = "signup-token/%s" ResetPasswordRedisKey = "reset-password/%s" ChangeEmailRedisKey = "change-email/%s" SignupTokenExpires = 24 * time.Hour // used for all tokens so far // Rate limits RateLimitRedisKey = "rate-limit/%s/%s" // namespace, id LoginRateLimitWindow = 1 * time.Hour LoginRateLimit = 10 // 10 failed login attempts = locked for full hour LoginRateLimitCooldownAt = 3 // 3 failed attempts = start throttling LoginRateLimitCooldown = 30 * time.Second // Contact form rate limits for logged-out users to curb spam robots: // - One message can be submitted every 2 minutes // - If they post 10 minutes in an hour they are paused for one hour. ContactRateLimitWindow = 1 * time.Hour ContactRateLimit = 10 ContactRateLimitCooldownAt = 1 ContactRateLimitCooldown = 2 * time.Minute // "Mark Explicit" rate limit to curb a mischievous user just bulk marking the // whole gallery as explicit. MarkExplicitRateLimitWindow = 1 * time.Hour MarkExplicitRateLimit = 20 // 10 failed MarkExplicit attempts = locked for full hour MarkExplicitRateLimitCooldownAt = 10 // 10 photos in an hour, start throttling. MarkExplicitRateLimitCooldown = time.Minute // How frequently to refresh LastLoginAt since sessions are long-lived. LastLoginAtCooldown = time.Hour // Chat room status refresh interval. ChatStatusRefreshInterval = 30 * time.Second ) var ( UsernameRegexp = regexp.MustCompile(`^[a-z0-9_.-]{3,32}$`) ReservedUsernames = []string{ "admin", "admins", "administrator", "moderator", "support", "staff", "nonshy", "here", "all", "everyone", "everybody", } ) // Photo Galleries const ( MaxPhotoWidth = 1280 ProfilePhotoWidth = 512 AltTextMaxLength = 5000 // Quotas for uploaded photos. PhotoQuotaUncertified = 6 PhotoQuotaCertified = 100 // Rate limit for too many Site Gallery pictures. // Some users sign up and immediately max out their gallery and spam // the Site Gallery page. These limits can ensure only a few Site Gallery // pictures can be posted per day. SiteGalleryRateLimitMax = 5 SiteGalleryRateLimitInterval = 24 * time.Hour ) // Forum settings const ( // Only ++ the Views count per user per thread within a small // window of time - if a user keeps reloading the same thread // rapidly it does not increment the view counter more. ThreadViewDebounceRedisKey = "debounce-view/user=%d/thr=%d" ThreadViewDebounceCooldown = 1 * time.Hour // Enable user-owned forums (feature flag) UserForumsEnabled = false ) // User-Owned Forums: Quota settings for how many forums a user can own. var ( // They get one forum after they've been Certified for 45 days. UserForumQuotaCertLifetimeDays = time.Hour * 24 * 45 // Schedule for gaining additional quota for a number of comments written // on any forum thread. The user must have the sum of all of these post // counts to gain one forum per level. UserForumQuotaCommentCountSchedule = []int64{ 10, // Get a forum after your first 10 posts. 20, // Get a 2nd forum after 20 additional posts (30 total) 30, // 30 more posts (60 total) 60, // 60 more posts (120 total) 80, // 80 more posts (200 total) 100, // and then one new forum for every 100 additional posts } ) // Poll settings var ( // Max number of responses to accept for a poll (how many form // values the app will read in). NOTE: also enforced in frontend // UX in new_post.html, update there if you change this. PollMaxAnswers = 100 // Poll color CSS classes (Bulma). Plugged in to templates like: // // Values will wrap around for long polls. PollProgressBarClasses = []string{ "progress is-success", "progress is-link", "progress is-warning", "progress is-danger", "progress is-primary", "progress is-info", } ) // Variables set by main.go to make them readily available. var ( RuntimeVersion string RuntimeBuild string RuntimeBuildDate string Debug bool // app is in debug mode )