async def login( form_data: OAuth2PasswordRequestForm = Depends(), user_agent=Header(None), x_moca_client=Header(None), db: Session = Depends(get_db), ): """Login to the MOCA Server. This will return an access token which can be used to authenticate all following requests.""" user: models.User = authenticate_user(form_data.username, form_data.password, db) if not user: raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Incorrect username or password", headers={"WWW-Authenticate": "Bearer"}, ) # Create a new session new_session = models.Session( user_id=user.user_id, name=x_moca_client if x_moca_client else user_agent, valid_until=datetime.now() + timedelta(days=30), ) db.add(new_session) # add is ok here db.commit() access_token_expires = timedelta(days=ACCESS_TOKEN_EXPIRE_DAYS) access_token = create_access_token( data={ "sub": str(user.user_id), "username": user.username, "jti": str(new_session.session_id), }, expires_delta=access_token_expires, ) return {"access_token": access_token, "token_type": "bearer"}
async def get_optional_current_user_token( authorization: Optional[str] = Header(None), ): """ Get and return authenticated user's access token if one is passed """ if not authorization: return if "Bearer" not in authorization: raise HTTPException(401, "Not authenticated") return authorization.split("Bearer")[-1].strip()
def replace_page( uid: str, page: UpdatePage, current_user: User = Security(get_current_user), if_match: Optional[str] = Header(None), ): try: update_response = services.pages.update(current_user, page, uid, etag=if_match) except ObjectNotFoundError: raise HTTPException( status_code=404, detail="object not found", ) return update_response
async def authenticate( req: Request, authorization: str = Header(None), db: Session = Depends(get_db) ) -> Request: if not authorization: raise HTTPException(status_code=400, detail="Missing claims in the request") key = settings.JWT_SECRET token = authorization.split('Bearer')[1].strip() claims = jwt.decode(token, key, algorithms=["HS256"]) username = claims['username'] user = await crud.user.get_by_username(db, username=username) if not user: raise HTTPException( status_code=404, detail="Claims are associated with an unknown user") req.state.is_admin = user.is_admin return req
def replace_user(uid: str, user: NewUser, current_user: User = Security(get_current_user), if_match: Optional[str] = Header(None)): return services.users.update(current_user, user, uid, etag=if_match)
async def token_validation(token: str = Header(None)): x = await validate_token(token) if not x: raise InvalidTokenResponseBody() return x
def is_portal(x_api_key: str = Header(None)) -> bool: # if x_api_key == settings.PORTAL_KEY: # return True # raise HTTPException(status_code=403, detail="Not Authorized") return True
def processes_filterable( response: Response, range: Optional[str] = None, sort: Optional[str] = None, filter: Optional[str] = None, if_none_match: Optional[str] = Header(None), ) -> List[Dict[str, Any]]: _range: Union[List[int], None] = list(map(int, range.split(","))) if range else None _sort: Union[List[str], None] = sort.split(",") if sort else None _filter: Union[List[str], None] = filter.split(",") if filter else None logger.info("processes_filterable() called", range=_range, sort=_sort, filter=_filter) # the joinedload on ProcessSubscriptionTable.subscription via ProcessBaseSchema.process_subscriptions prevents a query for every subscription later. # tracebacks are not presented in the list of processes and can be really large. query = ProcessTable.query.options( joinedload(ProcessTable.process_subscriptions).joinedload( ProcessSubscriptionTable.subscription).joinedload( SubscriptionTable.product), defer("traceback"), ) if _filter is not None: if len(_filter) == 0 or (len(_filter) % 2) > 0: raise_status(HTTPStatus.BAD_REQUEST, "Invalid number of filter arguments") for filter_pair in chunked(_filter, 2): field, value = filter_pair field = field.lower() if value is not None: if field == "istask": value_as_bool = value.lower() in ("yes", "y", "ye", "true", "1", "ja") query = query.filter( ProcessTable.is_task.is_(value_as_bool)) elif field == "assignee": assignees = value.split("-") query = query.filter(ProcessTable.assignee.in_(assignees)) elif field == "status": statuses = value.split("-") query = query.filter( ProcessTable.last_status.in_(statuses)) elif field == "workflow": query = query.filter( ProcessTable.workflow.ilike("%" + value + "%")) elif field == "creator": query = query.filter( ProcessTable.created_by.ilike("%" + value + "%")) elif field == "organisation": try: value_as_uuid = UUID(value) except (ValueError, AttributeError): msg = "Not a valid customer_id, must be a UUID: '{value}'" logger.exception(msg) raise_status(HTTPStatus.BAD_REQUEST, msg) process_subscriptions = ( db.session.query(ProcessSubscriptionTable).join( SubscriptionTable).filter( SubscriptionTable.customer_id == value_as_uuid).subquery()) query = query.filter( ProcessTable.pid == process_subscriptions.c.pid) elif field == "product": process_subscriptions = ( db.session.query(ProcessSubscriptionTable).join( SubscriptionTable, ProductTable).filter( ProductTable.name.ilike("%" + value + "%")).subquery()) query = query.filter( ProcessTable.pid == process_subscriptions.c.pid) elif field == "tag": tags = value.split("-") process_subscriptions = ( db.session.query(ProcessSubscriptionTable).join( SubscriptionTable, ProductTable).filter( ProductTable.tag.in_(tags)).subquery()) query = query.filter( ProcessTable.pid == process_subscriptions.c.pid) elif field == "subscriptions": process_subscriptions = (db.session.query( ProcessSubscriptionTable ).join(SubscriptionTable).filter( SubscriptionTable.description.ilike("%" + value + "%")).subquery()) query = query.filter( ProcessTable.pid == process_subscriptions.c.pid) elif field == "pid": query = query.filter( cast(ProcessTable.pid, String).ilike("%" + value + "%")) elif field == "target": targets = value.split("-") process_subscriptions = ( db.session.query(ProcessSubscriptionTable).filter( ProcessSubscriptionTable.workflow_target.in_( targets)).subquery()) query = query.filter( ProcessTable.pid == process_subscriptions.c.pid) else: raise_status(HTTPStatus.BAD_REQUEST, f"Invalid filter '{field}'") if _sort is not None and len(_sort) >= 2: for item in chunked(_sort, 2): if item and len(item) == 2 and item[0] in VALID_SORT_KEYS: sort_key = VALID_SORT_KEYS[item[0]] if item[1].upper() == "DESC": query = query.order_by( expression.desc(ProcessTable.__dict__[sort_key])) else: query = query.order_by( expression.asc(ProcessTable.__dict__[sort_key])) else: raise_status(HTTPStatus.BAD_REQUEST, "Invalid Sort parameters") if _range is not None and len(_range) == 2: try: range_start = int(_range[0]) range_end = int(_range[1]) if range_start >= range_end: raise ValueError("range start must be lower than end") except (ValueError, AssertionError): msg = "Invalid range parameters" logger.exception(msg) raise_status(HTTPStatus.BAD_REQUEST, msg) total = query.count() query = query.slice(range_start, range_end) response.headers[ "Content-Range"] = f"processes {range_start}-{range_end}/{total}" results = query.all() # Calculate a CRC32 checksum of all the process id's and last_modified_at dates in order as entity tag checksum = 0 for p in results: checksum = zlib.crc32(p.pid.bytes, checksum) last_modified_as_bytes = struct.pack("d", p.last_modified_at.timestamp()) checksum = zlib.crc32(last_modified_as_bytes, checksum) entity_tag = hex(checksum) response.headers["ETag"] = f'W/"{entity_tag}"' # When the If-None-Match header contains the same CRC we can be sure that the resource has not changed # so we can skip serialization at the backend and rerendering at the frontend. if if_none_match == entity_tag: raise CacheHit(HTTPStatus.NOT_MODIFIED, headers=dict(response.headers)) return [asdict(enrich_process(p)) for p in results]
def x_correlation_id(x_correlation_id: str = Header(None)): pass
async def verify_key(x_key:str=Header(...)): if x_key!="fake-super-secret-key": raise HTTPException(status_code=400,detail="X-Key header invaild") return x_key
async def verify_token(x_token:str=Header(...)): if x_token!="fake-super-secret-token": raise HTTPException(status_code=400,detail="X-Token header invalid")