added basic documentation with pyscaffold and tox. A lot of it is probably wrong.

This commit is contained in:
Josiah Baldwin
2024-11-05 22:21:35 -08:00
parent 8dab88bfea
commit 69afbfeba7
34 changed files with 2053 additions and 725 deletions

View File

@@ -1 +1,16 @@
from .session import Session
import sys
if sys.version_info[:2] >= (3, 8):
# TODO: Import directly (no need for conditional) when `python_requires = >= 3.8`
from importlib.metadata import PackageNotFoundError, version # pragma: no cover
else:
from importlib_metadata import PackageNotFoundError, version # pragma: no cover
try:
# Change here if project is renamed and does not equal the package name
dist_name = "meshctrl"
__version__ = version(dist_name)
except PackageNotFoundError: # pragma: no cover
__version__ = "unknown"
finally:
del version, PackageNotFoundError

View File

@@ -1,45 +1,87 @@
import enum
try:
from enum_tools.documentation import document_enum
except:
def document_enum(cls, *args, **kwargs):
return cls
@document_enum
class UserRights(enum.IntFlag):
"""
Bitwise flags for user rights
"""
#: Give user no rights
norights = 0
backup = enum.auto()
#: Allow backup of mesh database
backup = enum.auto()
#: User can add or remove users
manageusers = enum.auto()
#: User can restore the database from a backup
restore = enum.auto()
#: User can upload files to server storage
fileaccess = enum.auto()
#: User can update server version
update = enum.auto()
#: User is disabled
locked = enum.auto()
nonewgroups = enum.auto()
notools = enum.auto()
usergroups = enum.auto()
#: User cannot create new meshes
nonewgroups = enum.auto() #
notools = enum.auto() #
#: User can create user groups
usergroups = enum.auto() #
#: User can record desktop sessions
recordings = enum.auto()
locksettings = enum.auto()
fullrights = backup|manageusers|restore|fileaccess|\
update|locked|nonewgroups|notools|usergroups|\
recordings|locksettings
#: User has full rights
fullrights = backup|manageusers|restore|fileaccess|update|locked|nonewgroups|notools|usergroups|recordings|locksettings
@document_enum
class MeshRights(enum.IntFlag):
"""
Bitwise flags for mesh rights
Pulls double duty as rights for a connected device
"""
#: Give user no rights
norights = 0
#: Edit the group
editgroup = enum.auto()
#: Add/remove users
manageusers = enum.auto()
#: Add/remove devices
managedevices = enum.auto()
#: Remote control access
remotecontrol = enum.auto()
#: Agent console access
agentconsole = enum.auto()
serverfiles = enum.auto()
#: Wake device from sleep
wakedevices = enum.auto()
#: Add notes to the device/mesh
notes = enum.auto()
#: Only view the desktop; no control
desktopviewonly = enum.auto()
#: No terminal access
noterminal = enum.auto()
#: No file access
nofiles = enum.auto()
#: No AMT access
noamt = enum.auto()
limiteddesktop = enum.auto()
limitedevents = enum.auto()
chatnotify = enum.auto()
uninstall = enum.auto()
#: Disable remote desktop
noremotedesktop = enum.auto()
#: Allow to send commands to the device
remotecommands = enum.auto()
#: Reset or poweroff device
resetpoweroff = enum.auto()
#: All rights
fullrights = 0xFFFFFFFF
@document_enum
class ConsentFlags(enum.IntFlag):
none = 0
desktopnotify = enum.auto()
@@ -49,9 +91,9 @@ class ConsentFlags(enum.IntFlag):
terminalprompt = enum.auto()
filesprompt = enum.auto()
desktopprivacybar = enum.auto()
all = desktopnotify|terminalnotify|filesnotify|desktopprompt|terminalprompt|\
filesprompt|filesprompt
all = desktopnotify|terminalnotify|filesnotify|desktopprompt|terminalprompt|filesprompt|filesprompt
@document_enum
class MeshFeatures(enum.IntFlag):
none = 0
autoremove = enum.auto()
@@ -59,15 +101,27 @@ class MeshFeatures(enum.IntFlag):
recordsessions = enum.auto()
all = autoremove|hostnamesync|recordsessions
@document_enum
class SharingType(enum.StrEnum):
"""
String constants used to determine which type of device share to create
"""
desktop = enum.auto()
terminal = enum.auto()
@document_enum
class SharingTypeInt(enum.IntEnum):
"""
Internal enum used to map SHARINGTYPE to the number used by MeshCentral
"""
desktop = enum.auto()
terminal = enum.auto()
@document_enum
class Icon(enum.IntEnum):
"""
Which icon to use for a device
"""
desktop = enum.auto()
laptop = enum.auto()
phone = enum.auto()

View File

@@ -1,21 +1,17 @@
class MeshCtrlError(Exception):
"""
Base class for Meshctrl errors
"""
pass
# /** Represents an error thrown from the server
# * @extends Error
# */
class ServerError(MeshCtrlError):
"""
Represents an error thrown from the server
"""
pass
# /** Represents an error in the websocket
# * @extends Error
# */
class SocketError(MeshCtrlError):
pass
# /** Represents that a command timed out
# * @extends Error
# */
class TimeoutError(MeshCtrlError):
pass
"""
Represents an error in the websocket
"""
pass

4
src/meshctrl/files.py Normal file
View File

@@ -0,0 +1,4 @@
from . import tunnel
class Files(tunnel.Tunnel):
pass

File diff suppressed because it is too large Load Diff

7
src/meshctrl/shell.py Normal file
View File

@@ -0,0 +1,7 @@
from . import tunnel
class Shell(tunnel.Tunnel):
pass
class SmartShell(tunnel.Tunnel):
pass

2
src/meshctrl/tunnel.py Normal file
View File

@@ -0,0 +1,2 @@
class Tunnel(object):
pass

View File

@@ -4,7 +4,7 @@ from cryptography.hazmat.primitives.ciphers.aead import AESGCM
import json
import base64
def encode_cookie(o, key):
def _encode_cookie(o, key):
o["time"] = int(time.time()); # Add the cookie creation time
iv = secrets.token_bytes(12)
key = AESGCM(key)
@@ -12,17 +12,41 @@ def encode_cookie(o, key):
return base64.b64encode(crypted).replace("+", '@').replace("/", '$');
class Eventer(object):
"""
Eventer object to allow pub/sub interactions with a Session object
"""
def __init__(self):
self._ons = {}
self._onces = {}
def on(self, event, func):
"""
Subscribe to `event`. `func` will be called when that event is emitted.
Args:
event (str): Event name to subscribe to
func (function(data: object)): Function to call when event is emitted. `data` could be of any type. Also used as a key to remove this subscription.
"""
self._ons.setdefault(event, set()).add(func)
def once(self, event, func):
"""
Subscribe to `event` once. `func` will be called when that event is emitted. The binding will then be removed.
Args:
event (str): Event name to subscribe to
func (function(data: object)): Function to call when event is emitted. `data` could be of any type. Also used as a key to remove this subscription.
"""
self._onces.setdefault(event, set()).add(func)
def off(self, event, func):
"""
Unsubscribe from `event`. `func` is the object originally passed during the bind.
Args:
event (str): Event name to unsubscribe from
func (object): Function which was originally passed when subscribing.
"""
try:
self._onces.setdefault(event, set()).remove(func)
except KeyError:
@@ -33,6 +57,13 @@ class Eventer(object):
pass
def emit(self, event, data):
"""
Emit `event` with `data`. All subscribed functions will be called (order is nonsensical).
Args:
event (str): Event name emit
data (object): Data to pass to all the bound functions
"""
for f in self._onces.get(event, []):
f(data)
try: