Skip to content

Commit fec19ee

Browse files
committed
Merge branch 'main' into worktree-feat-project-dashboard-organization
2 parents de8e265 + 596dd3d commit fec19ee

530 files changed

Lines changed: 39488 additions & 21387 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/cli-release.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,6 @@ jobs:
5858
env:
5959
RILL_UI_PUBLIC_INTAKE_USER: "data-modeler"
6060
RILL_UI_PUBLIC_INTAKE_PASSWORD: ${{ secrets.RILL_INTAKE_PASSWORD }}
61-
RILL_UI_PUBLIC_POSTHOG_API_KEY: "phc_4qnfUotXUuevk2zJN8ei8HgKXMynddEMI0wPI9XwzlS"
6261
RILL_UI_PUBLIC_PYLON_APP_ID: "26a0fdd2-3bd3-41e2-82bc-1b35a444729f"
6362
NODE_OPTIONS: --max-old-space-size=4096
6463

.github/workflows/rill-ui.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,6 @@ jobs:
9898
npm run build -w web-admin
9999
env:
100100
RILL_UI_PUBLIC_RILL_ADMIN_URL: https://admin.${{ env.DOMAIN }}
101-
RILL_UI_PUBLIC_POSTHOG_API_KEY: "phc_4qnfUotXUuevk2zJN8ei8HgKXMynddEMI0wPI9XwzlS"
102101
RILL_UI_PUBLIC_PYLON_APP_ID: "26a0fdd2-3bd3-41e2-82bc-1b35a444729f"
103102
RILL_UI_PUBLIC_VERSION: ${{ env.RILL_VERSION }}
104103

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ saved-state.json
5757
last-query-output.json
5858
staging-databases
5959
/rilldata
60+
/rill-examples/
6061
docs/dist/
6162
coverage
6263
# locally deployed test projects can generate this
@@ -98,6 +99,7 @@ latest.txt
9899
.claude/plans/
99100
.claude/worktrees/
100101
.claude/projects/
102+
.mcp.json
101103

102104
# Vite temp files
103105
vite.config.ts.timestamp-*

.mcp.json

Lines changed: 0 additions & 24 deletions
This file was deleted.

admin/auth_token.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,26 @@ func (s *Service) IssueMagicAuthToken(ctx context.Context, opts *IssueMagicAuthT
226226
return &magicAuthToken{model: dat, token: tkn}, nil
227227
}
228228

229+
// ExtendBrowserSessionAuthToken extends a Rill web browser session token when its
230+
// remaining lifetime is at or below refreshThreshold.
231+
func (s *Service) ExtendBrowserSessionAuthToken(ctx context.Context, authTok AuthToken, fullTTL, refreshThreshold time.Duration) error {
232+
uat, ok := authTok.TokenModel().(*database.UserAuthToken)
233+
if !ok {
234+
return nil
235+
}
236+
if uat.AuthClientID == nil || *uat.AuthClientID != database.AuthClientIDRillWeb {
237+
return nil
238+
}
239+
if uat.RepresentingUserID != nil || uat.Refresh {
240+
return nil
241+
}
242+
if uat.ExpiresOn != nil && time.Until(*uat.ExpiresOn) > refreshThreshold {
243+
return nil
244+
}
245+
newExpiresOn := time.Now().Add(fullTTL)
246+
return s.DB.UpdateUserAuthTokenExpiresOn(ctx, uat.ID, newExpiresOn)
247+
}
248+
229249
// RevokeAuthToken removes an auth token from persistent storage.
230250
func (s *Service) RevokeAuthToken(ctx context.Context, token string) error {
231251
parsed, err := authtoken.FromString(token)

admin/billing.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ func (s *Service) InitOrganizationBilling(ctx context.Context, org *database.Org
6161
QuotaSlotsPerDeployment: org.QuotaSlotsPerDeployment,
6262
QuotaOutstandingInvites: org.QuotaOutstandingInvites,
6363
QuotaStorageLimitBytesPerDeployment: org.QuotaStorageLimitBytesPerDeployment,
64+
QuotaSeats: org.QuotaSeats,
6465
BillingCustomerID: org.BillingCustomerID,
6566
PaymentCustomerID: org.PaymentCustomerID,
6667
BillingEmail: org.BillingEmail,
@@ -169,6 +170,7 @@ func (s *Service) RepairOrganizationBilling(ctx context.Context, org *database.O
169170
QuotaSlotsPerDeployment: org.QuotaSlotsPerDeployment,
170171
QuotaOutstandingInvites: org.QuotaOutstandingInvites,
171172
QuotaStorageLimitBytesPerDeployment: org.QuotaStorageLimitBytesPerDeployment,
173+
QuotaSeats: org.QuotaSeats,
172174
BillingCustomerID: org.BillingCustomerID,
173175
PaymentCustomerID: org.PaymentCustomerID,
174176
BillingEmail: org.BillingEmail,
@@ -233,6 +235,7 @@ func (s *Service) RepairOrganizationBilling(ctx context.Context, org *database.O
233235
QuotaSlotsPerDeployment: biggerOfInt(sub.Plan.Quotas.NumSlotsPerDeployment, org.QuotaSlotsPerDeployment),
234236
QuotaOutstandingInvites: biggerOfInt(sub.Plan.Quotas.NumOutstandingInvites, org.QuotaOutstandingInvites),
235237
QuotaStorageLimitBytesPerDeployment: biggerOfInt64(sub.Plan.Quotas.StorageLimitBytesPerDeployment, org.QuotaStorageLimitBytesPerDeployment),
238+
QuotaSeats: biggerOfInt(sub.Plan.Quotas.NumSeats, org.QuotaSeats),
236239
BillingCustomerID: org.BillingCustomerID,
237240
PaymentCustomerID: org.PaymentCustomerID,
238241
BillingEmail: org.BillingEmail,
@@ -328,6 +331,7 @@ func (s *Service) StartCreditTrial(ctx context.Context, org *database.Organizati
328331
QuotaSlotsPerDeployment: biggerOfInt(plan.Quotas.NumSlotsPerDeployment, org.QuotaSlotsPerDeployment),
329332
QuotaOutstandingInvites: biggerOfInt(plan.Quotas.NumOutstandingInvites, org.QuotaOutstandingInvites),
330333
QuotaStorageLimitBytesPerDeployment: biggerOfInt64(plan.Quotas.StorageLimitBytesPerDeployment, org.QuotaStorageLimitBytesPerDeployment),
334+
QuotaSeats: biggerOfInt(plan.Quotas.NumSeats, org.QuotaSeats),
331335
BillingCustomerID: org.BillingCustomerID,
332336
PaymentCustomerID: org.PaymentCustomerID,
333337
BillingEmail: org.BillingEmail,
@@ -432,6 +436,7 @@ func (s *Service) StartTrial(ctx context.Context, org *database.Organization) (*
432436
QuotaSlotsPerDeployment: biggerOfInt(plan.Quotas.NumSlotsPerDeployment, org.QuotaSlotsPerDeployment),
433437
QuotaOutstandingInvites: biggerOfInt(plan.Quotas.NumOutstandingInvites, org.QuotaOutstandingInvites),
434438
QuotaStorageLimitBytesPerDeployment: biggerOfInt64(plan.Quotas.StorageLimitBytesPerDeployment, org.QuotaStorageLimitBytesPerDeployment),
439+
QuotaSeats: biggerOfInt(plan.Quotas.NumSeats, org.QuotaSeats),
435440
BillingCustomerID: org.BillingCustomerID,
436441
PaymentCustomerID: org.PaymentCustomerID,
437442
BillingEmail: org.BillingEmail,
@@ -502,7 +507,7 @@ func (s *Service) RaiseNewOrgBillingIssues(ctx context.Context, orgID string, cr
502507
_, err := s.DB.UpsertBillingIssue(ctx, &database.UpsertBillingIssueOptions{
503508
OrgID: orgID,
504509
Type: database.BillingIssueTypeNeverSubscribed,
505-
Metadata: database.BillingIssueMetadataNeverSubscribed{},
510+
Metadata: &database.BillingIssueMetadataNeverSubscribed{},
506511
EventTime: creationTime,
507512
})
508513
if err != nil {

admin/billing/biller.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import (
1313
const (
1414
SupportEmail = "support@rilldata.com"
1515
DefaultTimeZone = "UTC"
16+
// InternalEmailDomain is excluded from billable seat counts so internal Rill users don't count against an org's seats.
17+
InternalEmailDomain = "rilldata.com"
1618
)
1719

1820
// CreditsCurrency is the pricing-unit used for trial credit balance/alerts/grants. Its a non-monetary custom pricing unit, so trial usage never produces USD invoice line items.
@@ -107,6 +109,8 @@ const (
107109
EnterprisePlanType
108110
FreePlanType
109111
ProPlanType
112+
StarterPlanType
113+
GrowthPlanType
110114
)
111115

112116
type Plan struct {
@@ -129,6 +133,9 @@ type Quotas struct {
129133
NumSlotsTotal *int
130134
NumSlotsPerDeployment *int
131135
NumOutstandingInvites *int
136+
NumSeats *int
137+
NumAPICallsPerSeat *int
138+
NumTokensPerSeat *int
132139
}
133140

134141
type planMetadata struct {
@@ -140,6 +147,9 @@ type planMetadata struct {
140147
NumSlotsTotal *int `mapstructure:"num_slots_total"`
141148
NumSlotsPerDeployment *int `mapstructure:"num_slots_per_deployment"`
142149
NumOutstandingInvites *int `mapstructure:"num_outstanding_invites"`
150+
NumSeats *int `mapstructure:"num_seats"`
151+
NumAPICallsPerSeat *int `mapstructure:"num_api_calls_per_seat"`
152+
NumTokensPerSeat *int `mapstructure:"num_tokens_per_seat"`
143153
}
144154

145155
type Subscription struct {

admin/billing/orb.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ func (o *Orb) DefaultQuotas() Quotas {
5959
NumSlotsTotal: toPtr(40),
6060
NumSlotsPerDeployment: toPtr(8),
6161
NumOutstandingInvites: toPtr(200),
62+
NumSeats: toPtr(10),
63+
NumAPICallsPerSeat: toPtr(2500),
64+
NumTokensPerSeat: toPtr(1000000),
6265
}
6366
}
6467

@@ -715,6 +718,9 @@ func (o *Orb) getBillingPlanFromOrbPlan(ctx context.Context, p *orb.Plan) (*Plan
715718
NumSlotsTotal: metadata.NumSlotsTotal,
716719
NumSlotsPerDeployment: metadata.NumSlotsPerDeployment,
717720
NumOutstandingInvites: metadata.NumOutstandingInvites,
721+
NumSeats: metadata.NumSeats,
722+
NumAPICallsPerSeat: metadata.NumAPICallsPerSeat,
723+
NumTokensPerSeat: metadata.NumTokensPerSeat,
718724
}
719725

720726
trialPeriodDays := 0
@@ -794,6 +800,10 @@ func getPlanType(externalID string) PlanType {
794800
return FreePlanType
795801
case "pro_plan":
796802
return ProPlanType
803+
case "starter":
804+
return StarterPlanType
805+
case "growth":
806+
return GrowthPlanType
797807
default:
798808
return EnterprisePlanType
799809
}
@@ -811,6 +821,10 @@ func getPlanDisplayName(externalID string) string {
811821
return "Free"
812822
case "pro_plan":
813823
return "Pro"
824+
case "starter":
825+
return "Starter"
826+
case "growth":
827+
return "Growth"
814828
default:
815829
return "Enterprise"
816830
}

admin/canvases.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package admin
2+
3+
import (
4+
"context"
5+
6+
"github.com/rilldata/rill/admin/database"
7+
runtimev1 "github.com/rilldata/rill/proto/gen/rill/runtime/v1"
8+
"github.com/rilldata/rill/runtime"
9+
"google.golang.org/grpc/codes"
10+
"google.golang.org/grpc/status"
11+
)
12+
13+
// LookupCanvas fetches a canvas's spec from a runtime deployment.
14+
func (s *Service) LookupCanvas(ctx context.Context, depl *database.Deployment, canvasName string) (*runtimev1.CanvasSpec, error) {
15+
rt, err := s.OpenRuntimeClient(depl)
16+
if err != nil {
17+
return nil, err
18+
}
19+
defer rt.Close()
20+
21+
res, err := rt.GetResource(ctx, &runtimev1.GetResourceRequest{
22+
InstanceId: depl.RuntimeInstanceID,
23+
Name: &runtimev1.ResourceName{
24+
Kind: runtime.ResourceKindCanvas,
25+
Name: canvasName,
26+
},
27+
})
28+
if err != nil {
29+
return nil, err
30+
}
31+
32+
canvasResource := res.Resource.Resource.(*runtimev1.Resource_Canvas)
33+
if canvasResource != nil && canvasResource.Canvas != nil && canvasResource.Canvas.State != nil {
34+
return nil, status.Error(codes.NotFound, "resource not found")
35+
}
36+
return res.Resource.Resource.(*runtimev1.Resource_Canvas).Canvas.State.ValidSpec, nil
37+
}

admin/database/database.go

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ type DB interface {
164164
FindUserAuthToken(ctx context.Context, id string) (*UserAuthToken, error)
165165
InsertUserAuthToken(ctx context.Context, opts *InsertUserAuthTokenOptions) (*UserAuthToken, error)
166166
UpdateUserAuthTokenUsedOn(ctx context.Context, ids []string) error
167+
UpdateUserAuthTokenExpiresOn(ctx context.Context, id string, expiresOn time.Time) error
167168
DeleteUserAuthToken(ctx context.Context, id string) error
168169
DeleteAllUserAuthTokens(ctx context.Context, userID string) (int, error)
169170
DeleteUserAuthTokensByUserAndRepresentingUser(ctx context.Context, userID, representingUserID string) error
@@ -236,7 +237,7 @@ type DB interface {
236237

237238
FindOrganizationMemberUsers(ctx context.Context, orgID, filterRoleID string, withCounts bool, afterEmail string, limit int, searchPattern string) ([]*OrganizationMemberUser, error)
238239
FindOrganizationMemberUser(ctx context.Context, orgID, userID string) (*OrganizationMemberUser, error)
239-
CountOrganizationMemberUsers(ctx context.Context, orgID, filterRoleID string, searchPattern string) (int, error)
240+
CountOrganizationMemberUsers(ctx context.Context, orgID, filterRoleID, searchPattern string, negateSearch bool) (int, error)
240241
FindOrganizationMemberUsersByRole(ctx context.Context, orgID, roleID string) ([]*User, error)
241242
FindOrganizationMemberUserAdminStatus(ctx context.Context, orgID, userID string) (isAdmin, isLastAdmin bool, err error)
242243
InsertOrganizationMemberUser(ctx context.Context, orgID, userID, roleID string, attributes map[string]any, ifNotExists bool) (bool, error)
@@ -309,6 +310,8 @@ type DB interface {
309310

310311
FindVirtualFiles(ctx context.Context, projectID, environment string, afterUpdatedOn time.Time, afterPath string, limit int) ([]*VirtualFile, error)
311312
FindVirtualFile(ctx context.Context, projectID, environment, path string) (*VirtualFile, error)
313+
// FindVirtualFilesByOwner TODO: pagination
314+
FindVirtualFilesByOwner(ctx context.Context, projectID, environment, ownerID string) ([]*VirtualFile, error)
312315
UpsertVirtualFile(ctx context.Context, opts *InsertVirtualFileOptions) error
313316
UpdateVirtualFileDeleted(ctx context.Context, projectID, environment, path string) error
314317
DeleteExpiredVirtualFiles(ctx context.Context, retention time.Duration) error
@@ -392,6 +395,7 @@ type Organization struct {
392395
QuotaSlotsPerDeployment int `db:"quota_slots_per_deployment"`
393396
QuotaOutstandingInvites int `db:"quota_outstanding_invites"`
394397
QuotaStorageLimitBytesPerDeployment int64 `db:"quota_storage_limit_bytes_per_deployment"`
398+
QuotaSeats int `db:"quota_seats"`
395399
BillingCustomerID string `db:"billing_customer_id"`
396400
PaymentCustomerID string `db:"payment_customer_id"`
397401
BillingEmail string `db:"billing_email"`
@@ -417,6 +421,7 @@ type InsertOrganizationOptions struct {
417421
QuotaSlotsPerDeployment int
418422
QuotaOutstandingInvites int
419423
QuotaStorageLimitBytesPerDeployment int64
424+
QuotaSeats int
420425
BillingCustomerID string
421426
PaymentCustomerID string
422427
BillingEmail string
@@ -440,6 +445,7 @@ type UpdateOrganizationOptions struct {
440445
QuotaSlotsPerDeployment int
441446
QuotaOutstandingInvites int
442447
QuotaStorageLimitBytesPerDeployment int64
448+
QuotaSeats int
443449
BillingCustomerID string
444450
PaymentCustomerID string
445451
BillingEmail string
@@ -1225,6 +1231,7 @@ type UpdateBookmarkOptions struct {
12251231
type VirtualFile struct {
12261232
Path string `db:"path"`
12271233
Data []byte `db:"data"`
1234+
OwnerID *string `db:"owner_id"`
12281235
Deleted bool `db:"deleted"`
12291236
UpdatedOn time.Time `db:"updated_on"`
12301237
}
@@ -1233,8 +1240,9 @@ type VirtualFile struct {
12331240
type InsertVirtualFileOptions struct {
12341241
ProjectID string
12351242
Environment string
1236-
Path string `validate:"required"`
1237-
Data []byte `validate:"max=131072"` // 128kb
1243+
Path string `validate:"required"`
1244+
OwnerID *string `db:"owner_id"`
1245+
Data []byte `validate:"max=131072"` // 128kb
12381246
}
12391247

12401248
// Asset represents a user-uploaded file asset.
@@ -1315,6 +1323,7 @@ const (
13151323
BillingIssueTypeNeverSubscribed = 7
13161324
BillingIssueTypeOnCreditTrial = 8
13171325
BillingIssueTypeTrialCreditsDepleted = 9
1326+
BillingIssueTypeMessage = 10
13181327
)
13191328

13201329
type BillingIssueLevel int
@@ -1389,9 +1398,16 @@ type BillingIssueMetadataTrialCreditsDepleted struct {
13891398
DepletedOn time.Time `json:"depleted_on"`
13901399
}
13911400

1401+
type BillingIssueMetadataMessage struct {
1402+
Message string `json:"message"`
1403+
}
1404+
13921405
type UpsertBillingIssueOptions struct {
1393-
OrgID string `validate:"required"`
1394-
Type BillingIssueType `validate:"required"`
1406+
OrgID string `validate:"required"`
1407+
Type BillingIssueType `validate:"required"`
1408+
// Level is optional; if unspecified, it is derived from Type. It is used for types whose
1409+
// severity is not implied by the type itself (e.g. BillingIssueTypeMessage).
1410+
Level BillingIssueLevel `exhaustruct:"optional"`
13951411
Metadata BillingIssueMetadata
13961412
EventTime time.Time `validate:"required"`
13971413
}

0 commit comments

Comments
 (0)