diff options
author | RaNaN <Mast3rRaNaN@hotmail.de> | 2013-03-23 21:56:42 +0100 |
---|---|---|
committer | RaNaN <Mast3rRaNaN@hotmail.de> | 2013-03-23 21:56:42 +0100 |
commit | 6e8a0f79f5ad7182a0bc35308ae06c63222667ed (patch) | |
tree | 0026179d34f19b64bc689c63af85b949ce57fb83 /module/remote | |
parent | show button when files are selected (diff) | |
download | pyload-6e8a0f79f5ad7182a0bc35308ae06c63222667ed.tar.xz |
implemented interactions for multi user, show waiting queries on webui
Diffstat (limited to 'module/remote')
-rw-r--r-- | module/remote/apitypes.py | 38 | ||||
-rw-r--r-- | module/remote/apitypes_debug.py | 16 | ||||
-rw-r--r-- | module/remote/pyload.thrift | 34 | ||||
-rw-r--r-- | module/remote/wsbackend/AsyncHandler.py | 20 |
4 files changed, 65 insertions, 43 deletions
diff --git a/module/remote/apitypes.py b/module/remote/apitypes.py index 83368c6de..83eb19450 100644 --- a/module/remote/apitypes.py +++ b/module/remote/apitypes.py @@ -43,7 +43,7 @@ class FileStatus: Missing = 1 Remote = 2 -class Input: +class InputType: NA = 0 Text = 1 Int = 2 @@ -58,6 +58,12 @@ class Input: List = 11 Table = 12 +class Interaction: + All = 0 + Notification = 1 + Captcha = 2 + Query = 4 + class MediaType: All = 0 Other = 1 @@ -67,12 +73,6 @@ class MediaType: Document = 16 Archive = 32 -class Output: - All = 0 - Notification = 1 - Captcha = 2 - Query = 4 - class PackageStatus: Ok = 0 Paused = 1 @@ -150,13 +150,13 @@ class ConfigInfo(BaseObject): self.activated = activated class ConfigItem(BaseObject): - __slots__ = ['name', 'label', 'description', 'type', 'default_value', 'value'] + __slots__ = ['name', 'label', 'description', 'input', 'default_value', 'value'] - def __init__(self, name=None, label=None, description=None, type=None, default_value=None, value=None): + def __init__(self, name=None, label=None, description=None, input=None, default_value=None, value=None): self.name = name self.label = label self.description = description - self.type = type + self.input = input self.default_value = default_value self.value = value @@ -211,14 +211,20 @@ class FileInfo(BaseObject): class Forbidden(ExceptionObject): pass +class Input(BaseObject): + __slots__ = ['type', 'data'] + + def __init__(self, type=None, data=None): + self.type = type + self.data = data + class InteractionTask(BaseObject): - __slots__ = ['iid', 'input', 'data', 'output', 'default_value', 'title', 'description', 'plugin'] + __slots__ = ['iid', 'type', 'input', 'default_value', 'title', 'description', 'plugin'] - def __init__(self, iid=None, input=None, data=None, output=None, default_value=None, title=None, description=None, plugin=None): + def __init__(self, iid=None, type=None, input=None, default_value=None, title=None, description=None, plugin=None): self.iid = iid + self.type = type self.input = input - self.data = data - self.output = output self.default_value = default_value self.title = title self.description = description @@ -438,12 +444,10 @@ class Iface(object): pass def getFilteredFiles(self, state): pass - def getInteractionTask(self, mode): + def getInteractionTasks(self, mode): pass def getLog(self, offset): pass - def getNotifications(self): - pass def getPackageContent(self, pid): pass def getPackageInfo(self, pid): diff --git a/module/remote/apitypes_debug.py b/module/remote/apitypes_debug.py index 4fab11f96..6909464d4 100644 --- a/module/remote/apitypes_debug.py +++ b/module/remote/apitypes_debug.py @@ -9,9 +9,9 @@ enums = [ "DownloadState", "DownloadStatus", "FileStatus", - "Input", + "InputType", + "Interaction", "MediaType", - "Output", "PackageStatus", "Permission", "Role", @@ -23,21 +23,22 @@ classes = { 'AddonService' : [basestring, basestring, (list, basestring), (None, int)], 'ConfigHolder' : [basestring, basestring, basestring, basestring, (list, ConfigItem), (None, (list, AddonInfo)), (None, (list, InteractionTask))], 'ConfigInfo' : [basestring, basestring, basestring, basestring, bool, (None, bool)], - 'ConfigItem' : [basestring, basestring, basestring, basestring, (None, basestring), basestring], + 'ConfigItem' : [basestring, basestring, basestring, Input, basestring, basestring], 'DownloadInfo' : [basestring, basestring, basestring, int, basestring, basestring], 'DownloadProgress' : [int, int, int, int], 'EventInfo' : [basestring, (list, basestring)], 'FileDoesNotExists' : [int], 'FileInfo' : [int, basestring, int, int, int, int, int, int, int, (None, DownloadInfo)], - 'InteractionTask' : [int, int, (list, basestring), int, (None, basestring), basestring, basestring, basestring], + 'Input' : [int, (None, basestring)], + 'InteractionTask' : [int, int, Input, (None, basestring), basestring, basestring, basestring], 'InvalidConfigSection' : [basestring], 'LinkStatus' : [basestring, basestring, basestring, int, int, basestring], - 'OnlineCheck' : [int, (dict, basestring, LinkStatus)], + 'OnlineCheck' : [int, (None, (dict, basestring, LinkStatus))], 'PackageDoesNotExists' : [int], 'PackageInfo' : [int, basestring, basestring, int, int, basestring, basestring, basestring, int, (list, basestring), int, bool, int, PackageStats, (list, int), (list, int)], 'PackageStats' : [int, int, int, int], 'ProgressInfo' : [basestring, basestring, basestring, int, int, int, (None, DownloadProgress)], - 'ServerStatus' : [int, int, int, int, int, int, bool, bool, bool], + 'ServerStatus' : [int, int, int, int, int, bool, bool, bool, bool], 'ServiceDoesNotExists' : [basestring, basestring], 'ServiceException' : [basestring], 'TreeCollection' : [PackageInfo, (dict, int, FileInfo), (dict, int, PackageInfo)], @@ -86,9 +87,8 @@ methods = { 'getFileTree': TreeCollection, 'getFilteredFileTree': TreeCollection, 'getFilteredFiles': TreeCollection, - 'getInteractionTask': InteractionTask, + 'getInteractionTasks': (list, InteractionTask), 'getLog': (list, basestring), - 'getNotifications': (list, InteractionTask), 'getPackageContent': TreeCollection, 'getPackageInfo': PackageInfo, 'getPluginConfig': (list, ConfigInfo), diff --git a/module/remote/pyload.thrift b/module/remote/pyload.thrift index 06add4208..76e755de0 100644 --- a/module/remote/pyload.thrift +++ b/module/remote/pyload.thrift @@ -69,7 +69,7 @@ enum PackageStatus { // some may only be place holder currently not supported // also all input - output combination are not reasonable, see InteractionManager for further info // Todo: how about: time, ip, s.o. -enum Input { +enum InputType { NA, Text, Int, @@ -88,7 +88,7 @@ enum Input { // this describes the type of the outgoing interaction // ensure they can be logcial or'ed -enum Output { +enum Interaction { All = 0, Notification = 1, Captcha = 2, @@ -111,6 +111,11 @@ enum Role { User = 1 } +struct Input { + 1: InputType type, + 2: optional JSONString data, +} + struct DownloadProgress { 1: FileID fid, 2: PackageID pid, @@ -200,7 +205,7 @@ struct ServerStatus { 3: i16 linksqueue, 4: ByteCount sizetotal, 5: ByteCount sizequeue, - 6: i16 notifications, + 6: bool notifications, 7: bool paused, 8: bool download, 9: bool reconnect, @@ -208,13 +213,12 @@ struct ServerStatus { struct InteractionTask { 1: InteractionID iid, - 2: Input input, - 3: list<string> data, - 4: Output output, - 5: optional JSONString default_value, - 6: string title, - 7: string description, - 8: PluginName plugin, + 2: Interaction type, + 3: Input input, + 4: optional JSONString default_value, + 5: string title, + 6: string description, + 7: PluginName plugin, } struct AddonService { @@ -234,7 +238,7 @@ struct ConfigItem { 1: string name, 2: string label, 3: string description, - 4: string type, + 4: Input input, 5: JSONString default_value, 6: JSONString value, } @@ -360,7 +364,7 @@ service Pyload { map<string, ConfigHolder> getConfig(), string getConfigValue(1: string section, 2: string option), - // two methods with ambigous classification, could be configuration or addon related + // two methods with ambigous classification, could be configuration or addon/plugin related list<ConfigInfo> getCoreConfig(), list<ConfigInfo> getPluginConfig(), list<ConfigInfo> getAvailablePlugins(), @@ -473,16 +477,14 @@ service Pyload { // User Interaction /////////////////////// - // mode = Output types binary ORed + // mode = interaction types binary ORed bool isInteractionWaiting(1: i16 mode), - InteractionTask getInteractionTask(1: i16 mode), + list<InteractionTask> getInteractionTasks(1: i16 mode), void setInteractionResult(1: InteractionID iid, 2: JSONString result), // generate a download link, everybody can download the file until timeout reached string generateDownloadLink(1: FileID fid, 2: i16 timeout), - list<InteractionTask> getNotifications(), - /////////////////////// // Account Methods /////////////////////// diff --git a/module/remote/wsbackend/AsyncHandler.py b/module/remote/wsbackend/AsyncHandler.py index 99ffe9894..b40f0ea4e 100644 --- a/module/remote/wsbackend/AsyncHandler.py +++ b/module/remote/wsbackend/AsyncHandler.py @@ -23,7 +23,7 @@ from time import time from mod_pywebsocket.msgutil import receive_message -from module.Api import EventInfo +from module.Api import EventInfo, Interaction from module.utils import lock from AbstractHandler import AbstractHandler @@ -44,7 +44,8 @@ class AsyncHandler(AbstractHandler): COMMAND = "start" PROGRESS_INTERVAL = 2 - EVENT_PATTERN = re.compile(r"^(package|file)", re.I) + EVENT_PATTERN = re.compile(r"^(package|file|interaction)", re.I) + INTERACTION = Interaction.All def __init__(self, api): AbstractHandler.__init__(self, api) @@ -58,6 +59,7 @@ class AsyncHandler(AbstractHandler): req.queue = Queue() req.interval = self.PROGRESS_INTERVAL req.events = self.EVENT_PATTERN + req.interaction = self.INTERACTION req.mode = Mode.STANDBY req.t = time() # time when update should be pushed self.clients.append(req) @@ -76,6 +78,18 @@ class AsyncHandler(AbstractHandler): event = EventInfo(event, [x.toInfoData() if hasattr(x, 'toInfoData') else x for x in args]) for req in self.clients: + # filter events that these user is no owner of + # TODO: events are security critical, this should be revised later + if not req.api.user.isAdmin(): + skip = False + for arg in args: + if hasattr(arg, 'owner') and arg.owner != req.api.primaryUID: + skip = True + break + + # user should not get this event + if skip: break + if req.events.search(event.eventname): self.log.debug("Pushing event %s" % event) req.queue.put(event) @@ -115,6 +129,8 @@ class AsyncHandler(AbstractHandler): req.interval = args[0] elif func == "setEvents": req.events = re.compile(args[0], re.I) + elif func == "setInteraction": + req.interaction = args[0] elif func == self.COMMAND: req.mode = Mode.RUNNING |