@@ -3,6 +3,7 @@ package workspaceapps
3
3
import (
4
4
"context"
5
5
"database/sql"
6
+ "errors"
6
7
"fmt"
7
8
"net/url"
8
9
"strconv"
@@ -317,6 +318,40 @@ func (r Request) getDatabase(ctx context.Context, db database.Store) (*databaseR
317
318
// This is only supported for subdomain-based applications.
318
319
appURL = fmt .Sprintf ("http://127.0.0.1:%d" , portUint )
319
320
appSharingLevel = database .AppSharingLevelOwner
321
+
322
+ // Port sharing authorization
323
+ // First check if there is a port share for the port
324
+ agentName := agentNameOrID
325
+ id , err := uuid .Parse (agentNameOrID )
326
+ if err == nil {
327
+ // If parsing works it's an ID, let's get the name
328
+ agent , err := db .GetWorkspaceAgentByID (ctx , id )
329
+ if err != nil {
330
+ return nil , xerrors .Errorf ("get workspace agent %q: %w" , agentNameOrID , err )
331
+ }
332
+ agentName = agent .Name
333
+ }
334
+
335
+ ps , err := db .GetWorkspaceAgentPortShare (ctx , database.GetWorkspaceAgentPortShareParams {
336
+ WorkspaceID : workspace .ID ,
337
+ AgentName : agentName ,
338
+ Port : int32 (portUint ),
339
+ })
340
+ if err != nil {
341
+ if ! errors .Is (err , sql .ErrNoRows ) {
342
+ return nil , xerrors .Errorf ("get workspace agent port share: %w" , err )
343
+ }
344
+ // No port share found, so we keep default to owner.
345
+ } else {
346
+ switch ps .ShareLevel {
347
+ case int32 (codersdk .WorkspaceAgentPortShareLevelAuthenticated ):
348
+ appSharingLevel = database .AppSharingLevelAuthenticated
349
+ case int32 (codersdk .WorkspaceAgentPortShareLevelPublic ):
350
+ appSharingLevel = database .AppSharingLevelPublic
351
+ default :
352
+ return nil , xerrors .Errorf ("invalid port share level %d" , ps .ShareLevel )
353
+ }
354
+ }
320
355
} else {
321
356
for _ , app := range apps {
322
357
if app .Slug == r .AppSlugOrPort {
0 commit comments