def post_articleCon_updateArticle(): jdata = bu.get_jdata(ensure=""" articleId, title, body, categoryId, status, """) sesh = auth.getSesh() oldArticle = articleMod.getArticle(jdata.articleId) # old => before update assert oldArticle assert auth.validateArticleEditable(oldArticle, sesh.user) if jdata.categoryId: newCategory = categoryMod.getCategory(jdata.categoryId) assert newCategory newArticle = utils.deepCopy(oldArticle) # new => after update newArticle.update({ "title": jdata.title, "body": bleachUp.bleachHtml(jdata.body), "categoryId": jdata.categoryId, "status": jdata.status, }) assert articleMod.validateArticle(newArticle) if oldArticle != newArticle: articleMod.replaceArticle(newArticle) return { "article": newArticle }
def post_categoryCon_editCategory(): jdata = bu.get_jdata(ensure="categoryId name rank parentId") sesh = auth.getSesh() oldCategory = categoryMod.getCategory(jdata.categoryId) # old => before update assert oldCategory and oldCategory._id assert auth.validateCategoryEditable(oldCategory, sesh.user) if jdata.parentId and jdata.parentId != oldCategory.parentId: newKaParent = categoryMod.getCategory(jdata.parentId) assert newKaParent newCategory = utils.deepCopy(oldCategory) # new => after update newCategory.update({ "name": jdata.name, "rank": jdata.rank, "parentId": jdata.parentId, }) assert categoryMod.validateCategory(newCategory) assert categoryMod.validateNonCircularParentage(newCategory) # Prevent circularity. if oldCategory != newCategory: categoryMod.replaceCategory(newCategory) return { "category": newCategory }
def post_dojoCon_updateDojo(): jdata = bu.get_jdata(ensure="dojoId") sesh = auth.getSesh() dojo = dojoMod.getDojo(jdata.dojoId) # TODO: Delete any inner/linked documents. dojoMod.deleteDojo(dojo) return { "deletedDojoId": dojo._id }
def post_articleCon_updateArticle(): jdata = bu.get_jdata(ensure="articleId") sesh = auth.getSesh() article = articleMod.getArticle(jdata.articleId) assert article assert auth.validateArticleDeletable(article, sesh.user) # TODO:Periodic-review-reqd: Delete any inner/linked documents. articleMod.deleteArticle(article) return { "deletedArticleId": article._id }
def post_dojoCon_createDojo(): jdata = bu.get_jdata(ensure="title") sesh = auth.getSesh() dojo = dojoMod.buildDojo( title=jdata.title, creatorId=sesh.user._id, ) assert dojoMod.validateDojo(dojo) dojoMod.insertDojo(dojo) return { "dojo": dojo }
def post_userCon_detectLogin(): assert bu.get_jdata() == {} sesh = auth.getSesh() if not sesh.user: return { "user": None } # <-- That's '200 OK'. CLI asked if there's a current user, SER says no. # ==> Current session detected: return { "user": userMod.snipUser(sesh.user), }
def post_articleCon_createArticle(): jdata = bu.get_jdata(ensure="title") sesh = auth.getSesh() assert auth.validateAccessLevel("author", sesh.user) article = articleMod.buildArticle( creatorId=sesh.user._id, title=jdata.title, ) assert articleMod.validateArticle(article) articleMod.insertArticle(article) return { "article": article }
def post_userCon_inviteUser(): jdata = bu.get_jdata(ensure=""" invitee_fname, invitee_lname, invitee_email, invitee_accessLevel, """) sesh = auth.getSesh() assert auth.validateAccessLevel("admin", sesh.user) inviter = sesh.user invitee = userMod.getUserByEmail(jdata.invitee_email) newVeriCode = userMod.genVeriCode() if not invitee: # ==> Invitee doesn't already exists. (fresh invite) invitee = userMod.buildUser( email=jdata.invitee_email, fname=jdata.invitee_fname, lname=jdata.invitee_lname, inviterId=inviter._id, veriCode=newVeriCode, accessLevel=jdata.invitee_accessLevel, ) else: # ==> Invitee already exists. (re-invite) if invitee.isVerified: return bu.abort( "That email address is already associated with a confirmed user." ) # ==> __NOT__ already verified. invitee.update({ "fname": jdata.invitee_fname, # Allow re-inviting w/ updated name. "lname": jdata.invitee_lname, "inviterId": inviter._id, # <-- Here, we're updating to latest inviter's id. "hVeriCode": utils.hashPw( newVeriCode ), # <-- On reinvite, new veriCode is gen'd, prev one expires. "accessLevel": jdata.invitee_accessLevel, }) assert invitee.email == jdata.invitee_email # <-- fname/lname/inviterId/hVeriCode can change, but not email. # ==> `invitee` object is now available. userMod.upsertUser(invitee) if emailer.checkSendingEnabled(): return_inviteLink = None sendInviteEmail(invitee, newVeriCode) else: return_inviteLink = genInviteLink(invitee, newVeriCode) return { "user": userMod.snipUser(invitee), "inviteLink": return_inviteLink, }
def post_dojoCon_updateDojo(): jdata = bu.get_jdata(ensure=""" dojoId, title, scratchpad, """) sesh = auth.getSesh() dojo = dojoMod.getDojo(jdata.dojoId) dojo.update({ "title": jdata.title, "scratchpad": jdata.scratchpad, }) assert dojoMod.validateDojo(dojo) dojoMod.replaceDojo(dojo) return { "dojo": dojo }
def post_categoryCon_createCategory(): jdata = bu.get_jdata(ensure="name rank parentId") sesh = auth.getSesh() assert auth.validateAccessLevel("author", sesh.user) category = categoryMod.buildCategory( creatorId=sesh.user._id, name=jdata.name, rank=jdata.rank, parentId=jdata.parentId, ) assert categoryMod.validateCategory(category) categoryMod.insertCategory(category) return { "category": category }
def post_userCon_acceptInvite(): j = bu.get_jdata("userId, email, fname, lname, pw, veriCode") user = getUnverifiedUserByVeriCode(j.userId, j.veriCode) assert all([ user._id == j.userId, user.email == j.email, user.fname == j.fname, user.lname == j.lname, utils.checkPw(j.veriCode, user.hVeriCode), user.hpw == "", ]) user.update({ # In-memory update. "isVerified": True, "hpw": utils.hashPw(j.pw), }) userMod.replaceUser(user) return auth.sendAuthSuccessResponse(user)
def post_categoryCon_deleteCategory(): jdata = bu.get_jdata(ensure="categoryId") sesh = auth.getSesh() category = categoryMod.getCategory(jdata.categoryId) assert category assert auth.validateCategoryDeletable(category, sesh.user) articleCount = articleMod.getArticleCount({ "categoryId": category._id, }) childCategoryCount = categoryMod.getCategoryCount({ "parentId": category._id, # i.e. child.parentId == category._id; }) if not (articleCount == 0 == childCategoryCount): return bu.abort("Can't delete non-empty categories.") assert articleCount == 0 == childCategoryCount categoryMod.deleteCategory(category) return { "deletedCategoryId": category._id }
def post_userCon_setupFirstUser(): jdata = bu.get_jdata(ensure="email fname lname pw") email, fname, lname, pw = utils.unpack(jdata, "email fname lname pw") print(email, fname, lname, pw) userCount = userMod.getUserCount() if userCount >= 1: return bu.abort( "Setup already completed. Please visite /login to log in.") user = userMod.buildUser( email=email, fname=fname, lname=lname, pw=pw, isRootAdmin=True, isVerified=True, accessLevel=auth.alm.getMaxLevel(), ) userMod.insertUser(user) return auth.sendAuthSuccessResponse(user)
def post_userCon_toggleUser_isDeactivated(): jdata = bu.get_jdata(ensure="thatUserId, preToggle_isDeactivated") sesh = auth.getSesh() assert auth.validateAccessLevel("admin", sesh.user) thatUser = userMod.getUser({ "_id": jdata.thatUserId, "isDeactivated": jdata. preToggle_isDeactivated, # This helps ensure that we don't accidently perform the opposite op. # No "isVerified" condition. # <-- This is as unverified (invited/pre-joined) users can be deactivated. }) if not thatUser: # ==> Couldn't find user to be de/reactivated. return bu.abort( "No such user. Can't de/reactivate. Please refresh (Ctrl+R) and retry." ) # ==> User to be de/reactivated found. if thatUser._id == sesh.user._id: assert not thatUser.isDeactivated # Assert active. If deactivated, this line must be unreachable. return bu.abort("One can't deactivate their own account.") # ==> Not trying to deactivate own account. if thatUser.isRootAdmin: assert not thatUser.isDeactivated # Assert active. Root-admin user cannot be deactivated. return bu.abort("Can't de/reactivate root admin.") # ==> `thatUser` is NOT the root admin. assert (thatUser and thatUser._id != sesh.user._id and # Like w/ db-query above, no 'isVerified' related assertion. thatUser.isDeactivated == jdata.preToggle_isDeactivated # and ) thatUser.update({ "isDeactivated": not thatUser.isDeactivated, }) assert userMod.validateUser(thatUser) userMod.replaceUser(thatUser) return { "user": userMod.snipUser(thatUser) }
def post_userCon_fetchInvitedUserByVeriCode(): j = bu.get_jdata(ensure="userId, veriCode") user = getUnverifiedUserByVeriCode(j.userId, j.veriCode) return { "user": userMod.snipUser(user) }