def api_entry_text_new(): """ Create a new entry You can POST a new page to this URL and get back the JSON-ified page, it's entry, the fully-spec'd ref, etc. input json: {'title' : title of the page, 'body' : body text } returns : {'entry' : standard entry doc, 'revision' : standard revision doc } or 400 if an invalid request """ if request.mimetype != "application/json": return "Invalid request type, must be application/json", 400 request_data = request.json if 'title' not in request_data: return "'title' not present in request", 400 if 'body' not in request_data: return "'body' not present in request", 400 title = request_data['title'] body = request_data['body'] rev = dm.text_entry_revision_create(title, body) rev.update(dm.revision_create(bson.dbref.DBRef("users", bson.objectid.ObjectId(session["user_id"])))) revid = g.db.revisions.insert(rev, safe=True) rev["_id"] = revid ent_dict = dm.entry_create(dbref("revisions", revid), 'text', rev) entid = g.db.entries.insert(ent_dict, safe=True) ent_dict["_id"] = entid rev["_id"] = revid rev_json = dm.entry_text_rev_to_json(rev) return jsonify({'entry' : {'class' : 'text', 'head' : str(revid), '_id' : str(entid)}, 'revision' : rev_json})
def save_entry(entryid): if request.method == "POST": # extract the fields from post # add the fields entry_class = request.form['entry_class'] entry_id = request.form['entry_id'] request_dict = {} # turn the multidict into a single dict for k in request.form: request_dict[k] = request.form[k] vdoc = dm.revision_class_create[entry_class](**request_dict) author = bson.dbref.DBRef(session["user_id"], "users") entry_ver = dm.revision_create(author=author, parent = request.form["rev_id"]) vdoc.update(entry_ver) # create the doc, now insert it into mongo col_entries = g.db['entries'] col_revisions = g.db['revisions'] oid = col_revisions.insert(vdoc, safe=True) tref = bson.dbref.DBRef("revisions", oid) # FIXME FIXME FIXME USE COMPARE AND SWAP HERE col_entries.save({'_id' : bson.objectid.ObjectId(entry_id), 'head' : tref}, safe=True) div = entry_divs.create[entry_class]({'_id' : entry_id, 'head' : tref, 'archived' : False}, vdoc) # FIXME archived print "Saved document!" return div else: pass
def page_new(): """ """ title = "New Page" entries = [] page_rev = dm.page_entry_revision_create(title, entries) author = dbref("users", session["user_id"]) page_rev.update(dm.revision_create(author)) revid = g.db.revisions.insert(page_rev, safe=True) page_rev["_id"] = revid ent_dict = dm.entry_create(dbref("revisions", revid), 'page', page_rev) entid = g.db.entries.insert(ent_dict, safe=True) return redirect("/page/%s" % entid)
def page_new(notebook): """ """ nbdb = g.dbconn[get_nb_dbname(notebook)] title = "New Page" entries = [] page_rev = dm.page_entry_revision_create(title, entries) author = session["user_id"] page_rev.update(dm.revision_create(author, app.config['DB_SYSTEM_DATABASE'])) revid = nbdb.revisions.insert(page_rev, safe=True) page_rev["_id"] = revid ent_dict = dm.entry_create(dbref("revisions", revid), 'page', page_rev) entid = nbdb.entries.insert(ent_dict, safe=True) return redirect("/notebook/%s/page/%s" % (notebook, entid))
def api_entry_new(notebook): """ Create a new revision and entry. You can POST a new json object to this URL and get back the JSON-ified page, it's entry, the fully-spec'd rev. Note the input json must contain class and then any of the requirements for this class, for example: all: archived: tags: text: title body page: title entries : [ {entry:, hidden:, rev:},] figure: title caption images returns : {'entry' : standard entry doc, 'revision' : standard revision doc } or 400 if an invalid request """ if request.mimetype != "application/json": return "Invalid request type, must be application/json", HTTP_ERROR_CLIENT_BADREQUEST request_data = request.json if 'class' not in request_data: return "'class' not present in request", HTTP_ERROR_CLIENT_BADREQUEST dclass = request_data['class'] if dclass not in dm.json_to_rev: return "Unknown class", HTTP_ERROR_CLIENT_BADREQUEST rev = dm.json_to_rev[dclass](request_data) archived = request_data.get("archived", False) tags = request_data.get("tags", []) rev.update(dm.revision_create(session["user_id"], app.config['DB_SYSTEM_DATABASE'], archived=archived, tags = tags)) nbdb = g.dbconn[get_nb_dbname(notebook)] revid = nbdb.revisions.insert(rev, safe=True) rev["_id"] = revid ent_dict = dm.entry_create(dbref("revisions", revid), dclass, rev) entid = nbdb.entries.insert(ent_dict, safe=True) ent_dict["_id"] = entid # tag cleanup [tagutils.inc_tag(nbdb, t) for t in tags] rev_json = dm.rev_to_json[dclass](rev) return jsonify({'entry' : {'class' : dclass, 'head' : str(revid), '_id' : str(entid)}, 'revision' : rev_json})
def api_entry_get_post(notebook, entryid): """ GET the latest entry and rev for an entry POST an updated rev. Note that we extract out the relevant fields from the submitted doc, and overwrite other relevant ones. Things that must be present include: class parent: Parent points to the old entry; this is also what we think the entry currently points to doc-specific entries we rewrite : author (current logged in author) date _id : with the new updated revid and update the entry If the entry is out of date, we reject, and instead return the latest entry/rev, with error 409 """ nbdb = g.dbconn[get_nb_dbname(notebook)] if request.method == 'POST': """ Perform an update, assuming that the doc is pretty well-formed """ if request.mimetype != "application/json": return "Invalid request type, must be application/json", HTTP_ERROR_CLIENT_BADREQUEST rd = request.json dclass = rd['class'] parent = rd['parent'] if dclass == 'text': rev = dm.text_entry_revision_create(rd['title'], rd['body']) elif dclass == 'figure': rev = dm.figure_entry_revision_create(rd['title'], rd['caption'], rd.get('maxsize', None), gallery = rd.get("gallery", False), images = rd['images']) elif dclass == 'markdown' : rev = dm.markdown_entry_revision_create(rd['title'], rd['body']) elif dclass == 'page': rev = dm.page_entry_revision_create(rd['title'], rd['entries']) else: raise Exception("Unknown entry class '%s'" % dclass) author = dbref("users", session["user_id"]) tags = rd.get("tags", []) pref = dbref("revisions", parent) rev.update(dm.revision_create(session["user_id"], app.config['DB_SYSTEM_DATABASE'], parent=pref, archived=rd.get('archived', False), tags = tags)) # save the revision new_rev_oid = nbdb.revisions.insert(rev, safe=True) rev["_id"] = new_rev_oid new_entry_doc = dm.entry_create(dbref('revisions', new_rev_oid), dclass, rev) res = nbdb.entries.update({'_id' : bson.objectid.ObjectId(entryid), 'head' : dbref('revisions', parent), 'class' : dclass}, new_entry_doc, safe=True) new_entry_doc["_id"] = bson.objectid.ObjectId(entryid) if res['updatedExisting'] == True: # success! # get the old revisions tags, compute the diff olddoc = nbdb.dereference(dbref('revisions', parent)) tagdeltas = tagutils.tagdelta(olddoc.get('tags', []), tags) [tagutils.inc_tag(nbdb, t) for t in tagdeltas[0]] [tagutils.dec_tag(nbdb, t) for t in tagdeltas[1]] new_rev_doc_json = dm.rev_to_json[dclass](rev) entry_doc_json = dm.entry_to_json(new_entry_doc) return jsonify({"latest_entry_doc" : entry_doc_json, "latest_revision_doc" : new_rev_doc_json}) else: # failed to update, meaning someone else updated the entry ahead of us nbdb.revisions.remove({'_id' : new_rev_oid}) entry_ref = dbref("entries", entryid) latest_entry_doc = nbdb.dereference(entry_ref) true_latest_rev_ref = latest_entry_doc['head'] latest_rev_doc = nbdb.dereference(true_latest_rev_ref) latest_rev_json = dm.page_rev_to_json(latest_rev_doc) entry_doc_json = dm.entry_to_json(latest_entry_doc) return jsonify_error({"reason" : "Incorrect latest", "latest_entry_doc": entry_doc_json, "latest_revision_doc" : latest_rev_json}, HTTP_ERROR_CLIENT_CONFLICT) elif request.method == "GET": # fixme update this to use denormalized stuff entry_ref = dbref("entries", entryid) entry_doc = nbdb.dereference(entry_ref) latest_page_ref = entry_doc['head'] latest_page_rev = nbdb.dereference(latest_page_ref) return jsonify({"entry" : dm.entry_to_json(entry_doc), "revision" : dm.rev_to_json[entry_doc['class']](latest_page_rev)})
def api_entry_get_post(entryid): """ GET the latest entry and rev for an entry POST an updated rev. Note that we extract out the relevant fields from the submitted doc, and overwrite other relevant ones. Things that must be present include: class parent: Parent points to the old entry; this is also what we think the entry currently points to doc-specific entries we rewrite : author (current logged in author) date _id : with the new updated revid and update the entry If the entry is out of date, we reject, and instead return the latest entry/rev """ if request.method == 'POST': """ Perform an update, assuming that the doc is pretty well-formed """ if request.mimetype != "application/json": return "Invalid request type, must be application/json", 400 rd = request.json dclass = rd['class'] parent = rd['parent'] if dclass == 'text': rev = dm.text_entry_revision_create(rd['title'], rd['body']) elif dclass == 'page': rev = dm.page_entry_revision_create(rd['title'], rd['entries']) else: raise Exception("Unknown entry") author = dbref("users", session["user_id"]) pref = dbref("revisions", parent) rev.update(dm.revision_create(author, parent=pref, archived=rd.get('archived', False))) # save the revision new_rev_oid = g.db.revisions.insert(rev, safe=True) rev["_id"] = new_rev_oid new_entry_doc = dm.entry_create(dbref('revisions', new_rev_oid), dclass, rev) res = g.db.entries.update({'_id' : bson.objectid.ObjectId(entryid), 'head' : dbref('revisions', parent), 'class' : dclass}, new_entry_doc, safe=True) new_entry_doc["_id"] = bson.objectid.ObjectId(entryid) if res['updatedExisting'] == True: # success! new_rev_doc_json = dm.rev_to_json[dclass](rev) entry_doc_json = dm.entry_to_json(new_entry_doc) return jsonify({"latest_entry_doc" : entry_doc_json, "latest_revision_doc" : new_rev_doc_json}) else: # failed to update, meaning someone else updated the entry ahead of us g.db.revisions.remove({'_id' : new_rev_oid}) entry_ref = dbref("entries", entryid) latest_entry_doc = g.db.dereference(entry_ref) true_latest_rev_ref = latest_entry_doc['head'] latest_rev_doc = g.db.dereference(true_latest_rev_ref) latest_rev_json = dm.page_rev_to_json(latest_rev_doc) resp = jsonify({"reason" : "Incorrect latest", "latest_revision_doc" : latest_rev_json}) resp.status = "400" return resp elif request.method == "GET": # fixme update this to use denormalized stuff entry_ref = dbref("entries", entryid) entry_doc = g.db.dereference(entry_ref) latest_page_ref = entry_doc['head'] latest_page_rev = g.db.dereference(latest_page_ref) return jsonify({"entry" : dm.entry_to_json(entry_doc), "revision" : dm.rev_to_json[entry_doc['class']](latest_page_rev)})
def api_page_new(): """ You can POST a new page to this URL and get back the JSON-ified page, it's entry, the fully-spec'd ref, etc. input json: {'title' : title of the page, 'entries' : [ {'entry' : text_string_of_entry_id, 'hidden' : boolean [default : False] 'rev' : text string of revision ID if pinned } ]} returns : {'entry' : standard entry doc, 'revision' : standard revision doc } or 400 if an invalid request note does not check to see if IDs are valid """ if request.mimetype != "application/json": return "Invalid request type, must be application/json", 400 request_data = request.json if 'title' not in request_data: return "'title' not present in request", 400 title = request_data['title'] entries = [] if 'entry' in request_data: for e in request_data['entries']: if 'entry' not in e: return 'invalid entry', 400 edict = {'entry' : bson.dbref.DBRef("entries", e['entry']), 'hidden' : get(e, 'hidden', False)} if 'rev' in e: edict['rev'] = bson.dbref.DBRef("revisions", e['rev']) entries.append(edict) page_rev = dm.page_entry_revision_create(title, entries) author = bson.dbref.DBRef("users", bson.objectid.ObjectId(session["user_id"])) page_rev.update(dm.revision_create(author)) revid = g.db.revisions.insert(page_rev, safe=True) page_rev["_id"] = revid ent_dict = dm.entry_create(dbref("revisions", revid), 'page', page_rev) entid = g.db.entries.insert(ent_dict, safe=True) ent_dict["_id"] = entid page_rev_json = dm.page_rev_to_json(page_rev) return jsonify({'entry' : {'class' : 'page', 'head' : str(revid), '_id' : str(entid)}, 'revision' : page_rev_json})
def api_page_mutate(page_entryid): """ Primary page mutation interface """ COMMIT_ATTEMPTS = 30 # otherwise something is pretty wrong! action = request.form('action') page_ver_id = request.form('page_ver_id') for commit_attempt in range(COMMIT_ATTEMPTS): latest_page_entry_doc = db_get_entry_doc(page_entryid) if str(latest_page_entry_doc.head) != page_ver_id: print "Page has been updated since this edit" latest_page_rev_doc = g.db.dereference(latest_page_entry_doc.head) if can_mutate_page(action, latest_page_rev_doc, action_data) : new_doc = mutate_page(action, latest_page_rev_doc, action_data) author = bson.dbref.DBRef(session["user_id"], "users") new_doc.update(dm.revision_create(author, parent=latest_page_rev)) new_doc_oid = revisions.insert(new_doc, safe=True) # create new, updated entry doc pointing to this doc new_entry_doc = d.entry_create(bson.dbref.DBRef(new_doc_oid, 'revisions'), latest_page_entry_doc['class']) # compare-and-swap res = entries.update(latest_page_entry_doc, new_entry_doc, safe=True) if res['updatedExisting'] == True: # success! return jsonify({"latest_page_revision_doc" : new_doc}) else: # failed to update, meaning someone else updated the entry ahead of us revisions.remove({'_id' : new_doc_oid}) # then loop else: # couldn't actually perform mutation, # return latst doc along with status "Invalid mutation" return jsonify({"reason" : "invalid mutation" , "latest_page_revision_doc" : latest_page_rev_doc}), 400 return jsonify({"reason" : "too much contention"}), 400
def api_page_new(): """ You can POST a new page to this URL and get back the JSON-ified page, it's entry, the fully-spec'd ref, etc. input json: {'title' : title of the page, 'entries' : [ {'entry' : text_string_of_entry_id, 'hidden' : boolean [default : False] 'rev' : text string of revision ID if pinned } ]} returns : {'entry' : standard entry doc, 'revision' : standard revision doc } or 400 if an invalid request note does not check to see if IDs are valid """ if 'title' not in request.form: return "'title' not present in request", 400 if 'entries' not in request.form: return "'entries' not present in request", 400 title = request.form['title'] entries = [] for e in request.form['entries']: if 'entry' not in e: return 'invalid entry', 400 edict = {'entry' : bson.dbref.DBRef("entries", e['entry']), 'hidden' : get(e, 'hidden', False)} if 'rev' in e: edict['rev'] = bson.dbref.DBRef("revisions", e['rev']) entries.append(edict) page_rev = dm.page_entry_revision_create(title, entries) page_rev.update(dm.revision_create(bson.dbref.DBRef("users", session["user_id"]))) revid = revisions.insert(page_rev, safe=True) ent_dict = entry_create(bson.dbref.DBRef("revisions", revid)) entid = entries.insert(ent_dict, safe=True) ent_dict["_id"] = entid page_rev["_id"] = revid return {'entry' : {'class' : 'page', 'head' : revid, '_id' : entid}, 'revision' : dm.page_to_json(page_rev)}
'This is a test 6' : 5, "And here is some more 7": 4, } entries = [] for title, revisions in docs_to_create.iteritems(): parent = None for r in range(revisions): rt = randomtext.text[revisions] t = dm.text_entry_revision_create(title, rt) t.update(dm.revision_create(u1oid, parent=parent)) toid = col_revisions.insert(t) t['_id'] = toid parent = toid e = dm.entry_create(toid, t['class'], t) eoid = col_entries.insert(e) entries.append({'entry' : bson.dbref.DBRef("entries", eoid), 'hidden' : False}) p = dm.page_entry_revision_create("This is a title for a page", entries) p.update(dm.revision_create(u1oid))