Пример #1
0
 def handleOauth2Request(self, params, request):
     plugin = params['pluginname']
     pluginClass = params['pluginclass']
     pluginConfig = params['config']
     configuration = Loader(self.context).configurationForPlugin(
         plugin, pluginClass, pluginConfig)
     if not configuration:
         return WebResponseJson({
             'success': False,
             'msg': 'Configuration not found'
         })
     if 'code' not in params:
         redirectUri = params['redirectUri']
         if not hasattr(configuration, 'activate'):
             return WebResponseJson({
                 'success':
                 False,
                 'msg':
                 'Configuration cannot be activated'
             })
         url = configuration.activate(redirectUri)
         return WebResponseJson({'success': True, 'url': url})
     params = configuration.activateCode(params['code'])
     try:
         config = {pluginClass: {pluginConfig: params}}
         Loader(self.context).saveConfiguration(plugin, config)
     except Exception as error:
         return WebResponseJson({'success': False, 'msg': str(error)})
     return WebResponseRedirect('%s/plugins?settings=%s' %
                                (request.base(), plugin))
Пример #2
0
    def handleRequest(plugin, path, params, **__kwargs):
        if plugin != 'telldus':
            return None

        if path == 'info':
            try:
                with open('/etc/distribution') as fd:
                    distribution = fd.readline().strip()
            except Exception as __error:
                distribution = ''
            return WebResponseJson({
                'firmware': {
                    'version': Board.firmwareVersion(),
                    'distribution': distribution,
                },
            })

        if path == 'setDistribution':
            if params.get('name', '') not in ['beta', 'stable']:
                return WebResponseJson({
                    'success': False,
                    'error': 'Invalid distribution'
                })
            retval = os.system('/usr/sbin/telldus-helper distribution %s' %
                               params['name'])
            if retval == 0:
                return WebResponseJson({'success': True})
            return WebResponseJson({
                'success':
                False,
                'error':
                'Could not change the firmware version'
            })

        return None
Пример #3
0
    def handleRequest(self, plugin, path, __params, **__kwargs):
        if plugin != 'hue':
            return None

        if path == 'state':
            if self.state == Hue.STATE_NO_BRIDGE:
                # If ssdp fails to detect, use the hue remote service
                self.searchNupnp()
            return WebResponseJson({'state': self.state})

        if path == 'reset':
            self.setState(Hue.STATE_NO_BRIDGE)
            return WebResponseJson({'success': True})
Пример #4
0
 def handleRequest(self, plugin, path, params, request):
     if path == '' and plugin == '':
         return WebResponseHtml('react.html')
     if plugin == 'telldus':
         if path == 'reactPlugins':
             return WebResponseJson(self.routes())
     fullPath = '/%s/%s' % (plugin,
                            path) if path is not '' else '/%s' % plugin
     for route in self.routes():
         if route['path'] == fullPath:
             return WebResponseHtml('react.html')
     return None
Пример #5
0
 def handleRequest(self, plugin, path, params, request):
     if path == '' and plugin == '':
         return WebResponseHtml('react.html')
     if plugin == 'telldus':
         if path == 'reactComponents':
             return WebResponseJson(self.components())
     fullPath = '/%s/%s' % (plugin,
                            path) if path is not '' else '/%s' % plugin
     components = self.components()
     for name in components:
         if components[name].get('path', None) == fullPath:
             return WebResponseHtml('react.html')
     return None
Пример #6
0
 def handleRequest(self, plugin, path, params, request, **kwargs):
     # Web requests
     if path in ['activate', 'code']:
         service = rauth.OAuth2Service(
             client_id=self.clientId,
             client_secret=self.clientSecret,
             access_token_url='https://api.netatmo.net/oauth2/token',
             authorize_url='https://api.netatmo.net/oauth2/authorize')
         if path == 'activate':
             params = {
                 'redirect_uri': '%s/netatmo/code' % request.base(),
                 'response_type': 'code'
             }
             url = service.get_authorize_url(**params)
             return WebResponseJson({'url': url})
         if path == 'code':
             data = {
                 'code': params['code'],
                 'grant_type': 'authorization_code',
                 'redirect_uri': '%s/netatmo/code' % request.base()
             }
             session = service.get_auth_session(
                 data=data, decoder=self.__decodeAccessToken)
             return WebResponseRedirect('%s/plugins?settings=netatmo' %
                                        request.base())
     if path == 'logout':
         self.accessToken = ''
         self.refreshToken = ''
         self.tokenTTL = 0
         self.setConfig(
             'oauth', {
                 'accessToken': self.accessToken,
                 'refreshToken': self.refreshToken,
                 'tokenTTL': self.tokenTTL,
             })
         self.configuration['oauth'].activated = False
         return WebResponseJson({'success': True})
     return None
Пример #7
0
 def handleRequest(self, plugin, path, params, **kwargs):
     script = None
     if path == 'save':
         if 'script' not in cherrypy.request.body.params or 'code' not in cherrypy.request.body.params:
             return WebResponseJson({
                 'error':
                 'Malformed request, parameter script or code missing'
             })
         self.saveScript(cherrypy.request.body.params['script'],
                         cherrypy.request.body.params['code'])
         return WebResponseJson({'success': True})
     elif path == 'new':
         okChars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-'
         if 'name' not in params:
             return WebResponseJson({'error': 'Invalid script name'})
         name = ''.join([c for c in params['name'] if c in okChars])
         if len(name) == 0:
             return WebResponseJson({'error': 'Invalid script name'})
         filename = '%s/%s.lua' % (Board.luaScriptPath(), name)
         with open(filename, 'w') as f:
             f.write(
                 '-- File: %s.lua\n\nfunction onInit()\n\tprint("Hello world")\nend'
                 % name)
         self.fileCreated(filename)
         return WebResponseJson({'success': True, 'name': '%s.lua' % name})
     elif path == 'delete':
         if 'name' not in params:
             return WebResponseJson({'error': 'Invalid script name'})
         for s in self.scripts:
             if s.name == params['name']:
                 os.remove(s.filename)
                 self.fileRemoved(s.filename)
                 break
         return WebResponseJson({'success': True})
     elif path == 'script':
         for s in self.scripts:
             if s.name == params['name']:
                 return WebResponseJson({
                     'name': params['name'],
                     'code': s.code,
                 })
         return WebResponseJson({})
     elif path == 'scripts':
         return WebResponseJson([{
             'name': script.name
         } for script in sorted(self.scripts, key=lambda s: s.name.lower())
                                 ])
     elif path == 'signals':
         return WebResponseJson(self.signals())
     elif 'edit' in params:
         for s in self.scripts:
             if s.name == params['edit']:
                 script = s
                 break
     return None
Пример #8
0
    def handleRequest(self, plugin, path, params, request, **kwargs):
        del kwargs
        if path == 'oauth2':
            return self.handleOauth2Request(params, request)

        if path == 'icon':
            for plugin in Loader(self.context).plugins:
                if plugin.name != params['name']:
                    continue
                return WebResponseLocalFile('%s/%s' %
                                            (plugin.path, plugin.icon))
            return None

        if path == 'import':
            filename = '%s/staging.zip' % (Board.pluginPath())
            if os.path.isfile(filename):
                try:
                    return WebResponseJson(
                        Loader(self.context).importPlugin(filename))
                except ImportError as error:
                    os.unlink('%s/staging.zip' % (Board.pluginPath()))
                    return WebResponseJson({
                        'success':
                        False,
                        'msg':
                        'Error importing plugin: %s' % error
                    })
            return WebResponseJson({
                'success':
                False,
                'msg':
                'Error importing plugin: No plugin uploaded'
            })

        if path == 'importkey':
            if 'discard' in params:
                os.unlink('%s/staging.zip' % (Board.pluginPath()))
                return WebResponseJson({'success': True})
            return WebResponseJson(
                Loader(self.context).importKey(params['key'] if 'key' in
                                               params else None))

        if path == 'installStorePlugin':
            if 'pluginname' not in params:
                return WebResponseJson({
                    'success': False,
                    'msg': 'No plugin specified'
                })
            return WebResponseJson(
                self.installStorePlugin(params['pluginname']))

        if path == 'reboot':
            retval = os.system('/usr/sbin/telldus-helper reboot')
            if retval == 0:
                return WebResponseJson({'success': True})
            return WebResponseJson({'success': False})

        if path == 'refreshStorePlugins':
            Loader(self.context).updatePluginsList()
            return WebResponseJson({'success': True})

        if path == 'remove':
            if 'pluginname' in params:
                Loader(self.context).removePlugin(params['pluginname'])
            elif 'key' in params and 'fingerprint' in params:
                Loader(self.context).removeKey(params['key'],
                                               params['fingerprint'])
            else:
                return WebResponseJson({
                    'success': False,
                    'msg': 'No plugin or key specified'
                })
            return WebResponseJson({'success': True})

        if path == 'plugins':
            return WebResponseJson([
                plugin.infoObject() for plugin in Loader(self.context).plugins
            ])

        if path == 'keys':
            return WebResponseJson([{
                'uids': key['uids'],
                'keyid': key['keyid'],
                'fingerprint': key['fingerprint']
            } for key in Loader(self.context).keys])

        if path == 'saveConfiguration' and request.method() == 'POST':
            plugin = params['pluginname']
            configuration = json.loads(params['configuration'])
            try:
                Loader(self.context).saveConfiguration(plugin, configuration)
            except Exception as error:
                return WebResponseJson({'success': False, 'msg': str(error)})
            return WebResponseJson({'success': True})

        if path == 'storePlugins':
            if not os.path.exists('%s/plugins.yml' % Board.pluginPath()):
                return WebResponseJson([])
            return WebResponseJson(self.storePlugins())

        if path == 'upload' and request.method() == 'POST':
            self.uploadPlugin(params['pluginfile'])
            filename = '%s/staging.zip' % (Board.pluginPath())
            try:
                return WebResponseJson(
                    Loader(self.context).importPlugin(filename))
            except ImportError as error:
                os.unlink(filename)
                return WebResponseJson({'success': False, 'msg': str(error)})
Пример #9
0
    def handleRequest(self, plugin, path, __params, **__kwargs):
        if path == 'list':
            return WebResponseJson(self._getData())

        if path == "config":
            if __params:
                settings = Settings(CONFIG)
                for param in __params:
                    if param in ['cloud_server', 'cloud_auth_key']:
                        settings[param] = __params[param]
                self._read_settings()
            return WebResponseJson(self._getConfig())

        if path == 'devices':
            devices = list(
                map(
                    lambda d: {
                        'id': d.id,
                        'name': d.friendly_name(),
                        'unit_id': d.unit_id,
                        'type': d.type,
                        'ip_addr': d.ip_addr,
                        'is_device': d.is_device,
                        'is_sensor': d.is_sensor,
                        'sub_name': d.sub_name,
                        'state_values': d.state_values,
                        'state': d.state,
                        'device_type': d.device_type,
                        'device_sub_type': d.device_sub_type,
                        'device_nr': d.device_nr,
                        'master_unit': d.master_unit,
                        'ext_sensor': d.ext_sensor,
                        'info_values': d.info_values,
                        'friendly_name': d.friendly_name()
                    }, self.pyShelly.devices))
            return WebResponseJson(devices)

        if path == 'blocks':
            blocks = list(
                map(
                    lambda d: {
                        'id': d.id,
                        'unit_id': d.unit_id,
                        'type': d.type,
                        'ip_addr': d.ip_addr,
                        'info_values': d.info_values
                    }, self.pyShelly.blocks.values()))
            return WebResponseJson(blocks)

        if path == 'dump':
            shellyDevices = self.deviceManager.retrieveDevices()
            devices = list(
                map(
                    lambda d: {
                        'id': d.id(),
                        'localid': d.localId(),
                        'name': d.name(),
                        'state': d.state(),
                        'params': d.params(),
                        'stateValues': d.stateValues(),
                        'sensorValues': d.sensorValues(),
                        'isDevice': d.isDevice(),
                        'isSensor': d.isSensor(),
                        'methods': d.methods(),
                        'parameters': d.parameters(),
                        'metadata': d.metadata(),
                        'type': d.typeString()
                    }, shellyDevices))
            return WebResponseJson({'devices': devices})

        if path in [
                'turnon', 'turnoff', 'up', 'down', 'stop', 'firmware_update'
        ]:
            LOGGER.info('Request ' + path)
            id = __params['id']
            device = self.deviceManager.device(int(id))
            if path == 'turnon':
                if hasattr(device.dev, 'brightness'):
                    device.dev.turn_on(brightness=100)
                else:
                    device.dev.turn_on()
            elif path == 'turnoff':
                device.dev.turn_off()
            elif path == 'up':
                device.dev.up()
            elif path == 'down':
                device.dev.down()
            elif path == 'stop':
                device.dev.stop()
            elif path == 'firmware_update':
                if device.dev.block:
                    device.dev.block.update_firmware()
            return WebResponseJson({})

        if path == "rgb":
            id = __params['id']
            r = __params['r']
            g = __params['g']
            b = __params['b']
            device = self.deviceManager.device(int(id))
            device.dev.set_values(rgb=[r, g, b])
            self.refreshClient()
            return WebResponseJson({})

        if path == "rename":
            id = __params['id']
            name = __params['name']
            device = self.deviceManager.device(int(id))
            device.local_name = name
            device.update_name()
            self.refreshClient()
            return WebResponseJson({})

        if path == "clean":
            self.deviceManager.removeDevicesByType('Shelly')
            self._initPyShelly()
            self.refreshClient()
            return WebResponseJson({'msg': 'Clean done'})

        if path == "discover":
            self.pyShelly.discover()
            return WebResponseJson({})

        if path == "addMember":
            LOGGER.debug("Add membership")
            import socket
            import struct
            mreq = struct.pack("=4sl", socket.inet_aton("224.0.1.187"),
                               socket.INADDR_ANY)
            self.pyShelly._socket.setsockopt(socket.IPPROTO_IP,
                                             socket.IP_ADD_MEMBERSHIP, mreq)
            return WebResponseJson({})

        if path == "dropMember":
            LOGGER.debug("Drop membership")
            import socket
            import struct
            mreq = struct.pack("=4sl", socket.inet_aton("224.0.1.187"),
                               socket.INADDR_ANY)
            self.pyShelly._socket.setsockopt(socket.IPPROTO_IP,
                                             socket.IP_DROP_MEMBERSHIP, mreq)
            return WebResponseJson({})

        if path == "initSocket":
            self.pyShelly.init_socket()
            return WebResponseJson({'msg': 'init socket done'})
Пример #10
0
	def handleRequest(self, plugin, path, params, request, **kwargs):
		if path == 'import':
			if os.path.isfile('%s/staging.zip' % (Board.pluginPath())):
				try:
					return WebResponseJson(self.importPlugin())
				except ImportError as e:
					os.unlink('%s/staging.zip' % (Board.pluginPath()))
					return WebResponseJson({'success': False, 'msg':'Error importing plugin: %s' % e})
			return WebResponseJson({'success': False, 'msg':'Error importing plugin: No plugin uploaded'})

		if path == 'importkey':
			if 'discard' in params:
				os.unlink('%s/staging.zip' % (Board.pluginPath()))
				return WebResponseJson({'success': True})
			return WebResponseJson(self.importKey(params['key'] if 'key' in params else None))

		if path == 'remove':
			if 'pluginname' in params:
				Loader(self.context).removePlugin(params['pluginname'])
			elif 'key' in params and 'fingerprint' in params:
				Loader(self.context).removeKey(params['key'], params['fingerprint'])
			else:
				return WebResponseJson({'success': False, 'msg': 'No plugin or key specified'})
			return WebResponseJson({'success': True})

		if path == 'plugins':
			return WebResponseJson([plugin.infoObject() for plugin in Loader(self.context).plugins])

		if path == 'keys':
			return WebResponseJson([
				{
					'uids': key['uids'],
					'keyid': key['keyid'],
					'fingerprint': key['fingerprint']
				}
				for key in Loader(self.context).keys
			])

		if path == 'saveConfiguration' and request.method() == 'POST':
			plugin = params['pluginname']
			configuration = json.loads(params['configuration'])
			try:
				Loader(self.context).saveConfiguration(plugin, configuration)
			except Exception as e:
				return WebResponseJson({'success': False, 'msg': str(e)})
			return WebResponseJson({'success': True})

		if path == 'upload' and request.method() == 'POST':
			self.uploadPlugin(params['pluginfile'])
			try:
				return WebResponseJson(self.importPlugin())
			except ImportError as e:
				os.unlink('%s/staging.zip' % (Board.pluginPath()))
				return WebResponseJson({'success': False, 'msg': str(e)})

		return 'pluginloader.html', {'msg':'', 'loader': Loader(self.context)}
Пример #11
0
    def handleRequest(self, plugin, path, params, request, **kwargs):
        if path == '':
            methods = {}
            for o in self.observers:
                for module, actions in getattr(o, '_apicalls', {}).iteritems():
                    for action, fn in actions.iteritems():
                        methods.setdefault(module, {})[action] = {
                            'doc': fn.__doc__
                        }
            return 'index.html', {'methods': methods}
        if path == 'token':
            if request.method() == 'PUT':
                token = uuid.uuid4().hex
                self.tokens[token] = {
                    'app': request.post('app'),
                    'authorized': False,
                }
                return WebResponseJson({
                    'authUrl':
                    '%s/api/authorize?token=%s' % (request.base(), token),
                    'token':
                    token
                })
            elif request.method() == 'GET':
                token = params.get('token', None)
                if token is None:
                    return WebResponseJson({'error': 'No token specified'},
                                           statusCode=400)
                if token not in self.tokens:
                    return WebResponseJson({'error': 'No such token'},
                                           statusCode=404)
                if self.tokens[token]['authorized'] is not True:
                    return WebResponseJson(
                        {'error': 'Token is not authorized'}, statusCode=403)
                claims = {
                    'aud': self.tokens[token]['app'],
                    'exp': int(time.time() + self.tokens[token]['ttl']),
                }
                body = {}
                if self.tokens[token]['allowRenew'] == True:
                    body['renew'] = True
                    body['ttl'] = self.tokens[token]['ttl']
                accessToken = jwt.encode(body,
                                         self.__tokenKey(),
                                         algorithm='HS256',
                                         headers=claims)
                resp = WebResponseJson({
                    'token':
                    accessToken,
                    'expires':
                    claims['exp'],
                    'allowRenew':
                    self.tokens[token]['allowRenew'],
                })
                del self.tokens[token]
                return resp
        if path == 'authorize':
            if 'token' not in params:
                return WebResponseJson({'error': 'No token specified'},
                                       statusCode=400)
            token = params['token']
            if token not in self.tokens:
                return WebResponseJson({'error': 'No such token'},
                                       statusCode=404)
            if request.method() == 'POST':
                self.tokens[token]['authorized'] = True
                self.tokens[token]['allowRenew'] = bool(
                    request.post('extend', False))
                self.tokens[token]['ttl'] = int(request.post('ttl', 0)) * 60
            return 'authorize.html', {'token': self.tokens[token]}

        # Check authorization
        token = request.header('Authorization')
        if token is None:
            return WebResponseJson(
                {'error': 'No token was found in the request'}, statusCode=401)
        if not token.startswith('Bearer '):
            return WebResponseJson(
                {
                    'error':
                    'The autorization token must be supplied as a bearer token'
                },
                statusCode=401)
        token = token[7:]
        try:
            body = jwt.decode(token, self.__tokenKey(), algorithms='HS256')
        except JWSError as e:
            return WebResponseJson({'error': str(e)}, statusCode=401)
        claims = jwt.get_unverified_headers(token)
        if 'exp' not in claims or claims['exp'] < time.time():
            return WebResponseJson({'error': 'The token has expired'},
                                   statusCode=401)
        if 'aud' not in claims or claims['aud'] is None:
            return WebResponseJson(
                {'error': 'No app was configured in the token'},
                statusCode=401)
        aud = claims['aud']

        if path == 'refreshToken':
            if 'renew' not in body or body['renew'] != True:
                return WebResponseJson(
                    {'error': 'The token is not authorized for refresh'},
                    statusCode=403)
            if 'ttl' not in body:
                return WebResponseJson(
                    {'error': 'No TTL was specified in the token'},
                    statusCode=401)
            ttl = body['ttl']
            exp = int(time.time() + ttl)
            accessToken = jwt.encode({
                'renew': True,
                'ttl': ttl
            },
                                     self.__tokenKey(),
                                     algorithm='HS256',
                                     headers={
                                         'aud': aud,
                                         'exp': exp,
                                     })
            return WebResponseJson({
                'token': accessToken,
                'expires': exp,
            })
        paths = path.split('/')
        if len(paths) < 2:
            return None
        module = paths[0]
        action = paths[1]
        for o in self.observers:
            fn = getattr(o, '_apicalls', {}).get(module, {}).get(action, None)
            if fn is None:
                continue
            try:
                params['app'] = aud
                retval = fn(o, **params)
            except Exception as e:
                logging.exception(e)
                return WebResponseJson({'error': str(e)})
            if retval == True:
                retval = {'status': 'success'}
            return WebResponseJson(retval)
        return WebResponseJson(
            {'error': 'The method %s/%s does not exist' % (module, action)},
            statusCode=404)
Пример #12
0
	def handleRequest(self, plugin, path, params, request, **kwargs):
		if path == 'icon':
			for plugin in Loader(self.context).plugins:
				if plugin.name != params['name']:
					continue
				return WebResponseLocalFile('%s/%s' % (plugin.path, plugin.icon))
			return None

		if path == 'import':
			filename = '%s/staging.zip' % (Board.pluginPath())
			if os.path.isfile(filename):
				try:
					return WebResponseJson(Loader(self.context).importPlugin(filename))
				except ImportError as e:
					os.unlink('%s/staging.zip' % (Board.pluginPath()))
					return WebResponseJson({'success': False, 'msg':'Error importing plugin: %s' % e})
			return WebResponseJson({'success': False, 'msg':'Error importing plugin: No plugin uploaded'})

		if path == 'importkey':
			if 'discard' in params:
				os.unlink('%s/staging.zip' % (Board.pluginPath()))
				return WebResponseJson({'success': True})
			return WebResponseJson(Loader(self.context).importKey(params['key'] if 'key' in params else None))

		if path == 'installStorePlugin':
			if 'pluginname' not in params:
				return WebResponseJson({'success': False, 'msg': 'No plugin specified'})
			for plugin in yaml.load(open('%s/plugins.yml' % Board.pluginPath(), 'r').read()):
				if plugin['name'] == params['pluginname']:
					Loader(self.context).installRemotePlugin(plugin['name'], plugin['file']['url'], plugin['file']['size'], plugin['file']['sha1'])
					return WebResponseJson({'success': True})
			return WebResponseJson({'success': False, 'msg': 'Plugin was not found in the store'})

		if path == 'reboot':
			retval = os.system('/usr/sbin/telldus-helper reboot')
			if retval == 0:
				return WebResponseJson({'success': True})
			return WebResponseJson({'success': False})

		if path == 'refreshStorePlugins':
			Loader(self.context).updatePluginsList()
			return WebResponseJson({'success': True})

		if path == 'remove':
			if 'pluginname' in params:
				Loader(self.context).removePlugin(params['pluginname'])
			elif 'key' in params and 'fingerprint' in params:
				Loader(self.context).removeKey(params['key'], params['fingerprint'])
			else:
				return WebResponseJson({'success': False, 'msg': 'No plugin or key specified'})
			return WebResponseJson({'success': True})

		if path == 'plugins':
			return WebResponseJson([plugin.infoObject() for plugin in Loader(self.context).plugins])

		if path == 'keys':
			return WebResponseJson([
				{
					'uids': key['uids'],
					'keyid': key['keyid'],
					'fingerprint': key['fingerprint']
				}
				for key in Loader(self.context).keys
			])

		if path == 'saveConfiguration' and request.method() == 'POST':
			plugin = params['pluginname']
			configuration = json.loads(params['configuration'])
			try:
				Loader(self.context).saveConfiguration(plugin, configuration)
			except Exception as e:
				return WebResponseJson({'success': False, 'msg': str(e)})
			return WebResponseJson({'success': True})

		if path == 'storePlugins':
			if os.path.exists('%s/plugins.yml' % Board.pluginPath()) == False:
				return WebResponseJson([])
			return WebResponseJson([
				{
					'author': plugin['author'],
					'author-email': plugin['author-email'],
					'category': plugin.get('category', 'other'),
					'color': plugin.get('color', None),
					'name': plugin['name'],
					'icon': plugin['icon'] if 'icon' in plugin else '',
					'description': plugin['description'],
					'size': plugin['file']['size'],
					'version': plugin['version'],
				}
				for plugin in yaml.load(open('%s/plugins.yml' % Board.pluginPath(), 'r').read())
			])

		if path == 'upload' and request.method() == 'POST':
			self.uploadPlugin(params['pluginfile'])
			filename = '%s/staging.zip' % (Board.pluginPath())
			try:
				return WebResponseJson(Loader(self.context).importPlugin(filename))
			except ImportError as e:
				os.unlink(filename)
				return WebResponseJson({'success': False, 'msg': str(e)})