~netlandish/links

5a23dcd63e00b8b0f5103e6083f996c64d265831 — Peter Sanchez 5 days ago 437eb31
Udating code to use the gobwebs PlaceholderFormat helpers.
M cmd/admin/main.go => cmd/admin/main.go +2 -0
@@ 6,6 6,7 @@ import (
	"links/cmd"
	"os"

	sq "github.com/Masterminds/squirrel"
	"netlandish.com/x/gobwebs/config"
	"netlandish.com/x/gobwebs/database"
	"netlandish.com/x/gobwebs/timezone"


@@ 21,6 22,7 @@ func main() {
		fmt.Fprintf(os.Stderr, "Error running command setup: %s\n", err)
	}
	defer db.Close()
	database.SetPlaceholderFormat(sq.Dollar)
	ctx := database.Context(context.Background(), db)
	// We need to provide timezone for querying the db
	ctx = timezone.Context(ctx, "UTC")

M cmd/api/main.go => cmd/api/main.go +4 -2
@@ 20,6 20,7 @@ import (

	work "git.sr.ht/~sircmpwn/dowork"
	"github.com/99designs/gqlgen/graphql"
	sq "github.com/Masterminds/squirrel"
	"github.com/labstack/echo/v4"
	"github.com/labstack/echo/v4/middleware"
	gobwebsgql "netlandish.com/x/gobwebs-graphql"


@@ 53,6 54,7 @@ func run() error {
		return fmt.Errorf("Unable to open connection to PostgreSQL: %v", err)
	}
	defer db.Close()
	database.SetPlaceholderFormat(sq.Dollar)

	entropy, ok := config.File.Get("access", "entropy")
	if !ok {


@@ 141,9 143,9 @@ func run() error {
	gqlConfig.Directives.Internal = directives.Internal
	gqlConfig.Directives.Private = directives.Private
	gqlConfig.Directives.Admin = directives.Admin
	gqlConfig.Directives.Access = func(ctx context.Context, obj interface{},
	gqlConfig.Directives.Access = func(ctx context.Context, obj any,
		next graphql.Resolver, scope model.AccessScope,
		kind model.AccessKind) (interface{}, error) {
		kind model.AccessKind) (any, error) {
		return directives.Access(ctx, obj, next, scope.String(), kind.String())
	}
	schema := graph.NewExecutableSchema(gqlConfig)

M cmd/domains/main.go => cmd/domains/main.go +2 -0
@@ 9,6 9,7 @@ import (
	"os"
	"strconv"

	sq "github.com/Masterminds/squirrel"
	"github.com/labstack/echo/v4"
	"netlandish.com/x/gobwebs/config"
	"netlandish.com/x/gobwebs/database"


@@ 49,6 50,7 @@ func run() error {
		return fmt.Errorf("Unable to open connection to PostgreSQL: %v", err)
	}
	defer db.Close()
	database.SetPlaceholderFormat(sq.Dollar)

	e := echo.New()
	e.GET("/_check/domain", func(c echo.Context) error {

M cmd/links/main.go => cmd/links/main.go +2 -0
@@ 31,6 31,7 @@ import (
	"github.com/alexedwards/scs/v2"

	work "git.sr.ht/~sircmpwn/dowork"
	sq "github.com/Masterminds/squirrel"
	"github.com/labstack/echo/v4"
	"github.com/labstack/echo/v4/middleware"
	formguard "netlandish.com/x/gobwebs-formguard"


@@ 135,6 136,7 @@ func run() error {
		return fmt.Errorf("Unable to open connection to PostgreSQL: %v", err)
	}
	defer db.Close()
	database.SetPlaceholderFormat(sq.Dollar)

	esvc, err := cmd.LoadEmailService(config)
	if err != nil {

M cmd/list/main.go => cmd/list/main.go +2 -0
@@ 17,6 17,7 @@ import (
	"time"

	work "git.sr.ht/~sircmpwn/dowork"
	sq "github.com/Masterminds/squirrel"
	"github.com/labstack/echo/v4"
	"netlandish.com/x/gobwebs/config"
	"netlandish.com/x/gobwebs/crypto"


@@ 69,6 70,7 @@ func run() error {
		return fmt.Errorf("Unable to open connection to PostgreSQL: %v", err)
	}
	defer db.Close()
	database.SetPlaceholderFormat(sq.Dollar)

	e := echo.New()
	// https://echo.labstack.com/docs/ip-address

M cmd/short/main.go => cmd/short/main.go +2 -0
@@ 15,6 15,7 @@ import (
	"text/template"

	work "git.sr.ht/~sircmpwn/dowork"
	sq "github.com/Masterminds/squirrel"
	"github.com/labstack/echo/v4"
	"netlandish.com/x/gobwebs/config"
	"netlandish.com/x/gobwebs/crypto"


@@ 67,6 68,7 @@ func run() error {
		return fmt.Errorf("Unable to open connection to PostgreSQL: %v", err)
	}
	defer db.Close()
	database.SetPlaceholderFormat(sq.Dollar)

	e := echo.New()
	// https://echo.labstack.com/docs/ip-address

M cmd/test/helpers.go => cmd/test/helpers.go +2 -0
@@ 27,6 27,7 @@ import (
	"git.sr.ht/~emersion/gqlclient"
	work "git.sr.ht/~sircmpwn/dowork"
	"github.com/99designs/gqlgen/graphql"
	sq "github.com/Masterminds/squirrel"
	"github.com/labstack/echo/v4"
	formguard "netlandish.com/x/gobwebs-formguard"
	gobwebsgql "netlandish.com/x/gobwebs-graphql"


@@ 51,6 52,7 @@ func newTestServer(t *testing.T, name string, config *config.Config) (*server.Se
	if err != nil {
		t.Fatalf("Open() err = %v; want nil", err)
	}
	database.SetPlaceholderFormat(sq.Dollar)
	t.Cleanup(func() {
		err = db.Close()
		if err != nil {

M models/base_url.go => models/base_url.go +4 -4
@@ 71,7 71,7 @@ func GetBaseURLs(ctx context.Context, opts *database.FilterOptions) ([]*BaseURL,
			LeftJoin("tags t ON t.id = tl.tag_id").
			GroupBy("b.id").
			Distinct().
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			QueryContext(ctx)
		if err != nil {


@@ 130,7 130,7 @@ func (b *BaseURL) Load(ctx context.Context) error {
				"parse_attempts", "last_parse_attempt", "created_on").
			From("base_urls").
			Where("id = ?", b.ID).
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			ScanContext(ctx, &b.ID, &b.Title, &b.URL, &b.Counter, &b.Data,
				&b.PublicReady, &b.Hash, &b.ParseAttempts, &b.LastParseAttempt, &b.CreatedOn)


@@ 183,7 183,7 @@ func (b *BaseURL) Store(ctx context.Context) error {
				Set("last_parse_attempt", b.LastParseAttempt).
				Where("id = ?", b.ID).
				Suffix(`RETURNING (updated_on)`).
				PlaceholderFormat(sq.Dollar).
				PlaceholderFormat(database.GetPlaceholderFormat()).
				RunWith(tx).
				ScanContext(ctx, &b.UpdatedOn)
		}


@@ 201,7 201,7 @@ func (b *BaseURL) Delete(ctx context.Context) error {
		_, err := sq.
			Delete("base_urls").
			Where("id = ?", b.ID).
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			ExecContext(ctx)
		return err

M models/confirmation.go => models/confirmation.go +1 -2
@@ 4,7 4,6 @@ import (
	"context"
	"database/sql"

	sq "github.com/Masterminds/squirrel"
	"netlandish.com/x/gobwebs/accounts"
	"netlandish.com/x/gobwebs/database"
)


@@ 22,7 21,7 @@ func GetConfirmations(ctx context.Context, opts *database.FilterOptions) ([]*acc
				"expire_time", "created_on", "updated_on").
			From("confirmations").
			Distinct().
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			QueryContext(ctx)
		if err != nil {

M models/daily_totals.go => models/daily_totals.go +4 -4
@@ 24,7 24,7 @@ func GetDailyTotals(ctx context.Context, opts *database.FilterOptions) ([]*Daily
				"dt.list_id", "dt.qr_id").
			From("daily_totals dt").
			Distinct().
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			QueryContext(ctx)
		if err != nil {


@@ 73,7 73,7 @@ func (d *DailyTotal) Load(ctx context.Context) error {
				"list_id", "qr_id").
			From("daily_totals").
			Where("id = ?", d.ID).
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			ScanContext(ctx, &d.ID, &d.Clicks, &d.UniqueClicks, &d.Date, &d.ListingLinkID,
				&d.LinkShortID, &d.ListID, &d.QRID)


@@ 101,7 101,7 @@ func (d *DailyTotal) Store(ctx context.Context) error {
			Columns("listing_link_id", "link_short_id", "list_id", "qr_id").
			Values(d.ListingLinkID, d.LinkShortID, d.ListID, d.QRID).
			Suffix(`RETURNING id, date`).
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			ScanContext(ctx, &d.ID, &d.Date)
	})


@@ 149,7 149,7 @@ func (d *DailyTotal) Delete(ctx context.Context) error {
		_, err := sq.
			Delete("daily_totals").
			Where("id = ?", d.ID).
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			ExecContext(ctx)
		return err

M models/domains.go => models/domains.go +6 -6
@@ 54,7 54,7 @@ func GetDomains(ctx context.Context, opts *database.FilterOptions) ([]*Domain, e
			From("domains d").
			LeftJoin("organizations o ON o.id = d.org_id").
			Distinct().
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			QueryContext(ctx)
		if err != nil {


@@ 105,7 105,7 @@ func (d *Domain) Load(ctx context.Context) error {
			From("domains d").
			Join("organizations o ON o.id = org_id").
			Where("id = ?", d.ID).
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			ScanContext(ctx, &d.Name, &d.OrgID, &d.Level, &d.Service, &d.Status,
				&d.IsActive, &d.LastAction, &d.CreatedOn, &d.UpdatedOn, &d.OrgSlug,


@@ 149,7 149,7 @@ func (d *Domain) Store(ctx context.Context) error {
				Columns("name", "lookup_name", "org_id", "level", "service", "status", "is_active").
				Values(d.Name, d.LookupName, d.OrgID, d.Level, d.Service, d.Status, d.IsActive).
				Suffix(`RETURNING id, created_on, updated_on`).
				PlaceholderFormat(sq.Dollar).
				PlaceholderFormat(database.GetPlaceholderFormat()).
				RunWith(tx).
				ScanContext(ctx, &d.ID, &d.CreatedOn, &d.UpdatedOn)
		} else {


@@ 165,7 165,7 @@ func (d *Domain) Store(ctx context.Context) error {
				Set("is_active", d.IsActive).
				Where("id = ?", d.ID).
				Suffix(`RETURNING (updated_on)`).
				PlaceholderFormat(sq.Dollar).
				PlaceholderFormat(database.GetPlaceholderFormat()).
				RunWith(tx).
				ScanContext(ctx, &d.UpdatedOn)
		}


@@ 194,7 194,7 @@ func (d *Domain) Delete(ctx context.Context) error {
		_, err := sq.
			Delete("domains").
			Where("id = ?", d.ID).
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			ExecContext(ctx)
		return err


@@ 228,7 228,7 @@ func ToggleDomainBatch(ctx context.Context, opts *database.FilterOptions, flag b
			Update("domains").
			Set("is_active", flag).
			Where(opts.Filter).
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			ExecContext(ctx)
		return err

M models/followers.go => models/followers.go +4 -4
@@ 23,7 23,7 @@ func GetFollowers(ctx context.Context, opts *database.FilterOptions) ([]*Followe
			Columns("f.id", "f.user_id", "f.org_id", "f.created_on").
			From("followers AS f").
			Distinct().
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			QueryContext(ctx)
		if err != nil {


@@ 70,7 70,7 @@ func (f *Follower) Load(ctx context.Context) error {
			Select("id", "user_id", "org_id", "created_on").
			From("followers").
			Where("id = ?", f.ID).
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			ScanContext(ctx, &f.ID, &f.UserID, &f.OrgID, &f.CreatedOn)



@@ 96,7 96,7 @@ func (f *Follower) Store(ctx context.Context) error {
				Columns("user_id", "org_id").
				Values(f.UserID, f.OrgID).
				Suffix(`RETURNING id, created_on`).
				PlaceholderFormat(sq.Dollar).
				PlaceholderFormat(database.GetPlaceholderFormat()).
				RunWith(tx).
				ScanContext(ctx, &f.ID, &f.CreatedOn)
		} else {


@@ 126,7 126,7 @@ func (f *Follower) Delete(ctx context.Context) error {
		_, err := sq.
			Delete("followers").
			Where("id = ?", f.ID).
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			ExecContext(ctx)
		return err

M models/invoice.go => models/invoice.go +6 -6
@@ 33,7 33,7 @@ func GetInvoices(ctx context.Context, opts *database.FilterOptions) ([]*Invoice,
				"i.updated_on", "o.slug").
			From("invoices i").
			Join("organizations o ON o.id = i.org_id").
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			QueryContext(ctx)
		if err != nil {


@@ 84,7 84,7 @@ func (i *Invoice) Load(ctx context.Context) error {
				"amount_paid", "amount_net", "amount_refunded", "payment_fee", "hosted_invoice_url", "created_on", "updated_on").
			From("invoices").
			Where(wq).
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			ScanContext(ctx,
				&i.UserID,


@@ 129,7 129,7 @@ func (i *Invoice) Store(ctx context.Context) error {
				Values(i.Status, i.UserID, i.OrgID, i.StripeID, i.SubscriptionID, i.Currency, i.Amount, i.AmountPaid,
					i.AmountNet, i.AmountRefunded, i.PaymentFee, i.HostedInvoiceURL).
				Suffix(`RETURNING id, created_on, updated_on`).
				PlaceholderFormat(sq.Dollar).
				PlaceholderFormat(database.GetPlaceholderFormat()).
				RunWith(tx).
				ScanContext(ctx, &i.ID, &i.CreatedOn, &i.UpdatedOn)
		} else {


@@ 148,7 148,7 @@ func (i *Invoice) Store(ctx context.Context) error {
				Set("payment_fee", i.PaymentFee).
				Where("id = ?", i.ID).
				Suffix("RETURNING (updated_on)").
				PlaceholderFormat(sq.Dollar).
				PlaceholderFormat(database.GetPlaceholderFormat()).
				RunWith(tx).
				ScanContext(ctx, &i.UpdatedOn)
		}


@@ 166,7 166,7 @@ func (i *Invoice) Delete(ctx context.Context) error {
		_, err := sq.
			Delete("invoices").
			Where("id = ?", i.ID).
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			ExecContext(ctx)
		return err


@@ 197,7 197,7 @@ func GetInvoicesTotal(ctx context.Context, opts *database.FilterOptions) (map[st
				"COALESCE(SUM(i.amount_net), 0)", "COALESCE(SUM(i.amount_refunded), 0)").
			From("invoices i").
			Join("organizations o ON o.id = i.org_id").
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			QueryContext(ctx)
		if err != nil {

M models/link_short.go => models/link_short.go +9 -9
@@ 30,7 30,7 @@ func GetLinkShorts(ctx context.Context, opts *database.FilterOptions) ([]*LinkSh
			LeftJoin("tags t ON t.id = tl.tag_id").
			GroupBy("l.id, d.lookup_name").
			Distinct().
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			QueryContext(ctx)
		if err != nil {


@@ 88,7 88,7 @@ func (l *LinkShort) Load(ctx context.Context) error {
				"user_id", "created_on", "updated_on").
			From("link_shorts").
			Where("id = ?", l.ID).
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			ScanContext(ctx, &l.ID, &l.Title, &l.URL, &l.ShortCode, &l.DomainID,
				&l.OrgID, &l.UserID, &l.CreatedOn, &l.UpdatedOn)


@@ 122,7 122,7 @@ func (l *LinkShort) Store(ctx context.Context) error {
				Columns("title", "url", "short_code", "domain_id", "org_id", "user_id").
				Values(&l.Title, &l.URL, &l.ShortCode, &l.DomainID, &l.OrgID, &l.UserID).
				Suffix(`RETURNING id, created_on, updated_on`).
				PlaceholderFormat(sq.Dollar).
				PlaceholderFormat(database.GetPlaceholderFormat()).
				RunWith(tx).
				ScanContext(ctx, &l.ID, &l.CreatedOn, &l.UpdatedOn)
		} else {


@@ 136,7 136,7 @@ func (l *LinkShort) Store(ctx context.Context) error {
				Set("user_id", l.UserID).
				Where("id = ?", l.ID).
				Suffix(`RETURNING (updated_on)`).
				PlaceholderFormat(sq.Dollar).
				PlaceholderFormat(database.GetPlaceholderFormat()).
				RunWith(tx).
				ScanContext(ctx, &l.UpdatedOn)
		}


@@ 165,7 165,7 @@ func (l *LinkShort) Delete(ctx context.Context) error {
		_, err := sq.
			Delete("link_shorts").
			Where("id = ?", l.ID).
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			ExecContext(ctx)
		return err


@@ 180,7 180,7 @@ func MigrateLinkShorts(ctx context.Context, domainID, orgID int) error {
			Update("link_shorts").
			Set("domain_id", domainID).
			Where("org_id = ?", orgID).
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			ExecContext(ctx)
		return err


@@ 202,7 202,7 @@ func GetLinkShortsAnalytics(ctx context.Context, opts *database.FilterOptions) (
			Join("daily_totals dt ON ls.id = dt.link_short_id").
			GroupBy("ls.id").
			Distinct().
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			QueryContext(ctx)
		if err != nil {


@@ 246,7 246,7 @@ func ExportLinkShorts(ctx context.Context, opts *database.FilterOptions) ([]*Exp
			LeftJoin("tags t ON t.id = tl.tag_id").
			GroupBy("l.id").
			Distinct().
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			QueryContext(ctx)
		if err != nil {


@@ 292,7 292,7 @@ func GetLinkShortsCount(ctx context.Context, opts *database.FilterOptions) (int,
			Columns("COUNT(*)").
			From("link_shorts").
			Distinct().
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			QueryContext(ctx)
		if err != nil {

M models/listing.go => models/listing.go +9 -9
@@ 32,7 32,7 @@ func GetListings(ctx context.Context, opts *database.FilterOptions) ([]*Listing,
			LeftJoin("tags t ON t.id = tl.tag_id").
			GroupBy("l.id, d.lookup_name").
			Distinct().
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			QueryContext(ctx)
		if err != nil {


@@ 90,7 90,7 @@ func (l *Listing) Load(ctx context.Context) error {
				"is_default", "is_active", "created_on", "updated_on").
			From("listings").
			Where("id = ?", l.ID).
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			ScanContext(ctx, &l.ID, &l.Title, &l.Slug, &l.Image, &l.Metadata, &l.DomainID, &l.OrgID, &l.UserID,
				&l.IsDefault, &l.IsActive, &l.CreatedOn, &l.UpdatedOn)


@@ 118,7 118,7 @@ func (l *Listing) Store(ctx context.Context) error {
				Values(&l.Title, &l.Slug, &l.Image, &l.Metadata, &l.DomainID, &l.OrgID, &l.UserID, &l.IsDefault,
					&l.IsActive).
				Suffix(`RETURNING id, created_on, updated_on`).
				PlaceholderFormat(sq.Dollar).
				PlaceholderFormat(database.GetPlaceholderFormat()).
				RunWith(tx).
				ScanContext(ctx, &l.ID, &l.CreatedOn, &l.UpdatedOn)
		} else {


@@ 135,7 135,7 @@ func (l *Listing) Store(ctx context.Context) error {
				Set("is_active", l.IsActive).
				Where("id = ?", l.ID).
				Suffix(`RETURNING (updated_on)`).
				PlaceholderFormat(sq.Dollar).
				PlaceholderFormat(database.GetPlaceholderFormat()).
				RunWith(tx).
				ScanContext(ctx, &l.UpdatedOn)
		}


@@ 164,7 164,7 @@ func (l *Listing) Delete(ctx context.Context) error {
		_, err := sq.
			Delete("listings").
			Where("id = ?", l.ID).
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			ExecContext(ctx)
		return err


@@ 186,7 186,7 @@ func GetListsAnalytics(ctx context.Context, opts *database.FilterOptions) ([]*Li
			Join("daily_totals dt ON l.id = dt.list_id").
			GroupBy("l.id").
			Distinct().
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			QueryContext(ctx)
		if err != nil {


@@ 231,7 231,7 @@ func ExportListings(ctx context.Context, opts *database.FilterOptions) ([]*Expor
			LeftJoin("tags t ON t.id = tl.tag_id").
			GroupBy("l.id").
			Distinct().
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			QueryContext(ctx)
		if err != nil {


@@ 281,7 281,7 @@ func ToggleListingBatch(ctx context.Context, opts *database.FilterOptions, flag 
			Update("listings").
			Set("is_active", flag).
			Where(opts.Filter).
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			ExecContext(ctx)
		return err


@@ 300,7 300,7 @@ func GetListingsCount(ctx context.Context, opts *database.FilterOptions) (int, e
			Columns("COUNT(*)").
			From("listings").
			Distinct().
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			QueryContext(ctx)
		if err != nil {

M models/listing_link.go => models/listing_link.go +6 -6
@@ 25,7 25,7 @@ func GetListingLinks(ctx context.Context, opts *database.FilterOptions) ([]*List
			From("listing_links ll").
			Join("listings l ON ll.listing_id = l.ID").
			Distinct().
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			QueryContext(ctx)
		if err != nil {


@@ 74,7 74,7 @@ func (l *ListingLink) Load(ctx context.Context) error {
				"created_on", "updated_on").
			From("listing_links").
			Where("id = ?", l.ID).
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			ScanContext(ctx, &l.ID, &l.Title, &l.ListingID, &l.LinkOrder, &l.URL, &l.Description,
				&l.UserID, &l.CreatedOn, &l.UpdatedOn)


@@ 101,7 101,7 @@ func (l *ListingLink) Store(ctx context.Context) error {
				Columns("title", "listing_id", "link_order", "url", "description", "user_id").
				Values(&l.Title, &l.ListingID, &l.LinkOrder, &l.URL, &l.Description, &l.UserID).
				Suffix(`RETURNING id, created_on, updated_on`).
				PlaceholderFormat(sq.Dollar).
				PlaceholderFormat(database.GetPlaceholderFormat()).
				RunWith(tx).
				ScanContext(ctx, &l.ID, &l.CreatedOn, &l.UpdatedOn)
		} else {


@@ 115,7 115,7 @@ func (l *ListingLink) Store(ctx context.Context) error {
				Set("user_id", l.UserID).
				Where("id = ?", l.ID).
				Suffix(`RETURNING (updated_on)`).
				PlaceholderFormat(sq.Dollar).
				PlaceholderFormat(database.GetPlaceholderFormat()).
				RunWith(tx).
				ScanContext(ctx, &l.UpdatedOn)
		}


@@ 144,7 144,7 @@ func (l *ListingLink) Delete(ctx context.Context) error {
		_, err := sq.
			Delete("listing_links").
			Where("id = ?", l.ID).
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			ExecContext(ctx)
		return err


@@ 167,7 167,7 @@ func GetListingLinksAnalytics(ctx context.Context, opts *database.FilterOptions)
			Join("daily_totals dt ON ll.id = dt.listing_link_id").
			GroupBy("ll.id").
			Distinct().
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			QueryContext(ctx)
		if err != nil {

M models/mattermost_connection.go => models/mattermost_connection.go +4 -4
@@ 25,7 25,7 @@ func GetMattermostConnections(ctx context.Context, opts *database.FilterOptions)
			From("mattermost_connections mc").
			Join("organizations o ON mc.org_id = o.id").
			Distinct().
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			QueryContext(ctx)
		if err != nil {


@@ 72,7 72,7 @@ func (m *MattermostConnection) Load(ctx context.Context) error {
			Select("id", "team_id", "org_id", "created_on").
			From("mattermost_connections").
			Where("id = ?", m.ID).
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			ScanContext(ctx, &m.ID, &m.TeamID, &m.OrgID, &m.CreatedOn)
		if err != nil {


@@ 97,7 97,7 @@ func (m *MattermostConnection) Store(ctx context.Context) error {
				Columns("team_id", "org_id").
				Values(m.TeamID, m.OrgID).
				Suffix(`RETURNING id, created_on`).
				PlaceholderFormat(sq.Dollar).
				PlaceholderFormat(database.GetPlaceholderFormat()).
				RunWith(tx).
				ScanContext(ctx, &m.ID, &m.CreatedOn)
		}


@@ 125,7 125,7 @@ func (m *MattermostConnection) Delete(ctx context.Context) error {
		_, err := sq.
			Delete("mattermost_connections").
			Where("id = ?", m.ID).
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			ExecContext(ctx)
		return err

M models/mattermost_users.go => models/mattermost_users.go +4 -4
@@ 24,7 24,7 @@ func GetMattermostUsers(ctx context.Context, opts *database.FilterOptions) ([]*M
			Columns("id", "mattermost_conn_id", "user_id", "mattermost_user", "created_on").
			From("mattermost_users").
			Distinct().
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			QueryContext(ctx)
		if err != nil {


@@ 71,7 71,7 @@ func (s *MattermostUser) Load(ctx context.Context) error {
			Select("id", "mattermost_conn_id", "user_id", "mattermost_user", "created_on").
			From("mattermost_users").
			Where("id = ?", s.ID).
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			ScanContext(ctx, &s.ID, &s.MattermostConnID, &s.UserID, &s.MattermostUser, &s.CreatedOn)
		if err != nil {


@@ 96,7 96,7 @@ func (s *MattermostUser) Store(ctx context.Context) error {
				Columns("mattermost_conn_id", "user_id", "mattermost_user").
				Values(s.MattermostConnID, s.UserID, s.MattermostUser).
				Suffix(`RETURNING id, created_on`).
				PlaceholderFormat(sq.Dollar).
				PlaceholderFormat(database.GetPlaceholderFormat()).
				RunWith(tx).
				ScanContext(ctx, &s.ID, &s.CreatedOn)
		}


@@ 124,7 124,7 @@ func (s *MattermostUser) Delete(ctx context.Context) error {
		_, err := sq.
			Delete("mattermost_users").
			Where("id = ?", s.ID).
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			ExecContext(ctx)
		return err

M models/org_link.go => models/org_link.go +10 -10
@@ 49,7 49,7 @@ func GetOrgLinks(ctx context.Context, opts *database.FilterOptions) ([]*OrgLink,
			LeftJoin("followers f ON f.org_id = ol.org_id").
			GroupBy("ol.id", "o.slug", "u.full_name", "b.data", "b.counter", "b.hash").
			Distinct().
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			QueryContext(ctx)
		if err != nil {


@@ 110,7 110,7 @@ func (o *OrgLink) Load(ctx context.Context) error {
				"created_on", "updated_on").
			From("org_links").
			Where("id = ?", o.ID).
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			ScanContext(ctx, &o.ID, &o.Title, &o.URL, &o.Description, &o.BaseURLID,
				&o.OrgID, &o.UserID, &o.Visibility, &o.Unread, &o.Starred, &o.ArchiveURL,


@@ 152,7 152,7 @@ func (o *OrgLink) Store(ctx context.Context) error {
				Suffix(`ON CONFLICT (base_url_id, org_id) DO UPDATE SET 
					updated_on = CURRENT_TIMESTAMP 
					RETURNING id, hash, created_on, updated_on`).
				PlaceholderFormat(sq.Dollar).
				PlaceholderFormat(database.GetPlaceholderFormat()).
				RunWith(tx).
				ScanContext(ctx, &o.ID, &o.Hash, &o.CreatedOn, &o.UpdatedOn)
		} else {


@@ 172,7 172,7 @@ func (o *OrgLink) Store(ctx context.Context) error {
				Set("hash", o.Hash).
				Where("id = ?", o.ID).
				Suffix(`RETURNING (updated_on)`).
				PlaceholderFormat(sq.Dollar).
				PlaceholderFormat(database.GetPlaceholderFormat()).
				RunWith(tx).
				ScanContext(ctx, &o.UpdatedOn)
		}


@@ 190,7 190,7 @@ func (o *OrgLink) Delete(ctx context.Context) error {
		_, err := sq.
			Delete("org_links").
			Where("id = ?", o.ID).
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			ExecContext(ctx)
		return err


@@ 247,7 247,7 @@ func GetOrgLinksAnalytics(ctx context.Context, opts *database.FilterOptions) ([]
			Join("daily_totals dt ON ol.id = dt.org_link_id").
			GroupBy("ol.id").
			Distinct().
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			QueryContext(ctx)
		if err != nil {


@@ 294,7 294,7 @@ func OrgLinkStoreBatch(ctx context.Context, links []*OrgLink) error {
			Suffix(`ON CONFLICT (base_url_id, org_id) DO UPDATE SET 
				updated_on = CURRENT_TIMESTAMP 
				RETURNING id, hash`).
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			QueryContext(ctx)
		if err != nil {


@@ 331,7 331,7 @@ func ExportOrgLinks(ctx context.Context, opts *database.FilterOptions) ([]*Expor
			LeftJoin("tags t ON t.id = tl.tag_id").
			GroupBy("ol.id").
			Distinct().
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			QueryContext(ctx)
		if err != nil {


@@ 373,7 373,7 @@ func ToggleOrgLinksVisibilityBatch(ctx context.Context, opts *database.FilterOpt
			Update("org_links").
			Set("visibility", vis).
			Where(opts.Filter).
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			ExecContext(ctx)
		return err


@@ 392,7 392,7 @@ func GetOrgLinksCount(ctx context.Context, opts *database.FilterOptions) (int, e
			Columns("COUNT(*)").
			From("org_links").
			Distinct().
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			QueryContext(ctx)
		if err != nil {

M models/org_user.go => models/org_user.go +6 -6
@@ 33,7 33,7 @@ func GetOrgUsers(ctx context.Context, opts *database.FilterOptions) ([]*OrgUser,
			Columns("id", "org_id", "user_id", "permission", "is_active", "created_on", "updated_on").
			From("organization_users").
			Distinct().
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			QueryContext(ctx)
		if err != nil {


@@ 81,7 81,7 @@ func (o *OrgUser) Load(ctx context.Context) error {
			Select("id", "org_id", "user_id", "permission", "is_active", "created_on", "updated_on").
			From("organization_users").
			Where("id = ?", o.ID).
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			ScanContext(ctx, &o.ID, &o.OrgID, &o.UserID, &o.Permission, &o.IsActive, &o.CreatedOn, &o.UpdatedOn)
		if err != nil {


@@ 106,7 106,7 @@ func (o *OrgUser) Store(ctx context.Context) error {
				Columns("org_id", "user_id", "permission").
				Values(o.OrgID, o.UserID, o.Permission).
				Suffix(`RETURNING id, created_on`).
				PlaceholderFormat(sq.Dollar).
				PlaceholderFormat(database.GetPlaceholderFormat()).
				RunWith(tx).
				ScanContext(ctx, &o.ID, &o.CreatedOn)
		} else {


@@ 118,7 118,7 @@ func (o *OrgUser) Store(ctx context.Context) error {
				Set("is_active", o.IsActive).
				Where("id = ?", o.ID).
				Suffix(`RETURNING (updated_on)`).
				PlaceholderFormat(sq.Dollar).
				PlaceholderFormat(database.GetPlaceholderFormat()).
				RunWith(tx).
				ScanContext(ctx, &o.UpdatedOn)
		}


@@ 136,7 136,7 @@ func (o *OrgUser) Delete(ctx context.Context) error {
		_, err := sq.
			Delete("organization_users").
			Where("id = ?", o.ID).
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			ExecContext(ctx)
		return err


@@ 162,7 162,7 @@ func ToggleOrgUserBatch(ctx context.Context, opts *database.FilterOptions, flag 
			Update("organization_users").
			Set("is_active", flag).
			Where(opts.Filter).
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			ExecContext(ctx)
		return err

M models/organization.go => models/organization.go +6 -6
@@ 82,7 82,7 @@ func GetOrganizations(ctx context.Context, opts *database.FilterOptions) ([]*Org
			LeftJoin("domains d ON o.id = d.org_id").
			LeftJoin("followers f ON f.org_id = o.id").
			Distinct().
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			QueryContext(ctx)
		if err != nil {


@@ 135,7 135,7 @@ func (o *Organization) Load(ctx context.Context) error {
			From("organizations o").
			Join("users u ON o.owner_id = u.id").
			Where("o.id = ?", o.ID).
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			ScanContext(ctx, &o.ID, &o.OwnerID, &o.OrgType, &o.Name, &o.Slug, &o.Image, &o.Timezone,
				&o.Settings, &o.IsActive, &o.CreatedOn, &o.UpdatedOn, &o.OwnerName)


@@ 167,7 167,7 @@ func (o *Organization) Store(ctx context.Context) error {
					"settings", "is_active").
				Values(o.OwnerID, o.OrgType, o.Name, o.Slug, o.Image, o.Timezone, settings, o.IsActive).
				Suffix(`RETURNING id, created_on, updated_on`).
				PlaceholderFormat(sq.Dollar).
				PlaceholderFormat(database.GetPlaceholderFormat()).
				RunWith(tx).
				ScanContext(ctx, &o.ID, &o.CreatedOn, &o.UpdatedOn)
		} else {


@@ 183,7 183,7 @@ func (o *Organization) Store(ctx context.Context) error {
				Set("is_active", o.IsActive).
				Where("id = ?", o.ID).
				Suffix(`RETURNING (updated_on)`).
				PlaceholderFormat(sq.Dollar).
				PlaceholderFormat(database.GetPlaceholderFormat()).
				RunWith(tx).
				ScanContext(ctx, &o.UpdatedOn)
		}


@@ 201,7 201,7 @@ func (o *Organization) Delete(ctx context.Context) error {
		_, err := sq.
			Delete("organizations").
			Where("id = ?", o.ID).
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			ExecContext(ctx)
		return err


@@ 329,7 329,7 @@ func ToggleOrganizaiongBatch(ctx context.Context, opts *database.FilterOptions, 
			Update("organizations").
			Set("is_active", flag).
			Where(opts.Filter).
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			ExecContext(ctx)
		return err

M models/qr_codes.go => models/qr_codes.go +14 -14
@@ 31,7 31,7 @@ func GetQRCodes(ctx context.Context, opts *database.FilterOptions) ([]*QRCode, e
			LeftJoin("qr_codes_shorts AS qs ON qs.qr_code_id = q.id").
			LeftJoin("qr_codes_lists AS ql ON ql.qr_code_id = q.id").
			Distinct().
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			QueryContext(ctx)
		if err != nil {


@@ 82,7 82,7 @@ func (q *QRCode) Load(ctx context.Context) error {
			LeftJoin("qr_codes_shorts AS qs ON qs.qr_code_id = q.id").
			LeftJoin("qr_codes_lists AS ql ON ql.qr_code_id = q.id").
			Where("q.id = ?", q.ID).
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			ScanContext(ctx, &q.ID, &q.Title, &q.HashID, &q.OrgID, &q.CodeType, &q.ImagePath, &q.URL,
				&q.UserID, &q.CreatedOn, &q.UpdatedOn, &q.ListID, &q.ShortID)


@@ 115,7 115,7 @@ func (q *QRCode) Store(ctx context.Context) error {
				Columns("title", "hash_id", "org_id", "code_type", "image_path", "url", "user_id").
				Values(&q.Title, &q.HashID, &q.OrgID, &q.CodeType, &q.ImagePath, &q.URL, &q.UserID).
				Suffix(`RETURNING id, created_on, updated_on`).
				PlaceholderFormat(sq.Dollar).
				PlaceholderFormat(database.GetPlaceholderFormat()).
				RunWith(tx).
				ScanContext(ctx, &q.ID, &q.CreatedOn, &q.UpdatedOn)
		} else {


@@ 128,7 128,7 @@ func (q *QRCode) Store(ctx context.Context) error {
				Set("url", q.URL).
				Where("id = ?", q.ID).
				Suffix(`RETURNING (updated_on)`).
				PlaceholderFormat(sq.Dollar).
				PlaceholderFormat(database.GetPlaceholderFormat()).
				RunWith(tx).
				ScanContext(ctx, &q.UpdatedOn)
		}


@@ 157,7 157,7 @@ func (q *QRCode) Delete(ctx context.Context) error {
		_, err := sq.
			Delete("qr_codes").
			Where("id = ?", q.ID).
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			ExecContext(ctx)
		return err


@@ 179,7 179,7 @@ func GetQRLists(ctx context.Context, opts *database.FilterOptions) ([]*QRList, e
			From("qr_codes_lists AS ql").
			InnerJoin("qr_codes AS q ON ql.qr_code_id = q.id").
			Distinct().
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			QueryContext(ctx)
		if err != nil {


@@ 226,7 226,7 @@ func (q *QRList) Load(ctx context.Context) error {
			Select("id", "qr_code_id", "list_id", "created_on").
			From("qr_codes_lists").
			Where("id = ?", q.ID).
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			ScanContext(ctx, &q.ID, &q.QRCodeID, &q.ListID, &q.CreatedOn)



@@ 252,7 252,7 @@ func (q *QRList) Store(ctx context.Context) error {
				Columns("qr_code_id", "list_id").
				Values(&q.QRCodeID, &q.ListID).
				Suffix(`RETURNING id, created_on`).
				PlaceholderFormat(sq.Dollar).
				PlaceholderFormat(database.GetPlaceholderFormat()).
				RunWith(tx).
				ScanContext(ctx, &q.ID, &q.CreatedOn)
		} else {


@@ 281,7 281,7 @@ func (q *QRList) Delete(ctx context.Context) error {
		_, err := sq.
			Delete("qr_codes_lists").
			Where("id = ?", q.ID).
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			ExecContext(ctx)
		return err


@@ 303,7 303,7 @@ func GetQRShorts(ctx context.Context, opts *database.FilterOptions) ([]*QRShort,
			From("qr_codes_shorts AS qs").
			InnerJoin("qr_codes AS q ON qs.qr_code_id = q.id").
			Distinct().
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			QueryContext(ctx)
		if err != nil {


@@ 350,7 350,7 @@ func (q *QRShort) Load(ctx context.Context) error {
			Select("id", "qr_code_id", "short_id", "created_on").
			From("qr_codes_shorts").
			Where("id = ?", q.ID).
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			ScanContext(ctx, &q.ID, &q.QRCodeID, &q.ShortID, &q.CreatedOn)



@@ 376,7 376,7 @@ func (q *QRShort) Store(ctx context.Context) error {
				Columns("qr_code_id", "short_id").
				Values(&q.QRCodeID, &q.ShortID).
				Suffix(`RETURNING id, created_on`).
				PlaceholderFormat(sq.Dollar).
				PlaceholderFormat(database.GetPlaceholderFormat()).
				RunWith(tx).
				ScanContext(ctx, &q.ID, &q.CreatedOn)
		} else {


@@ 405,7 405,7 @@ func (q *QRShort) Delete(ctx context.Context) error {
		_, err := sq.
			Delete("qr_codes_shorts").
			Where("id = ?", q.ID).
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			ExecContext(ctx)
		return err


@@ 430,7 430,7 @@ func GetQRAnalytics(ctx context.Context, opts *database.FilterOptions) ([]*QRCod
			LeftJoin("qr_codes_shorts qs ON qs.qr_code_id = q.id").
			GroupBy("q.id").
			Distinct().
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			QueryContext(ctx)
		if err != nil {

M models/slack_connection.go => models/slack_connection.go +4 -4
@@ 26,7 26,7 @@ func GetSlackConnections(ctx context.Context, opts *database.FilterOptions) ([]*
			From("slack_connections sc").
			Join("organizations o ON sc.org_id = o.id").
			Distinct().
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			QueryContext(ctx)
		if err != nil {


@@ 74,7 74,7 @@ func (s *SlackConnection) Load(ctx context.Context) error {
			Select("id", "token", "team_id", "org_id", "created_on").
			From("slack_connections").
			Where("id = ?", s.ID).
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			ScanContext(ctx, &s.ID, &s.Token, &s.TeamID, &s.OrgID, &s.CreatedOn)
		if err != nil {


@@ 99,7 99,7 @@ func (s *SlackConnection) Store(ctx context.Context) error {
				Columns("token", "team_id", "org_id").
				Values(s.Token, s.TeamID, s.OrgID).
				Suffix(`RETURNING id, created_on`).
				PlaceholderFormat(sq.Dollar).
				PlaceholderFormat(database.GetPlaceholderFormat()).
				RunWith(tx).
				ScanContext(ctx, &s.ID, &s.CreatedOn)
		}


@@ 127,7 127,7 @@ func (s *SlackConnection) Delete(ctx context.Context) error {
		_, err := sq.
			Delete("slack_connections").
			Where("id = ?", s.ID).
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			ExecContext(ctx)
		return err

M models/slack_users.go => models/slack_users.go +4 -4
@@ 24,7 24,7 @@ func GetSlackUsers(ctx context.Context, opts *database.FilterOptions) ([]*SlackU
			Columns("id", "slack_conn_id", "user_id", "slack_user", "created_on").
			From("slack_users").
			Distinct().
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			QueryContext(ctx)
		if err != nil {


@@ 71,7 71,7 @@ func (s *SlackUser) Load(ctx context.Context) error {
			Select("id", "slack_conn_id", "user_id", "slack_user", "created_on").
			From("slack_users").
			Where("id = ?", s.ID).
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			ScanContext(ctx, &s.ID, &s.SlackConnID, &s.UserID, &s.SlackUser, &s.CreatedOn)
		if err != nil {


@@ 96,7 96,7 @@ func (s *SlackUser) Store(ctx context.Context) error {
				Columns("slack_conn_id", "user_id", "slack_user").
				Values(s.SlackConnID, s.UserID, s.SlackUser).
				Suffix(`RETURNING id, created_on`).
				PlaceholderFormat(sq.Dollar).
				PlaceholderFormat(database.GetPlaceholderFormat()).
				RunWith(tx).
				ScanContext(ctx, &s.ID, &s.CreatedOn)
		}


@@ 124,7 124,7 @@ func (s *SlackUser) Delete(ctx context.Context) error {
		_, err := sq.
			Delete("slack_users").
			Where("id = ?", s.ID).
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			ExecContext(ctx)
		return err

M models/subscription_plan.go => models/subscription_plan.go +5 -5
@@ 38,7 38,7 @@ func GetSubscriptionPlans(ctx context.Context, opts *database.FilterOptions) ([]
		rows, err := q.
			Columns("id", "name", "plan_id", "stripe_price_id", "price", "type", "is_active", "created_on", "updated_on").
			From("subscription_plans").
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			QueryContext(ctx)
		if err != nil {


@@ 86,7 86,7 @@ func (s *SubscriptionPlan) Load(ctx context.Context) error {
			Select("id", "name", "plan_id", "stripe_price_id", "price", "type", "is_active", "created_on", "updated_on").
			From("subscription_plans").
			Where("id = ?", s.ID).
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			ScanContext(ctx, &s.ID, &s.Name, &s.PlanID, &s.StripePriceID, &s.Price, &s.Type, &s.IsActive,
				&s.CreatedOn, &s.UpdatedOn)


@@ 109,7 109,7 @@ func (s *SubscriptionPlan) Store(ctx context.Context) error {
				Columns("name", "plan_id", "stripe_price_id", "price", "type", "is_active").
				Values(s.Name, s.PlanID, s.StripePriceID, s.Price, s.Type, s.IsActive).
				Suffix(`RETURNING id, created_on, updated_on`).
				PlaceholderFormat(sq.Dollar).
				PlaceholderFormat(database.GetPlaceholderFormat()).
				RunWith(tx).
				ScanContext(ctx, &s.ID, &s.CreatedOn, &s.UpdatedOn)
		} else {


@@ 123,7 123,7 @@ func (s *SubscriptionPlan) Store(ctx context.Context) error {
				Set("is_active", s.IsActive).
				Where("id = ?", s.ID).
				Suffix(`RETURNING (updated_on)`).
				PlaceholderFormat(sq.Dollar).
				PlaceholderFormat(database.GetPlaceholderFormat()).
				RunWith(tx).
				ScanContext(ctx, &s.UpdatedOn)
		}


@@ 142,7 142,7 @@ func (s *SubscriptionPlan) Delete(ctx context.Context) error {
		_, err = sq.
			Delete("subscription_plans").
			Where("id = ?", s.ID).
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			ExecContext(ctx)
		return err

M models/subscriptions.go => models/subscriptions.go +6 -6
@@ 26,7 26,7 @@ func GetSubscriptions(ctx context.Context, opts *database.FilterOptions) ([]*Sub
			).
			From("subscriptions s").
			LeftJoin("subscription_plans sp ON sp.id = s.subscription_plan_id").
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			QueryContext(ctx)
		if err != nil {


@@ 76,7 76,7 @@ func (s *Subscription) Load(ctx context.Context) error {
				"is_active", "created_on", "updated_on").
			From("subscriptions").
			Where(wq).
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			ScanContext(ctx,
				&s.UserID,


@@ 111,7 111,7 @@ func (s *Subscription) Store(ctx context.Context) error {
				Columns("user_id", "org_id", "stripe_id", "subscription_plan_id", "start_date", "end_date", "cancel_end", "is_active").
				Values(s.UserID, s.OrgID, s.StripeID, s.SubscriptionPlanID, s.StartDate, s.EndDate, s.CancelAtEnd, s.IsActive).
				Suffix(`RETURNING id, created_on, updated_on`).
				PlaceholderFormat(sq.Dollar).
				PlaceholderFormat(database.GetPlaceholderFormat()).
				RunWith(tx).
				ScanContext(ctx, &s.ID, &s.CreatedOn, &s.UpdatedOn)
		} else {


@@ 127,7 127,7 @@ func (s *Subscription) Store(ctx context.Context) error {
				Set("is_active", s.IsActive).
				Where("id = ?", s.ID).
				Suffix("RETURNING (updated_on)").
				PlaceholderFormat(sq.Dollar).
				PlaceholderFormat(database.GetPlaceholderFormat()).
				RunWith(tx).
				ScanContext(ctx, &s.UpdatedOn)
		}


@@ 145,7 145,7 @@ func (s *Subscription) Delete(ctx context.Context) error {
		_, err := sq.
			Delete("subscriptions").
			Where("id = ?", s.ID).
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			ExecContext(ctx)
		return err


@@ 177,7 177,7 @@ func GetSubscriptionCount(ctx context.Context, opts *database.FilterOptions) (in
			Columns("COUNT(*)").
			From("subscriptions").
			Distinct().
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			QueryContext(ctx)
		if err != nil {

M models/tag.go => models/tag.go +4 -4
@@ 61,7 61,7 @@ func GetTags(ctx context.Context, opts *database.FilterOptions) ([]*Tag, error) 
			LeftJoin("tag_link_shorts ts ON ts.tag_id = t.id").
			LeftJoin("link_shorts s ON ts.link_short_id = s.id").
			Distinct().
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			QueryContext(ctx)
		if err != nil {


@@ 108,7 108,7 @@ func (t *Tag) Load(ctx context.Context) error {
			Select("id", "name", "slug", "created_on").
			From("tags").
			Where("id = ?", t.ID).
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			ScanContext(ctx, &t.ID, &t.Name, &t.Slug, &t.CreatedOn)
		if err != nil {


@@ 171,7 171,7 @@ func (t *Tag) Delete(ctx context.Context) error {
		_, err := sq.
			Delete("tags").
			Where("id = ?", t.ID).
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			ExecContext(ctx)
		return err


@@ 192,7 192,7 @@ func GetTagCloud(ctx context.Context, opts *database.FilterOptions) ([]*Tag, err
			Join("org_links ol on ol.id = tl.org_link_id").
			GroupBy("t.id", "t.name", "t.slug").
			Distinct().
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			QueryContext(ctx)


M models/tag_link_shorts.go => models/tag_link_shorts.go +6 -6
@@ 24,7 24,7 @@ func GetTagLinkShorts(ctx context.Context, opts *database.FilterOptions) ([]*Tag
			Columns("id", "link_short_id", "tag_id", "created_on").
			From("tag_link_shorts").
			Distinct().
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			QueryContext(ctx)
		if err != nil {


@@ 72,7 72,7 @@ func CreateBatchTagLinkShorts(ctx context.Context, linkShortID int, tagIDs []int
		}
		_, err = q.
			Suffix("ON CONFLICT (link_short_id, tag_id) DO NOTHING").
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			ExecContext(ctx)



@@ 92,7 92,7 @@ func RemoveTagsFromLinkShort(ctx context.Context, tagIDs []int) error {
		_, err := sq.
			Delete("tag_link_shorts").
			Where(sq.Eq{"tag_id": tagIDs}).
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			ExecContext(ctx)
		return err


@@ 111,7 111,7 @@ func (tl *TagLinkShort) Load(ctx context.Context) error {
			Select("id", "link_short_id", "tag_id", "created_on").
			From("tag_link_shorts").
			Where("id = ?", tl.ID).
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			ScanContext(ctx, &tl.ID, &tl.LinkShortID, &tl.TagID, &tl.CreatedOn)
		if err != nil {


@@ 136,7 136,7 @@ func (tl *TagLinkShort) Store(ctx context.Context) error {
				Columns("link_short_id", "tag_id").
				Values(tl.LinkShortID, tl.TagID).
				Suffix(`RETURNING id, created_on`).
				PlaceholderFormat(sq.Dollar).
				PlaceholderFormat(database.GetPlaceholderFormat()).
				RunWith(tx).
				ScanContext(ctx, &tl.ID, &tl.CreatedOn)
		}


@@ 164,7 164,7 @@ func (tl *TagLinkShort) Delete(ctx context.Context) error {
		_, err := sq.
			Delete("tag_link_shorts").
			Where("id = ?", tl.ID).
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			ExecContext(ctx)
		return err

M models/tag_links.go => models/tag_links.go +6 -6
@@ 24,7 24,7 @@ func GetTagLinks(ctx context.Context, opts *database.FilterOptions) ([]*TagLink,
			Columns("id", "org_link_id", "tag_id", "created_on").
			From("tag_links").
			Distinct().
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			QueryContext(ctx)
		if err != nil {


@@ 72,7 72,7 @@ func CreateBatchTagLinks(ctx context.Context, linkID int, tagIDs []int) error {
		}
		_, err = q.
			Suffix("ON CONFLICT (org_link_id, tag_id) DO NOTHING").
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			ExecContext(ctx)
		return err


@@ 88,7 88,7 @@ func RemoveTagsFromLink(ctx context.Context, tagIDs []int) error {
		_, err := sq.
			Delete("tag_links").
			Where(sq.Eq{"tag_id": tagIDs}).
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			ExecContext(ctx)
		return err


@@ 107,7 107,7 @@ func (tl *TagLink) Load(ctx context.Context) error {
			Select("id", "org_link_id", "tag_id", "created_on").
			From("tag_links").
			Where("id = ?", tl.ID).
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			ScanContext(ctx, &tl.ID, &tl.OrgLinkID, &tl.TagID, &tl.CreatedOn)
		if err != nil {


@@ 132,7 132,7 @@ func (tl *TagLink) Store(ctx context.Context) error {
				Columns("org_link_id", "tag_id").
				Values(tl.OrgLinkID, tl.TagID).
				Suffix(`RETURNING id, created_on`).
				PlaceholderFormat(sq.Dollar).
				PlaceholderFormat(database.GetPlaceholderFormat()).
				RunWith(tx).
				ScanContext(ctx, &tl.ID, &tl.CreatedOn)
		}


@@ 160,7 160,7 @@ func (tl *TagLink) Delete(ctx context.Context) error {
		_, err := sq.
			Delete("tag_links").
			Where("id = ?", tl.ID).
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			ExecContext(ctx)
		return err

M models/tag_listing.go => models/tag_listing.go +6 -6
@@ 24,7 24,7 @@ func GetTagListings(ctx context.Context, opts *database.FilterOptions) ([]*TagLi
			Columns("id", "listing_id", "tag_id", "created_on").
			From("tag_listings").
			Distinct().
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			QueryContext(ctx)
		if err != nil {


@@ 72,7 72,7 @@ func CreateBatchTagListings(ctx context.Context, linkShortID int, tagIDs []int) 
		}
		_, err = q.
			Suffix("ON CONFLICT (listing_id, tag_id) DO NOTHING").
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			ExecContext(ctx)



@@ 92,7 92,7 @@ func RemoveTagsFromListing(ctx context.Context, tagIDs []int) error {
		_, err := sq.
			Delete("tag_listings").
			Where(sq.Eq{"tag_id": tagIDs}).
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			ExecContext(ctx)
		return err


@@ 111,7 111,7 @@ func (tl *TagListing) Load(ctx context.Context) error {
			Select("id", "listing_id", "tag_id", "created_on").
			From("tag_listings").
			Where("id = ?", tl.ID).
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			ScanContext(ctx, &tl.ID, &tl.ListingID, &tl.TagID, &tl.CreatedOn)
		if err != nil {


@@ 136,7 136,7 @@ func (tl *TagListing) Store(ctx context.Context) error {
				Columns("listing_id", "tag_id").
				Values(tl.ListingID, tl.TagID).
				Suffix(`RETURNING id, created_on`).
				PlaceholderFormat(sq.Dollar).
				PlaceholderFormat(database.GetPlaceholderFormat()).
				RunWith(tx).
				ScanContext(ctx, &tl.ID, &tl.CreatedOn)
		}


@@ 164,7 164,7 @@ func (tl *TagListing) Delete(ctx context.Context) error {
		_, err := sq.
			Delete("tag_listings").
			Where("id = ?", tl.ID).
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			ExecContext(ctx)
		return err

M models/totals_meta.go => models/totals_meta.go +4 -4
@@ 29,7 29,7 @@ func GetTotalsMetas(ctx context.Context, opts *database.FilterOptions) ([]*Total
			Columns("td.id", "td.daily_total_id", "td.meta_type", "td.meta_value", "td.clicks", "td.unique_clicks").
			From("totals_meta td").
			Distinct().
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			QueryContext(ctx)
		if err != nil {


@@ 72,7 72,7 @@ func (t *TotalsMeta) Load(ctx context.Context) error {
			Select("id", "daily_total_id", "meta_type", "meta_value", "clicks", "unique_clicks").
			From("totals_meta").
			Where("id = ?", t.ID).
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			ScanContext(ctx, &t.ID, &t.DailyTotalID, &t.MetaType, &t.MetaValue, &t.Clicks, &t.UniqueClicks)



@@ 141,7 141,7 @@ func (t *TotalsMeta) Delete(ctx context.Context) error {
		_, err := sq.
			Delete("totals_meta").
			Where("id = ?", t.ID).
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			ExecContext(ctx)
		return err


@@ 164,7 164,7 @@ func GetAnalyticsData(ctx context.Context, opts *database.FilterOptions) (Analyt
			GroupBy("m.meta_value").
			OrderBy("sum_clicks DESC").
			Distinct().
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			QueryContext(ctx)
		if err != nil {

M models/user.go => models/user.go +5 -5
@@ 77,7 77,7 @@ func GetUser(ctx context.Context, uid any, markAuth bool) (*User, error) {
			From("users u").
			LeftJoin("organizations o ON o.owner_id = u.id").
			Where(where).
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			ScanContext(ctx,
				&user.ID,


@@ 132,7 132,7 @@ func GetUsers(ctx context.Context, opts *database.FilterOptions) ([]*User, error
			LeftJoin("organizations o ON o.owner_id = u.id").
			LeftJoin("organization_users ou ON u.id = ou.user_id").
			Distinct().
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			QueryContext(ctx)
		if err != nil {


@@ 186,7 186,7 @@ func (u *User) Store(ctx context.Context) error {
					u.IsVerified(), u.IsSuperUser(), u.IsStaff(),
					u.IsLocked, u.LockReason).
				Suffix(`RETURNING (id)`).
				PlaceholderFormat(sq.Dollar).
				PlaceholderFormat(database.GetPlaceholderFormat()).
				RunWith(tx).
				ScanContext(ctx, &u.ID)
		} else {


@@ 202,7 202,7 @@ func (u *User) Store(ctx context.Context) error {
				Set("is_locked", u.IsLocked).
				Set("lock_reason", u.LockReason).
				Where("id = ?", u.GetID()).
				PlaceholderFormat(sq.Dollar).
				PlaceholderFormat(database.GetPlaceholderFormat()).
				RunWith(tx).
				ExecContext(ctx)
		}


@@ 218,7 218,7 @@ func (u *User) WritePassword(ctx context.Context) error {
			Update("users").
			Set("password", u.Password).
			Where("id = ?", u.GetID()).
			PlaceholderFormat(sq.Dollar).
			PlaceholderFormat(database.GetPlaceholderFormat()).
			RunWith(tx).
			ExecContext(ctx)
		return err

M models/utils.go => models/utils.go +2 -1
@@ 8,6 8,7 @@ import (
	"time"

	sq "github.com/Masterminds/squirrel"
	"netlandish.com/x/gobwebs/database"
)

func getShortCode(ctx context.Context, tx *sql.Tx, table, field string, filter sq.Sqlizer) (string, error) {


@@ 57,7 58,7 @@ func checkCode(ctx context.Context, tx *sql.Tx, table string, filter sq.Sqlizer)
		Select("id").
		From(table).
		Where(filter).
		PlaceholderFormat(sq.Dollar).
		PlaceholderFormat(database.GetPlaceholderFormat()).
		RunWith(tx).
		ScanContext(ctx)
	if err != nil {

Do not follow this link