async def get_current_user(token: str = Security(reuseable_oauth2)): try: payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM]) token_data = TokenPayload(**payload) except PyJWTError: raise HTTPException(status_code=HTTP_403_FORBIDDEN, detail="Could not validate credentials") db = get_database() # ? CAN'T USE -> user = crud.user.get(db, username=token_data.username) logging.info("USERNAME : "******"SCOPE: " + token_data.scope) logging.info("CONTEXT: " + token_data.context) scope = token_data.scope if scope == USERTYPE_PERSONA: collection = get_collection(db, DOCTYPE_PERSONA) user = await collection.find_one({ "username": token_data.username, "prj_id": ObjectId(token_data.context) }) elif (scope == USERTYPE_CLIENT or scope == USERTYPE_EXPERT): collection = get_collection(db, DOCTYPE_PROJECT) user = await get_project_member(db, token_data.context, token_data.username) else: collection = get_collection(db, DOCTYPE_USER) user = await collection.find_one({"username": token_data.username}) user["context"] = token_data.context if not (scope == USERTYPE_GAIA or scope == USERTYPE_LICENSE): user['admin_roles'] = [] logging.info(token_data.context) if not user: raise HTTPException(status_code=404, detail="User not found") return user
async def prepare_persona_batteries(db: DBClient, id: str, batch_id: str): """Update batch participants' progress and batteries""" logging.info(f">>> {__name__}:{prepare_persona_batteries.__name__}") collection = utils.get_collection(db, config.DOCTYPE_PROJECT) rs = await collection.find_one( { "_id": ObjectId(id), "batches.batch_id": batch_id }, { "_id": 0, "workbooks": 1, "facetimes": 1, "batches": { "$elemMatch": { "batch_id": batch_id } } }) batch = rs['batches'][0] usernames = batch['participants'] sessions = batch['workbook_sessions'] + batch['facetime_sessions'] batteries = [] for a in sessions: batteries.append({ 'type': a['module'], 'items': a['module_items'], 'touched': None }) progress = { 'state': "idle", 'battery': None, 'touched': None, 'next': batteries[0]['type'] } collection = utils.get_collection(db, config.DOCTYPE_PERSONA) rs = await collection.update_many( { "prj_id": ObjectId(id), "username": { "$in": usernames } }, {"$set": { "batteries": batteries, "progress": progress }}) return {"updated_personas": rs.modified_count}
async def reset_password(token: str = Body(...), new_password: str = Body(...)): """ Reset password [NOT IMPLEMENTED YET] """ logging.info(">>> " + __name__ + ":" + reset_password.__name__ ) username = verify_password_reset_token(token) if not username: raise HTTPException(status_code=400, detail="Invalid token") db = get_database() user = await crud.get(db, username) if not user: raise HTTPException( status_code=404, detail="The user with this username does not exist in the system.", ) # NOT IMPLEMENTED YET # elif not crud.user.is_active(user): # raise HTTPException(status_code=400, detail="Inactive user") # user_in = UserUpdate(name=username, password=new_password) # user = crud.user.update(bucket, username=username, user_in=user_in) logging.info("FULL NAME: " + user['full_name']) hashed_password = get_password_hash(password=new_password) collection = get_collection(db, DOCTYPE_USER) rs = await collection.update_one( {"username": username}, {'$set': { 'hashed_password': hashed_password, 'modified': datetime.utcnow() } } ) return {"msg": "Password updated successfully"}
async def add_facetime_session(db: DBClient, id: str, batch_id: str, data: FacetimeSession): logging.info(f">>> {__name__}:{add_facetime_session.__name__}") collection = utils.get_collection(db, config.DOCTYPE_PROJECT) # dic = data.dict() """ $ matched index """ rs = await collection.find_one_and_update( { "_id": ObjectId(id), "batches.batch_id": batch_id }, {"$push": { "batches.$.facetime_sessions": data.dict() }}, { "_id": 0, "batches": { "$elemMatch": { "batch_id": batch_id } } }, return_document=ReturnDocument.AFTER) print(rs) count = len(rs['batches'][0]['facetime_sessions']) return rs['batches'][0]['facetime_sessions'][count - 1]
async def add_member(db: DBClient, ref: str, mtype: str, data: GuestCreate): logging.info(f">>> {__name__}:{add_member.__name__}") collection = utils.get_collection(db, config.DOCTYPE_PROJECT) dic = { "_id": str(ObjectId()), **data.dict(), "type": mtype, "hashed_password": get_password_hash(data.password) } del dic["password"] rs = await collection.find_one_and_update( {"_id": ObjectId(ref)}, {"$push": { "members": dic }}, { "_id": 0, "members": { "$elemMatch": { "username": data.username } } }, return_document=ReturnDocument.AFTER) if rs['members']: return rs['members'][0] return None
async def create_db_template(db: DBClient, prj_id: str, username: str, fullname: str, rows: int = GPQ_TOTAL_ITEMS): """ We just persist data. Make sure you provide correct `prj_id`, `username`, and `fullname`. """ logging.info(f">>> {__name__}:{create_db_template.__name__}") # if not ObjectId.is_valid(prj_id): # return None prj_id = ObjectId(prj_id) records: List[GPQRow] = [] seqs = [i for i in range(1, rows + 1)] shuffle(seqs) for i in range(rows): records.append(GPQRow(seq=i + 1, wb_seq=seqs[i])) collection = crudutils.get_collection(db, DOCTYPE_EV_GPQ) template = { 'prj_id': prj_id, 'username': username, 'fullname': fullname, 'records': records } data = GPQEvidenceInDB(**template) return await crudutils.create(collection, data)
async def get_by_project(db: DBClient, id: str, limit: int, skip: int): logging.info(f">>> {__name__}:{get_by_project.__name__}") collection = crudutils.get_collection(db, DOCTYPE_EV_GPQ) rs: List[BaseModel] = [] cursor = collection.find({"prj_id": ObjectId(id)}, limit=limit, skip=skip) async for row in cursor: rs.append(row) return rs
async def authenticate(db: DBClient, username: str, password: str): collection = utils.get_collection(db, config.USER_DOCTYPE) user = await collection.find_one({"username": username}) if not user: return None if not verify_password(password, user['hashed_password']): return None return user
async def create_multi(db: DBClient, data: List[Any]): logging.info(f">>> {__name__}:{create_multi.__name__}") collection = utils.get_collection(db, DOCTYPE_PERSONA) # result = db.test.insert_many([{'x': i} for i in range(2)]) # rs = await collection.insert_many([ {p.dict()} for p in data ]) print(data) rs = await collection.insert_many(data) return rs.inserted_ids
async def get_multi_by_filter(db: DBClient, filter: dict, limit: int = 50, skip: int = 0): logging.info(">>> " + __name__ + ":" + get_multi_by_filter.__name__) collection = utils.get_collection(db, config.DOCTYPE_PROJECT) # filter = {} return await utils.get_multi_by_filter(collection, filter, limit, skip)
async def get(db: DBClient, ref: str): logging.info(">>> " + __name__ + ":" + get.__name__) collection = utils.get_collection(db, config.DOCTYPE_USER) if ObjectId.is_valid(ref): logging.info("objectid") return await utils.get(collection, ref) elif ("@" in ref) and ("." in ref): return await utils.get(collection, ref, "email") return await utils.get(collection, ref, "username")
async def check_free_email_username(db: DBClient, data: UserLogin): logging.info(">>> " + __name__ + ":" + check_free_email_username.__name__ ) collection = utils.get_collection(db, config.USER_DOCTYPE) user = await collection.find_one({"username": data.username}) if user: return "Username already registered" user = await collection.find_one({"email": data.email}) if user: return "Email already registered"
async def get_project_manager(db: DBClient, id: str): logging.info(f">>> {__name__}:{get_project_manager.__name__}") collection = utils.get_collection(db, config.DOCTYPE_PROJECT) rs = await collection.find_one({'_id': ObjectId(id)}, { '_id': 0, 'lead_by': 1 }) print(rs) return rs['lead_by']
async def check_free_email_username(db: DBClient, username: str, email: str): logging.info(">>> " + __name__ + ":" + check_free_email_username.__name__) collection = utils.get_collection(db, config.DOCTYPE_USER) user = await collection.find_one({"username": username}) if user: return "Username already registered" user = await collection.find_one({"email": email}) if user: return "Email already registered"
async def update_progress(db: DBClient, prj_id: str, username: str, progress: Progress): collection = utils.get_collection(db, DOCTYPE_PERSONA) rs = await collection.find_one_and_update( {"prj_id": ObjectId(prj_id), "username": username}, {"$set": {"progress": progress}}, {"_id": 0, "progress": 1}, return_document=ReturnDocument.AFTER ) return rs
async def authenticate(db: DBClient, username: str, password: str, prj_id: str): collection = utils.get_collection(db, DOCTYPE_PERSONA) user = await collection.find_one( {"username": username, "prj_id": ObjectId(prj_id)} ) if not user: return None if not verify_password(password, user['hashed_password']): return None return user
async def get_batches(db: DBClient, id: str): logging.info(f">>> {__name__}:{get_members.__name__}") collection = utils.get_collection(db, config.DOCTYPE_PROJECT) rs = await collection.find_one({"_id": ObjectId(id)}, { "_id": 0, "batches": 1 }) batches = rs['batches'] print(batches) return batches
async def authenticate_persona(db: DBClient, username: str, password: str, prj_id: str): logging.info(f">>> {__name__}:{authenticate_persona.__name__}") collection = utils.get_collection(db, DOCTYPE_PERSONA) user = await collection.find_one( {"username": username, "prj_id": ObjectId(prj_id)} ) if not user: return None if not verify_password(password, user['hashed_password']): return None return user
async def authenticate(db: DBClient, username: str, password: str): logging.info(f">>> {__name__}:{authenticate.__name__}") collection = utils.get_collection(db, config.DOCTYPE_USER) user = await collection.find_one({ "username": username, "type": "gaia", }) if not user: return None if not verify_password(password, user['hashed_password']): return None return user
async def init(db: DBClient, id: str): logging.info(f">>> {__name__}:{init.__name__}") # If it is in stacks, just return it if (id in gpq_touch_stacks and "initiated" in gpq_touch_stacks[id] and gpq_touch_stacks[id]["initiated"]): return {"initiated": gpq_touch_stacks[id]["initiated"]} # It is not in stacks, check db else: gpq_touch_stacks[id] = { "initiated": None, "started": None, "touched": None } # Check state from db collection = crudutils.get_collection(db, DOCTYPE_EV_GPQ) ev = await collection.find_one({"_id": ObjectId(id)}, { "_id": 0, "initiated": 1, "started": 1 }) logging.info(str(ev)) ts = round(time() * 1000) if not ev["initiated"] or ev["initiated"] is None: gpq_touch_stacks[id]["initiated"] = ts gpq_touch_stacks[id]["started"] = None gpq_touch_stacks[id]["touched"] = ts rs = await collection.find_one_and_update( {"_id": ObjectId(id)}, {"$set": { "initiated": ts, "touched": ts }}, { "_id": 0, "initiated": 1 }, return_document=ReturnDocument.AFTER) return rs else: gpq_touch_stacks[id]["initiated"] = ev["initiated"] if ev["started"]: gpq_touch_stacks[id]["started"] = ev["started"] gpq_touch_stacks[id]["touched"] = ts rs = await collection.find_one_and_update( {"_id": ObjectId(id)}, {"$set": { "touched": ts }}, { "_id": 0, "initiated": 1 }) return rs
async def add_note(db: DBClient, prj_id: str, note: str): logging.info(f">>> {__name__}:{add_note.__name__}") collection = utils.get_collection(db, config.DOCTYPE_PROJECT) rs = await collection.find_one_and_update( {"_id": ObjectId(prj_id)}, {"$push": { "notes": note }}, { "_id": 0, "notes": [note] }, return_document=ReturnDocument.AFTER) print(rs['notes'][0]) return rs['notes'][0]
async def get_members(db: DBClient, id: str, type: str): logging.info(f">>> {__name__}:{get_members.__name__}") collection = utils.get_collection(db, config.DOCTYPE_PROJECT) rs = await collection.find_one({"_id": ObjectId(id)}, { "_id": 0, "members": 1 }) members = rs['members'] guests = [] for guest in members: if guest['type'] == type: guests.append(Guest(**guest)) return guests
async def is_project_manager(db: DBClient, user: UserInApp, id: str): logging.info(f">>> {__name__}:{is_project_manager.__name__}") collection = utils.get_collection(db, config.DOCTYPE_PROJECT) rs = await collection.find_one( { '_id': ObjectId(id), 'lead_by': user['username'] }, { '_id': 0, 'lead_by': 1 }) if rs is None: return False return user['username'] == rs['lead_by']
async def init2(db: DBClient, id: str): logging.info(f">>> {__name__}:{init.__name__}") collection = crudutils.get_collection(db, DOCTYPE_EV_GPQ) ts = round(time() * 1000) rs = await collection.find_one_and_update( {"_id": ObjectId(id)}, {"$set": { "started": ts, "touched": ts }}, { "_id": 0, u"started": 1 }, return_document=ReturnDocument.AFTER) return rs
async def authenticate_licensee(db: DBClient, username: str, password: str, scope: str, context: str): logging.info(f">>> {__name__}:{authenticate_licensee.__name__}") collection = utils.get_collection(db, config.DOCTYPE_USER) user = await collection.find_one({ "_id": ObjectId(context), "type": scope, "username": username }) if not user: return None if not verify_password(password, user['hashed_password']): return None return user
async def create_many(db: DBClient, users: List[UserCreate]): logging.info(">>> " + __name__ + ":" + create_many.__name__) collection = utils.get_collection(db, config.DOCTYPE_USER) data = [] for x in users: dic = x.dict() dic["hashed_password"] = get_password_hash(x.password) print(dic) data.append(dic) rs = await collection.insert_many(data) ids = [] for i in rs.inserted_ids: ids.append(str(i)) return ids
async def create_db_template2( db: DBClient, prj_id: str, # username: str, # fullname: str, persona_id: str, rows: int = GPQ_TOTAL_ITEMS): logging.info(f">>> {__name__}:{create_db_template.__name__}") # if not ObjectId.is_valid(prj_id): # return None collection = crudutils.get_collection(db, DOCTYPE_PERSONA) persona = await collection.find_one({"_id": ObjectId(persona_id)}) print(persona) print("----------------------") # return {"response": "test"} _id = "GPQ" + persona_id prj_id = ObjectId(prj_id) records: List[GPQRow] = [] seqs = [i for i in range(1, rows + 1)] shuffle(seqs) for i in range(rows): records.append(GPQRow(seq=i + 1, wb_seq=seqs[i])) collection = crudutils.get_collection(db, DOCTYPE_EV_GPQ) template = { '_id': _id, 'prj_id': prj_id, 'username': persona['username'], 'fullname': persona['fullname'], 'records': records } print(template) data = GPQEvidenceInDB(**template) return await crudutils.create(collection, data)
async def update( db: DBClient, id: str, seq: int, wb_seq: int, element: str, statement: str, # last_touch: int ): logging.info(f">>> {__name__}:{update_row.__name__}") collection = crudutils.get_collection(db, DOCTYPE_EV_GPQ) if not id in gpq_touch_stacks: # If app has been restarted and id isn't in stack ev = await collection.find_one({"_id": ObjectId(id)}, { "_id": 1, "touched": 1 }) gpq_touch_stacks[id] = ev["touched"] last_touch = gpq_touch_stacks[id] ts = round(time() * 1000) elapsed = ts - last_touch gpq_touch_stacks[id] = ts dic = {} dic['seq'] = seq dic['wb_seq'] = wb_seq dic['element'] = element dic['statement'] = statement dic["saved"] = ts dic["elapsed"] = elapsed index = seq - 1 docpath = "records." + str(index) rs = await collection.find_one_and_update( {"_id": ObjectId(id)}, {"$set": { "touched": ts, docpath: dic }}, { "_id": 0, u"touched": 1 }, return_document=ReturnDocument.AFTER) if rs: return rs # ['records'][index] return None
async def add_modules(db: DBClient, ref: str, data: List[Workbook]): """Add one or more modules""" logging.info(f">>> {__name__}:{add_modules.__name__}") collection = utils.get_collection(db, config.DOCTYPE_PROJECT) modified_count = 0 # Manually one by one # TODO: for x in data: rs = await collection.update_one({"_id": ObjectId(ref)}, {"$push": { "modules": x.dict() }}) modified_count += rs.modified_count logging.info("Modified: " + str(modified_count)) if rs.modified_count > 0: return data
async def batch_batteries(db: DBClient, id: str, batch_id: str): collection = utils.get_collection(db, config.DOCTYPE_PROJECT) rs = await collection.find_one({"_id": ObjectId(id)}, { "_id": 0, "batches": { "$elemMatch": { "batch_id": batch_id } } }) batch = rs['batches'][0] sessions = batch['workbook_sessions'] + batch['facetime_sessions'] batteries: List[Battery] = [] for a in sessions: batteries.append( Battery(type=a['module'], items=a['module_items'], touched=0)) return batteries