summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--module/Api.py181
-rw-r--r--module/database/DatabaseBackend.py34
-rw-r--r--module/database/FileDatabase.py38
-rw-r--r--module/remote/socketbackend/ttypes.py41
-rw-r--r--module/remote/thriftbackend/pyload.thrift83
-rwxr-xr-xmodule/remote/thriftbackend/thriftgen/pyload/Pyload-remote44
-rw-r--r--module/remote/thriftbackend/thriftgen/pyload/Pyload.py364
-rw-r--r--module/remote/thriftbackend/thriftgen/pyload/ttypes.py108
-rw-r--r--module/web/utils.py14
9 files changed, 675 insertions, 232 deletions
diff --git a/module/Api.py b/module/Api.py
index c969045f8..bab039ea1 100644
--- a/module/Api.py
+++ b/module/Api.py
@@ -52,7 +52,7 @@ perm_map = {}
user_context = {}
# decorator only called on init, never initialized, so has no effect on runtime
-def permission(bits):
+def RequirePerm(bits):
class _Dec(object):
def __new__(cls, func, *args, **kwargs):
perm_map[func.__name__] = bits
@@ -100,27 +100,9 @@ class UserContext(object):
urlmatcher = re.compile(r"((https?|ftps?|xdcc|sftp):((//)|(\\\\))+[\w\d:#@%/;$()~_?\+\-=\\\.&]*)", re.IGNORECASE)
-class PERMS:
- ALL = 0 # requires no permission, but login
- ADD = 1 # can add packages
- DELETE = 2 # can delete packages
- STATUS = 4 # see and change server status
- LIST = 16 # see listed downloads
- MODIFY = 32 # moddify some attribute of downloads
- DOWNLOAD = 64 # can download from webinterface
- SETTINGS = 128 # can access settings
- ACCOUNTS = 256 # can access accounts
- LOGS = 512 # can see server logs
- INTERACTION = 1024 # can interact with plugins
-
-class ROLE:
- ADMIN = 0 #admin has all permissions implicit
- USER = 1
-
-
-def has_permission(userperms, perms):
- return bits_set(perms, userperms)
+def has_permission(userPermission, Permission):
+ return bits_set(Permission, userPermission)
class UserApi(object):
@@ -157,13 +139,13 @@ class Api(Iface):
def __init__(self, core):
self.core = core
- self.t = self.inUserContext("TestUser")
+ self.t = self.withUserContext("TestUser")
print self.t.getServerVersion()
# TODO, create user instance, work
- def inUserContext(self, user):
+ def withUserContext(self, user):
""" Returns a proxy version of the api, to call method in user context
:param user: user id
@@ -177,13 +159,13 @@ class Api(Iface):
##########################
@UserContext #TODO: only for testing
- @permission(PERMS.ALL)
+ @RequirePerm(Permission.All)
def getServerVersion(self):
"""pyLoad Core version """
print user
return self.core.version
- @permission(PERMS.LIST)
+ @RequirePerm(Permission.List)
def statusServer(self):
"""Some general information about the current status of pyLoad.
@@ -199,17 +181,17 @@ class Api(Iface):
return serverStatus
- @permission(PERMS.STATUS)
+ @RequirePerm(Permission.Status)
def pauseServer(self):
"""Pause server: It won't start any new downloads, but nothing gets aborted."""
self.core.threadManager.pause = True
- @permission(PERMS.STATUS)
+ @RequirePerm(Permission.Status)
def unpauseServer(self):
"""Unpause server: New Downloads will be started."""
self.core.threadManager.pause = False
- @permission(PERMS.STATUS)
+ @RequirePerm(Permission.Status)
def togglePause(self):
"""Toggle pause state.
@@ -218,7 +200,7 @@ class Api(Iface):
self.core.threadManager.pause ^= True
return self.core.threadManager.pause
- @permission(PERMS.STATUS)
+ @RequirePerm(Permission.Status)
def toggleReconnect(self):
"""Toggle reconnect activation.
@@ -227,7 +209,7 @@ class Api(Iface):
self.core.config["reconnect"]["activated"] ^= True
return self.core.config["reconnect"]["activated"]
- @permission(PERMS.STATUS)
+ @RequirePerm(Permission.Status)
def freeSpace(self):
"""Available free space at download directory in bytes"""
return free_space(self.core.config["general"]["download_folder"])
@@ -241,7 +223,6 @@ class Api(Iface):
"""Restart pyload core"""
self.core.do_restart = True
- @permission(PERMS.LOGS)
def getLog(self, offset=0):
"""Returns most recent log entries.
@@ -259,7 +240,7 @@ class Api(Iface):
except:
return ['No log available']
- @permission(PERMS.STATUS)
+ @RequirePerm(Permission.Status)
def isTimeDownload(self):
"""Checks if pyload will start new downloads according to time in config.
@@ -269,7 +250,7 @@ class Api(Iface):
end = self.core.config['downloadTime']['end'].split(":")
return compare_time(start, end)
- @permission(PERMS.STATUS)
+ @RequirePerm(Permission.Status)
def isTimeReconnect(self):
"""Checks if pyload will try to make a reconnect
@@ -283,7 +264,7 @@ class Api(Iface):
def scanDownloadFolder(self):
pass
- @permission(PERMS.STATUS)
+ @RequirePerm(Permission.Status)
def getProgressInfo(self):
""" Status of all currently running tasks
@@ -306,7 +287,6 @@ class Api(Iface):
# Configuration
##########################
- @permission(PERMS.SETTINGS)
def getConfigValue(self, section, option):
"""Retrieve config value.
@@ -317,7 +297,6 @@ class Api(Iface):
value = self.core.config.get(section, option)
return to_string(value)
- @permission(PERMS.SETTINGS)
def setConfigValue(self, section, option, value):
"""Set new config value.
@@ -330,7 +309,6 @@ class Api(Iface):
self.core.config.set(section, option, value)
- @permission(PERMS.SETTINGS)
def getConfig(self):
"""Retrieves complete config of core.
@@ -343,7 +321,6 @@ class Api(Iface):
section, data in self.core.config.getBaseSections()])
- @permission(PERMS.SETTINGS)
def getPluginConfig(self):
"""Retrieves complete config for all plugins.
@@ -353,7 +330,6 @@ class Api(Iface):
data.name, data.description, data.long_desc)) for
section, data in self.core.config.getPluginSections()])
- @permission(PERMS.SETTINGS)
def configureSection(self, section):
data = self.core.config.config[section]
sec = ConfigSection(section, data.name, data.description, data.long_desc)
@@ -367,7 +343,6 @@ class Api(Iface):
return sec
- @permission(PERMS.SETTINGS)
def setConfigHandler(self, plugin, iid, value):
pass
@@ -379,7 +354,7 @@ class Api(Iface):
# Download Preparing
##########################
- @permission(PERMS.ADD)
+ @RequirePerm(Permission.Add)
def parseURLs(self, html=None, url=None):
"""Parses html content or any arbitrary text for links and returns result of `checkURLs`
@@ -399,7 +374,7 @@ class Api(Iface):
return self.checkURLs(set(urls))
- @permission(PERMS.ADD)
+ @RequirePerm(Permission.Add)
def checkURLs(self, urls):
""" Gets urls and returns pluginname mapped to list of matching urls.
@@ -417,7 +392,7 @@ class Api(Iface):
return plugins
- @permission(PERMS.ADD)
+ @RequirePerm(Permission.Add)
def checkOnlineStatus(self, urls):
""" initiates online status check, will also decrypt files.
@@ -441,7 +416,7 @@ class Api(Iface):
return OnlineCheck(rid, result)
- @permission(PERMS.ADD)
+ @RequirePerm(Permission.Add)
def checkOnlineStatusContainer(self, urls, container, data):
""" checks online status of urls and a submitted container file
@@ -456,7 +431,7 @@ class Api(Iface):
urls.append(th.name)
return self.checkOnlineStatus(urls)
- @permission(PERMS.ADD)
+ @RequirePerm(Permission.Add)
def pollResults(self, rid):
""" Polls the result available for ResultID
@@ -472,7 +447,7 @@ class Api(Iface):
return OnlineCheck(rid, result)
- @permission(PERMS.ADD)
+ @RequirePerm(Permission.Add)
def generatePackages(self, links):
""" Parses links, generates packages names from urls
@@ -486,7 +461,7 @@ class Api(Iface):
# Adding/Deleting
##########################
- @permission(PERMS.ADD)
+ @RequirePerm(Permission.Add)
def generateAndAddPackages(self, links, paused=False):
"""Generates and add packages
@@ -497,11 +472,11 @@ class Api(Iface):
return [self.addPackageP(name, urls, "", paused) for name, urls
in self.generatePackages(links).iteritems()]
- @permission(PERMS.ADD)
+ @RequirePerm(Permission.Add)
def autoAddLinks(self, links):
pass
- @permission(PERMS.ADD)
+ @RequirePerm(Permission.Add)
def createPackage(self, name, folder, root, password="", site="", comment="", paused=False):
"""Create a new package.
@@ -526,7 +501,7 @@ class Api(Iface):
return pid
- @permission(PERMS.ADD)
+ @RequirePerm(Permission.Add)
def addPackage(self, name, links, password=""):
"""Convenient method to add a package to the top-level and for adding links.
@@ -534,12 +509,12 @@ class Api(Iface):
"""
self.addPackageChild(name, links, password, -1, False)
- @permission(PERMS.ADD)
+ @RequirePerm(Permission.Add)
def addPackageP(self, name, links, password, paused):
""" Same as above with additional paused attribute. """
self.addPackageChild(name, links, password, -1, paused)
- @permission(PERMS.ADD)
+ @RequirePerm(Permission.Add)
def addPackageChild(self, name, links, password, root, paused):
"""Adds a package, with links to desired package.
@@ -556,7 +531,7 @@ class Api(Iface):
return pid
- @permission(PERMS.ADD)
+ @RequirePerm(Permission.Add)
def addLinks(self, pid, links):
"""Adds links to specific package. Initiates online status fetching.
@@ -574,7 +549,7 @@ class Api(Iface):
self.core.log.info((_("Added %d links to package") + " #%d" % pid) % len(hoster))
self.core.files.save()
- @permission(PERMS.ADD)
+ @RequirePerm(Permission.Add)
def uploadContainer(self, filename, data):
"""Uploads and adds a container file to pyLoad.
@@ -587,7 +562,7 @@ class Api(Iface):
return self.addPackage(th.name, [th.name])
- @permission(PERMS.DELETE)
+ @RequirePerm(Permission.Delete)
def deleteFiles(self, fids):
"""Deletes several file entries from pyload.
@@ -598,7 +573,7 @@ class Api(Iface):
self.core.files.save()
- @permission(PERMS.DELETE)
+ @RequirePerm(Permission.Delete)
def deletePackages(self, pids):
"""Deletes packages and containing links.
@@ -613,27 +588,27 @@ class Api(Iface):
# Collector
##########################
- @permission(PERMS.LIST)
+ @RequirePerm(Permission.List)
def getCollector(self):
pass
- @permission(PERMS.ADD)
+ @RequirePerm(Permission.Add)
def addToCollector(self, links):
pass
- @permission(PERMS.ADD)
+ @RequirePerm(Permission.Add)
def addFromCollector(self, name, paused):
pass
- @permission(PERMS.DELETE)
+ @RequirePerm(Permission.Delete)
def deleteCollPack(self, name):
pass
- @permission(PERMS.DELETE)
+ @RequirePerm(Permission.Delete)
def deleteCollLink(self, url):
pass
- @permission(PERMS.ADD)
+ @RequirePerm(Permission.Add)
def renameCollPack(self, name, new_name):
pass
@@ -641,17 +616,17 @@ class Api(Iface):
# File Information retrival
#############################
- @permission(PERMS.LIST)
+ @RequirePerm(Permission.List)
def getAllFiles(self):
""" same as `getFileTree` for toplevel root and full tree"""
return self.getFileTree(-1, True)
- @permission(PERMS.LIST)
+ @RequirePerm(Permission.List)
def getAllUnfinishedFiles(self):
""" same as `getUnfinishedFileTree for toplevel root and full tree"""
return self.getUnfinishedFileTree(-1, True)
- @permission(PERMS.LIST)
+ @RequirePerm(Permission.List)
def getFileTree(self, pid, full):
""" Retrieve data for specific package. full=True will retrieve all data available
and can result in greater delays.
@@ -662,7 +637,7 @@ class Api(Iface):
"""
return self.core.files.getView(pid, full, False)
- @permission(PERMS.LIST)
+ @RequirePerm(Permission.List)
def getUnfinishedFileTree(self, pid, full):
""" Same as `getFileTree` but only contains unfinished files.
@@ -672,12 +647,12 @@ class Api(Iface):
"""
return self.core.files.getView(pid, full, False)
- @permission(PERMS.LIST)
+ @RequirePerm(Permission.List)
def getPackageContent(self, pid):
""" Only retrieve content of a specific package. see `getFileTree`"""
return self.getFileTree(pid, False)
- @permission(PERMS.LIST)
+ @RequirePerm(Permission.List)
def getPackageInfo(self, pid):
"""Returns information about package, without detailed information about containing files
@@ -690,7 +665,7 @@ class Api(Iface):
raise PackageDoesNotExists(pid)
return info
- @permission(PERMS.LIST)
+ @RequirePerm(Permission.List)
def getFileInfo(self, fid):
""" Info for specific file
@@ -704,7 +679,7 @@ class Api(Iface):
raise FileDoesNotExists(fid)
return info
- @permission(PERMS.LIST)
+ @RequirePerm(Permission.List)
def findFiles(self, pattern):
pass
@@ -712,7 +687,7 @@ class Api(Iface):
# Modify Downloads
#############################
- @permission(PERMS.MODIFY)
+ @RequirePerm(Permission.Modify)
def restartPackage(self, pid):
"""Restarts a package, resets every containing files.
@@ -720,7 +695,7 @@ class Api(Iface):
"""
self.core.files.restartPackage(pid)
- @permission(PERMS.MODIFY)
+ @RequirePerm(Permission.Modify)
def restartFile(self, fid):
"""Resets file status, so it will be downloaded again.
@@ -728,12 +703,12 @@ class Api(Iface):
"""
self.core.files.restartFile(fid)
- @permission(PERMS.MODIFY)
+ @RequirePerm(Permission.Modify)
def recheckPackage(self, pid):
"""Check online status of all files in a package, also a default action when package is added. """
self.core.files.reCheckPackage(pid)
- @permission(PERMS.MODIFY)
+ @RequirePerm(Permission.Modify)
def stopAllDownloads(self):
"""Aborts all running downloads."""
@@ -741,7 +716,7 @@ class Api(Iface):
for pyfile in pyfiles:
pyfile.abortDownload()
- @permission(PERMS.MODIFY)
+ @RequirePerm(Permission.Modify)
def stopDownloads(self, fids):
"""Aborts specific downloads.
@@ -753,7 +728,7 @@ class Api(Iface):
if pyfile.id in fids:
pyfile.abortDownload()
- @permission(PERMS.MODIFY)
+ @RequirePerm(Permission.Modify)
def restartFailed(self):
"""Restarts all failed failes."""
self.core.files.restartFailed()
@@ -762,19 +737,19 @@ class Api(Iface):
# Modify Files/Packages
#############################
- @permission(PERMS.MODIFY)
+ @RequirePerm(Permission.Modify)
def setFilePaused(self, fid, paused):
pass
- @permission(PERMS.MODIFY)
+ @RequirePerm(Permission.Modify)
def setPackagePaused(self, pid, paused):
pass
- @permission(PERMS.MODIFY)
+ @RequirePerm(Permission.Modify)
def setPackageFolder(self, pid, path):
pass
- @permission(PERMS.MODIFY)
+ @RequirePerm(Permission.Modify)
def movePackage(self, pid, root):
""" Set a new root for specific package. This will also moves the files on disk\
and will only work when no file is currently downloading.
@@ -786,7 +761,7 @@ class Api(Iface):
"""
return self.core.files.movePackage(pid, root)
- @permission(PERMS.MODIFY)
+ @RequirePerm(Permission.Modify)
def moveFiles(self, fids, pid):
"""Move multiple files to another package. This will move the files on disk and\
only work when files are not downloading. All files needs to be continuous ordered
@@ -798,7 +773,7 @@ class Api(Iface):
"""
return self.core.files.moveFiles(fids, pid)
- @permission(PERMS.MODIFY)
+ @RequirePerm(Permission.Modify)
def orderPackage(self, pid, position):
"""Set new position for a package.
@@ -807,7 +782,7 @@ class Api(Iface):
"""
self.core.files.orderPackage(pid, position)
- @permission(PERMS.MODIFY)
+ @RequirePerm(Permission.Modify)
def orderFiles(self, fids, pid, position):
""" Set a new position for a bunch of files within a package.
All files have to be in the same package and must be **continuous**\
@@ -819,7 +794,7 @@ class Api(Iface):
"""
self.core.files.orderFiles(fids, pid, position)
- @permission(PERMS.MODIFY)
+ @RequirePerm(Permission.Modify)
def setPackageData(self, pid, data):
"""Allows to modify several package attributes.
@@ -840,7 +815,7 @@ class Api(Iface):
# User Interaction
#############################
- @permission(PERMS.INTERACTION)
+ @RequirePerm(Permission.Interaction)
def isInteractionWaiting(self, mode):
""" Check if task is waiting.
@@ -849,7 +824,7 @@ class Api(Iface):
"""
return self.core.interactionManager.isTaskWaiting(mode)
- @permission(PERMS.INTERACTION)
+ @RequirePerm(Permission.Interaction)
def getInteractionTask(self, mode):
"""Retrieve task for specific mode.
@@ -860,7 +835,7 @@ class Api(Iface):
return InteractionTask(-1) if not task else task
- @permission(PERMS.INTERACTION)
+ @RequirePerm(Permission.Interaction)
def setInteractionResult(self, iid, result):
"""Set Result for a interaction task. It will be immediately removed from task queue afterwards
@@ -871,7 +846,7 @@ class Api(Iface):
if task:
task.setResult(result)
- @permission(PERMS.INTERACTION)
+ @RequirePerm(Permission.Interaction)
def getNotifications(self):
"""List of all available notifcations. They stay in queue for some time, client should\
save which notifications it already has seen.
@@ -880,15 +855,15 @@ class Api(Iface):
"""
return self.core.interactionManager.getNotifications()
- @permission(PERMS.INTERACTION)
+ @RequirePerm(Permission.Interaction)
def getAddonHandler(self):
pass
- @permission(PERMS.INTERACTION)
+ @RequirePerm(Permission.Interaction)
def callAddonHandler(self, plugin, func, pid_or_fid):
pass
- @permission(PERMS.DOWNLOAD)
+ @RequirePerm(Permission.Download)
def generateDownloadLink(self, fid, timeout):
pass
@@ -896,7 +871,7 @@ class Api(Iface):
# Event Handling
#############################
- @permission(PERMS.STATUS)
+ @RequirePerm(Permission.Status)
def getEvents(self, uuid):
"""Lists occured events, may be affected to changes in future.
@@ -910,7 +885,7 @@ class Api(Iface):
# Account Methods
#############################
- @permission(PERMS.ACCOUNTS)
+ @RequirePerm(Permission.Accounts)
def getAccounts(self, refresh):
"""Get information about all entered accounts.
@@ -924,7 +899,7 @@ class Api(Iface):
return accounts
- @permission(PERMS.ALL)
+ @RequirePerm(Permission.All)
def getAccountTypes(self):
"""All available account types.
@@ -932,12 +907,12 @@ class Api(Iface):
"""
return self.core.pluginManager.getPlugins("accounts").keys()
- @permission(PERMS.ACCOUNTS)
+ @RequirePerm(Permission.Accounts)
def updateAccount(self, plugin, account, password=None, options={}):
"""Changes pw/options for specific account."""
self.core.accountManager.updateAccount(plugin, account, password, options)
- @permission(PERMS.ACCOUNTS)
+ @RequirePerm(Permission.Accounts)
def removeAccount(self, plugin, account):
"""Remove account from pyload.
@@ -950,7 +925,7 @@ class Api(Iface):
# Auth+User Information
#############################
- @permission(PERMS.ALL)
+ @RequirePerm(Permission.All)
def login(self, username, password, remoteip=None):
"""Login into pyLoad, this **must** be called when using rpc before any methods can be used.
@@ -993,7 +968,7 @@ class Api(Iface):
return False
- @permission(PERMS.ALL)
+ @RequirePerm(Permission.All)
def getUserData(self, username, password):
"""similar to `checkAuth` but returns UserData thrift type """
user = self.checkAuth(username, password)
@@ -1022,7 +997,7 @@ class Api(Iface):
# RPC Plugin Methods
#############################
- @permission(PERMS.INTERACTION)
+ @RequirePerm(Permission.Interaction)
def getServices(self):
""" A dict of available services, these can be defined by addon plugins.
@@ -1034,11 +1009,11 @@ class Api(Iface):
return data
- @permission(PERMS.INTERACTION)
+ @RequirePerm(Permission.Interaction)
def hasService(self, plugin, func):
pass
- @permission(PERMS.INTERACTION)
+ @RequirePerm(Permission.Interaction)
def call(self, plugin, func, arguments):
"""Calls a service (a method in addon plugin).
@@ -1054,7 +1029,7 @@ class Api(Iface):
except Exception, e:
raise ServiceException(e.message)
- @permission(PERMS.STATUS)
+ @RequirePerm(Permission.Status)
def getAllInfo(self):
"""Returns all information stored by addon plugins. Values are always strings
@@ -1062,7 +1037,7 @@ class Api(Iface):
"""
return self.core.addonManager.getAllInfo()
- @permission(PERMS.STATUS)
+ @RequirePerm(Permission.Status)
def getInfoByPlugin(self, plugin):
"""Returns information stored by a specific plugin.
diff --git a/module/database/DatabaseBackend.py b/module/database/DatabaseBackend.py
index 6373120ff..516aa981f 100644
--- a/module/database/DatabaseBackend.py
+++ b/module/database/DatabaseBackend.py
@@ -301,13 +301,10 @@ class DatabaseBackend(Thread):
self.c.execute(
'CREATE TABLE IF NOT EXISTS "collector" ('
- '"url" TEXT NOT NULL, '
- '"name" TEXT NOT NULL, '
- '"plugin" TEXT DEFAULT "BasePlugin" NOT NULL, '
- '"size" INTEGER DEFAULT 0 NOT NULL, '
- '"status" INTEGER DEFAULT 3 NOT NULL, '
- '"packagename" TEXT DEFAULT "" NOT NULL, '
- 'PRIMARY KEY (url, packagename) ON CONFLICT REPLACE'
+ '"owner" INTEGER NOT NULL, '
+ '"data" TEXT NOT NULL, '
+ 'FOREIGN KEY(owner) REFERENCES users(uid)'
+ 'PRIMARY KEY(owner) ON CONFLICT REPLACE'
') '
)
@@ -322,25 +319,27 @@ class DatabaseBackend(Thread):
self.c.execute(
'CREATE TABLE IF NOT EXISTS "users" ('
- '"id" INTEGER PRIMARY KEY AUTOINCREMENT, '
+ '"uid" INTEGER PRIMARY KEY AUTOINCREMENT, '
'"name" TEXT NOT NULL, '
'"email" TEXT DEFAULT "" NOT NULL, '
'"password" TEXT NOT NULL, '
'"role" INTEGER DEFAULT 0 NOT NULL, '
'"permission" INTEGER DEFAULT 0 NOT NULL, '
'"folder" TEXT DEFAULT "" NOT NULL, '
- '"ratio" INTEGER DEFAULT -1 NOT NULL, '
- '"limit" INTEGER DEFAULT -1 NOT NULL, '
+ '"traffic" INTEGER DEFAULT -1 NOT NULL, '
+ '"dllimit" INTEGER DEFAULT -1 NOT NULL, '
'"template" TEXT DEFAULT "default" NOT NULL, '
- '"user" INTEGER DEFAULT -1 NOT NULL, '
- 'FOREIGN KEY(user) REFERENCES users(id)'
+ '"user" INTEGER DEFAULT -1 NOT NULL, ' # set by trigger to self
+ 'FOREIGN KEY(user) REFERENCES users(uid)'
')'
)
+ self.c.execute('CREATE INDEX IF NOT EXISTS "username_index" ON users(name)')
+
self.c.execute(
'CREATE TRIGGER IF NOT EXISTS "insert_user" AFTER INSERT ON "users"'
'BEGIN '
- 'UPDATE users SET user = new.id '
+ 'UPDATE users SET user = new.uid, folder=new.name '
'WHERE rowid = new.rowid;'
'END'
)
@@ -350,7 +349,7 @@ class DatabaseBackend(Thread):
'"plugin" TEXT NOT NULL, '
'"owner" INTEGER NOT NULL, '
'"configuration" TEXT NOT NULL, '
- 'FOREIGN KEY(owner) REFERENCES users(id), '
+ 'FOREIGN KEY(owner) REFERENCES users(uid), '
'PRIMARY KEY (plugin, owner) ON CONFLICT REPLACE'
')'
)
@@ -359,12 +358,13 @@ class DatabaseBackend(Thread):
'CREATE TABLE IF NOT EXISTS "accounts" ('
'"plugin" TEXT NOT NULL, '
'"loginname" TEXT NOT NULL, '
+ '"owner", INTEGER NOT NULL, '
'"activated" INTEGER DEFAULT 1, '
'"password" TEXT DEFAULT "", '
+ '"shared" INTEGER DEFAULT 0, '
'"options" TEXT DEFAULT "", '
-# '"owner" INTEGER NOT NULL, ' TODO: shared, owner attribute
-# 'FOREIGN KEY(owner) REFERENCES users(id)'
- 'PRIMARY KEY (plugin, loginname) ON CONFLICT REPLACE'
+ 'FOREIGN KEY(owner) REFERENCES users(uid)'
+ 'PRIMARY KEY (plugin, loginname, owner) ON CONFLICT REPLACE'
')'
)
diff --git a/module/database/FileDatabase.py b/module/database/FileDatabase.py
index 19dca84c7..b783d15d9 100644
--- a/module/database/FileDatabase.py
+++ b/module/database/FileDatabase.py
@@ -85,36 +85,20 @@ class FileMethods(DatabaseMethods):
(order, package))
@async
- def addCollector(self, plugin, package, data):
- """ fill collector, data as (name, size, status,[ hash,] url) list """
- if data and len(data[0]) == 4:
- data = [(r[0], r[1], r[2], r[3], plugin, package) for r in data]
- else:
- data = [(r[0], r[1], r[2], r[4], plugin, package) for r in data]
-
- self.c.executemany("INSERT INTO collector(name, size, status, url, plugin, packagename) VALUES (?,?,?,?,?,?)",
- data)
-
- @async
- def deleteCollector(self, package=None, url=None):
- qry = 'DELETE FROM collector'
- if package:
- self.c.execute(qry + " WHERE packagename=?", (package,))
- elif url:
- self.c.execute(qry + " WHERE url=?", (url,))
- else:
- self.c.execute(qry)
+ def saveCollector(self, owner, data):
+ """ simply save the json string to database """
+ self.c.execute("INSERT INTO collector(owner, data) VALUES (?,?)", (owner, data))
@queue
- def getCollector(self, package=None):
- """ get collector data, optionally filtered by package """
- qry = 'SELECT url, name, plugin, size, status, packagename FROM collector'
- if package:
- self.c.execute(qry + " WHERE packagename=?", (package,))
- else:
- self.c.execute(qry)
+ def retrieveCollector(self, owner):
+ """ retrieve the saved string """
+ self.c.execute('SELECT data FROM collector owner=?', (owner,))
+ return self.c.fetchone()[0]
- return [LinkStatus(*r) for r in self.c]
+ @async
+ def deleteCollector(self, owner):
+ """ drop saved user collector """
+ self.c.execute('DELETE FROM collector WHERE owner=?', (owner,))
@queue
def getAllFiles(self, package=None, search=None, unfinished=False):
diff --git a/module/remote/socketbackend/ttypes.py b/module/remote/socketbackend/ttypes.py
index 1fd61ae72..36f2b01ef 100644
--- a/module/remote/socketbackend/ttypes.py
+++ b/module/remote/socketbackend/ttypes.py
@@ -62,18 +62,36 @@ class PackageStatus:
Paused = 1
Remote = 2
+class Permission:
+ Accounts = 128
+ Add = 1
+ Addons = 512
+ All = 0
+ Delete = 2
+ Download = 64
+ Interaction = 256
+ List = 16
+ Modify = 32
+ Status = 4
+
+class Role:
+ Admin = 0
+ User = 1
+
class AccountInfo(BaseObject):
- __slots__ = ['plugin', 'loginname', 'valid', 'validuntil', 'trafficleft', 'maxtraffic', 'premium', 'activated', 'options']
+ __slots__ = ['plugin', 'loginname', 'owner', 'valid', 'validuntil', 'trafficleft', 'maxtraffic', 'premium', 'activated', 'shared', 'options']
- def __init__(self, plugin=None, loginname=None, valid=None, validuntil=None, trafficleft=None, maxtraffic=None, premium=None, activated=None, options=None):
+ def __init__(self, plugin=None, loginname=None, owner=None, valid=None, validuntil=None, trafficleft=None, maxtraffic=None, premium=None, activated=None, shared=None, options=None):
self.plugin = plugin
self.loginname = loginname
+ self.owner = owner
self.valid = valid
self.validuntil = validuntil
self.trafficleft = trafficleft
self.maxtraffic = maxtraffic
self.premium = premium
self.activated = activated
+ self.shared = shared
self.options = options
class AddonInfo(BaseObject):
@@ -273,13 +291,18 @@ class ServiceException(Exception):
self.msg = msg
class UserData(BaseObject):
- __slots__ = ['name', 'email', 'role', 'permission', 'templateName']
+ __slots__ = ['uid', 'name', 'email', 'role', 'permission', 'folder', 'traffic', 'limit', 'user', 'templateName']
- def __init__(self, name=None, email=None, role=None, permission=None, templateName=None):
+ def __init__(self, uid=None, name=None, email=None, role=None, permission=None, folder=None, traffic=None, limit=None, user=None, templateName=None):
+ self.uid = uid
self.name = name
self.email = email
self.role = role
self.permission = permission
+ self.folder = folder
+ self.traffic = traffic
+ self.limit = limit
+ self.user = user
self.templateName = templateName
class UserDoesNotExists(Exception):
@@ -301,6 +324,8 @@ class Iface:
pass
def addToCollector(self, links):
pass
+ def addUser(self, username, password):
+ pass
def autoAddLinks(self, links):
pass
def call(self, plugin, func, arguments):
@@ -383,7 +408,7 @@ class Iface:
pass
def getUnfinishedFileTree(self, pid, full):
pass
- def getUserData(self, username, password):
+ def getUserData(self):
pass
def hasService(self, plugin, func):
pass
@@ -415,6 +440,8 @@ class Iface:
pass
def removeAccount(self, plugin, account):
pass
+ def removeUser(self, uid):
+ pass
def renameCollPack(self, name, new_name):
pass
def restart(self):
@@ -441,6 +468,8 @@ class Iface:
pass
def setPackagePaused(self, pid, paused):
pass
+ def setPassword(self, username, old_password, new_password):
+ pass
def statusServer(self):
pass
def stopAllDownloads(self):
@@ -455,6 +484,8 @@ class Iface:
pass
def updateAccount(self, plugin, account, password, options):
pass
+ def updateUserData(self, data):
+ pass
def uploadContainer(self, filename, data):
pass
diff --git a/module/remote/thriftbackend/pyload.thrift b/module/remote/thriftbackend/pyload.thrift
index df82dae2d..254f41068 100644
--- a/module/remote/thriftbackend/pyload.thrift
+++ b/module/remote/thriftbackend/pyload.thrift
@@ -4,12 +4,12 @@ typedef i32 FileID
typedef i32 PackageID
typedef i32 ResultID
typedef i32 InteractionID
+typedef i32 UserID
typedef i64 UTCDate
typedef i64 ByteCount
typedef list<string> LinkList
-// a string that can represent multiple types int, bool, time, etc..
-typedef string ValueString
typedef string PluginName
+typedef string JSONString
// NA - Not Available
enum DownloadStatus {
@@ -80,6 +80,24 @@ enum Output {
Query = 4,
}
+enum Permission {
+ All = 0, // requires no permission, but login
+ Add = 1, // can add packages
+ Delete = 2, // can delete packages
+ Status = 4, // see and change server status
+ List = 16, // see listed downloads
+ Modify = 32, // modify some attribute of downloads
+ Download = 64, // can download from webinterface
+ Accounts = 128, // can access accounts
+ Interaction = 256, // can interact with plugins
+ Addons = 512 // user can activate addons
+}
+
+enum Role {
+ Admin = 0, //admin has all permissions implicit
+ User = 1
+}
+
struct ProgressInfo {
1: FileID fid,
2: string name,
@@ -176,7 +194,7 @@ struct InteractionTask {
2: Input input,
3: list<string> data,
4: Output output,
- 5: optional ValueString default_value,
+ 5: optional JSONString default_value,
6: string title,
7: string description,
8: PluginName plugin,
@@ -185,7 +203,7 @@ struct InteractionTask {
struct AddonInfo {
1: string func_name,
2: string description,
- 3: ValueString value,
+ 3: JSONString value,
}
struct ConfigItem {
@@ -193,8 +211,8 @@ struct ConfigItem {
2: string display_name,
3: string description,
4: string type,
- 5: ValueString default_value,
- 6: ValueString value,
+ 5: JSONString default_value,
+ 6: JSONString value,
}
struct ConfigSection {
@@ -213,23 +231,30 @@ struct EventInfo {
}
struct UserData {
- 1: string name,
- 2: string email,
- 3: i32 role,
- 4: i32 permission,
- 5: string templateName
+ 1: UserID uid,
+ 2: string name,
+ 3: string email,
+ 4: i16 role,
+ 5: i16 permission,
+ 6: string folder,
+ 7: ByteCount traffic
+ 8: i16 dllimit
+ 9: UserID user
+ 10: string templateName
}
struct AccountInfo {
1: PluginName plugin,
2: string loginname,
- 3: bool valid,
- 4: UTCDate validuntil,
- 5: ByteCount trafficleft,
- 6: ByteCount maxtraffic,
- 7: bool premium,
- 8: bool activated,
- 9: map<string, string> options,
+ 3: UserID owner,
+ 4: bool valid,
+ 5: UTCDate validuntil,
+ 6: ByteCount trafficleft,
+ 7: ByteCount maxtraffic,
+ 8: bool premium,
+ 9: bool activated,
+ 10: bool shared,
+ 11: map<string, string> options,
}
struct AddonService {
@@ -300,7 +325,7 @@ service Pyload {
map<string, ConfigSection> getConfig(),
map<PluginName, ConfigSection> getPluginConfig(),
ConfigSection configureSection(1: string section),
- void setConfigHandler(1: PluginName plugin, 2: InteractionID iid, 3: ValueString value),
+ void setConfigHandler(1: PluginName plugin, 2: InteractionID iid, 3: JSONString value),
///////////////////////
// Download Preparing
@@ -410,7 +435,7 @@ service Pyload {
// mode = Output types binary ORed
bool isInteractionWaiting(1: i16 mode),
InteractionTask getInteractionTask(1: i16 mode),
- void setInteractionResult(1: InteractionID iid, 2: ValueString result),
+ 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),
@@ -440,8 +465,20 @@ service Pyload {
/////////////////////////
bool login(1: string username, 2: string password),
- UserData getUserData(1: string username, 2: string password) throws (1: UserDoesNotExists ex),
- map<string, UserData> getAllUserData(),
+ // returns own user data
+ UserData getUserData(),
+
+ // all user, for admins only
+ map<UserID, UserData> getAllUserData(),
+
+ UserData addUser(1: string username, 2:string password),
+
+ // normal user can only update their own userdata and not all attributes
+ void updateUserData(1: UserData data),
+ void removeUser(1: UserID uid),
+
+ // works contextual, admin can change every password
+ bool setPassword(1: string username, 2: string old_password, 3: string new_password),
///////////////////////
// Addon Methods
@@ -451,7 +488,7 @@ service Pyload {
bool hasService(1: PluginName plugin, 2: string func),
// empty string or json encoded list as args
- string call(1: PluginName plugin, 2: string func, 3: string arguments) throws (1: ServiceDoesNotExists ex, 2: ServiceException e),
+ string call(1: PluginName plugin, 2: string func, 3: JSONString arguments) throws (1: ServiceDoesNotExists ex, 2: ServiceException e),
map<PluginName, list<AddonInfo>> getAllInfo(),
list<AddonInfo> getInfoByPlugin(1: PluginName plugin),
diff --git a/module/remote/thriftbackend/thriftgen/pyload/Pyload-remote b/module/remote/thriftbackend/thriftgen/pyload/Pyload-remote
index 55f9a1823..c2c13d8ed 100755
--- a/module/remote/thriftbackend/thriftgen/pyload/Pyload-remote
+++ b/module/remote/thriftbackend/thriftgen/pyload/Pyload-remote
@@ -42,7 +42,7 @@ if len(sys.argv) <= 1 or sys.argv[1] == '--help':
print ' getConfig()'
print ' getPluginConfig()'
print ' ConfigSection configureSection(string section)'
- print ' void setConfigHandler(PluginName plugin, InteractionID iid, ValueString value)'
+ print ' void setConfigHandler(PluginName plugin, InteractionID iid, JSONString value)'
print ' checkURLs(LinkList urls)'
print ' parseURLs(string html, string url)'
print ' OnlineCheck checkOnlineStatus(LinkList urls)'
@@ -89,7 +89,7 @@ if len(sys.argv) <= 1 or sys.argv[1] == '--help':
print ' void orderFiles( fids, PackageID pid, i16 position)'
print ' bool isInteractionWaiting(i16 mode)'
print ' InteractionTask getInteractionTask(i16 mode)'
- print ' void setInteractionResult(InteractionID iid, ValueString result)'
+ print ' void setInteractionResult(InteractionID iid, JSONString result)'
print ' string generateDownloadLink(FileID fid, i16 timeout)'
print ' getNotifications()'
print ' getAddonHandler()'
@@ -100,11 +100,15 @@ if len(sys.argv) <= 1 or sys.argv[1] == '--help':
print ' void updateAccount(PluginName plugin, string account, string password, options)'
print ' void removeAccount(PluginName plugin, string account)'
print ' bool login(string username, string password)'
- print ' UserData getUserData(string username, string password)'
+ print ' UserData getUserData()'
print ' getAllUserData()'
+ print ' UserData addUser(string username, string password)'
+ print ' void updateUserData(UserData data)'
+ print ' void removeUser(UserID uid)'
+ print ' bool setPassword(string username, string old_password, string new_password)'
print ' getServices()'
print ' bool hasService(PluginName plugin, string func)'
- print ' string call(PluginName plugin, string func, string arguments)'
+ print ' string call(PluginName plugin, string func, JSONString arguments)'
print ' getAllInfo()'
print ' getInfoByPlugin(PluginName plugin)'
print ''
@@ -621,10 +625,10 @@ elif cmd == 'login':
pp.pprint(client.login(args[0],args[1],))
elif cmd == 'getUserData':
- if len(args) != 2:
- print 'getUserData requires 2 args'
+ if len(args) != 0:
+ print 'getUserData requires 0 args'
sys.exit(1)
- pp.pprint(client.getUserData(args[0],args[1],))
+ pp.pprint(client.getUserData())
elif cmd == 'getAllUserData':
if len(args) != 0:
@@ -632,6 +636,30 @@ elif cmd == 'getAllUserData':
sys.exit(1)
pp.pprint(client.getAllUserData())
+elif cmd == 'addUser':
+ if len(args) != 2:
+ print 'addUser requires 2 args'
+ sys.exit(1)
+ pp.pprint(client.addUser(args[0],args[1],))
+
+elif cmd == 'updateUserData':
+ if len(args) != 1:
+ print 'updateUserData requires 1 args'
+ sys.exit(1)
+ pp.pprint(client.updateUserData(eval(args[0]),))
+
+elif cmd == 'removeUser':
+ if len(args) != 1:
+ print 'removeUser requires 1 args'
+ sys.exit(1)
+ pp.pprint(client.removeUser(eval(args[0]),))
+
+elif cmd == 'setPassword':
+ if len(args) != 3:
+ print 'setPassword requires 3 args'
+ sys.exit(1)
+ pp.pprint(client.setPassword(args[0],args[1],args[2],))
+
elif cmd == 'getServices':
if len(args) != 0:
print 'getServices requires 0 args'
@@ -648,7 +676,7 @@ elif cmd == 'call':
if len(args) != 3:
print 'call requires 3 args'
sys.exit(1)
- pp.pprint(client.call(eval(args[0]),args[1],args[2],))
+ pp.pprint(client.call(eval(args[0]),args[1],eval(args[2]),))
elif cmd == 'getAllInfo':
if len(args) != 0:
diff --git a/module/remote/thriftbackend/thriftgen/pyload/Pyload.py b/module/remote/thriftbackend/thriftgen/pyload/Pyload.py
index 51c8621ba..c45663d25 100644
--- a/module/remote/thriftbackend/thriftgen/pyload/Pyload.py
+++ b/module/remote/thriftbackend/thriftgen/pyload/Pyload.py
@@ -9,7 +9,7 @@
from thrift.Thrift import TType, TMessageType, TException
from ttypes import *
from thrift.Thrift import TProcessor
-from thrift.protocol.TBase import TBase, TExceptionBase
+from thrift.protocol.TBase import TBase, TExceptionBase, TApplicationException
class Iface(object):
@@ -508,7 +508,13 @@ class Iface(object):
"""
pass
- def getUserData(self, username, password):
+ def getUserData(self, ):
+ pass
+
+ def getAllUserData(self, ):
+ pass
+
+ def addUser(self, username, password):
"""
Parameters:
- username
@@ -516,7 +522,27 @@ class Iface(object):
"""
pass
- def getAllUserData(self, ):
+ def updateUserData(self, data):
+ """
+ Parameters:
+ - data
+ """
+ pass
+
+ def removeUser(self, uid):
+ """
+ Parameters:
+ - uid
+ """
+ pass
+
+ def setPassword(self, username, old_password, new_password):
+ """
+ Parameters:
+ - username
+ - old_password
+ - new_password
+ """
pass
def getServices(self, ):
@@ -2808,20 +2834,13 @@ class Client(Iface):
return result.success
raise TApplicationException(TApplicationException.MISSING_RESULT, "login failed: unknown result");
- def getUserData(self, username, password):
- """
- Parameters:
- - username
- - password
- """
- self.send_getUserData(username, password)
+ def getUserData(self, ):
+ self.send_getUserData()
return self.recv_getUserData()
- def send_getUserData(self, username, password):
+ def send_getUserData(self, ):
self._oprot.writeMessageBegin('getUserData', TMessageType.CALL, self._seqid)
args = getUserData_args()
- args.username = username
- args.password = password
args.write(self._oprot)
self._oprot.writeMessageEnd()
self._oprot.trans.flush()
@@ -2838,8 +2857,6 @@ class Client(Iface):
self._iprot.readMessageEnd()
if result.success is not None:
return result.success
- if result.ex is not None:
- raise result.ex
raise TApplicationException(TApplicationException.MISSING_RESULT, "getUserData failed: unknown result");
def getAllUserData(self, ):
@@ -2867,6 +2884,128 @@ class Client(Iface):
return result.success
raise TApplicationException(TApplicationException.MISSING_RESULT, "getAllUserData failed: unknown result");
+ def addUser(self, username, password):
+ """
+ Parameters:
+ - username
+ - password
+ """
+ self.send_addUser(username, password)
+ return self.recv_addUser()
+
+ def send_addUser(self, username, password):
+ self._oprot.writeMessageBegin('addUser', TMessageType.CALL, self._seqid)
+ args = addUser_args()
+ args.username = username
+ args.password = password
+ args.write(self._oprot)
+ self._oprot.writeMessageEnd()
+ self._oprot.trans.flush()
+
+ def recv_addUser(self, ):
+ (fname, mtype, rseqid) = self._iprot.readMessageBegin()
+ if mtype == TMessageType.EXCEPTION:
+ x = TApplicationException()
+ x.read(self._iprot)
+ self._iprot.readMessageEnd()
+ raise x
+ result = addUser_result()
+ result.read(self._iprot)
+ self._iprot.readMessageEnd()
+ if result.success is not None:
+ return result.success
+ raise TApplicationException(TApplicationException.MISSING_RESULT, "addUser failed: unknown result");
+
+ def updateUserData(self, data):
+ """
+ Parameters:
+ - data
+ """
+ self.send_updateUserData(data)
+ self.recv_updateUserData()
+
+ def send_updateUserData(self, data):
+ self._oprot.writeMessageBegin('updateUserData', TMessageType.CALL, self._seqid)
+ args = updateUserData_args()
+ args.data = data
+ args.write(self._oprot)
+ self._oprot.writeMessageEnd()
+ self._oprot.trans.flush()
+
+ def recv_updateUserData(self, ):
+ (fname, mtype, rseqid) = self._iprot.readMessageBegin()
+ if mtype == TMessageType.EXCEPTION:
+ x = TApplicationException()
+ x.read(self._iprot)
+ self._iprot.readMessageEnd()
+ raise x
+ result = updateUserData_result()
+ result.read(self._iprot)
+ self._iprot.readMessageEnd()
+ return
+
+ def removeUser(self, uid):
+ """
+ Parameters:
+ - uid
+ """
+ self.send_removeUser(uid)
+ self.recv_removeUser()
+
+ def send_removeUser(self, uid):
+ self._oprot.writeMessageBegin('removeUser', TMessageType.CALL, self._seqid)
+ args = removeUser_args()
+ args.uid = uid
+ args.write(self._oprot)
+ self._oprot.writeMessageEnd()
+ self._oprot.trans.flush()
+
+ def recv_removeUser(self, ):
+ (fname, mtype, rseqid) = self._iprot.readMessageBegin()
+ if mtype == TMessageType.EXCEPTION:
+ x = TApplicationException()
+ x.read(self._iprot)
+ self._iprot.readMessageEnd()
+ raise x
+ result = removeUser_result()
+ result.read(self._iprot)
+ self._iprot.readMessageEnd()
+ return
+
+ def setPassword(self, username, old_password, new_password):
+ """
+ Parameters:
+ - username
+ - old_password
+ - new_password
+ """
+ self.send_setPassword(username, old_password, new_password)
+ return self.recv_setPassword()
+
+ def send_setPassword(self, username, old_password, new_password):
+ self._oprot.writeMessageBegin('setPassword', TMessageType.CALL, self._seqid)
+ args = setPassword_args()
+ args.username = username
+ args.old_password = old_password
+ args.new_password = new_password
+ args.write(self._oprot)
+ self._oprot.writeMessageEnd()
+ self._oprot.trans.flush()
+
+ def recv_setPassword(self, ):
+ (fname, mtype, rseqid) = self._iprot.readMessageBegin()
+ if mtype == TMessageType.EXCEPTION:
+ x = TApplicationException()
+ x.read(self._iprot)
+ self._iprot.readMessageEnd()
+ raise x
+ result = setPassword_result()
+ result.read(self._iprot)
+ self._iprot.readMessageEnd()
+ if result.success is not None:
+ return result.success
+ raise TApplicationException(TApplicationException.MISSING_RESULT, "setPassword failed: unknown result");
+
def getServices(self, ):
self.send_getServices()
return self.recv_getServices()
@@ -3101,6 +3240,10 @@ class Processor(Iface, TProcessor):
self._processMap["login"] = Processor.process_login
self._processMap["getUserData"] = Processor.process_getUserData
self._processMap["getAllUserData"] = Processor.process_getAllUserData
+ self._processMap["addUser"] = Processor.process_addUser
+ self._processMap["updateUserData"] = Processor.process_updateUserData
+ self._processMap["removeUser"] = Processor.process_removeUser
+ self._processMap["setPassword"] = Processor.process_setPassword
self._processMap["getServices"] = Processor.process_getServices
self._processMap["hasService"] = Processor.process_hasService
self._processMap["call"] = Processor.process_call
@@ -4001,10 +4144,7 @@ class Processor(Iface, TProcessor):
args.read(iprot)
iprot.readMessageEnd()
result = getUserData_result()
- try:
- result.success = self._handler.getUserData(args.username, args.password)
- except UserDoesNotExists, ex:
- result.ex = ex
+ result.success = self._handler.getUserData()
oprot.writeMessageBegin("getUserData", TMessageType.REPLY, seqid)
result.write(oprot)
oprot.writeMessageEnd()
@@ -4021,6 +4161,50 @@ class Processor(Iface, TProcessor):
oprot.writeMessageEnd()
oprot.trans.flush()
+ def process_addUser(self, seqid, iprot, oprot):
+ args = addUser_args()
+ args.read(iprot)
+ iprot.readMessageEnd()
+ result = addUser_result()
+ result.success = self._handler.addUser(args.username, args.password)
+ oprot.writeMessageBegin("addUser", TMessageType.REPLY, seqid)
+ result.write(oprot)
+ oprot.writeMessageEnd()
+ oprot.trans.flush()
+
+ def process_updateUserData(self, seqid, iprot, oprot):
+ args = updateUserData_args()
+ args.read(iprot)
+ iprot.readMessageEnd()
+ result = updateUserData_result()
+ self._handler.updateUserData(args.data)
+ oprot.writeMessageBegin("updateUserData", TMessageType.REPLY, seqid)
+ result.write(oprot)
+ oprot.writeMessageEnd()
+ oprot.trans.flush()
+
+ def process_removeUser(self, seqid, iprot, oprot):
+ args = removeUser_args()
+ args.read(iprot)
+ iprot.readMessageEnd()
+ result = removeUser_result()
+ self._handler.removeUser(args.uid)
+ oprot.writeMessageBegin("removeUser", TMessageType.REPLY, seqid)
+ result.write(oprot)
+ oprot.writeMessageEnd()
+ oprot.trans.flush()
+
+ def process_setPassword(self, seqid, iprot, oprot):
+ args = setPassword_args()
+ args.read(iprot)
+ iprot.readMessageEnd()
+ result = setPassword_result()
+ result.success = self._handler.setPassword(args.username, args.old_password, args.new_password)
+ oprot.writeMessageBegin("setPassword", TMessageType.REPLY, seqid)
+ result.write(oprot)
+ oprot.writeMessageEnd()
+ oprot.trans.flush()
+
def process_getServices(self, seqid, iprot, oprot):
args = getServices_args()
args.read(iprot)
@@ -6695,6 +6879,60 @@ class login_result(TBase):
class getUserData_args(TBase):
+
+ __slots__ = [
+ ]
+
+ thrift_spec = (
+ )
+
+
+class getUserData_result(TBase):
+ """
+ Attributes:
+ - success
+ """
+
+ __slots__ = [
+ 'success',
+ ]
+
+ thrift_spec = (
+ (0, TType.STRUCT, 'success', (UserData, UserData.thrift_spec), None, ), # 0
+ )
+
+ def __init__(self, success=None,):
+ self.success = success
+
+
+class getAllUserData_args(TBase):
+
+ __slots__ = [
+ ]
+
+ thrift_spec = (
+ )
+
+
+class getAllUserData_result(TBase):
+ """
+ Attributes:
+ - success
+ """
+
+ __slots__ = [
+ 'success',
+ ]
+
+ thrift_spec = (
+ (0, TType.MAP, 'success', (TType.I32,None,TType.STRUCT,(UserData, UserData.thrift_spec)), None, ), # 0
+ )
+
+ def __init__(self, success=None,):
+ self.success = success
+
+
+class addUser_args(TBase):
"""
Attributes:
- username
@@ -6717,38 +6955,108 @@ class getUserData_args(TBase):
self.password = password
-class getUserData_result(TBase):
+class addUser_result(TBase):
"""
Attributes:
- success
- - ex
"""
__slots__ = [
'success',
- 'ex',
]
thrift_spec = (
(0, TType.STRUCT, 'success', (UserData, UserData.thrift_spec), None, ), # 0
- (1, TType.STRUCT, 'ex', (UserDoesNotExists, UserDoesNotExists.thrift_spec), None, ), # 1
)
- def __init__(self, success=None, ex=None,):
+ def __init__(self, success=None,):
self.success = success
- self.ex = ex
-class getAllUserData_args(TBase):
+class updateUserData_args(TBase):
+ """
+ Attributes:
+ - data
+ """
__slots__ = [
+ 'data',
]
thrift_spec = (
+ None, # 0
+ (1, TType.STRUCT, 'data', (UserData, UserData.thrift_spec), None, ), # 1
)
+ def __init__(self, data=None,):
+ self.data = data
+
-class getAllUserData_result(TBase):
+class updateUserData_result(TBase):
+
+ __slots__ = [
+ ]
+
+ thrift_spec = (
+ )
+
+
+class removeUser_args(TBase):
+ """
+ Attributes:
+ - uid
+ """
+
+ __slots__ = [
+ 'uid',
+ ]
+
+ thrift_spec = (
+ None, # 0
+ (1, TType.I32, 'uid', None, None, ), # 1
+ )
+
+ def __init__(self, uid=None,):
+ self.uid = uid
+
+
+class removeUser_result(TBase):
+
+ __slots__ = [
+ ]
+
+ thrift_spec = (
+ )
+
+
+class setPassword_args(TBase):
+ """
+ Attributes:
+ - username
+ - old_password
+ - new_password
+ """
+
+ __slots__ = [
+ 'username',
+ 'old_password',
+ 'new_password',
+ ]
+
+ thrift_spec = (
+ None, # 0
+ (1, TType.STRING, 'username', None, None, ), # 1
+ (2, TType.STRING, 'old_password', None, None, ), # 2
+ (3, TType.STRING, 'new_password', None, None, ), # 3
+ )
+
+ def __init__(self, username=None, old_password=None, new_password=None,):
+ self.username = username
+ self.old_password = old_password
+ self.new_password = new_password
+
+
+class setPassword_result(TBase):
"""
Attributes:
- success
@@ -6759,7 +7067,7 @@ class getAllUserData_result(TBase):
]
thrift_spec = (
- (0, TType.MAP, 'success', (TType.STRING,None,TType.STRUCT,(UserData, UserData.thrift_spec)), None, ), # 0
+ (0, TType.BOOL, 'success', None, None, ), # 0
)
def __init__(self, success=None,):
diff --git a/module/remote/thriftbackend/thriftgen/pyload/ttypes.py b/module/remote/thriftbackend/thriftgen/pyload/ttypes.py
index fbbc599a8..c177a9dd2 100644
--- a/module/remote/thriftbackend/thriftgen/pyload/ttypes.py
+++ b/module/remote/thriftbackend/thriftgen/pyload/ttypes.py
@@ -191,6 +191,58 @@ class Output(TBase):
"Query": 4,
}
+class Permission(TBase):
+ All = 0
+ Add = 1
+ Delete = 2
+ Status = 4
+ List = 16
+ Modify = 32
+ Download = 64
+ Accounts = 128
+ Interaction = 256
+ Addons = 512
+
+ _VALUES_TO_NAMES = {
+ 0: "All",
+ 1: "Add",
+ 2: "Delete",
+ 4: "Status",
+ 16: "List",
+ 32: "Modify",
+ 64: "Download",
+ 128: "Accounts",
+ 256: "Interaction",
+ 512: "Addons",
+ }
+
+ _NAMES_TO_VALUES = {
+ "All": 0,
+ "Add": 1,
+ "Delete": 2,
+ "Status": 4,
+ "List": 16,
+ "Modify": 32,
+ "Download": 64,
+ "Accounts": 128,
+ "Interaction": 256,
+ "Addons": 512,
+ }
+
+class Role(TBase):
+ Admin = 0
+ User = 1
+
+ _VALUES_TO_NAMES = {
+ 0: "Admin",
+ 1: "User",
+ }
+
+ _NAMES_TO_VALUES = {
+ "Admin": 0,
+ "User": 1,
+ }
+
class ProgressInfo(TBase):
"""
@@ -750,35 +802,55 @@ class EventInfo(TBase):
class UserData(TBase):
"""
Attributes:
+ - uid
- name
- email
- role
- permission
+ - folder
+ - traffic
+ - limit
+ - user
- templateName
"""
__slots__ = [
+ 'uid',
'name',
'email',
'role',
'permission',
+ 'folder',
+ 'traffic',
+ 'limit',
+ 'user',
'templateName',
]
thrift_spec = (
None, # 0
- (1, TType.STRING, 'name', None, None, ), # 1
- (2, TType.STRING, 'email', None, None, ), # 2
- (3, TType.I32, 'role', None, None, ), # 3
- (4, TType.I32, 'permission', None, None, ), # 4
- (5, TType.STRING, 'templateName', None, None, ), # 5
+ (1, TType.I32, 'uid', None, None, ), # 1
+ (2, TType.STRING, 'name', None, None, ), # 2
+ (3, TType.STRING, 'email', None, None, ), # 3
+ (4, TType.I16, 'role', None, None, ), # 4
+ (5, TType.I16, 'permission', None, None, ), # 5
+ (6, TType.STRING, 'folder', None, None, ), # 6
+ (7, TType.I64, 'traffic', None, None, ), # 7
+ (8, TType.I16, 'limit', None, None, ), # 8
+ (9, TType.I32, 'user', None, None, ), # 9
+ (10, TType.STRING, 'templateName', None, None, ), # 10
)
- def __init__(self, name=None, email=None, role=None, permission=None, templateName=None,):
+ def __init__(self, uid=None, name=None, email=None, role=None, permission=None, folder=None, traffic=None, limit=None, user=None, templateName=None,):
+ self.uid = uid
self.name = name
self.email = email
self.role = role
self.permission = permission
+ self.folder = folder
+ self.traffic = traffic
+ self.limit = limit
+ self.user = user
self.templateName = templateName
@@ -787,24 +859,28 @@ class AccountInfo(TBase):
Attributes:
- plugin
- loginname
+ - owner
- valid
- validuntil
- trafficleft
- maxtraffic
- premium
- activated
+ - shared
- options
"""
__slots__ = [
'plugin',
'loginname',
+ 'owner',
'valid',
'validuntil',
'trafficleft',
'maxtraffic',
'premium',
'activated',
+ 'shared',
'options',
]
@@ -812,24 +888,28 @@ class AccountInfo(TBase):
None, # 0
(1, TType.STRING, 'plugin', None, None, ), # 1
(2, TType.STRING, 'loginname', None, None, ), # 2
- (3, TType.BOOL, 'valid', None, None, ), # 3
- (4, TType.I64, 'validuntil', None, None, ), # 4
- (5, TType.I64, 'trafficleft', None, None, ), # 5
- (6, TType.I64, 'maxtraffic', None, None, ), # 6
- (7, TType.BOOL, 'premium', None, None, ), # 7
- (8, TType.BOOL, 'activated', None, None, ), # 8
- (9, TType.MAP, 'options', (TType.STRING,None,TType.STRING,None), None, ), # 9
+ (3, TType.I32, 'owner', None, None, ), # 3
+ (4, TType.BOOL, 'valid', None, None, ), # 4
+ (5, TType.I64, 'validuntil', None, None, ), # 5
+ (6, TType.I64, 'trafficleft', None, None, ), # 6
+ (7, TType.I64, 'maxtraffic', None, None, ), # 7
+ (8, TType.BOOL, 'premium', None, None, ), # 8
+ (9, TType.BOOL, 'activated', None, None, ), # 9
+ (10, TType.BOOL, 'shared', None, None, ), # 10
+ (11, TType.MAP, 'options', (TType.STRING,None,TType.STRING,None), None, ), # 11
)
- def __init__(self, plugin=None, loginname=None, valid=None, validuntil=None, trafficleft=None, maxtraffic=None, premium=None, activated=None, options=None,):
+ def __init__(self, plugin=None, loginname=None, owner=None, valid=None, validuntil=None, trafficleft=None, maxtraffic=None, premium=None, activated=None, shared=None, options=None,):
self.plugin = plugin
self.loginname = loginname
+ self.owner = owner
self.valid = valid
self.validuntil = validuntil
self.trafficleft = trafficleft
self.maxtraffic = maxtraffic
self.premium = premium
self.activated = activated
+ self.shared = shared
self.options = options
diff --git a/module/web/utils.py b/module/web/utils.py
index 5cb0cebdd..ac4bdd4f8 100644
--- a/module/web/utils.py
+++ b/module/web/utils.py
@@ -20,7 +20,7 @@ from bottle import request, HTTPError, redirect, ServerAdapter
from webinterface import env, TEMPLATE
-from module.Api import has_permission, PERMS, ROLE
+from module.Api import has_permission, Permission, Role
def render_to_response(name, args={}, proc=[]):
for p in proc:
@@ -31,14 +31,14 @@ def render_to_response(name, args={}, proc=[]):
def parse_permissions(session):
- perms = dict([(x, False) for x in dir(PERMS) if not x.startswith("_")])
+ perms = dict([(x, False) for x in dir(Permission) if not x.startswith("_")])
perms["ADMIN"] = False
perms["is_admin"] = False
if not session.get("authenticated", False):
return perms
- if session.get("role") == ROLE.ADMIN:
+ if session.get("role") == Role.Admin:
for k in perms.iterkeys():
perms[k] = True
@@ -50,7 +50,7 @@ def parse_permissions(session):
def permlist():
- return [x for x in dir(PERMS) if not x.startswith("_") and x != "ALL"]
+ return [x for x in dir(Permission) if not x.startswith("_") and x != "ALL"]
def get_permission(perms, p):
@@ -60,7 +60,7 @@ def get_permission(perms, p):
:param p: bits
"""
for name in permlist():
- perms[name] = has_permission(p, getattr(PERMS, name))
+ perms[name] = has_permission(p, getattr(Permission, name))
def set_permission(perms):
@@ -69,11 +69,11 @@ def set_permission(perms):
:param perms: dict
"""
permission = 0
- for name in dir(PERMS):
+ for name in dir(Permission):
if name.startswith("_"): continue
if name in perms and perms[name]:
- permission |= getattr(PERMS, name)
+ permission |= getattr(Permission, name)
return permission