org.go

  1package database
  2
  3import (
  4	"context"
  5
  6	"github.com/charmbracelet/soft-serve/pkg/access"
  7	"github.com/charmbracelet/soft-serve/pkg/db"
  8	"github.com/charmbracelet/soft-serve/pkg/db/models"
  9	"github.com/charmbracelet/soft-serve/pkg/store"
 10)
 11
 12var _ store.OrgStore = (*orgStore)(nil)
 13
 14type orgStore struct{ *handleStore }
 15
 16// UpdateOrgContactEmail implements store.OrgStore.
 17func (*orgStore) UpdateOrgContactEmail(ctx context.Context, h db.Handler, org int64, email string) error {
 18	query := h.Rebind(`
 19		UPDATE organizations
 20		SET
 21		  contact_email = ?
 22		WHERE
 23		  id = ?
 24	`)
 25
 26	_, err := h.ExecContext(ctx, query, email, org)
 27	return err
 28}
 29
 30// ListOrgs implements store.OrgStore.
 31func (*orgStore) ListOrgs(ctx context.Context, h db.Handler, uid int64) ([]models.Organization, error) {
 32	var m []models.Organization
 33	query := h.Rebind(`
 34		SELECT
 35		  o.*,
 36		  h AS handle
 37		FROM
 38		  organizations o
 39		  JOIN handles h ON h.id = o.handle_id
 40		  JOIN organization_members om ON om.org_id = o.id
 41		WHERE
 42		  o.user_id = ?
 43	`)
 44	err := h.SelectContext(ctx, &m, query, uid)
 45	return m, err
 46}
 47
 48// Delete implements store.OrgStore.
 49func (s *orgStore) DeleteOrgByID(ctx context.Context, h db.Handler, user, id int64) error {
 50	_, err := s.getOrgByIDWithAccess(ctx, h, user, id, access.AdminAccess)
 51	if err != nil {
 52		return err
 53	}
 54	query := h.Rebind(`DELETE FROM organizations WHERE id = ?;`)
 55	_, err = h.ExecContext(ctx, query, id)
 56	return err
 57}
 58
 59// Create implements store.OrgStore.
 60func (s *orgStore) CreateOrg(ctx context.Context, h db.Handler, user int64, name, email string) (models.Organization, error) {
 61	handle, err := s.CreateHandle(ctx, h, name)
 62	if err != nil {
 63		return models.Organization{}, err
 64	}
 65
 66	query := h.Rebind(`
 67		INSERT INTO
 68		  organizations (handle_id, contact_email, updated_at)
 69		VALUES
 70		  (?, ?, CURRENT_TIMESTAMP) RETURNING id;
 71	`)
 72
 73	var id int64
 74	if err := h.GetContext(ctx, &id, query, handle, email); err != nil {
 75		return models.Organization{}, err
 76	}
 77	if err := s.AddUserToOrg(ctx, h, id, user, access.AdminAccess); err != nil {
 78		return models.Organization{}, err
 79	}
 80
 81	return s.GetOrgByID(ctx, h, user, id)
 82}
 83
 84func (*orgStore) UpdateUserAccessInOrg(ctx context.Context, h db.Handler, org, user int64, lvl access.AccessLevel) error {
 85	query := h.Rebind(`
 86		UPDATE organization_members
 87		WHERE
 88		  organization_id = ?
 89		  AND user_id = ?
 90		SET
 91		  access_level = ?
 92	`)
 93	_, err := h.ExecContext(ctx, query, org, user, lvl)
 94	return err
 95}
 96
 97func (*orgStore) RemoveUserFromOrg(ctx context.Context, h db.Handler, org, user int64) error {
 98	query := h.Rebind(`
 99		DELETE FROM organization_members
100		WHERE
101		  organization_id = ?
102		  AND user_id = ?
103	`)
104	_, err := h.ExecContext(ctx, query, org, user)
105	return err
106}
107
108func (*orgStore) AddUserToOrg(ctx context.Context, h db.Handler, org, user int64, lvl access.AccessLevel) error {
109	query := h.Rebind(`
110		INSERT INTO
111		  organization_members (
112		    organization_id,
113		    user_id,
114		    access_level,
115		    updated_at
116		  )
117		VALUES
118		  (?, ?, ?, CURRENT_TIMESTAMP);
119	`)
120	_, err := h.ExecContext(ctx, query, org, user, lvl)
121	return err
122}
123
124// FindByName implements store.OrgStore.
125func (*orgStore) FindOrgByHandle(ctx context.Context, h db.Handler, user int64, name string) (models.Organization, error) {
126	var m models.Organization
127	query := h.Rebind(`
128		SELECT
129		  o.*,
130		  h AS handle
131		FROM
132		  organizations o
133		  JOIN handles h ON h.id = o.handle_id
134		  JOIN organization_members om ON om.organization_id = o.id
135		WHERE
136		  om.user_id = ?
137		  AND h.handle = ?;
138	`)
139	err := h.GetContext(ctx, &m, query, user, name)
140	return m, err
141}
142
143// GetByID implements store.OrgStore.
144func (s *orgStore) GetOrgByID(ctx context.Context, h db.Handler, user, id int64) (models.Organization, error) {
145	return s.getOrgByIDWithAccess(ctx, h, user, id, access.ReadOnlyAccess)
146}
147
148func (*orgStore) getOrgByIDWithAccess(ctx context.Context, h db.Handler, user, id int64, level access.AccessLevel) (models.Organization, error) {
149	var m models.Organization
150	query := h.Rebind(`
151		SELECT
152		  o.*,
153		  h AS handle
154		FROM
155		  organizations o
156		  JOIN handles h ON h.id = o.handle_id
157		  JOIN organization_members om ON om.organization_id = o.id
158		WHERE
159		  om.user_id = ?
160		  AND id = ?
161		  AND om.access_level >= ?;
162	`)
163	err := h.GetContext(ctx, &m, query, user, id, level)
164	return m, err
165}