diff --git a/front/gemini/gemini.go b/front/gemini/gemini.go index 7dc35015..1b2be5da 100644 --- a/front/gemini/gemini.go +++ b/front/gemini/gemini.go @@ -67,7 +67,7 @@ func getUser(ctx context.Context, db *sql.DB, conn net.Conn, tlsConn *tls.Conn, return &actor, nil } -func handle(ctx context.Context, handler front.Handler, conn net.Conn, db *sql.DB, resolver *fed.Resolver, wg *sync.WaitGroup, log *slog.Logger) { +func Handle(ctx context.Context, handler front.Handler, conn net.Conn, db *sql.DB, resolver *fed.Resolver, wg *sync.WaitGroup, log *slog.Logger) { if err := conn.SetDeadline(time.Now().Add(reqTimeout)); err != nil { log.Warn("Failed to set deadline", "error", err) return @@ -187,7 +187,7 @@ func ListenAndServe(ctx context.Context, log *slog.Logger, db *sql.DB, handler f wg.Add(1) go func() { - handle(requestCtx, handler, conn, db, resolver, &wg, log) + Handle(requestCtx, handler, conn, db, resolver, &wg, log) conn.Close() timer.Stop() cancelRequest() diff --git a/front/register.go b/front/register.go index 31317121..40284268 100644 --- a/front/register.go +++ b/front/register.go @@ -19,14 +19,18 @@ package front import ( "crypto/sha256" "crypto/tls" + "database/sql" "fmt" "github.com/dimkr/tootik/cfg" "github.com/dimkr/tootik/front/text" "github.com/dimkr/tootik/front/user" "net/url" "regexp" + "time" ) +const registrationInterval = time.Hour + var userNameRegex = regexp.MustCompile(`^[a-zA-Z0-9-_]{4,32}$`) func register(w text.Writer, r *request) { @@ -103,6 +107,22 @@ func register(w text.Writer, r *request) { return } + var lastRegister sql.NullInt64 + if err := r.QueryRow(`select max(inserted) from persons where host = ?`, cfg.Domain).Scan(&lastRegister); err != nil { + r.Log.Warn("Failed to check last registration time", "name", userName, "error", err) + w.Error() + return + } + + if lastRegister.Valid { + now := time.Now() + elapsed := now.Sub(time.Unix(lastRegister.Int64, 0)) + if elapsed < registrationInterval { + w.Statusf(40, "Registration is closed for %s", (registrationInterval - elapsed).Truncate(time.Second).String()) + return + } + } + r.Log.Info("Creating new user", "name", userName) if _, err := user.Create(r.Context, r.DB, fmt.Sprintf("https://%s/user/%s", cfg.Domain, userName), userName, certHash); err != nil { diff --git a/front/stats.go b/front/stats.go index 4be4266f..7e774290 100644 --- a/front/stats.go +++ b/front/stats.go @@ -74,7 +74,7 @@ func getUsersGraph(r *request) string { func getInstancesGraph(r *request) string { keys := make([]string, 7) values := make([]int64, 7) - return getGraph(r, `select strftime('%Y-%m-%d', datetime(days.day, 'unixepoch')), count(*) from (select substr(substr(persons.id, 9), 1, instr(substr(persons.id, 9), '/')-1) as host, min(inserted/(60*60*24)*60*60*24) as day from persons group by host) hosts join (select distinct inserted/(60*60*24)*60*60*24 as day from persons where inserted>unixepoch()-60*60*24*7 and insertedunixepoch()-60*60*24*7 and inserted