summaryrefslogtreecommitdiffstats
path: root/pyload/Api.py
diff options
context:
space:
mode:
authorGravatar RaNaN <Mast3rRaNaN@hotmail.de> 2013-06-09 18:10:22 +0200
committerGravatar RaNaN <Mast3rRaNaN@hotmail.de> 2013-06-09 18:10:23 +0200
commit16af85004c84d0d6c626b4f8424ce9647669a0c1 (patch)
tree025d479862d376dbc17e934f4ed20031c8cd97d1 /pyload/Api.py
parentadapted to jshint config (diff)
downloadpyload-16af85004c84d0d6c626b4f8424ce9647669a0c1.tar.xz
moved everything from module to pyload
Diffstat (limited to 'pyload/Api.py')
-rw-r--r--pyload/Api.py206
1 files changed, 206 insertions, 0 deletions
diff --git a/pyload/Api.py b/pyload/Api.py
new file mode 100644
index 000000000..32a077c08
--- /dev/null
+++ b/pyload/Api.py
@@ -0,0 +1,206 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+###############################################################################
+# Copyright(c) 2008-2013 pyLoad Team
+# http://www.pyload.org
+#
+# This file is part of pyLoad.
+# pyLoad is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# Subjected to the terms and conditions in LICENSE
+#
+# @author: RaNaN
+###############################################################################
+
+import re
+from types import MethodType
+
+from remote.apitypes import *
+
+# contains function names mapped to their permissions
+# unlisted functions are for admins only
+perm_map = {}
+
+# decorator only called on init, never initialized, so has no effect on runtime
+def RequirePerm(bits):
+ class _Dec(object):
+ def __new__(cls, func, *args, **kwargs):
+ perm_map[func.__name__] = bits
+ return func
+
+ return _Dec
+
+urlmatcher = re.compile(r"((https?|ftps?|xdcc|sftp):((//)|(\\\\))+[\w\d:#@%/;$()~_?\+\-=\\\.&]*)", re.IGNORECASE)
+
+stateMap = {
+ DownloadState.All: frozenset(getattr(DownloadStatus, x) for x in dir(DownloadStatus) if not x.startswith("_")),
+ DownloadState.Finished: frozenset((DownloadStatus.Finished, DownloadStatus.Skipped)),
+ DownloadState.Unfinished: None, # set below
+ DownloadState.Failed: frozenset((DownloadStatus.Failed, DownloadStatus.TempOffline, DownloadStatus.Aborted)),
+ DownloadState.Unmanaged: None, #TODO
+}
+
+stateMap[DownloadState.Unfinished] = frozenset(stateMap[DownloadState.All].difference(stateMap[DownloadState.Finished]))
+
+def state_string(state):
+ return ",".join(str(x) for x in stateMap[state])
+
+from datatypes.User import User
+
+class Api(Iface):
+ """
+ **pyLoads API**
+
+ This is accessible either internal via core.api, websocket backend or json api.
+
+ see Thrift specification file remote/thriftbackend/pyload.thrift\
+ for information about data structures and what methods are usable with rpc.
+
+ Most methods requires specific permissions, please look at the source code if you need to know.\
+ These can be configured via web interface.
+ Admin user have all permissions, and are the only ones who can access the methods with no specific permission.
+ """
+
+ EXTERNAL = Iface # let the json api know which methods are external
+ EXTEND = False # only extendable when set too true
+
+ def __init__(self, core):
+ self.core = core
+ self.user_apis = {}
+
+ @property
+ def user(self):
+ return None #TODO return default user?
+
+ @property
+ def primaryUID(self):
+ return self.user.primary if self.user else None
+
+ @classmethod
+ def initComponents(cls):
+ # Allow extending the api
+ # This prevents unintentionally registering of the components,
+ # but will only work once when they are imported
+ cls.EXTEND = True
+ # Import all Api modules, they register themselves.
+ import pyload.api
+ # they will vanish from the namespace afterwards
+
+
+ @classmethod
+ def extend(cls, api):
+ """Takes all params from api and extends cls with it.
+ api class can be removed afterwards
+
+ :param api: Class with methods to extend
+ """
+ if cls.EXTEND:
+ for name, func in api.__dict__.iteritems():
+ if name.startswith("_"): continue
+ setattr(cls, name, MethodType(func, None, cls))
+
+ return cls.EXTEND
+
+ def withUserContext(self, uid):
+ """ Returns a proxy version of the api, to call method in user context
+
+ :param uid: user or userData instance or uid
+ :return: :class:`UserApi`
+ """
+ if isinstance(uid, User):
+ uid = uid.uid
+
+ if uid not in self.user_apis:
+ user = self.core.db.getUserData(uid=uid)
+ if not user: #TODO: anonymous user?
+ return None
+
+ self.user_apis[uid] = UserApi(self.core, User.fromUserData(self, user))
+
+ return self.user_apis[uid]
+
+
+ #############################
+ # Auth+User Information
+ #############################
+
+ # TODO
+
+ @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.
+
+ :param username:
+ :param password:
+ :param remoteip: Omit this argument, its only used internal
+ :return: bool indicating login was successful
+ """
+ return True if self.checkAuth(username, password, remoteip) else False
+
+ def checkAuth(self, username, password, remoteip=None):
+ """Check authentication and returns details
+
+ :param username:
+ :param password:
+ :param remoteip:
+ :return: dict with info, empty when login is incorrect
+ """
+ self.core.log.info(_("User '%s' tries to log in") % username)
+
+ return self.core.db.checkAuth(username, password)
+
+ def isAuthorized(self, func, user):
+ """checks if the user is authorized for specific method
+
+ :param func: function name
+ :param user: `User`
+ :return: boolean
+ """
+ if user.isAdmin():
+ return True
+ elif func in perm_map and user.hasPermission(perm_map[func]):
+ return True
+ else:
+ return False
+
+ # TODO
+ @RequirePerm(Permission.All)
+ def getUserData(self, username, password):
+ """similar to `checkAuth` but returns UserData thrift type """
+ user = self.checkAuth(username, password)
+ if not user:
+ raise UserDoesNotExists(username)
+
+ return user.toUserData()
+
+ def getAllUserData(self):
+ """returns all known user and info"""
+ return self.core.db.getAllUserData()
+
+ def changePassword(self, username, oldpw, newpw):
+ """ changes password for specific user """
+ return self.core.db.changePassword(username, oldpw, newpw)
+
+ def setUserPermission(self, user, permission, role):
+ self.core.db.setPermission(user, permission)
+ self.core.db.setRole(user, role)
+
+
+class UserApi(Api):
+ """ Proxy object for api that provides all methods in user context """
+
+ def __init__(self, core, user):
+ # No need to init super class
+ self.core = core
+ self._user = user
+
+ def withUserContext(self, uid):
+ raise Exception("Not allowed")
+
+ @property
+ def user(self):
+ return self._user \ No newline at end of file