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))
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
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})
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
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
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
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
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)})
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'})
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)}
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)
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)})