website/pkg/config/config.go
Noah Petherbridge 2f31d678d0 Usage Statistics and Website Demographics
Adds two new features to collect and show useful analytics.

Usage Statistics:
* Begin tracking daily active users who log in and interact with major features
  of the website each day, such as the chat room, forum and gallery.

Demographics page:
* For marketing, the home page now shows live statistics about the breakdown of
  content (explicit vs. non-explicit) on the site, and the /insights page gives
  a lot more data in detail.
* Show the percent split in photo gallery content and how many users opt-in or
  share explicit content on the site.
* Show high-level demographics of the members (by age range, gender, orientation)

Misc cleanup:
* Rearrange model list in data export to match the auto-create statements.
* In data exports, include the forum_memberships, push_notifications and
  usage_statistics tables.
2024-09-11 19:28:52 -07:00

183 lines
5.6 KiB
Go

// 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
// How to rate limit same types of emails being delivered, e.g.
// signups, cert approvals (double post), etc.
EmailDebounceDefault = 24 * time.Hour // default debounce per type of email
EmailDebounceResetPassword = 4 * time.Hour // "forgot password" emails debounce
// 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
// Cache TTL for the demographics page.
DemographicsCacheTTL = time.Hour
)
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 = true
)
// 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:
// <progress class="$CLASS">
// 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
)