Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 170a6e1

Browse files
feat: add chat sharing foundation (#25041)
1 parent 2732378 commit 170a6e1

49 files changed

Lines changed: 1872 additions & 103 deletions

Some content is hidden

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

cli/testdata/coder_server_--help.golden

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ OPTIONS:
3636
creating a token without specifying a duration, such as when
3737
authenticating the CLI or an IDE plugin.
3838

39+
--disable-chat-sharing bool, $CODER_DISABLE_CHAT_SHARING
40+
Disable chat sharing. Chat ACL checking is disabled and only owners
41+
can access their chats.
42+
3943
--disable-owner-workspace-access bool, $CODER_DISABLE_OWNER_WORKSPACE_ACCESS
4044
Remove the permission for the 'owner' role to have workspace execution
4145
on all workspaces. This prevents the 'owner' from ssh, apps, and

cli/testdata/server-config.yaml.golden

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -530,6 +530,10 @@ disableOwnerWorkspaceAccess: false
530530
# --disable-owner-workspace-access.
531531
# (default: <unset>, type: bool)
532532
disableWorkspaceSharing: false
533+
# Disable chat sharing. Chat ACL checking is disabled and only owners can access
534+
# their chats.
535+
# (default: <unset>, type: bool)
536+
disableChatSharing: false
533537
# These options change the behavior of how clients interact with the Coder.
534538
# Clients include the Coder CLI, Coder Desktop, IDE extensions, and the web UI.
535539
client:

coderd/apidoc/docs.go

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/apidoc/swagger.json

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/coderd.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -343,16 +343,20 @@ func New(options *Options) *API {
343343
panic("developer error: options.PrometheusRegistry is nil and not running a unit test")
344344
}
345345

346-
if options.DeploymentValues.DisableOwnerWorkspaceExec || options.DeploymentValues.DisableWorkspaceSharing {
346+
if options.DeploymentValues.DisableOwnerWorkspaceExec || options.DeploymentValues.DisableWorkspaceSharing || options.DeploymentValues.DisableChatSharing {
347347
rbac.ReloadBuiltinRoles(&rbac.RoleOptions{
348348
NoOwnerWorkspaceExec: bool(options.DeploymentValues.DisableOwnerWorkspaceExec),
349349
NoWorkspaceSharing: bool(options.DeploymentValues.DisableWorkspaceSharing),
350+
NoChatSharing: bool(options.DeploymentValues.DisableChatSharing),
350351
})
351352
}
352353

353354
if options.DeploymentValues.DisableWorkspaceSharing {
354355
rbac.SetWorkspaceACLDisabled(true)
355356
}
357+
if options.DeploymentValues.DisableChatSharing {
358+
rbac.SetChatACLDisabled(true)
359+
}
356360

357361
if options.PrometheusRegistry == nil {
358362
options.PrometheusRegistry = prometheus.NewRegistry()

coderd/database/check_constraint.go

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/dbauthz/dbauthz.go

Lines changed: 71 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2682,6 +2682,17 @@ func (q *querier) GetAuthorizationUserRoles(ctx context.Context, userID uuid.UUI
26822682
return q.db.GetAuthorizationUserRoles(ctx, userID)
26832683
}
26842684

2685+
func (q *querier) GetChatACLByID(ctx context.Context, id uuid.UUID) (database.GetChatACLByIDRow, error) {
2686+
chat, err := q.db.GetChatByID(ctx, id)
2687+
if err != nil {
2688+
return database.GetChatACLByIDRow{}, err
2689+
}
2690+
if err := q.authorizeContext(ctx, policy.ActionRead, chat); err != nil {
2691+
return database.GetChatACLByIDRow{}, err
2692+
}
2693+
return q.db.GetChatACLByID(ctx, id)
2694+
}
2695+
26852696
func (q *querier) GetChatAdvisorConfig(ctx context.Context) (string, error) {
26862697
// The advisor configuration is a deployment-wide setting read by any
26872698
// authenticated chat user and by chatd when deciding whether to attach
@@ -2884,25 +2895,56 @@ func (q *querier) GetChatFileByID(ctx context.Context, id uuid.UUID) (database.C
28842895
if err != nil {
28852896
return database.ChatFile{}, err
28862897
}
2887-
if err := q.authorizeContext(ctx, policy.ActionRead, file); err != nil {
2898+
fileAuthErr := q.authorizeContext(ctx, policy.ActionRead, file)
2899+
if fileAuthErr == nil {
2900+
return file, nil
2901+
}
2902+
2903+
prepared, err := prepareSQLFilter(ctx, q.auth, policy.ActionRead, rbac.ResourceChat.Type)
2904+
if err != nil {
2905+
return database.ChatFile{}, xerrors.Errorf("(dev error) prepare sql filter: %w", err)
2906+
}
2907+
chats, err := q.db.GetAuthorizedChatsByChatFileID(ctx, id, prepared)
2908+
if err != nil {
28882909
return database.ChatFile{}, err
28892910
}
2911+
if len(chats) == 0 {
2912+
return database.ChatFile{}, fileAuthErr
2913+
}
28902914
return file, nil
28912915
}
28922916

28932917
func (q *querier) GetChatFileMetadataByChatID(ctx context.Context, chatID uuid.UUID) ([]database.GetChatFileMetadataByChatIDRow, error) {
2894-
return fetchWithPostFilter(q.auth, policy.ActionRead, q.db.GetChatFileMetadataByChatID)(ctx, chatID)
2918+
if _, err := q.GetChatByID(ctx, chatID); err != nil {
2919+
return nil, err
2920+
}
2921+
return q.db.GetChatFileMetadataByChatID(ctx, chatID)
28952922
}
28962923

28972924
func (q *querier) GetChatFilesByIDs(ctx context.Context, ids []uuid.UUID) ([]database.ChatFile, error) {
28982925
files, err := q.db.GetChatFilesByIDs(ctx, ids)
28992926
if err != nil {
29002927
return nil, err
29012928
}
2929+
var prepared rbac.PreparedAuthorized
29022930
for _, f := range files {
2903-
if err := q.authorizeContext(ctx, policy.ActionRead, f); err != nil {
2931+
fileAuthErr := q.authorizeContext(ctx, policy.ActionRead, f)
2932+
if fileAuthErr == nil {
2933+
continue
2934+
}
2935+
if prepared == nil {
2936+
prepared, err = prepareSQLFilter(ctx, q.auth, policy.ActionRead, rbac.ResourceChat.Type)
2937+
if err != nil {
2938+
return nil, xerrors.Errorf("(dev error) prepare sql filter: %w", err)
2939+
}
2940+
}
2941+
chats, err := q.db.GetAuthorizedChatsByChatFileID(ctx, f.ID, prepared)
2942+
if err != nil {
29042943
return nil, err
29052944
}
2945+
if len(chats) == 0 {
2946+
return nil, fileAuthErr
2947+
}
29062948
}
29072949
return files, nil
29082950
}
@@ -3164,6 +3206,10 @@ func (q *querier) GetChats(ctx context.Context, arg database.GetChatsParams) ([]
31643206
return q.db.GetAuthorizedChats(ctx, arg, prep)
31653207
}
31663208

3209+
func (q *querier) GetChatsByChatFileID(ctx context.Context, fileID uuid.UUID) ([]database.Chat, error) {
3210+
return fetchWithPostFilter(q.auth, policy.ActionRead, q.db.GetChatsByChatFileID)(ctx, fileID)
3211+
}
3212+
31673213
func (q *querier) GetChatsByWorkspaceIDs(ctx context.Context, ids []uuid.UUID) ([]database.Chat, error) {
31683214
return fetchWithPostFilter(q.auth, policy.ActionRead, q.db.GetChatsByWorkspaceIDs)(ctx, ids)
31693215
}
@@ -6392,6 +6438,24 @@ func (q *querier) UpdateAPIKeyByID(ctx context.Context, arg database.UpdateAPIKe
63926438
return update(q.log, q.auth, fetch, q.db.UpdateAPIKeyByID)(ctx, arg)
63936439
}
63946440

6441+
func (q *querier) UpdateChatACLByID(ctx context.Context, arg database.UpdateChatACLByIDParams) error {
6442+
if rbac.ChatACLDisabled() {
6443+
return NotAuthorizedError{Err: xerrors.New("chat sharing is disabled")}
6444+
}
6445+
fetch := func(ctx context.Context, arg database.UpdateChatACLByIDParams) (database.Chat, error) {
6446+
chat, err := q.db.GetChatByID(ctx, arg.ID)
6447+
if err != nil {
6448+
return database.Chat{}, err
6449+
}
6450+
if chat.IsSubChat() {
6451+
return database.Chat{}, NotAuthorizedError{Err: xerrors.New("chat ACLs can only be updated on root chats")}
6452+
}
6453+
return chat, nil
6454+
}
6455+
6456+
return fetchAndExec(q.log, q.auth, policy.ActionShare, fetch, q.db.UpdateChatACLByID)(ctx, arg)
6457+
}
6458+
63956459
func (q *querier) UpdateChatBuildAgentBinding(ctx context.Context, arg database.UpdateChatBuildAgentBindingParams) (database.Chat, error) {
63966460
chat, err := q.db.GetChatByID(ctx, arg.ID)
63976461
if err != nil {
@@ -8323,3 +8387,7 @@ func (q *querier) ListAuthorizedAIBridgeSessionThreads(ctx context.Context, arg
83238387
func (q *querier) GetAuthorizedChats(ctx context.Context, arg database.GetChatsParams, _ rbac.PreparedAuthorized) ([]database.GetChatsRow, error) {
83248388
return q.GetChats(ctx, arg)
83258389
}
8390+
8391+
func (q *querier) GetAuthorizedChatsByChatFileID(ctx context.Context, fileID uuid.UUID, prepared rbac.PreparedAuthorized) ([]database.Chat, error) {
8392+
return q.db.GetAuthorizedChatsByChatFileID(ctx, fileID, prepared)
8393+
}

0 commit comments

Comments
 (0)