diff --git a/platypush/message/response/system/__init__.py b/platypush/message/response/system/__init__.py index f08458588..26631b12e 100644 --- a/platypush/message/response/system/__init__.py +++ b/platypush/message/response/system/__init__.py @@ -8,30 +8,6 @@ class SystemResponse(Response): pass -class ConnectUserResponse(SystemResponse): - def __init__( - self, - name: str, - terminal: str, - host: str, - started: datetime, - pid: Optional[int] = None, - *args, - **kwargs - ): - super().__init__( - *args, - output={ - 'name': name, - 'terminal': terminal, - 'host': host, - 'started': started, - 'pid': pid, - }, - **kwargs - ) - - class ProcessResponse(SystemResponse): def __init__( self, @@ -93,11 +69,6 @@ class SystemResponseList(SystemResponse): super().__init__(output=[r.output for r in responses], *args, **kwargs) -class ConnectedUserResponseList(SystemResponseList): - def __init__(self, responses: List[ConnectUserResponse], *args, **kwargs): - super().__init__(responses=responses, *args, **kwargs) - - class ProcessResponseList(SystemResponseList): def __init__(self, responses: List[ProcessResponse], *args, **kwargs): super().__init__(responses=responses, *args, **kwargs) diff --git a/platypush/plugins/system/__init__.py b/platypush/plugins/system/__init__.py index 8d50e8392..9d527be7d 100644 --- a/platypush/plugins/system/__init__.py +++ b/platypush/plugins/system/__init__.py @@ -24,8 +24,6 @@ from platypush.entities.system import ( SystemTemperature, ) from platypush.message.response.system import ( - ConnectedUserResponseList, - ConnectUserResponse, ProcessResponseList, ProcessResponse, ) @@ -56,6 +54,8 @@ from platypush.schemas.system import ( SystemInfoSchema, Temperature, TemperatureSchema, + User, + UserSchema, ) @@ -403,26 +403,17 @@ class SystemPlugin(SensorPlugin, EntityManager): battery = self._sensors_battery() return BatterySchema().dump(battery) if battery else None # type: ignore + def _connected_users(self) -> List[User]: + return UserSchema().load(psutil.users(), many=True) # type: ignore + @action - def connected_users(self) -> ConnectedUserResponseList: + def connected_users(self) -> List[dict]: """ Get the list of connected users. - :return: List of :class:`platypush.message.response.system.ConnectUserResponse`. - """ - users = psutil.users() - return ConnectedUserResponseList( - [ - ConnectUserResponse( - name=u.name, - terminal=u.terminal, - host=u.host, - started=datetime.fromtimestamp(u.started), - pid=u.pid, - ) - for u in users - ] - ) + :return: .. schema:: system.UserSchema + """ + return UserSchema().dump(self._connected_users(), many=True) @action def processes(self, filter: Optional[str] = '') -> ProcessResponseList: diff --git a/platypush/schemas/system/__init__.py b/platypush/schemas/system/__init__.py index 437b6ef64..7292522cd 100644 --- a/platypush/schemas/system/__init__.py +++ b/platypush/schemas/system/__init__.py @@ -18,6 +18,7 @@ from ._model import SystemInfo from ._network import NetworkInterface, NetworkInterfaceSchema from ._schemas import SystemInfoSchema from ._temperature import Temperature, TemperatureSchema +from ._user import User, UserSchema __all__ = [ @@ -48,4 +49,6 @@ __all__ = [ "SystemInfoSchema", "Temperature", "TemperatureSchema", + "User", + "UserSchema", ] diff --git a/platypush/schemas/system/_user/__init__.py b/platypush/schemas/system/_user/__init__.py new file mode 100644 index 000000000..643cabc8c --- /dev/null +++ b/platypush/schemas/system/_user/__init__.py @@ -0,0 +1,4 @@ +from ._model import User +from ._schemas import UserSchema + +__all__ = ['User', 'UserSchema'] diff --git a/platypush/schemas/system/_user/_base.py b/platypush/schemas/system/_user/_base.py new file mode 100644 index 000000000..be32bb4f6 --- /dev/null +++ b/platypush/schemas/system/_user/_base.py @@ -0,0 +1,22 @@ +from datetime import datetime + +from dateutil.tz import gettz +from marshmallow import pre_load + +from .._base import SystemBaseSchema + + +class UserBaseSchema(SystemBaseSchema): + """ + Base schema for system users. + """ + + @pre_load + def pre_load(self, data: dict, **_) -> dict: + data = super().pre_load(data) + started_ts = data.pop('started', None) + if started_ts is not None: + data['started'] = datetime.fromtimestamp(started_ts).replace(tzinfo=gettz()) + + data['username'] = data.pop('name', data.pop('username', None)) + return data diff --git a/platypush/schemas/system/_user/_model.py b/platypush/schemas/system/_user/_model.py new file mode 100644 index 000000000..d957547b1 --- /dev/null +++ b/platypush/schemas/system/_user/_model.py @@ -0,0 +1,46 @@ +from dataclasses import dataclass, field +from datetime import datetime +from typing import Optional + + +@dataclass +class User: + """ + System user wrapper. + """ + + username: str = field( + metadata={ + 'metadata': { + 'description': 'Username', + 'example': 'root', + } + } + ) + + terminal: Optional[str] = field( + metadata={ + 'metadata': { + 'description': 'Identifier of the terminal the user is connected to', + 'example': 'pts/1', + } + } + ) + + started: Optional[datetime] = field( + metadata={ + 'metadata': { + 'description': 'When the user session started', + 'example': 'pts/1', + } + } + ) + + pid: Optional[int] = field( + metadata={ + 'metadata': { + 'description': 'PID of the process that holds the session', + 'example': 12345, + } + } + ) diff --git a/platypush/schemas/system/_user/_schemas.py b/platypush/schemas/system/_user/_schemas.py new file mode 100644 index 000000000..ae3395db7 --- /dev/null +++ b/platypush/schemas/system/_user/_schemas.py @@ -0,0 +1,7 @@ +from marshmallow_dataclass import class_schema + +from ._base import UserBaseSchema +from ._model import User + + +UserSchema = class_schema(User, base_schema=UserBaseSchema)