@@ -17,6 +17,7 @@ import (
1717
1818 "cdr.dev/slog"
1919 "cdr.dev/slog/sloggers/sloghuman"
20+ "github.com/coder/preview/types"
2021 "github.com/coder/preview/web"
2122 "github.com/coder/serpent"
2223 "github.com/coder/websocket"
@@ -80,6 +81,15 @@ func (r *RootCmd) WebsocketServer() *serpent.Command {
8081
8182 mux .Use (debugMiddleware (logger ))
8283
84+ mux .HandleFunc ("/users/{dir}" , func (rw http.ResponseWriter , r * http.Request ) {
85+ dirFS := os .DirFS (chi .URLParam (r , "dir" ))
86+ availableUsers , err := availableUsers (dirFS )
87+ if err != nil {
88+ http .Error (rw , err .Error (), http .StatusInternalServerError )
89+ return
90+ }
91+ _ = json .NewEncoder (rw ).Encode (availableUsers )
92+ })
8393 mux .HandleFunc ("/directories" , func (rw http.ResponseWriter , r * http.Request ) {
8494 entries , err := os .ReadDir ("." )
8595 if err != nil {
@@ -132,19 +142,19 @@ func (r *RootCmd) WebsocketServer() *serpent.Command {
132142
133143func websocketHandler (logger slog.Logger ) func (rw http.ResponseWriter , r * http.Request ) {
134144 return func (rw http.ResponseWriter , r * http.Request ) {
135-
136- logger .Debug (r .Context (), "WebSocket connection attempt" ,
145+
146+ logger .Debug (r .Context (), "WebSocket connection attempt" ,
137147 slog .F ("remote_addr" , r .RemoteAddr ),
138148 slog .F ("path" , r .URL .Path ),
139149 slog .F ("query" , r .URL .RawQuery ))
140-
150+
141151 // Validate all parameters BEFORE upgrading the connection
142152 dir := chi .URLParam (r , "dir" )
143153 logger .Debug (r .Context (), "Directory parameter" , slog .F ("dir" , dir ))
144-
154+
145155 dinfo , err := os .Stat (dir )
146156 if err != nil {
147- logger .Error (r .Context (), "Directory validation failed" ,
157+ logger .Error (r .Context (), "Directory validation failed" ,
148158 slog .Error (err ),
149159 slog .F ("dir" , dir ))
150160 http .Error (rw , "Could not stat directory: " + err .Error (), http .StatusBadRequest )
@@ -173,11 +183,57 @@ func websocketHandler(logger slog.Logger) func(rw http.ResponseWriter, r *http.R
173183 return
174184 }
175185 logger .Debug (r .Context (), "WebSocket connection established" )
176-
186+
187+ var owner types.WorkspaceOwner
177188 dirFS := os .DirFS (dir )
178189 planPath := r .URL .Query ().Get ("plan" )
190+ user := r .URL .Query ().Get ("user" )
191+ if user != "" {
192+ available , err := availableUsers (dirFS )
193+ if err != nil {
194+ _ = conn .Close (websocket .StatusInternalError , err .Error ())
195+ return
196+ }
197+
198+ var ok bool
199+ owner , ok = available [user ]
200+ if ! ok {
201+ _ = conn .Close (websocket .StatusInternalError , err .Error ())
202+ return
203+ }
204+ }
179205
180- session := web .NewSession (logger , dirFS , planPath )
206+ session := web .NewSession (logger , dirFS , web.SessionInputs {
207+ PlanPath : planPath ,
208+ User : owner ,
209+ })
181210 session .Listen (r .Context (), conn )
182211 }
183212}
213+
214+ func availableUsers (dirFS fs.FS ) (map [string ]types.WorkspaceOwner , error ) {
215+ entries , err := fs .ReadDir (dirFS , "." )
216+ if err != nil {
217+ return nil , fmt .Errorf ("could not read directory: %w" , err )
218+ }
219+
220+ idx := slices .IndexFunc (entries , func (entry fs.DirEntry ) bool {
221+ return entry .Name () == "users.json"
222+ })
223+ if idx == - 1 {
224+ return map [string ]types.WorkspaceOwner {}, nil
225+ }
226+
227+ file , err := dirFS .Open (entries [idx ].Name ())
228+ if err != nil {
229+ return nil , fmt .Errorf ("could not open users file: %w" , err )
230+ }
231+ defer file .Close ()
232+
233+ var users map [string ]types.WorkspaceOwner
234+ if err := json .NewDecoder (file ).Decode (& users ); err != nil {
235+ return nil , fmt .Errorf ("could not decode users file: %w" , err )
236+ }
237+
238+ return users , nil
239+ }
0 commit comments