Mirror of @tangled.org/core. Running on a Raspberry Pi Zero 2 (Please be gentle).
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

appview/signup: username blacklist

Signed-off-by: Anirudh Oppiliappan <anirudh@tangled.sh>

authored by

Anirudh Oppiliappan and committed by
Tangled
1ebd3b6b 0b922f7b

+80 -21
+6 -5
appview/config/config.go
··· 10 10 ) 11 11 12 12 type CoreConfig struct { 13 - CookieSecret string `env:"COOKIE_SECRET, default=00000000000000000000000000000000"` 14 - DbPath string `env:"DB_PATH, default=appview.db"` 15 - ListenAddr string `env:"LISTEN_ADDR, default=0.0.0.0:3000"` 16 - AppviewHost string `env:"APPVIEW_HOST, default=https://tangled.sh"` 17 - Dev bool `env:"DEV, default=false"` 13 + CookieSecret string `env:"COOKIE_SECRET, default=00000000000000000000000000000000"` 14 + DbPath string `env:"DB_PATH, default=appview.db"` 15 + ListenAddr string `env:"LISTEN_ADDR, default=0.0.0.0:3000"` 16 + AppviewHost string `env:"APPVIEW_HOST, default=https://tangled.sh"` 17 + Dev bool `env:"DEV, default=false"` 18 + DisallowedNicknamesFile string `env:"DISALLOWED_NICKNAMES_FILE"` 18 19 } 19 20 20 21 type OAuthConfig struct {
+1 -1
appview/pages/templates/user/completeSignup.html
··· 51 51 name="code" 52 52 tabindex="1" 53 53 required 54 - placeholder="pds-tngl-sh-foo-bar" 54 + placeholder="tngl-sh-foo-bar" 55 55 /> 56 56 <span class="text-sm text-gray-500 mt-1"> 57 57 Enter the code sent to your email.
+73 -15
appview/signup/signup.go
··· 1 1 package signup 2 2 3 3 import ( 4 + "bufio" 4 5 "fmt" 5 6 "log/slog" 6 7 "net/http" 8 + "os" 9 + "strings" 7 10 8 11 "github.com/go-chi/chi/v5" 9 12 "github.com/posthog/posthog-go" ··· 21 18 ) 22 19 23 20 type Signup struct { 24 - config *config.Config 25 - db *db.DB 26 - cf *dns.Cloudflare 27 - posthog posthog.Client 28 - xrpc *xrpcclient.Client 29 - idResolver *idresolver.Resolver 30 - pages *pages.Pages 31 - l *slog.Logger 21 + config *config.Config 22 + db *db.DB 23 + cf *dns.Cloudflare 24 + posthog posthog.Client 25 + xrpc *xrpcclient.Client 26 + idResolver *idresolver.Resolver 27 + pages *pages.Pages 28 + l *slog.Logger 29 + disallowedNicknames map[string]bool 32 30 } 33 31 34 32 func New(cfg *config.Config, database *db.DB, pc posthog.Client, idResolver *idresolver.Resolver, pages *pages.Pages, l *slog.Logger) *Signup { ··· 42 38 } 43 39 } 44 40 41 + disallowedNicknames := loadDisallowedNicknames(cfg.Core.DisallowedNicknamesFile, l) 42 + 45 43 return &Signup{ 46 - config: cfg, 47 - db: database, 48 - posthog: pc, 49 - idResolver: idResolver, 50 - cf: cf, 51 - pages: pages, 52 - l: l, 44 + config: cfg, 45 + db: database, 46 + posthog: pc, 47 + idResolver: idResolver, 48 + cf: cf, 49 + pages: pages, 50 + l: l, 51 + disallowedNicknames: disallowedNicknames, 53 52 } 53 + } 54 + 55 + func loadDisallowedNicknames(filepath string, logger *slog.Logger) map[string]bool { 56 + disallowed := make(map[string]bool) 57 + 58 + if filepath == "" { 59 + logger.Debug("no disallowed nicknames file configured") 60 + return disallowed 61 + } 62 + 63 + file, err := os.Open(filepath) 64 + if err != nil { 65 + logger.Warn("failed to open disallowed nicknames file", "file", filepath, "error", err) 66 + return disallowed 67 + } 68 + defer file.Close() 69 + 70 + scanner := bufio.NewScanner(file) 71 + lineNum := 0 72 + for scanner.Scan() { 73 + lineNum++ 74 + line := strings.TrimSpace(scanner.Text()) 75 + if line == "" || strings.HasPrefix(line, "#") { 76 + continue // skip empty lines and comments 77 + } 78 + 79 + nickname := strings.ToLower(line) 80 + if userutil.IsValidSubdomain(nickname) { 81 + disallowed[nickname] = true 82 + } else { 83 + logger.Warn("invalid nickname format in disallowed nicknames file", 84 + "file", filepath, "line", lineNum, "nickname", nickname) 85 + } 86 + } 87 + 88 + if err := scanner.Err(); err != nil { 89 + logger.Error("error reading disallowed nicknames file", "file", filepath, "error", err) 90 + } 91 + 92 + logger.Info("loaded disallowed nicknames", "count", len(disallowed), "file", filepath) 93 + return disallowed 94 + } 95 + 96 + // isNicknameAllowed checks if a nickname is allowed (not in the disallowed list) 97 + func (s *Signup) isNicknameAllowed(nickname string) bool { 98 + return !s.disallowedNicknames[strings.ToLower(nickname)] 54 99 } 55 100 56 101 func (s *Signup) Router() http.Handler { ··· 181 128 182 129 if !userutil.IsValidSubdomain(username) { 183 130 s.pages.Notice(w, "signup-error", "Invalid username. Username must be 4–63 characters, lowercase letters, digits, or hyphens, and can't start or end with a hyphen.") 131 + return 132 + } 133 + 134 + if !s.isNicknameAllowed(username) { 135 + s.pages.Notice(w, "signup-error", "This username is not available. Please choose a different one.") 184 136 return 185 137 } 186 138