diff --git a/.woodpecker/.backend.yml b/.woodpecker/.backend.yml new file mode 100644 index 0000000..07b7898 --- /dev/null +++ b/.woodpecker/.backend.yml @@ -0,0 +1,13 @@ +when: + branch: + exclude: stable + +steps: + check: + image: golang:alpine + commands: + - apk update && apk add curl vips-dev build-base + - make backend + # Install golangci-lint + - curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.55.2 + - golangci-lint run diff --git a/.woodpecker/.frontend.yml b/.woodpecker/.frontend.yml new file mode 100644 index 0000000..bedfa1f --- /dev/null +++ b/.woodpecker/.frontend.yml @@ -0,0 +1,20 @@ +when: + branch: + exclude: stable + +steps: + check: + image: node + directory: frontend + environment: # SvelteKit expects these in the environment during build time. + - PRIVATE_SENTRY_DSN= + - PUBLIC_BASE_URL=http://pronouns.localhost + - PUBLIC_MEDIA_URL=http://pronouns.localhost/media + - PUBLIC_SHORT_BASE=http://prns.localhost + - PUBLIC_HCAPTCHA_SITEKEY=non_existent_sitekey + commands: + - corepack enable + - pnpm install + - pnpm check + - pnpm lint + - pnpm build diff --git a/Makefile b/Makefile index 1b15eff..8a7c089 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ all: generate backend frontend .PHONY: backend backend: - go build -v -o pronouns -ldflags="-buildid= -X codeberg.org/pronounscc/pronouns.cc/backend/server.Revision=`git rev-parse --short HEAD` -X codeberg.org/pronounscc/pronouns.cc/backend/server.Tag=`git describe --tags --long`" . + go build -v -o pronouns -ldflags="-buildid= -X codeberg.org/pronounscc/pronouns.cc/backend/server.Revision=`git rev-parse --short HEAD` -X codeberg.org/pronounscc/pronouns.cc/backend/server.Tag=`git describe --tags --long --always`" . .PHONY: generate generate: diff --git a/backend/db/export.go b/backend/db/export.go index 6141aac..5095445 100644 --- a/backend/db/export.go +++ b/backend/db/export.go @@ -79,7 +79,7 @@ func (db *DB) CreateExport(ctx context.Context, userID xid.ID, filename string, return de, errors.Wrap(err, "building query") } - pgxscan.Get(ctx, db, &de, sql, args...) + err = pgxscan.Get(ctx, db, &de, sql, args...) if err != nil { return de, errors.Wrap(err, "executing sql") } diff --git a/backend/db/invites.go b/backend/db/invites.go index d56662e..d13ab0e 100644 --- a/backend/db/invites.go +++ b/backend/db/invites.go @@ -6,6 +6,7 @@ import ( "encoding/base64" "time" + "codeberg.org/pronounscc/pronouns.cc/backend/log" "emperror.dev/errors" "github.com/georgysavva/scany/v2/pgxscan" "github.com/jackc/pgx/v5" @@ -43,7 +44,12 @@ func (db *DB) CreateInvite(ctx context.Context, userID xid.ID) (i Invite, err er if err != nil { return i, errors.Wrap(err, "beginning transaction") } - defer tx.Rollback(ctx) + defer func() { + err := tx.Rollback(ctx) + if err != nil && !errors.Is(err, pgx.ErrTxClosed) { + log.Error("rolling back transaction:", err) + } + }() var maxInvites, inviteCount int err = tx.QueryRow(ctx, "SELECT max_invites FROM users WHERE id = $1", userID).Scan(&maxInvites) diff --git a/backend/db/member.go b/backend/db/member.go index 6eb444c..a50c431 100644 --- a/backend/db/member.go +++ b/backend/db/member.go @@ -7,6 +7,7 @@ import ( "time" "codeberg.org/pronounscc/pronouns.cc/backend/common" + "codeberg.org/pronounscc/pronouns.cc/backend/log" "emperror.dev/errors" "github.com/Masterminds/squirrel" "github.com/georgysavva/scany/v2/pgxscan" @@ -287,7 +288,12 @@ func (db *DB) RerollMemberSID(ctx context.Context, userID, memberID xid.ID) (new if err != nil { return "", errors.Wrap(err, "beginning transaction") } - defer tx.Rollback(ctx) + defer func() { + err := tx.Rollback(ctx) + if err != nil && !errors.Is(err, pgx.ErrTxClosed) { + log.Error("rolling back transaction:", err) + } + }() sql, args, err := sq.Update("members"). Set("sid", squirrel.Expr("find_free_member_sid()")). diff --git a/backend/main.go b/backend/main.go index d9efd98..c17679e 100644 --- a/backend/main.go +++ b/backend/main.go @@ -26,7 +26,8 @@ var Command = &cli.Command{ func run(c *cli.Context) error { // initialize sentry if dsn := os.Getenv("SENTRY_DSN"); dsn != "" { - sentry.Init(sentry.ClientOptions{ + // We don't need to check the error here--it's fine if no DSN is set. + _ = sentry.Init(sentry.ClientOptions{ Dsn: dsn, Debug: os.Getenv("DEBUG") == "true", Release: server.Tag, diff --git a/backend/routes/v1/auth/discord.go b/backend/routes/v1/auth/discord.go index c725a2b..f814cd9 100644 --- a/backend/routes/v1/auth/discord.go +++ b/backend/routes/v1/auth/discord.go @@ -12,6 +12,7 @@ import ( "emperror.dev/errors" "github.com/bwmarrin/discordgo" "github.com/go-chi/render" + "github.com/jackc/pgx/v5" "github.com/mediocregopher/radix/v4" "github.com/rs/xid" "golang.org/x/oauth2" @@ -292,7 +293,12 @@ func (s *Server) discordSignup(w http.ResponseWriter, r *http.Request) error { if err != nil { return errors.Wrap(err, "beginning transaction") } - defer tx.Rollback(ctx) + defer func() { + err := tx.Rollback(ctx) + if err != nil && !errors.Is(err, pgx.ErrTxClosed) { + log.Error("rolling back transaction:", err) + } + }() du := new(discordgo.User) err = s.DB.GetJSON(ctx, "discord:"+req.Ticket, &du) diff --git a/backend/routes/v1/auth/fedi_mastodon.go b/backend/routes/v1/auth/fedi_mastodon.go index e86827f..f7fd0f2 100644 --- a/backend/routes/v1/auth/fedi_mastodon.go +++ b/backend/routes/v1/auth/fedi_mastodon.go @@ -12,6 +12,7 @@ import ( "codeberg.org/pronounscc/pronouns.cc/backend/server" "emperror.dev/errors" "github.com/go-chi/render" + "github.com/jackc/pgx/v5" "github.com/mediocregopher/radix/v4" "github.com/rs/xid" ) @@ -320,7 +321,12 @@ func (s *Server) mastodonSignup(w http.ResponseWriter, r *http.Request) error { if err != nil { return errors.Wrap(err, "beginning transaction") } - defer tx.Rollback(ctx) + defer func() { + err := tx.Rollback(ctx) + if err != nil && !errors.Is(err, pgx.ErrTxClosed) { + log.Error("rolling back transaction:", err) + } + }() mu := new(partialMastodonAccount) err = s.DB.GetJSON(ctx, "mastodon:"+req.Ticket, &mu) diff --git a/backend/routes/v1/auth/fedi_misskey.go b/backend/routes/v1/auth/fedi_misskey.go index 36637e6..5e12ca9 100644 --- a/backend/routes/v1/auth/fedi_misskey.go +++ b/backend/routes/v1/auth/fedi_misskey.go @@ -13,6 +13,7 @@ import ( "codeberg.org/pronounscc/pronouns.cc/backend/server" "emperror.dev/errors" "github.com/go-chi/render" + "github.com/jackc/pgx/v5" "github.com/mediocregopher/radix/v4" "github.com/rs/xid" ) @@ -248,7 +249,12 @@ func (s *Server) misskeySignup(w http.ResponseWriter, r *http.Request) error { if err != nil { return errors.Wrap(err, "beginning transaction") } - defer tx.Rollback(ctx) + defer func() { + err := tx.Rollback(ctx) + if err != nil && !errors.Is(err, pgx.ErrTxClosed) { + log.Error("rolling back transaction:", err) + } + }() mu := new(partialMisskeyAccount) err = s.DB.GetJSON(ctx, "misskey:"+req.Ticket, &mu) diff --git a/backend/routes/v1/auth/google.go b/backend/routes/v1/auth/google.go index f0a680b..0ef113f 100644 --- a/backend/routes/v1/auth/google.go +++ b/backend/routes/v1/auth/google.go @@ -11,6 +11,7 @@ import ( "codeberg.org/pronounscc/pronouns.cc/backend/server" "emperror.dev/errors" "github.com/go-chi/render" + "github.com/jackc/pgx/v5" "github.com/mediocregopher/radix/v4" "github.com/rs/xid" "golang.org/x/oauth2" @@ -295,7 +296,12 @@ func (s *Server) googleSignup(w http.ResponseWriter, r *http.Request) error { if err != nil { return errors.Wrap(err, "beginning transaction") } - defer tx.Rollback(ctx) + defer func() { + err := tx.Rollback(ctx) + if err != nil && !errors.Is(err, pgx.ErrTxClosed) { + log.Error("rolling back transaction:", err) + } + }() gu := new(partialGoogleUser) err = s.DB.GetJSON(ctx, "google:"+req.Ticket, &gu) diff --git a/backend/routes/v1/auth/routes.go b/backend/routes/v1/auth/routes.go index 103d43e..2e1a724 100644 --- a/backend/routes/v1/auth/routes.go +++ b/backend/routes/v1/auth/routes.go @@ -185,7 +185,7 @@ func (s *Server) oauthURLs(w http.ResponseWriter, r *http.Request) error { if googleOAuthConfig.ClientID != "" { googleCfg := googleOAuthConfig googleCfg.RedirectURL = req.CallbackDomain + "/auth/login/google" - resp.Google = googleCfg.AuthCodeURL(state) + resp.Google = googleCfg.AuthCodeURL(state) + "&prompt=select_account" } render.JSON(w, r, resp) diff --git a/backend/routes/v1/auth/tokens.go b/backend/routes/v1/auth/tokens.go index e48662d..0f8b8b8 100644 --- a/backend/routes/v1/auth/tokens.go +++ b/backend/routes/v1/auth/tokens.go @@ -5,9 +5,11 @@ import ( "time" "codeberg.org/pronounscc/pronouns.cc/backend/db" + "codeberg.org/pronounscc/pronouns.cc/backend/log" "codeberg.org/pronounscc/pronouns.cc/backend/server" "emperror.dev/errors" "github.com/go-chi/render" + "github.com/jackc/pgx/v5" "github.com/rs/xid" ) @@ -63,7 +65,12 @@ func (s *Server) deleteToken(w http.ResponseWriter, r *http.Request) error { if err != nil { return errors.Wrap(err, "beginning transaction") } - defer tx.Rollback(ctx) + defer func() { + err := tx.Rollback(ctx) + if err != nil && !errors.Is(err, pgx.ErrTxClosed) { + log.Error("rolling back transaction:", err) + } + }() err = s.DB.InvalidateAllTokens(ctx, tx, claims.UserID) if err != nil { diff --git a/backend/routes/v1/auth/tumblr.go b/backend/routes/v1/auth/tumblr.go index 6b81013..30edcd5 100644 --- a/backend/routes/v1/auth/tumblr.go +++ b/backend/routes/v1/auth/tumblr.go @@ -13,6 +13,7 @@ import ( "codeberg.org/pronounscc/pronouns.cc/backend/server" "emperror.dev/errors" "github.com/go-chi/render" + "github.com/jackc/pgx/v5" "github.com/mediocregopher/radix/v4" "github.com/rs/xid" "golang.org/x/oauth2" @@ -328,7 +329,12 @@ func (s *Server) tumblrSignup(w http.ResponseWriter, r *http.Request) error { if err != nil { return errors.Wrap(err, "beginning transaction") } - defer tx.Rollback(ctx) + defer func() { + err := tx.Rollback(ctx) + if err != nil && !errors.Is(err, pgx.ErrTxClosed) { + log.Error("rolling back transaction:", err) + } + }() tui := new(tumblrUserInfo) err = s.DB.GetJSON(ctx, "tumblr:"+req.Ticket, &tui) diff --git a/backend/routes/v1/member/create_member.go b/backend/routes/v1/member/create_member.go index c94915a..288aafc 100644 --- a/backend/routes/v1/member/create_member.go +++ b/backend/routes/v1/member/create_member.go @@ -11,6 +11,7 @@ import ( "codeberg.org/pronounscc/pronouns.cc/backend/server" "emperror.dev/errors" "github.com/go-chi/render" + "github.com/jackc/pgx/v5" ) type CreateMemberRequest struct { @@ -119,7 +120,12 @@ func (s *Server) createMember(w http.ResponseWriter, r *http.Request) (err error if err != nil { return errors.Wrap(err, "starting transaction") } - defer tx.Rollback(ctx) + defer func() { + err := tx.Rollback(ctx) + if err != nil && !errors.Is(err, pgx.ErrTxClosed) { + log.Error("rolling back transaction:", err) + } + }() m, err := s.DB.CreateMember(ctx, tx, claims.UserID, cmr.Name, cmr.DisplayName, cmr.Bio, cmr.Links) if err != nil { diff --git a/backend/routes/v1/member/patch_member.go b/backend/routes/v1/member/patch_member.go index f8cee31..c26cf37 100644 --- a/backend/routes/v1/member/patch_member.go +++ b/backend/routes/v1/member/patch_member.go @@ -13,6 +13,7 @@ import ( "emperror.dev/errors" "github.com/go-chi/chi/v5" "github.com/go-chi/render" + "github.com/jackc/pgx/v5" "github.com/rs/xid" ) @@ -246,7 +247,12 @@ func (s *Server) patchMember(w http.ResponseWriter, r *http.Request) error { log.Errorf("creating transaction: %v", err) return errors.Wrap(err, "creating transaction") } - defer tx.Rollback(ctx) + defer func() { + err := tx.Rollback(ctx) + if err != nil && !errors.Is(err, pgx.ErrTxClosed) { + log.Error("rolling back transaction:", err) + } + }() m, err = s.DB.UpdateMember(ctx, tx, m.ID, req.Name, req.DisplayName, req.Bio, req.Unlisted, req.Links, avatarHash) if err != nil { diff --git a/backend/routes/v1/mod/resolve_report.go b/backend/routes/v1/mod/resolve_report.go index 77e4b8d..c36cb86 100644 --- a/backend/routes/v1/mod/resolve_report.go +++ b/backend/routes/v1/mod/resolve_report.go @@ -10,6 +10,7 @@ import ( "emperror.dev/errors" "github.com/go-chi/chi/v5" "github.com/go-chi/render" + "github.com/jackc/pgx/v5" ) type resolveReportRequest struct { @@ -43,7 +44,12 @@ func (s *Server) resolveReport(w http.ResponseWriter, r *http.Request) error { log.Errorf("creating transaction: %v", err) return errors.Wrap(err, "creating transaction") } - defer tx.Rollback(ctx) + defer func() { + err := tx.Rollback(ctx) + if err != nil && !errors.Is(err, pgx.ErrTxClosed) { + log.Error("rolling back transaction:", err) + } + }() report, err := s.DB.Report(ctx, tx, id) if err != nil { diff --git a/backend/routes/v1/user/delete_user.go b/backend/routes/v1/user/delete_user.go index 1523978..1132f05 100644 --- a/backend/routes/v1/user/delete_user.go +++ b/backend/routes/v1/user/delete_user.go @@ -3,9 +3,11 @@ package user import ( "net/http" + "codeberg.org/pronounscc/pronouns.cc/backend/log" "codeberg.org/pronounscc/pronouns.cc/backend/server" "emperror.dev/errors" "github.com/go-chi/render" + "github.com/jackc/pgx/v5" ) func (s *Server) deleteUser(w http.ResponseWriter, r *http.Request) error { @@ -20,7 +22,12 @@ func (s *Server) deleteUser(w http.ResponseWriter, r *http.Request) error { if err != nil { return errors.Wrap(err, "creating transaction") } - defer tx.Rollback(ctx) + defer func() { + err := tx.Rollback(ctx) + if err != nil && !errors.Is(err, pgx.ErrTxClosed) { + log.Error("rolling back transaction:", err) + } + }() err = s.DB.DeleteUser(ctx, tx, claims.UserID, true, "") if err != nil { diff --git a/backend/routes/v1/user/flags.go b/backend/routes/v1/user/flags.go index b9c3ced..c7b6ad7 100644 --- a/backend/routes/v1/user/flags.go +++ b/backend/routes/v1/user/flags.go @@ -13,6 +13,7 @@ import ( "emperror.dev/errors" "github.com/go-chi/chi/v5" "github.com/go-chi/render" + "github.com/jackc/pgx/v5" "github.com/rs/xid" ) @@ -80,7 +81,12 @@ func (s *Server) postUserFlag(w http.ResponseWriter, r *http.Request) error { if err != nil { return errors.Wrap(err, "starting transaction") } - defer tx.Rollback(ctx) + defer func() { + err := tx.Rollback(ctx) + if err != nil && !errors.Is(err, pgx.ErrTxClosed) { + log.Error("rolling back transaction:", err) + } + }() flag, err := s.DB.CreateFlag(ctx, tx, claims.UserID, req.Name, req.Description) if err != nil { @@ -192,7 +198,12 @@ func (s *Server) patchUserFlag(w http.ResponseWriter, r *http.Request) error { if err != nil { return errors.Wrap(err, "beginning transaction") } - defer tx.Rollback(ctx) + defer func() { + err := tx.Rollback(ctx) + if err != nil && !errors.Is(err, pgx.ErrTxClosed) { + log.Error("rolling back transaction:", err) + } + }() flag, err = s.DB.EditFlag(ctx, tx, flag.ID, req.Name, req.Description, nil) if err != nil { diff --git a/backend/routes/v1/user/patch_user.go b/backend/routes/v1/user/patch_user.go index ca489ce..6e4f6ab 100644 --- a/backend/routes/v1/user/patch_user.go +++ b/backend/routes/v1/user/patch_user.go @@ -12,6 +12,7 @@ import ( "emperror.dev/errors" "github.com/go-chi/render" "github.com/google/uuid" + "github.com/jackc/pgx/v5" "github.com/rs/xid" ) @@ -221,7 +222,12 @@ func (s *Server) patchUser(w http.ResponseWriter, r *http.Request) error { log.Errorf("creating transaction: %v", err) return errors.Wrap(err, "creating transaction") } - defer tx.Rollback(ctx) + defer func() { + err := tx.Rollback(ctx) + if err != nil && !errors.Is(err, pgx.ErrTxClosed) { + log.Error("rolling back transaction:", err) + } + }() // update username if req.Username != nil && *req.Username != u.Username { diff --git a/backend/server/server.go b/backend/server/server.go index bfc785d..30cd552 100644 --- a/backend/server/server.go +++ b/backend/server/server.go @@ -100,23 +100,23 @@ func New() (*Server, error) { // set scopes // users - rateLimiter.Scope("GET", "/users/*", 60) - rateLimiter.Scope("PATCH", "/users/@me", 10) + _ = rateLimiter.Scope("GET", "/users/*", 60) + _ = rateLimiter.Scope("PATCH", "/users/@me", 10) // members - rateLimiter.Scope("GET", "/users/*/members", 60) - rateLimiter.Scope("GET", "/users/*/members/*", 60) + _ = rateLimiter.Scope("GET", "/users/*/members", 60) + _ = rateLimiter.Scope("GET", "/users/*/members/*", 60) - rateLimiter.Scope("POST", "/members", 10) - rateLimiter.Scope("GET", "/members/*", 60) - rateLimiter.Scope("PATCH", "/members/*", 20) - rateLimiter.Scope("DELETE", "/members/*", 5) + _ = rateLimiter.Scope("POST", "/members", 10) + _ = rateLimiter.Scope("GET", "/members/*", 60) + _ = rateLimiter.Scope("PATCH", "/members/*", 20) + _ = rateLimiter.Scope("DELETE", "/members/*", 5) // auth - rateLimiter.Scope("*", "/auth/*", 20) - rateLimiter.Scope("*", "/auth/tokens", 10) - rateLimiter.Scope("*", "/auth/invites", 10) - rateLimiter.Scope("POST", "/auth/discord/*", 10) + _ = rateLimiter.Scope("*", "/auth/*", 20) + _ = rateLimiter.Scope("*", "/auth/tokens", 10) + _ = rateLimiter.Scope("*", "/auth/invites", 10) + _ = rateLimiter.Scope("POST", "/auth/discord/*", 10) s.Router.Use(rateLimiter.Handler()) diff --git a/frontend/.eslintrc.cjs b/frontend/.eslintrc.cjs index 09dcc6a..4b0d793 100644 --- a/frontend/.eslintrc.cjs +++ b/frontend/.eslintrc.cjs @@ -17,4 +17,15 @@ module.exports = { es2017: true, node: true, }, + rules: { + "no-unused-vars": "off", + "@typescript-eslint/no-unused-vars": [ + "error", + { + argsIgnorePattern: "^_", + destructuredArrayIgnorePattern: "^_", + varsIgnorePattern: "^_", + }, + ], + }, }; diff --git a/frontend/package.json b/frontend/package.json index a460457..1628226 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -12,11 +12,13 @@ "format": "prettier --plugin-search-dir . --write ." }, "devDependencies": { - "@sveltejs/adapter-auto": "^2.0.0", - "@sveltejs/adapter-node": "^1.2.3", - "@sveltejs/kit": "^1.15.0", - "@types/luxon": "^3.2.2", - "@types/markdown-it": "^12.2.3", + "@sveltejs/adapter-auto": "^3.0.0", + "@sveltejs/adapter-node": "^2.0.0", + "@sveltejs/kit": "^2.0.0", + "@sveltejs/vite-plugin-svelte": "^3.0.0", + "@sveltestrap/sveltestrap": "^6.0.5", + "@types/luxon": "^3.3.7", + "@types/markdown-it": "^13.0.7", "@types/node": "^18.15.11", "@types/sanitize-html": "^2.9.0", "@typescript-eslint/eslint-plugin": "^5.57.1", @@ -25,14 +27,13 @@ "eslint-config-prettier": "^8.8.0", "eslint-plugin-svelte3": "^4.0.0", "prettier": "^2.8.7", - "prettier-plugin-svelte": "^2.10.0", - "svelte": "^3.58.0", - "svelte-check": "^3.1.4", + "prettier-plugin-svelte": "^2.10.1", + "svelte": "^4.0.0", + "svelte-check": "^3.4.3", "svelte-hcaptcha": "^0.1.1", - "sveltestrap": "^5.10.0", "tslib": "^2.5.0", - "typescript": "^4.9.5", - "vite": "^4.2.1", + "typescript": "^5.0.0", + "vite": "^5.0.0", "vite-plugin-markdown": "^2.1.0" }, "type": "module", @@ -41,8 +42,8 @@ "@popperjs/core": "^2.11.7", "@sentry/node": "^7.46.0", "base64-arraybuffer": "^1.0.2", - "bootstrap": "5.3.0-alpha1", - "bootstrap-icons": "^1.10.4", + "bootstrap": "^5.3.2", + "bootstrap-icons": "^1.11.2", "jose": "^4.13.1", "luxon": "^3.3.0", "markdown-it": "^13.0.1", diff --git a/frontend/src/app.d.ts b/frontend/src/app.d.ts index d4759fd..9489da5 100644 --- a/frontend/src/app.d.ts +++ b/frontend/src/app.d.ts @@ -16,23 +16,4 @@ declare global { } } -declare module "svelte-hcaptcha" { - import type { SvelteComponent } from "svelte"; - - export interface HCaptchaProps { - sitekey?: string; - apihost?: string; - hl?: string; - reCaptchaCompat?: boolean; - theme?: CaptchaTheme; - size?: string; - } - - declare class HCaptcha extends SvelteComponent { - $$prop_def: HCaptchaProps; - } - - export default HCaptcha; -} - export {}; diff --git a/frontend/src/hooks.server.ts b/frontend/src/hooks.server.ts index e073554..670f914 100644 --- a/frontend/src/hooks.server.ts +++ b/frontend/src/hooks.server.ts @@ -2,7 +2,9 @@ import { PRIVATE_SENTRY_DSN } from "$env/static/private"; import * as Sentry from "@sentry/node"; import type { HandleServerError } from "@sveltejs/kit"; -Sentry.init({ dsn: PRIVATE_SENTRY_DSN }); +if (PRIVATE_SENTRY_DSN) { + Sentry.init({ dsn: PRIVATE_SENTRY_DSN }); +} export const handleError = (({ error, event }) => { console.log(error); diff --git a/frontend/src/lib/api/entities.ts b/frontend/src/lib/api/entities.ts index e245522..5aa5b2a 100644 --- a/frontend/src/lib/api/entities.ts +++ b/frontend/src/lib/api/entities.ts @@ -1,3 +1,4 @@ +/* eslint-disable no-unused-vars */ import { PUBLIC_BASE_URL, PUBLIC_MEDIA_URL } from "$env/static/public"; export const MAX_MEMBERS = 500; diff --git a/frontend/src/lib/components/ActiveLink.svelte b/frontend/src/lib/components/ActiveLink.svelte index d9bc887..969cfbd 100644 --- a/frontend/src/lib/components/ActiveLink.svelte +++ b/frontend/src/lib/components/ActiveLink.svelte @@ -1,5 +1,5 @@ diff --git a/frontend/src/lib/components/IconButton.svelte b/frontend/src/lib/components/IconButton.svelte index c131a4d..240339a 100644 --- a/frontend/src/lib/components/IconButton.svelte +++ b/frontend/src/lib/components/IconButton.svelte @@ -1,5 +1,5 @@ diff --git a/frontend/src/routes/@[username]/+page.server.ts b/frontend/src/routes/@[username]/+page.server.ts index 447c5e3..0ae4617 100644 --- a/frontend/src/routes/@[username]/+page.server.ts +++ b/frontend/src/routes/@[username]/+page.server.ts @@ -11,7 +11,7 @@ export const load = async ({ params }) => { return resp; } catch (e) { if ((e as APIError).code === ErrorCode.UserNotFound) { - throw error(404, e as APIError); + error(404, e as App.Error); } throw e; diff --git a/frontend/src/routes/@[username]/+page.svelte b/frontend/src/routes/@[username]/+page.svelte index 56542fc..a9fd5b4 100644 --- a/frontend/src/routes/@[username]/+page.svelte +++ b/frontend/src/routes/@[username]/+page.svelte @@ -4,7 +4,6 @@ import { Alert, - Badge, Button, ButtonGroup, Icon, @@ -14,8 +13,8 @@ ModalBody, ModalFooter, Tooltip, - } from "sveltestrap"; - import { DateTime, Duration, FixedOffsetZone, Zone } from "luxon"; + } from "@sveltestrap/sveltestrap"; + import { DateTime, FixedOffsetZone } from "luxon"; import FieldCard from "$lib/components/FieldCard.svelte"; import PronounLink from "$lib/components/PronounLink.svelte"; import PartialMemberCard from "$lib/components/PartialMemberCard.svelte"; @@ -46,6 +45,7 @@ import ProfileFlag from "./ProfileFlag.svelte"; import IconButton from "$lib/components/IconButton.svelte"; import Badges from "./badges/Badges.svelte"; + import PreferencesCheatsheet from "./PreferencesCheatsheet.svelte"; export let data: PageData; @@ -190,14 +190,15 @@ {/if} {#if data.utc_offset} Current time - {currentTime} (UTC{timezone}) + + {currentTime} (UTC{timezone}) {/if} {#if profileEmpty && $userStore?.id === data.id}

- Your profile is empty! You can customize it by going to the edit profileedit profile page. (only you can see this)

@@ -258,6 +259,12 @@ {/each} +
diff --git a/frontend/src/routes/@[username]/PreferencesCheatsheet.svelte b/frontend/src/routes/@[username]/PreferencesCheatsheet.svelte new file mode 100644 index 0000000..ef06482 --- /dev/null +++ b/frontend/src/routes/@[username]/PreferencesCheatsheet.svelte @@ -0,0 +1,65 @@ + + +
+
    + {#each usedDefaultPreferences as pref (pref.id)} +
  • + + {pref.preference.tooltip} +
  • + {/each} +
+ {#if usedCustomPreferences} +
    + {#each usedCustomPreferences as pref (pref.id)} +
  • + + {pref.preference.tooltip} +
  • + {/each} +
+ {/if} +
diff --git a/frontend/src/routes/@[username]/ProfileFlag.svelte b/frontend/src/routes/@[username]/ProfileFlag.svelte index 3ef4c63..6862770 100644 --- a/frontend/src/routes/@[username]/ProfileFlag.svelte +++ b/frontend/src/routes/@[username]/ProfileFlag.svelte @@ -1,6 +1,6 @@ diff --git a/frontend/src/routes/@[username]/[memberName]/edit/fields/+page.svelte b/frontend/src/routes/@[username]/[memberName]/edit/fields/+page.svelte index a77b13a..5cf0b62 100644 --- a/frontend/src/routes/@[username]/[memberName]/edit/fields/+page.svelte +++ b/frontend/src/routes/@[username]/[memberName]/edit/fields/+page.svelte @@ -1,7 +1,7 @@ diff --git a/frontend/src/routes/@[username]/edit/+layout.svelte b/frontend/src/routes/@[username]/edit/+layout.svelte index 6bcb23b..de6dbf3 100644 --- a/frontend/src/routes/@[username]/edit/+layout.svelte +++ b/frontend/src/routes/@[username]/edit/+layout.svelte @@ -2,7 +2,7 @@ import { setContext } from "svelte"; import { writable } from "svelte/store"; import type { LayoutData } from "./$types"; - import { Button, ButtonGroup, Icon, Nav, NavItem } from "sveltestrap"; + import { Button, ButtonGroup, Icon, Nav, NavItem } from "@sveltestrap/sveltestrap"; import type { MeUser, APIError } from "$lib/api/entities"; import ErrorAlert from "$lib/components/ErrorAlert.svelte"; import { addToast, delToast } from "$lib/toast"; diff --git a/frontend/src/routes/@[username]/edit/+layout.ts b/frontend/src/routes/@[username]/edit/+layout.ts index 2fd9c4c..950d945 100644 --- a/frontend/src/routes/@[username]/edit/+layout.ts +++ b/frontend/src/routes/@[username]/edit/+layout.ts @@ -1,6 +1,6 @@ -import type { PrideFlag, APIError, MeUser, PronounsJson } from "$lib/api/entities"; +import type { PrideFlag, MeUser, PronounsJson } from "$lib/api/entities"; import { apiFetchClient } from "$lib/api/fetch"; -import { error, redirect, type Redirect } from "@sveltejs/kit"; +import { error, redirect } from "@sveltejs/kit"; import pronounsRaw from "$lib/pronouns.json"; const pronouns = pronounsRaw as PronounsJson; @@ -13,7 +13,7 @@ export const load = async ({ params }) => { const flags = await apiFetchClient("/users/@me/flags"); if (params.username !== user.name) { - throw redirect(303, `/@${user.name}/edit`); + redirect(303, `/@${user.name}/edit`); } return { @@ -21,8 +21,9 @@ export const load = async ({ params }) => { pronouns: pronouns.autocomplete, flags, }; - } catch (e) { - if ("code" in e) throw error(500, e as APIError); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + } catch (e: any) { + if ("code" in e) error(500, e as App.Error); throw e; } }; diff --git a/frontend/src/routes/@[username]/edit/+page.svelte b/frontend/src/routes/@[username]/edit/+page.svelte index e727633..d5c2aeb 100644 --- a/frontend/src/routes/@[username]/edit/+page.svelte +++ b/frontend/src/routes/@[username]/edit/+page.svelte @@ -3,7 +3,7 @@ import type { Writable } from "svelte/store"; import prettyBytes from "pretty-bytes"; import { encode } from "base64-arraybuffer"; - import { FormGroup, Icon, Input } from "sveltestrap"; + import { FormGroup, Icon, Input } from "@sveltestrap/sveltestrap"; import { userAvatars, type MeUser } from "$lib/api/entities"; import FallbackImage from "$lib/components/FallbackImage.svelte"; import EditableName from "$lib/components/edit/EditableName.svelte"; diff --git a/frontend/src/routes/@[username]/edit/bio/+page.svelte b/frontend/src/routes/@[username]/edit/bio/+page.svelte index 2cbbf38..572fa35 100644 --- a/frontend/src/routes/@[username]/edit/bio/+page.svelte +++ b/frontend/src/routes/@[username]/edit/bio/+page.svelte @@ -4,7 +4,7 @@ import { MAX_DESCRIPTION_LENGTH, type MeUser } from "$lib/api/entities"; import { charCount, renderMarkdown } from "$lib/utils"; import MarkdownHelp from "$lib/components/edit/MarkdownHelp.svelte"; - import { Card, CardBody, CardHeader } from "sveltestrap"; + import { Card, CardBody, CardHeader } from "@sveltestrap/sveltestrap"; const user = getContext>("user"); diff --git a/frontend/src/routes/@[username]/edit/fields/+page.svelte b/frontend/src/routes/@[username]/edit/fields/+page.svelte index f09d89d..9ad8d0a 100644 --- a/frontend/src/routes/@[username]/edit/fields/+page.svelte +++ b/frontend/src/routes/@[username]/edit/fields/+page.svelte @@ -1,7 +1,7 @@ diff --git a/frontend/src/routes/page/changelog/+page.svelte b/frontend/src/routes/page/changelog/+page.svelte index 51cc848..bd98e56 100644 --- a/frontend/src/routes/page/changelog/+page.svelte +++ b/frontend/src/routes/page/changelog/+page.svelte @@ -1,5 +1,8 @@ diff --git a/frontend/src/routes/page/terms/+page.svelte b/frontend/src/routes/page/terms/+page.svelte index ea126d0..92044e4 100644 --- a/frontend/src/routes/page/terms/+page.svelte +++ b/frontend/src/routes/page/terms/+page.svelte @@ -1,4 +1,7 @@ diff --git a/frontend/src/routes/pronouns/[...pronouns]/+page.svelte b/frontend/src/routes/pronouns/[...pronouns]/+page.svelte index fd9536f..09a4329 100644 --- a/frontend/src/routes/pronouns/[...pronouns]/+page.svelte +++ b/frontend/src/routes/pronouns/[...pronouns]/+page.svelte @@ -1,6 +1,6 @@ diff --git a/frontend/src/routes/settings/+layout.svelte b/frontend/src/routes/settings/+layout.svelte index fc225ee..1120447 100644 --- a/frontend/src/routes/settings/+layout.svelte +++ b/frontend/src/routes/settings/+layout.svelte @@ -9,7 +9,7 @@ Modal, ModalBody, ModalFooter, - } from "sveltestrap"; + } from "@sveltestrap/sveltestrap"; import { userStore } from "$lib/store"; import { goto } from "$app/navigation"; import { addToast } from "$lib/toast"; diff --git a/frontend/src/routes/settings/+layout.ts b/frontend/src/routes/settings/+layout.ts index 415bf6c..acf0e5e 100644 --- a/frontend/src/routes/settings/+layout.ts +++ b/frontend/src/routes/settings/+layout.ts @@ -40,7 +40,7 @@ export const load = (async ({ parent }) => { }; } catch (e) { if ((e as APIError).code !== ErrorCode.InternalServerError) { - throw redirect(303, "/auth/login"); + redirect(303, "/auth/login"); } throw e; } diff --git a/frontend/src/routes/settings/+page.svelte b/frontend/src/routes/settings/+page.svelte index 92451e1..e2c57db 100644 --- a/frontend/src/routes/settings/+page.svelte +++ b/frontend/src/routes/settings/+page.svelte @@ -23,9 +23,8 @@ ModalFooter, ModalHeader, Table, - } from "sveltestrap"; + } from "@sveltestrap/sveltestrap"; import type { PageData } from "./$types"; - import { onMount } from "svelte"; import { DateTime } from "luxon"; export let data: PageData; diff --git a/frontend/src/routes/settings/auth/+page.svelte b/frontend/src/routes/settings/auth/+page.svelte index 2d03bb5..c55d9bb 100644 --- a/frontend/src/routes/settings/auth/+page.svelte +++ b/frontend/src/routes/settings/auth/+page.svelte @@ -13,7 +13,7 @@ Modal, ModalBody, ModalFooter, - } from "sveltestrap"; + } from "@sveltestrap/sveltestrap"; import type { PageData } from "./$types"; export let data: PageData; diff --git a/frontend/src/routes/settings/export/+page.svelte b/frontend/src/routes/settings/export/+page.svelte index 31f87e7..97733f6 100644 --- a/frontend/src/routes/settings/export/+page.svelte +++ b/frontend/src/routes/settings/export/+page.svelte @@ -1,7 +1,7 @@