You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			75 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			Python
		
	
			
		
		
	
	
			75 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			Python
		
	
"""Tornado handlers for the terminal emulator."""
 | 
						|
# Copyright (c) Jupyter Development Team.
 | 
						|
# Distributed under the terms of the Modified BSD License.
 | 
						|
from __future__ import annotations
 | 
						|
 | 
						|
import typing as t
 | 
						|
 | 
						|
from jupyter_core.utils import ensure_async
 | 
						|
from jupyter_server._tz import utcnow
 | 
						|
from jupyter_server.auth.utils import warn_disabled_authorization
 | 
						|
from jupyter_server.base.handlers import JupyterHandler
 | 
						|
from jupyter_server.base.websocket import WebSocketMixin
 | 
						|
from terminado.management import NamedTermManager
 | 
						|
from terminado.websocket import TermSocket as BaseTermSocket
 | 
						|
from tornado import web
 | 
						|
 | 
						|
from .base import TerminalsMixin
 | 
						|
 | 
						|
AUTH_RESOURCE = "terminals"
 | 
						|
 | 
						|
 | 
						|
class TermSocket(TerminalsMixin, WebSocketMixin, JupyterHandler, BaseTermSocket):
 | 
						|
    """A terminal websocket."""
 | 
						|
 | 
						|
    auth_resource = AUTH_RESOURCE
 | 
						|
 | 
						|
    def initialize(  # type:ignore[override]
 | 
						|
        self, name: str, term_manager: NamedTermManager, **kwargs: t.Any
 | 
						|
    ) -> None:
 | 
						|
        """Initialize the socket."""
 | 
						|
        BaseTermSocket.initialize(self, term_manager, **kwargs)
 | 
						|
        TerminalsMixin.initialize(self, name)
 | 
						|
 | 
						|
    def origin_check(self, origin: t.Any = None) -> bool:
 | 
						|
        """Terminado adds redundant origin_check
 | 
						|
        Tornado already calls check_origin, so don't do anything here.
 | 
						|
        """
 | 
						|
        return True
 | 
						|
 | 
						|
    async def get(self, *args: t.Any, **kwargs: t.Any) -> None:
 | 
						|
        """Get the terminal socket."""
 | 
						|
        user = self.current_user
 | 
						|
 | 
						|
        if not user:
 | 
						|
            raise web.HTTPError(403)
 | 
						|
 | 
						|
        # authorize the user.
 | 
						|
        if self.authorizer is None:
 | 
						|
            # Warn if an authorizer is unavailable.
 | 
						|
            warn_disabled_authorization()  # type:ignore[unreachable]
 | 
						|
        elif not self.authorizer.is_authorized(self, user, "execute", self.auth_resource):
 | 
						|
            raise web.HTTPError(403)
 | 
						|
 | 
						|
        if args[0] not in self.term_manager.terminals:  # type:ignore[attr-defined]
 | 
						|
            raise web.HTTPError(404)
 | 
						|
        resp = super().get(*args, **kwargs)
 | 
						|
        if resp is not None:
 | 
						|
            await ensure_async(resp)  # type:ignore[arg-type]
 | 
						|
 | 
						|
    async def on_message(self, message: t.Any) -> None:  # type:ignore[override]
 | 
						|
        """Handle a socket message."""
 | 
						|
        await ensure_async(super().on_message(message))  # type:ignore[arg-type]
 | 
						|
        self._update_activity()
 | 
						|
 | 
						|
    def write_message(self, message: t.Any, binary: bool = False) -> None:  # type:ignore[override]
 | 
						|
        """Write a message to the socket."""
 | 
						|
        super().write_message(message, binary=binary)
 | 
						|
        self._update_activity()
 | 
						|
 | 
						|
    def _update_activity(self) -> None:
 | 
						|
        self.application.settings["terminal_last_activity"] = utcnow()
 | 
						|
        # terminal may not be around on deletion/cull
 | 
						|
        if self.term_name in self.terminal_manager.terminals:
 | 
						|
            self.terminal_manager.terminals[self.term_name].last_activity = utcnow()  # type:ignore[attr-defined]
 |