def form_create(): """Creates a new form with a blank schema and uiSchema. """ from ..main import app request_body = app.current_request.json_body or {} if request_body.get("formId", None): # todo: add permissions check -- some forms should not be able to be duplicated. formId = request_body.get("formId", None) old_form = Form.objects.get({"_id": ObjectId(formId)}) form = Form( name=old_form.name + " Copy - " + datetime.datetime.now().isoformat(), version=1, center="None", id=ObjectId(), cff_permissions={app.get_current_user_id(): { "owner": True }}, schema=old_form.schema, uiSchema=old_form.uiSchema, formOptions=old_form.formOptions, date_modified=datetime.datetime.now().isoformat(), date_created=datetime.datetime.now().isoformat()) form.save() return {'res': {'form': serialize_model(form)}} else: form_name = request_body.get( "form_name", "Untitled form {}".format(datetime.datetime.now().isoformat())) form = Form( name=form_name, version=1, center="None", id=ObjectId(), cff_permissions={app.get_current_user_id(): { "owner": True }}, schema={ "title": "Form", "type": "object", "properties": { "name": { "type": "string" } } }, uiSchema={"name": { "ui:placeholder": "Name" }}, formOptions=FormOptions(confirmationEmailInfo={}, paymentInfo={}, paymentMethods={}, dataOptions={}, defaultFormData={}), date_modified=datetime.datetime.now().isoformat(), date_created=datetime.datetime.now().isoformat()) form.save() return {'res': {'form': serialize_model(form)}}
def response_edit_common(responseId, response_base_path): from ..main import app response = Response.objects.get({"_id": ObjectId(responseId)}) path = app.current_request.json_body.get("path", None) value = app.current_request.json_body.get("value", None) batch = app.current_request.json_body.get("batch", None) if batch is None: batch = [{"path": path, "value": value}] if response_base_path == "value": if all(item["path"].endswith(".checkin") for item in batch): app.check_permissions(response.form, ["Responses_CheckIn", "Responses_Edit"]) else: app.check_permissions(response.form, "Responses_Edit") elif response_base_path == "admin_info": app.check_permissions(response.form, "Responses_AdminInfo_Edit") else: raise Exception( "response_base_path specified is not valid or you not have permissions to perform the specified action." ) for item in batch: update_response_path(response, item["path"], item["value"], response_base_path) response.save() return {"res": {"success": True, "response": serialize_model(response)}}
def response_payment(responseId): from ..main import app response = Response.objects.get({"_id": ObjectId(responseId)}) app.check_permissions(response.form, "Responses_Edit") amount = app.current_request.json_body["amount"] currency = app.current_request.json_body["currency"] date = app.current_request.json_body.get("date", None) if date and "$date" in date: date = dateutil.parser.parse(date["$date"]) id = app.current_request.json_body["id"] method = app.current_request.json_body["method"] send_email = app.current_request.json_body.get("sendEmail", True) paid = mark_successful_payment(response.form, response, { "type": "manual", "method": method, "id": id }, method, amount, currency, id, date=date, send_email=send_email) response.save() return { "res": { "success": True, "paid": paid, "response": serialize_model(response) } }
def do_stuff(): i = 1 subs = [] first = True paginationToken = None while first or paginationToken: first = False if paginationToken: response = client.list_users( UserPoolId=pool, AttributesToGet=["email", "email_verified"], PaginationToken=paginationToken) else: response = client.list_users( UserPoolId=pool, AttributesToGet=["email", "email_verified"]) subs += [u["Username"] for u in response["Users"]] paginationToken = response.get("PaginationToken", None) print(subs) response = Response.objects.raw({ "user": { "$exists": 1 } }).project({"user": 1}) for r in response: _, user = r.user.split("cm:cognitoUserPool:") if user not in subs: print("NO!!! ", user, serialize_model(r)) # print("OK") pass
def response_delete(responseId): from ..main import app response = Response.objects.get({"_id": ObjectId(responseId)}) app.check_permissions(response.form, "Responses_Delete") response.delete() return {"res": {"success": True, "response": serialize_model(response)}}
def group_edit(formId): from ..main import app form = Form.objects.get({"_id": ObjectId(formId)}) app.check_permissions(form, 'Forms_Edit') groups = app.current_request.json_body["groups"] form.formOptions.dataOptions["groups"] = groups form.save() return {"res": {"success": True, "form": serialize_model(form)}}
def fill_string_from_template(response, templateText): flat = flatdict.FlatterDict(response.value) for i in flat: flat[human_readable_key(i)] = flat.pop(i) kwargs = dict(serialize_model(response), response=flat) if kwargs.get("modify_link", None): kwargs["view_link"] = kwargs["modify_link"] + "&mode=view" msgBody = env.from_string(templateText).render(**kwargs) return msgBody
def fix_data(): for response in responses: indexes_to_delete = [] i = 0 for item in response.payment_trail: idx_payment_trail = 0 idx_payment_status_detail = 0 if item.method == "paypal_ipn" and item.value["custom"] != str( response.id): if item.status != "SUCCESS": indexes_to_delete.append([i]) continue print("Doing it...") idx_payment_trail = i # Find the associated payment_status_detail item. idx_payment_status_detail = find_index( response.payment_status_detail, lambda x: x.date == item.date) if idx_payment_status_detail == -1: idx_payment_status_detail = find_index( response.payment_status_detail, lambda x: (x.date - item.date).total_seconds() < .1) print(item.date, response.payment_status_detail, serialize_model(response)) assert idx_payment_status_detail != -1 payment_status_detail_item = response.payment_status_detail[ idx_payment_status_detail] print("old", len(response.payment_status_detail)) assert payment_status_detail_item.method == "paypal_ipn" assert payment_status_detail_item.amount == str( item.value["mc_gross"]) assert payment_status_detail_item.id == None or payment_status_detail_item.id == item.value[ "txn_id"] assert Response.objects.raw({ "payment_trail": { "$elemMatch": { "value.txn_id": item.value["txn_id"] } } }).count() > 1 if response.paid == True and response.paymentInfo.get( "total", 0) > 0: assert len(response.payment_trail) > 1 indexes_to_delete.append( [idx_payment_trail, idx_payment_status_detail]) print("new", len(response.payment_status_detail)) i += 1 print("indexes to delete", indexes_to_delete) for item in indexes_to_delete: del response.payment_trail[item[0]] if len(item) > 1: del response.payment_status_detail[item[1]] if not TEST: response.save()
def response_send_email(responseId): from ..main import app response = Response.objects.get({"_id": ObjectId(responseId)}) app.check_permissions(response.form, ["Responses_Edit", "Responses_SendEmail"]) email_template_id = _parse_email_parameters(app.current_request.json_body) send_email_receipt(response, response.form.formOptions, email_template_id) response.save() return {"res": {"success": True, "response": serialize_model(response)}}
def form_response_summary(formId): """Show response agg. summary""" from ..main import app form = Form.objects.only("formOptions", "cff_permissions").get({"_id": ObjectId(formId)}) app.check_permissions(form, "Responses_ViewSummary") # todo: use aggregation framework here instead. responses = Response.objects.raw({"form": form.id, "paid": True}) responses = serialize_model(responses) result = aggregate_data(form.formOptions.dataOptions, responses) return {"res": result}
def form_list(): """Get forms user has access to.""" from ..main import app userId = app.get_current_user_id() forms = Form.objects.raw({ f"cff_permissions.{userId}": { "$exists": True } }).only("name", "cff_permissions", "date_modified", "date_created") forms = serialize_model(list(forms)) return {"res": forms}
def response_view(responseId): """View an individual response.""" from ..main import app try: response = Response.objects.get({"_id": ObjectId(responseId)}) if True: # if response.user == app.get_current_user_id() or app.check_permissions(response.select_related("form"), ["Responses_View", "Responses_CheckIn"]): return {"success": True, "res": serialize_model(response)} else: raise UnauthorizedError("Unauthorized to access this response.") except DoesNotExist: raise NotFoundError(f"Response with ID {responseId} not found")
def form_render(formId): """Render single form.""" form = None try: form = Form.objects.only("name", "schema", "uiSchema", "formOptions", "cff_permissions").get( {"_id": ObjectId(formId)}) # Convert __$ref back to $ref. if form.schema: form.schema = renameKey(form.schema, "__$ref", "$ref") except DoesNotExist: raise NotFoundError(f"Form ID not found: {formId}") return {"res": serialize_model(form)}
def form_edit(formId): from ..main import app form = Form.objects.get({"_id": ObjectId(formId)}) app.check_permissions(form, 'Forms_Edit') body = pick(app.current_request.json_body, ["schema", "uiSchema", "formOptions", "name"]) for k, v in body.items(): setattr(form, k, v) # Validate $ref properly. if form.schema: form.schema = renameKey(form.schema, "$ref", "__$ref") form.save() form = Form.objects.get({"_id": ObjectId(formId)}) return {"res": {"success": True, "updated_values": serialize_model(form)}}
def response_view(responseId): """View an individual response.""" from ..main import app try: response = Response.objects.get({"_id": ObjectId(responseId)}) if response.user and response.user.id == app.get_current_user_id(): pass # user owns this response elif response.form.formOptions.responseCanViewByLink: pass # can view response by link else: app.check_permissions(response.form, ["Responses_View"]) return {"success": True, "res": serialize_model(response)} except DoesNotExist: raise NotFoundError(f"Response with ID {responseId} not found")
def form_list(): """Get forms user has access to.""" from ..main import app userId = app.get_current_user_id() # Get all forms for superusers query = ( {} if app.is_superuser() else {f"cff_permissions.{userId}": {"$exists": True}} ) forms = Form.objects.raw(query).only( "name", "cff_permissions", "date_modified", "date_created", "tags" ) forms = serialize_model(list(forms)) return {"res": forms}
def form_render_response(formId): from ..main import app form = Form.objects.only("formOptions").get({"_id": ObjectId(formId)}) if (get(form, "formOptions.loginRequired", False) == True and app.get_current_user_id() != "cm:cognitoUserPool:anonymousUser"): try: response = Response.objects.get({ "form": ObjectId(formId), "user": app.get_current_user_id() }) return {"res": serialize_model(response)} except DoesNotExist: predicateFormId = get(form, "formOptions.predicate.formId") if not predicateFormId: return {"res": None, "error": "No predicate formId."} try: predicateForm = Form.objects.only("formOptions").get( {"_id": ObjectId(predicateFormId)}) if get(predicateForm, "formOptions.successor.formId") != formId: return { "res": None, "error": "Successor formId doesn't match current formId.", } response = Response.objects.get({ "form": ObjectId(predicateFormId), "paid": True, "user": app.get_current_user_id(), }) value = patch_predicate( response.value, get(form, "formOptions.predicate.patches", [])) return { "res": { "value": value, "form": predicateFormId }, "predicate": True, } except DoesNotExist: return {"res": None} return {"res": None}
def response_add_payment(responseId): from ..main import app response = Response.objects.get({"_id": ObjectId(responseId)}) app.check_permissions(response.form, ["Responses_Edit", "Responses_AddPayment"]) amount = app.current_request.json_body["amount"] currency = app.current_request.json_body["currency"] date = app.current_request.json_body.get("date", None) if date and "$date" in date: date = dateutil.parser.parse(date["$date"]) id = app.current_request.json_body["id"] method = app.current_request.json_body["method"] send_email = app.current_request.json_body.get("sendEmail", True) email_template_id = _parse_email_parameters(app.current_request.json_body) notes = app.current_request.json_body.get("notes", None) if notes == "": notes = None value = {"type": "manual", "method": method, "id": id} if notes is not None: value = dict(value, notes=notes) paid = mark_successful_payment( response.form, response, value, method, amount, currency, id, date=date, send_email=send_email, notes=notes, email_template_id=email_template_id, ) response.save() return { "res": { "success": True, "paid": paid, "response": serialize_model(response) } }
def form_edit(formId): from ..main import app form = Form.objects.get({"_id": ObjectId(formId)}) app.check_permissions(form, "Forms_Edit") body = pick( app.current_request.json_body, ["schema", "uiSchema", "formOptions", "name", "tags"], ) for k, v in body.items(): setattr(form, k, v) # Rename $ref properly. if form.schema: form.schema = renameKey(form.schema, "$ref", "__$ref") if (form.formOptions and form.formOptions.dataOptions and "views" in form.formOptions.dataOptions): form.formOptions.dataOptions["views"] = replaceKey( replaceKey(form.formOptions.dataOptions["views"], "$", "|"), ".", "||") form.save() form = Form.objects.get({"_id": ObjectId(formId)}) return {"res": {"success": True, "updated_values": serialize_model(form)}}
item.value["mc_gross"]) if payment_status_detail_item.id == None: payment_status_detail_item.id = item.value["txn_id"] if not TEST: response.save() # update_trail # payment_trail # email_trail # payment_status_detail with open("input-prod.txt", "w+") as file: file.writelines([ json.dumps(serialize_model(response), indent=4, sort_keys=True) + "\n" for response in responses ]) fix_data() fix_txn_ids() with open("output-prod.txt", "w+") as file: file.writelines([ json.dumps(serialize_model(response), indent=4, sort_keys=True) + "\n" for response in responses ]) if not TEST: responses = Response.objects.raw({})
def form_create(): """Creates a new form with a blank schema and uiSchema. """ from ..main import app request_body = app.current_request.json_body or {} # todo: multiple orgs? try: org = Org.objects.get({}) except DoesNotExist: raise UnauthorizedError( "Organization does not exist, so forms cannot be created.") app.check_permissions(org, ["Orgs_FormsCreate"]) if request_body.get("formId", None): # todo: add permissions check on forms -- some forms should not be able to be duplicated. formId = request_body.get("formId", None) old_form = Form.objects.get({"_id": ObjectId(formId)}) form = Form( name=old_form.name + " Copy - " + datetime.datetime.now().isoformat(), version=1, center="None", id=ObjectId(), cff_permissions={app.get_current_user_id(): { "owner": True }}, schema=old_form.schema, uiSchema=old_form.uiSchema, formOptions=old_form.formOptions, date_modified=datetime.datetime.now().isoformat(), date_created=datetime.datetime.now().isoformat(), ) form.save() return {"res": {"form": serialize_model(form)}} else: form_name = request_body.get( "form_name", "Untitled form {}".format(datetime.datetime.now().isoformat())) form = Form( name=form_name, version=1, center="None", id=ObjectId(), cff_permissions={app.get_current_user_id(): { "owner": True }}, schema={ "title": "Form", "type": "object", "properties": { "name": { "type": "string" } }, }, uiSchema={"name": { "ui:placeholder": "Name" }}, formOptions=FormOptions( confirmationEmailInfo={}, paymentInfo={}, paymentMethods={}, dataOptions={}, defaultFormData={}, ), date_modified=datetime.datetime.now().isoformat(), date_created=datetime.datetime.now().isoformat(), ) form.save() return {"res": {"form": serialize_model(form)}}
def _search(form, query, autocomplete, search_by_id, show_unpaid): search_fields = get(form.formOptions.dataOptions, "search.searchFields", ["_id"]) if search_by_id is not None: search_fields = ["_id"] result_limit = get(form.formOptions.dataOptions, "search.resultLimit", 10) result_fields = get(form.formOptions.dataOptions, "search.resultFields", ["_id"]) autocomplete_fields = get( form.formOptions.dataOptions, "search.autocompleteFields", ["_id"] ) if show_unpaid is not None: default_mongo_query = {"paid": False} else: default_mongo_query = {"paid": True} mongo_query = {"$or": []} for word in query.split(" "): for field in search_fields: if field == "_id": if len(word) <= 24: try: queryObjectIdStart = ObjectId( word + "0" * (24 - len(word)) ) # fill in zeroes to create object id, e.g. 5cba --> 5cba0000000000000000000 queryObjectIdEnd = ObjectId(word + "e" * (24 - len(word))) mongo_query["$or"].append( { field: { "$gte": queryObjectIdStart, "$lte": queryObjectIdEnd, } } ) except bson.errors.InvalidId: pass else: if field.startswith("value.participants."): _, subfield = field.split("value.participants.") mongo_query["$or"].append( { "value.participants": { "$elemMatch": { subfield: {"$regex": "^" + word, "$options": "i"} } } } ) else: mongo_query["$or"].append( {field: {"$regex": "^" + word, "$options": "i"}} ) mongo_query["form"] = form.id if len(mongo_query["$or"]) == 0: del mongo_query["$or"] # Default query paid = True if mongo_query: mongo_query = {"$and": [default_mongo_query, mongo_query]} else: mongo_query = default_mongo_query if autocomplete is not None: projection = {field: 1 for field in autocomplete_fields} result_limit = 5 else: projection = {} for field in result_fields: projection[field] = 1 responses = ( Response.objects.raw(mongo_query).limit(result_limit).project(projection) ) return {"res": [serialize_model(r) for r in responses]}
def form_response_list(formId): """Show all responses for a particular form. Example /responses?query=test /responses?query=test&autocomplete=1 /responses?query=5cdf&autocomplete=1&search_by_id=1 """ from ..main import app form = Form.objects.only("formOptions", "cff_permissions").get({"_id": ObjectId(formId)}) # todo: use search framework, don't return all! query = app.current_request.query_params and app.current_request.query_params.get( "query", None) autocomplete = app.current_request.query_params and app.current_request.query_params.get( "autocomplete", None) search_by_id = app.current_request.query_params and app.current_request.query_params.get( "search_by_id", None) show_unpaid = app.current_request.query_params and app.current_request.query_params.get( "show_unpaid", None) if query: # autocomplete, participant name, assign bibs functionality app.check_permissions(form, ["Responses_View", "Responses_CheckIn"]) search_fields = get(form.formOptions.dataOptions, "search.searchFields", ["_id"]) if search_by_id is not None: search_fields = ["_id"] result_limit = get(form.formOptions.dataOptions, "search.resultLimit", 10) result_fields = get(form.formOptions.dataOptions, "search.resultFields", ["_id"]) autocomplete_fields = get(form.formOptions.dataOptions, "search.autocompleteFields", ["_id"]) if show_unpaid is not None: default_mongo_query = {"paid": False} else: default_mongo_query = {"paid": True} mongo_query = {"$or": []} for word in query.split(" "): for field in search_fields: if field == "_id": if len(word) <= 24: try: queryObjectIdStart = ObjectId( word + "0" * (24 - len(word)) ) # fill in zeroes to create object id, e.g. 5cba --> 5cba0000000000000000000 queryObjectIdEnd = ObjectId(word + "e" * (24 - len(word))) mongo_query["$or"].append({ field: { "$gte": queryObjectIdStart, "$lte": queryObjectIdEnd } }) except bson.errors.InvalidId: pass else: if field.startswith("value.participants."): _, subfield = field.split("value.participants.") mongo_query["$or"].append({ "value.participants": { "$elemMatch": { subfield: { "$regex": '^' + word, "$options": "i" } } } }) else: mongo_query["$or"].append( {field: { "$regex": '^' + word, "$options": "i" }}) mongo_query["form"] = form.id if len(mongo_query["$or"]) == 0: del mongo_query["$or"] # Default query paid = True if mongo_query: mongo_query = {"$and": [default_mongo_query, mongo_query]} else: mongo_query = default_mongo_query if autocomplete is not None: projection = {field: 1 for field in autocomplete_fields} result_limit = 5 else: projection = {} for field in result_fields: projection[field] = 1 responses = Response.objects.raw(mongo_query).limit( result_limit).project(projection) else: app.check_permissions(form, ["Responses_View"]) responses = Response.objects.all()._collection.find( {"form": form.id}, { "value": 1, "_id": 1, "amount_paid": 1, "user": 1, "form": 1, "paymentInfo": 1, "date_created": 1, "date_modified": 1, "paid": 1, "counter": 1 }) return {"res": [r for r in json.loads(dumps(responses))]} return {"res": [serialize_model(r) for r in responses]}