package main import ( "context" "atlas9.dev/c/core" "atlas9.dev/c/core/dbi" "atlas9.dev/c/core/iam" ) type SqliteTenantMemberStore struct { db dbi.DBI } var _ iam.TenantMemberStore = (*SqliteTenantMemberStore)(nil) func NewSqliteTenantMemberStore(db dbi.DBI) *SqliteTenantMemberStore { return &SqliteTenantMemberStore{db: db} } func (s *SqliteTenantMemberStore) Add(ctx context.Context, tenantID core.ID, userID core.ID, status iam.MemberStatus) error { _, err := s.db.Exec(ctx, ` INSERT INTO tenant_members (tenant_id, user_id, status) VALUES ($1, $2, $3) ON CONFLICT (tenant_id, user_id) DO NOTHING `, tenantID, userID, status) return err } func (s *SqliteTenantMemberStore) SetStatus(ctx context.Context, tenantID core.ID, userID core.ID, status iam.MemberStatus) error { _, err := s.db.Exec(ctx, ` UPDATE tenant_members SET status = $1 WHERE tenant_id = $2 AND user_id = $3 `, status, tenantID, userID) return err } func (s *SqliteTenantMemberStore) Remove(ctx context.Context, tenantID core.ID, userID core.ID) error { if tenantID.Equal(userID) { var tenantType iam.TenantType err := s.db.QueryRow(ctx, `SELECT type FROM tenants WHERE id = $1`, tenantID).Scan(&tenantType) if err == nil && tenantType == iam.TenantPersonal { return iam.ErrCannotRemovePersonalTenantOwner } } _, err := s.db.Exec(ctx, ` DELETE FROM tenant_members WHERE tenant_id = $1 AND user_id = $2 `, tenantID, userID) return err } func (s *SqliteTenantMemberStore) Get(ctx context.Context, tenantID core.ID, userID core.ID) (*iam.TenantMember, error) { var m iam.TenantMember err := dbi.Get(ctx, s.db, &m, ` SELECT tenant_id, user_id, status FROM tenant_members WHERE tenant_id = $1 AND user_id = $2 `, tenantID, userID) return &m, err } func (s *SqliteTenantMemberStore) ListByTenant(ctx context.Context, tenantID core.ID, page core.PageReq) (core.Page[iam.TenantMember], error) { limit := page.Limit if limit <= 0 { limit = 100 } rows, err := s.db.Query(ctx, ` SELECT tenant_id, user_id, status FROM tenant_members WHERE tenant_id = $1 AND user_id > $2 ORDER BY user_id LIMIT $3 `, tenantID, page.Cursor, limit) if err != nil { return core.Page[iam.TenantMember]{}, err } defer rows.Close() var items []iam.TenantMember for rows.Next() { var m iam.TenantMember if err := rows.Scan(&m.TenantID, &m.UserID, &m.Status); err != nil { return core.Page[iam.TenantMember]{}, err } items = append(items, m) } if err := rows.Err(); err != nil { return core.Page[iam.TenantMember]{}, err } var cursor string if len(items) == limit { cursor = items[limit-1].UserID.String() } return core.Page[iam.TenantMember]{Items: items, Cursor: cursor}, nil } func (s *SqliteTenantMemberStore) ListByUser(ctx context.Context, userID core.ID, page core.PageReq) (core.Page[iam.TenantMember], error) { limit := page.Limit if limit <= 0 { limit = 100 } rows, err := s.db.Query(ctx, ` SELECT tenant_id, user_id, status FROM tenant_members WHERE user_id = $1 AND tenant_id > $2 ORDER BY tenant_id LIMIT $3 `, userID, page.Cursor, limit) if err != nil { return core.Page[iam.TenantMember]{}, err } defer rows.Close() var items []iam.TenantMember for rows.Next() { var m iam.TenantMember if err := rows.Scan(&m.TenantID, &m.UserID, &m.Status); err != nil { return core.Page[iam.TenantMember]{}, err } items = append(items, m) } if err := rows.Err(); err != nil { return core.Page[iam.TenantMember]{}, err } var cursor string if len(items) == limit { cursor = items[limit-1].TenantID.String() } return core.Page[iam.TenantMember]{Items: items, Cursor: cursor}, nil }