def change_status(self): """Manually change the status of the BITS system""" with session_scope() as session: curstatus = query.get_current_status(session) if curstatus is None: textstatus = Status.CLOSED else: textstatus = Status.OPEN if curstatus.value == Status.CLOSED else Status.CLOSED LOG.info('Change of BITS to status={}'.format(textstatus) + ' from web interface.') message = '' try: status = query.log_status(session, textstatus, 'web') broadcast(status.jsondict()) notifier.send_status(textstatus) message = "Ora la sede è {}.".format(textstatus) except IntegrityError: LOG.error("Status changed too quickly, not logged.") message = "Errore: modifica troppo veloce!" raise finally: self.render('templates/admin.html', page_message=message)
def start(): """Setup HTTP/WS server. **MUST** be called prior to any operation.""" StatusRouter = SockJSRouter(handlers.StatusConnection, "/data") application = tornado.web.Application([ # FIXME daltonism workaround, should be implemented client-side (r'/(?:|blind)', handlers.HomePageHandler), (r'/log', handlers.LogPageHandler), (r'/status', handlers.StatusPageHandler), (r'/presence', handlers.PresenceForecastHandler), (r'/(info)', handlers.MarkdownPageHandler), (r'/login', handlers.LoginPageHandler), (r'/logout', handlers.LogoutPageHandler), (r'/admin', handlers.AdminPageHandler), (r'/message', handlers.MessagePageHandler), (r'/data.php', handlers.RTCHandler) ] + StatusRouter.urls, ui_modules=uimodules, gzip=True, debug=options.developer_mode, static_path=options.assets_path, xsrf_cookies=True, cookie_secret=options.cookie_secret ) server = tornado.httpserver.HTTPServer(application) #TODO other options LOG.info('Starting HTTP/WS server...') bind(server, options.web_port, options.web_usocket)
def start(): """Setup HTTP/WS server. **MUST** be called prior to any operation.""" StatusRouter = SockJSRouter(handlers.StatusConnection, "/data") application = tornado.web.Application( [ # FIXME daltonism workaround, should be implemented client-side (r'/(?:|blind)', handlers.HomePageHandler), (r'/log', handlers.LogPageHandler), (r'/status', handlers.StatusPageHandler), (r'/presence', handlers.PresenceForecastHandler), (r'/(info)', handlers.MarkdownPageHandler), (r'/login', handlers.LoginPageHandler), (r'/logout', handlers.LogoutPageHandler), (r'/admin', handlers.AdminPageHandler), (r'/message', handlers.MessagePageHandler), (r'/data.php', handlers.RTCHandler) ] + StatusRouter.urls, ui_modules=uimodules, gzip=True, debug=options.developer_mode, static_path=options.assets_path, xsrf_cookies=True, cookie_secret=options.cookie_secret) server = tornado.httpserver.HTTPServer(application) #TODO other options LOG.info('Starting HTTP/WS server...') bind(server, options.web_port, options.web_usocket)
def change_status(self): """Manually change the status of the BITS system""" with session_scope() as session: curstatus = query.get_current_status(session) if curstatus is None: textstatus = Status.CLOSED else: textstatus = Status.OPEN if curstatus.value == Status.CLOSED else Status.CLOSED LOG.info('Change of BITS to status=%r from web interface.', textstatus) message = '' try: status = query.log_status(session, textstatus, 'web') broadcast(status.jsondict()) notifier.send_status(textstatus) message = "Ora la sede è {}.".format(textstatus) except IntegrityError: LOG.error("Status changed too quickly, not logged.") message = "Errore: modifica troppo veloce!" raise finally: self.render( 'templates/admin.html', page_message=message, roster=MACUpdateHandler.ROSTER )
def start(): """Setup HTTP/WS server. **MUST** be called prior to any operation.""" auth.ReCaptcha.init() application = tornado.web.Application([ # FIXME daltonism workaround, should be implemented client-side (r'/(?:|blind)', handlers.HomePageHandler), (r'/log', handlers.LogPageHandler), (r'/status', handlers.StatusPageHandler), (r'/data', handlers.DataPageHandler), (r'/presence', handlers.PresenceForecastHandler), (r'/(info)', handlers.MarkdownPageHandler), (r'/ws', handlers.StatusHandler), (r'/login', handlers.LoginPageHandler), (r'/logout', handlers.LogoutPageHandler), (r'/admin', handlers.AdminPageHandler), (r'/message', handlers.MessagePageHandler), (r'/data.php', handlers.RTCHandler), (r'/macupdate', handlers.MACUpdateHandler), ], ui_modules=uimodules, gzip=True, debug=options.developer_mode, static_path=options.assets_path, xsrf_cookies=True, cookie_secret=options.cookie_secret ) server = tornado.httpserver.HTTPServer(application, xheaders=options.reverse_proxied) LOG.info('Starting HTTP/WS server...') bind(server, options.web_port, options.web_usocket)
def handle_enter_command(userid): """Handles signal triggered when a new user enters.""" LOG.info('Received enter command: id={}'.format(userid)) try: userid = int(userid) except ValueError: LOG.error('Wrong type for parameters in temperature command!') return LOG.error('handle_enter_command not implemented.')
def handle_leave_command(userid): """Handles signal triggered when a known user leaves.""" LOG.info('Received leave command: id={}'.format(userid)) try: userid = int(userid) except ValueError: LOG.error('Wrong type for parameters in temperature command!') return LOG.error('handle_leave_command not implemented.')
def handle_sound_command(soundid): """Handles requests to play a sound.""" LOG.info('Received sound command: id={}'.format(soundid)) try: soundid = int(soundid) except ValueError: LOG.error('Wrong type for parameters in temperature command!') return else: notifier.send_sound(soundid)
def handle_leave_command(userid): """Handles signal triggered when a known user leaves.""" LOG.info('Received leave command: id=%r', userid) try: userid = int(userid) except ValueError: LOG.error('Wrong type for parameters in temperature command!') return LOG.error('handle_leave_command not implemented.')
def handle_sound_command(soundid): """Handles requests to play a sound.""" LOG.info('Received sound command: id=%r', soundid) try: soundid = int(soundid) except ValueError: LOG.error('Wrong type for parameters in temperature command!') return else: notifier.send_sound(soundid)
def start(): """Connect and bind listeners. **MUST** be called at startup.""" __inject_broadcast() fonera = RemoteListener() LOG.info('Starting remote control...') LOG.info('My IP address is {}, remote IP address is {}'.format( options.control_local_address, options.control_remote_address)) bind(fonera, options.control_local_port, options.control_local_usocket, address=options.control_local_address)
def handle_temperature_command(sensorid, value): """Receives and log data received from remote sensor.""" LOG.info('Received temperature: sensorid=%r, value=%r', sensorid, value) try: sensorid = int(sensorid) value = float(value) except ValueError: LOG.error('Wrong type for parameters in temperature command!') return with session_scope() as session: temp = query.log_temperature(session, value, sensorid, 'BITS') broadcast(temp.jsondict())
def handle_temperature_command(sensorid, value): """Receives and log data received from remote sensor.""" LOG.info('Received temperature: sensorid={}, value={}'.format( sensorid, value)) try: sensorid = int(sensorid) value = float(value) except ValueError: LOG.error('Wrong type for parameters in temperature command!') return with session_scope() as session: temp = query.log_temperature(session, value, sensorid, 'BITS') broadcast(temp.jsondict())
def handle_stream(self, stream, address): """Handles inbound TCP connections asynchronously.""" LOG.info("New connection from Fonera.") if address[0] != options.control_remote_address: LOG.error( "Connection from `%s`, expected from `%s`. Ignoring.", address, options.control_remote_address ) return if RemoteListener.STREAM is not None: LOG.warning("Another connection was open, closing the previous one.") RemoteListener.STREAM.close() RemoteListener.STREAM = stream RemoteListener.STREAM.read_until(b'\n', self.handle_command)
def start(): """Connect and bind listeners. **MUST** be called at startup.""" __inject_broadcast() fonera = RemoteListener() LOG.info('Starting remote control...') LOG.info( 'My IP address is {}, remote IP address is {}'.format( options.control_local_address, options.control_remote_address ) ) bind( fonera, options.control_local_port, options.control_local_usocket, address=options.control_local_address )
def handle_message_command(message): """Handles message broadcast requests.""" LOG.info('Received message command: message=%r', message) try: decodedmex = base64.b64decode(message) except TypeError: LOG.error('Received message is not valid base64: %r', message) else: text = decodedmex.decode('utf8') #FIXME maybe get author ID from message? user = "******" with session_scope() as session: user = query.get_user(session, user) if not user: LOG.error("Non-existent user %r, not logging message.", user) return message = query.log_message(session, user, text) broadcast(message.jsondict()) notifier.send_message(text)
def post(self): username = self.get_argument("username", None) password = self.get_argument("password", None) next = self.get_argument("next", "/") with session_scope() as session: authenticated = verify(session, username, password) if authenticated: self.set_secure_cookie(self.USER_COOKIE_NAME, username, expires_days=options.cookie_max_age_days) LOG.info("Authenticating user `{}`".format(username)) self.redirect(next) else: LOG.warning("Wrong authentication for user `{}`".format(username)) self.render('templates/login.html', next=next, message="Password/username sbagliati!")
def post(self): username = self.get_argument("username") password = self.get_argument("password") ip_address = self.request.remote_ip next = self.get_argument("next", "/") captcha_challenge = self.get_argument("recaptcha_challenge_field", "") captcha_response = self.get_argument("recaptcha_response_field", "") has_recaptcha = captcha_challenge or captcha_response with session_scope() as session: try: verified = verify(session, username, password, ip_address, has_recaptcha, captcha_challenge, captcha_response) except DoSError as error: LOG.warning("DoS protection: %s", error) self.log_offender_details() self.render( 'templates/login.html', next=next, message="Tentativi dal tuo IP over 9000...", show_recaptcha=True, previous_attempt_incorrect=has_recaptcha ) return if verified: self.set_secure_cookie( self.USER_COOKIE_NAME, username, expires_days=options.cookie_max_age_days ) LOG.info("Authenticating user %r", username) self.redirect(next) else: LOG.warning("Failed authentication for user %r", username) self.log_offender_details() self.render( 'templates/login.html', next=next, message="Password/username sbagliati!", show_recaptcha=has_recaptcha, # If we have a captcha at this point, it means we already failed once previous_attempt_incorrect=True )
def handle_message_command(message): """Handles message broadcast requests.""" LOG.info('Received message command: message={!r}'.format(message)) try: decodedmex = base64.b64decode(message) except TypeError: LOG.error('Received message is not valid base64: {!r}'.format(message)) else: text = decodedmex.decode('utf8') #FIXME maybe get author ID from message? user = "******" with session_scope() as session: user = query.get_user(session, user) if not user: LOG.error( "Non-existent user {}, not logging message.".format(user)) return message = query.log_message(session, user, text) broadcast(message.jsondict()) notifier.send_message(text)
def post(self): now = datetime.now() remote_ip = self.request.remote_ip with session_scope() as session: last = query.get_last_login_attempt(session, remote_ip) if last is None: last = LoginAttempt(None, remote_ip) persist(session, last) else: if (now - last.timestamp) < timedelta(seconds=options.mac_update_interval): LOG.warning("Too frequent attempts to update, remote IP address is %s", remote_ip) raise HTTPError(403, "Too frequent") else: last.timestamp = now persist(session, last) try: password = self.get_argument("password") macs = self.get_argument("macs") except MissingArgumentError: LOG.warning("MAC update received malformed parameters: %s", self.request.arguments) raise HTTPError(400, "Bad parameters list") if not secure_compare(password, options.mac_update_password): LOG.warning("Client provided wrong password for MAC update!") raise HTTPError(403, "Wrong password") LOG.info("Authorized request to update list of checked-in users from IP address %s", remote_ip) macs = json.loads(macs) with session_scope() as session: names = session.\ query(distinct(User.name)).\ filter(User.userid == MACToUser.userid).\ filter(MACToUser.mac_hash .in_ (macs)).\ all() MACUpdateHandler.ROSTER = [n[0] for n in names] LOG.debug("Updated list of checked in users: %s", MACUpdateHandler.ROSTER)
def post(self): username = self.get_argument("username", None) password = self.get_argument("password", None) next = self.get_argument("next", "/") with session_scope() as session: authenticated = verify(session, username, password) if authenticated: self.set_secure_cookie( self.USER_COOKIE_NAME, username, expires_days=options.cookie_max_age_days ) LOG.info("Authenticating user `{}`".format(username)) self.redirect(next) else: LOG.warning("Wrong authentication for user `{}`".format(username)) self.render( 'templates/login.html', next=next, message="Password/username sbagliati!" )
def handle_status_command(status): """Update status. Will reject two identical and consecutive updates (prevents opening when already open and vice-versa).""" LOG.info('Received status: %r', status) try: status = int(status) except ValueError: LOG.error('Wrong type for parameters in temperature command') return if status not in (0, 1): LOG.error('Non existent status %r, ignoring.', status) return textstatus = Status.OPEN if status == 1 else Status.CLOSED with session_scope() as session: curstatus = query.get_current_status(session) if curstatus is None or curstatus.value != textstatus: status = query.log_status(session, textstatus, 'BITS') broadcast(status.jsondict()) notifier.send_status(textstatus) else: LOG.error('BITS already open/closed! Ignoring.')
def handle_status_command(status): """Update status. Will reject two identical and consecutive updates (prevents opening when already open and vice-versa).""" LOG.info('Received status: {}'.format(status)) try: status = int(status) except ValueError: LOG.error('Wrong type for parameters in temperature command') return if status not in (0, 1): LOG.error('Non existent status {}, ignoring.'.format(status)) return textstatus = Status.OPEN if status == 1 else Status.CLOSED with session_scope() as session: curstatus = query.get_current_status(session) if curstatus is None or curstatus.value != textstatus: status = query.log_status(session, textstatus, 'BITS') broadcast(status.jsondict()) notifier.send_status(textstatus) else: LOG.error('BITS already open/closed! Ignoring.')
def start(): """Will setup connection and ensure that all tables exist. MUST be called prior to any operation.""" LOG.info('Connecting to DB...') engine.connect() # Create tables if they don't exist. LOG.info('Checking tables in the DB...') models.check() LOG.info('Done')
def post(self): text = self.get_argument('msgtext') username = self.get_current_user() text = xhtml_escape(text) LOG.info("{} sent message {!r} from web".format(username, text)) with session_scope() as session: user = query.get_user(session, username) message = query.log_message(session, user, text) LOG.info("Broadcasting to clients") broadcast(message.jsondict()) LOG.info("Notifying Fonera") notifier.send_message(text) self.render('templates/message.html', message='Messaggio inviato correttamente!', text=text)
def post(self): text = self.get_argument('msgtext') username = self.get_current_user() LOG.info("%r sent message %r from web", username, text) with session_scope() as session: user = query.get_user(session, username) message = query.log_message(session, user, text) LOG.info("Broadcasting to clients") broadcast(message.jsondict()) LOG.info("Notifying Fonera") notifier.send_message(text) self.render( 'templates/message.html', message='Messaggio inviato correttamente!', text=text )
def shutdown(): """Stop server and add callback to stop i/o loop.""" io_loop = tornado.ioloop.IOLoop.instance() LOG.info('Shutting down in 2 seconds') io_loop.add_timeout(time.time() + 2, io_loop.stop)