Пример #1
0
    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)
Пример #2
0
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)
Пример #3
0
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)
Пример #4
0
    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
                )
Пример #5
0
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)
Пример #6
0
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.')
Пример #7
0
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.')
Пример #8
0
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)
Пример #9
0
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.')
Пример #10
0
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)
Пример #11
0
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)
Пример #12
0
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())
Пример #13
0
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())
Пример #14
0
 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)
Пример #15
0
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
    )
Пример #16
0
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)
Пример #17
0
    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!")
Пример #18
0
    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
            )
Пример #19
0
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)
Пример #20
0
    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)
Пример #21
0
    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!"
            )
Пример #22
0
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.')
Пример #23
0
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.')
Пример #24
0
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')
Пример #25
0
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')
Пример #26
0
    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)
Пример #27
0
    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
        )
Пример #28
0
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)
Пример #29
0
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)