Antonio Mika
·
2026-10-11
1package postgres
2
3import (
4 "fmt"
5 "time"
6
7 "github.com/picosh/pico/pkg/db"
8)
9
10func (me *PsqlDB) FindWhoInvitedUser(toUserID string) (string, error) {
11 var inviterName string
12 query := `
13 SELECT app_users.name
14 FROM invites
15 LEFT JOIN app_users ON app_users.id = invites.from_user_id
16 WHERE to_user_id=$1
17 `
18 err := me.Db.Get(&inviterName, query, toUserID)
19 if err != nil {
20 return "", err
21 }
22
23 return inviterName, nil
24}
25
26func (me *PsqlDB) FindInvitesByUser(userID string) ([]*db.Invite, error) {
27 var invites []*db.Invite
28 query := `SELECT
29 invites.id, invites.from_user_id, invites.to_user_id, invites.created_at,
30 app_users.name as to_user_name
31 FROM invites
32 LEFT JOIN app_users ON app_users.id = invites.to_user_id
33 WHERE from_user_id=$1`
34 err := me.Db.Select(&invites, query, userID)
35 if err != nil {
36 return nil, err
37 }
38 return invites, nil
39}
40
41// inviteFeatures are the services an invite grants access to.
42var inviteFeatures = []string{"prose", "pgs", "pastes"}
43
44func (me *PsqlDB) hasActiveInvite(userID string) (bool, error) {
45 var invited bool
46 err := me.Db.Get(&invited, `SELECT EXISTS (SELECT 1 FROM invites WHERE to_user_id = $1)`, userID)
47 if err != nil || !invited {
48 return false, err
49 }
50 for _, name := range inviteFeatures {
51 if db.HasFeature(me, userID, name) {
52 return true, nil
53 }
54 }
55 return false, nil
56}
57
58func (me *PsqlDB) InviteUser(fromUserID string, toUserID string) error {
59 canInvite := db.HasFeature(me, fromUserID, "plus")
60 if !canInvite {
61 invited, err := me.hasActiveInvite(fromUserID)
62 if err != nil {
63 return err
64 }
65 canInvite = invited
66 }
67
68 if !canInvite {
69 return fmt.Errorf("must have valid pico+ membership or an active invite from someone")
70 }
71
72 _, err := me.Db.Exec(
73 `INSERT INTO invites (from_user_id, to_user_id) VALUES ($1, $2)`,
74 fromUserID, toUserID,
75 )
76 if err != nil {
77 return err
78 }
79
80 expiresAt := time.Now().Add(5 * 365 * 24 * time.Hour)
81 for _, name := range inviteFeatures {
82 if _, err := me.InsertFeature(toUserID, name, expiresAt); err != nil {
83 return err
84 }
85 }
86 return nil
87}