def save_session(self, app, session, response): if not session or not session.keys(): return if not session.session_id: session.session_id = generate_sid() session.permanent = True DEBUG and Log.note("save session {{session}}", session=session) now = Date.now().unix session_id = session.session_id result = self.db.query( sql_query({ "from": self.table, "where": { "eq": { "session_id": session_id } } })) saved_record = first(Data(zip(result.header, r)) for r in result.data) expires = min(session.expires, now + self.cookie.inactive_lifetime.seconds) if saved_record: DEBUG and Log.note("found session {{session}}", session=saved_record) saved_record.data = value2json(session) saved_record.expires = expires saved_record.last_used = now with self.db.transaction() as t: t.execute("UPDATE " + quote_column(self.table) + SQL_SET + sql_list( sql_eq(**{k: v}) for k, v in saved_record.items()) + SQL_WHERE + sql_eq(session_id=session_id)) else: new_record = { "session_id": session_id, "data": value2json(session), "expires": expires, "last_used": now, } DEBUG and Log.note("new record for db {{session}}", session=new_record) with self.db.transaction() as t: t.execute(sql_insert(self.table, new_record)) response.set_cookie(app.session_cookie_name, session_id, expires=expires)
def update_session(self, session_id, props): """ UPDATE GIVEN SESSION WITH PROPERTIES :param session_id: :param props: :return: """ now = Date.now().unix session = self.get_session(session_id) for k, v in props.items(): session[k] = v session.last_used = now record = { "session_id": session_id, "data": value2json(session), "expires": session.expires, "last_used": session.last_used, } with self.db.transaction() as t: t.execute(SQL_UPDATE + quote_column(self.table) + SQL_SET + sql_list(sql_eq(**{k: v}) for k, v in record.items()) + SQL_WHERE + sql_eq(session_id=session_id))
def _gen_ids(): while True: with db.transaction() as t: top_id = first( first( t.query( sql_query({ "select": "next_id", "from": VERSION_TABLE })).data)) max_id = top_id + 1000 t.execute(SQL_UPDATE + quote_column(VERSION_TABLE) + SQL_SET + sql_eq(next_id=max_id)) while top_id < max_id: yield top_id top_id += 1
def id_generator(db): """ INSTALL AN ID GENERATOR """ about = db.about(VERSION_TABLE) if not about: with db.transaction() as t: t.execute( sql_create(VERSION_TABLE, { "version": "TEXT", "next_id": "LONG" })) t.execute( sql_insert(VERSION_TABLE, { "version": "1.0", "next_id": 1000 })) else: for cid, name, dtype, notnull, dfft_value, pk in about: if name == "next_id": break else: with db.transaction() as t: t.execute("ALTER TABLE " + quote_column(VERSION_TABLE) + " ADD COLUMN next_id LONG") t.execute(SQL_UPDATE + quote_column(VERSION_TABLE) + SQL_SET + sql_eq(next_id=1000)) def _gen_ids(): while True: with db.transaction() as t: top_id = first( first( t.query( sql_query({ "select": "next_id", "from": VERSION_TABLE })).data)) max_id = top_id + 1000 t.execute(SQL_UPDATE + quote_column(VERSION_TABLE) + SQL_SET + sql_eq(next_id=max_id)) while top_id < max_id: yield top_id top_id += 1 return _gen_ids().__next__
def _gen_ids(self): while True: with self.db.transaction() as t: top_id = first( first( t.query( SQL_SELECT + quote_column("next_id") + SQL_FROM + quote_column(ABOUT_TABLE) ).data ) ) max_id = top_id + 1000 t.execute( SQL_UPDATE + quote_column(ABOUT_TABLE) + SQL_SET + sql_eq(next_id=max_id) ) while top_id < max_id: yield top_id top_id += 1
def device_callback(self, path=None): # HANDLE BROWESR RETURN FROM AUTH0 LOGIN error = request.args.get("error") if error: Log.error("You did it wrong") code = request.args.get("code") state = request.args.get("state") referer = request.headers.get("Referer") result = self.device.db.query( sql_query({ "from": "device", "select": "session_id", "where": { "eq": { "state": state } }, })) if not result.data: Log.error("expecting valid state") device_session_id = result.data[0][0] # GO BACK TO AUTH0 TO GET TOKENS token_request = { "client_id": self.device.auth0.client_id, "redirect_uri": self.device.auth0.redirect_uri, "code_verifier": session.code_verifier, "code": code, "grant_type": "authorization_code", } DEBUG and Log.note("Send token request to Auth0:\n {{request}}", request=token_request) auth_response = requests.request( "POST", str(URL("https://" + self.device.auth0.domain, path="oauth/token")), headers={ "Accept": "application/json", "Content-Type": "application/json", # "Referer": str(URL(self.device.auth0.redirect_uri, query={"code": code, "state": state})), }, data=value2json(token_request), ) try: auth_result = wrap(auth_response.json()) except Exception as e: Log.error("not json {{value}}", value=auth_response.content, cause=e) # VERIFY TOKENS, ADD USER TO DEVICE'S SESSION user_details = self.verify_opaque_token(auth_result.access_token) self.session_manager.update_session( device_session_id, {"user": self.permissions.get_or_create_user(user_details)}, ) # REMOVE DEVICE SETUP STATE with self.device.db.transaction() as t: t.execute(SQL_DELETE + SQL_FROM + quote_column(self.device.table) + SQL_WHERE + sql_eq(state=state)) Log.note("login complete") return Response("Login complete. You may close this page", status=200)