Example #1
0
    def get(self, linkKeyStr):
        logging.debug('linkKeyStr=' + linkKeyStr)

        # Collect inputs
        cursor = self.request.get('cursor', None)
        cursor = Cursor(urlsafe=cursor) if cursor else None
        getReasons = (self.request.get('getReasons', 'true') == 'true')
        logging.debug('getReasons=' + str(getReasons))

        httpRequestId = os.environ.get(conf.REQUEST_LOG_ID)
        responseData = {'success': False, 'httpRequestId': httpRequestId}

        cookieData = httpServer.validate(self.request,
                                         self.request.GET,
                                         responseData,
                                         self.response,
                                         idRequired=False)
        userId = cookieData.id()

        # Retrieve requestId from linkKey.  destinationType must be RequestForProposals.
        linkKeyRecord = linkKey.LinkKey.get_by_id(linkKeyStr)
        logging.debug('GetRequestData.get() linkKeyRecord=' +
                      str(linkKeyRecord))

        if (linkKeyRecord == None) or (linkKeyRecord.destinationType !=
                                       conf.REQUEST_CLASS_NAME):
            return httpServer.outputJson(cookieData,
                                         responseData,
                                         self.response,
                                         errorMessage=conf.BAD_LINK)

        # Retrieve RequestForProposal by id, filter/transform fields for display.
        requestId = linkKeyRecord.destinationId
        requestRecordFuture = requestForProposals.RequestForProposals.get_by_id_async(
            int(requestId))

        requestRecord = requestRecordFuture.get_result(
        ) if requestRecordFuture else None

        logging.debug('GetRequestData.get() userId=' + str(userId) +
                      ' requestRecord.creator=' + str(requestRecord.creator))

        # If userId exists... async-retrieve user's ReasonVotes by KeyProperty requestId x userId.
        voteRecordsFuture = None
        if getReasons and userId:
            voteRecordsFuture = reasonVote.ReasonVote.query(
                reasonVote.ReasonVote.requestId == requestId,
                reasonVote.ReasonVote.userId == userId).fetch_async()

        # Retrieve Proposals by KeyProperty requestId
        # Get all data up to current page maximum length.  + Refreshes earlier proposal data.
        maxProposals = const.INITIAL_MAX_PROPOSALS
        proposalRecords, cursor, hasMore = proposal.retrieveTopProposals(
            requestId, maxProposals, cursor=cursor)
        cursor = cursor.urlsafe() if cursor else None

        # Async-retrieve top N reasons per proposal, equal number of pro/con reasons
        reasonRecordsFutures = []
        if getReasons:
            for proposalRec in proposalRecords:
                maxReasonsPerType = conf.MAX_TOP_REASONS / 2
                proRecordsFuture, conRecordsFuture = reason.retrieveTopReasonsAsync(
                    proposalRec.key.id(), maxReasonsPerType)
                reasonRecordsFutures.append(proRecordsFuture)
                reasonRecordsFutures.append(conRecordsFuture)

        # Wait for parallel retrievals
        logging.debug('GetRequestData.get() requestRecord=' +
                      str(requestRecord))

        reasonRecords = []
        for reasonRecordsFuture in reasonRecordsFutures:
            reasonRecordsForProp, cursor, hasMore = reasonRecordsFuture.get_result(
            )
            logging.debug('GetRequestData.get() reasonRecordsForProp=' +
                          str(reasonRecordsForProp))
            reasonRecords.extend(reasonRecordsForProp)
        reasonRecords = sorted(reasonRecords, key=lambda r: -r.score)
        logging.debug('GetRequestData.get() reasonRecords=' +
                      str(reasonRecords))

        voteRecords = voteRecordsFuture.get_result(
        ) if voteRecordsFuture else []
        logging.debug('GetRequestData.get() voteRecords=' + str(voteRecords))

        # Transform records for display.
        linkKeyDisp = httpServer.linkKeyToDisplay(linkKeyRecord)
        logging.debug('GetRequestData.get() linkKeyDisp=' + str(linkKeyDisp))

        requestDisp = httpServer.requestToDisplay(requestRecord, userId)
        logging.debug('GetRequestData.get() requestDisp=' + str(requestDisp))

        proposalDisps = [
            httpServer.proposalToDisplay(p,
                                         userId,
                                         requestRecord=requestRecord)
            for p in proposalRecords
        ]
        logging.debug('GetRequestData.get() proposalDisps=' +
                      str(proposalDisps))

        reasonDisps = [
            httpServer.reasonToDisplay(r, userId) for r in reasonRecords
        ]
        logging.debug('GetRequestData.get() reasonDisps=' + str(reasonDisps))

        # For each reason... collect user vote in reason.myVote
        reasonToVoteRec = {v.reasonId: v
                           for v in voteRecords} if voteRecords else {}
        logging.debug('GetRequestData.get() reasonToVoteRec=' +
                      str(reasonToVoteRec))

        for r in reasonDisps:
            voteRec = reasonToVoteRec.get(r['id'])
            r['myVote'] = voteRec.voteUp if voteRec else False

        # Store request to user's recent requests (cookie).
        user.storeRecentLinkKey(linkKeyStr, cookieData)

        # Display request data.
        responseData = {
            'success': True,
            'linkKey': linkKeyDisp,
            'request': requestDisp,
            'proposals': proposalDisps,
            'reasons': reasonDisps,
            'maxProposals': maxProposals,
            'cursor': cursor,
        }
        logging.debug(
            'GetRequestData.get() responseData=' +
            json.dumps(responseData, indent=4, separators=(', ', ':')))
        httpServer.outputJson(cookieData, responseData, self.response)
Example #2
0
    def post(self, linkKeyStr):
        logging.debug('linkKeyStr=' + linkKeyStr)

        # Collect inputs
        inputData = json.loads(self.request.body)
        if conf.isDev:
            logging.debug('SuggestReasons.post() inputData=' + str(inputData))
        content = text.formTextToStored(inputData.get('content', ''))

        httpRequestId = os.environ.get(conf.REQUEST_LOG_ID)
        responseData = {'success': False, 'httpRequestId': httpRequestId}

        cookieData = httpServer.validate(self.request,
                                         self.request.GET,
                                         responseData,
                                         self.response,
                                         idRequired=False)
        userId = cookieData.id()

        if not content:
            return httpServer.outputJson(cookieData,
                                         responseData,
                                         self.response,
                                         errorMessage='Empty input')

        # Retrieve link-record
        linkKeyRecord = linkKey.LinkKey.get_by_id(linkKeyStr)
        if (linkKeyRecord == None) or (linkKeyRecord.destinationType !=
                                       conf.REQUEST_CLASS_NAME):
            return httpServer.outputJson(cookieData,
                                         responseData,
                                         self.response,
                                         errorMessage=conf.BAD_LINK)
        requestId = linkKeyRecord.destinationId

        # Retrieve RequestForProposal
        requestRecord = requestForProposals.RequestForProposals.get_by_id(
            int(requestId))
        if requestRecord and (requestRecord.freezeUserInput):
            return httpServer.outputJson(cookieData,
                                         responseData,
                                         self.response,
                                         errorMessage=conf.FROZEN)

        # Retrieve Proposals
        proposalRecords = proposal.retrieveTopProposalsForStart(
            requestRecord.key.id(), content)

        linkKeyDisp = httpServer.linkKeyToDisplay(linkKeyRecord)
        requestDisp = httpServer.requestToDisplay(requestRecord, userId)
        proposalDisps = [
            httpServer.proposalToDisplay(p,
                                         userId,
                                         requestRecord=requestRecord)
            for p in proposalRecords
        ]

        # Display
        responseData = {
            'success': True,
            'linkKey': linkKeyDisp,
            'request': requestDisp,
            'proposals': proposalDisps
        }
        httpServer.outputJson(cookieData, responseData, self.response)
Example #3
0
    def post(self):
        logging.debug(
            LogMessage('SubmitEditRequest', 'request.body=',
                       self.request.body))

        # Collect inputs
        requestLogId = os.environ.get(conf.REQUEST_LOG_ID)
        inputData = json.loads(self.request.body)
        logging.debug(LogMessage('SubmitEditRequest', 'inputData=', inputData))

        title = text.formTextToStored(inputData.get('inputTitle', ''))
        detail = text.formTextToStored(inputData.get('inputDetail', ''))
        linkKeyString = inputData.get('linkKey', None)
        browserCrumb = inputData.get('crumb', '')
        loginCrumb = inputData.get('crumbForLogin', '')
        logging.debug(
            LogMessage('SubmitEditRequest', 'title=', title, 'detail=', detail,
                       'browserCrumb=', browserCrumb, 'loginCrumb=',
                       loginCrumb, 'linkKeyString=', linkKeyString))

        # User id from cookie, crumb...
        responseData = {'success': False, 'requestLogId': requestLogId}
        cookieData = httpServer.validate(self.request, inputData, responseData,
                                         self.response)
        if not cookieData.valid(): return
        userId = cookieData.id()

        # Require link-key, and convert it to requestId.
        linkKeyRec = linkKey.LinkKey.get_by_id(linkKeyString)
        logging.debug(
            LogMessage('SubmitEditRequest', 'linkKeyRec=', linkKeyRec))

        if linkKeyRec is None:
            return httpServer.outputJson(cookieData,
                                         responseData,
                                         self.response,
                                         errorMessage='linkKey not found')
        if linkKeyRec.destinationType != conf.REQUEST_CLASS_NAME:
            return httpServer.outputJson(cookieData,
                                         responseData,
                                         self.response,
                                         errorMessage='linkKey not a request')
        requestId = int(linkKeyRec.destinationId)
        logging.debug(LogMessage('SubmitEditRequest', 'requestId=', requestId))

        if linkKeyRec.loginRequired and not cookieData.loginId:
            return httpServer.outputJson(cookieData,
                                         responseData,
                                         self.response,
                                         errorMessage=conf.NO_LOGIN)

        # Check request length.
        if not httpServer.isLengthOk(title, detail, conf.minLengthRequest):
            return httpServer.outputJson(cookieData,
                                         responseData,
                                         self.response,
                                         errorMessage=conf.TOO_SHORT)

        # Retrieve request record.
        requestForProposalsRec = requestForProposals.RequestForProposals.get_by_id(
            requestId)
        logging.debug(
            LogMessage('SubmitEditRequest', 'requestForProposalsRec=',
                       requestForProposalsRec))
        if requestForProposalsRec is None:
            return httpServer.outputJson(
                cookieData,
                responseData,
                self.response,
                errorMessage='requestForProposalsRec not found')

        # Verify that request is editable.
        if userId != requestForProposalsRec.creator:
            return httpServer.outputJson(cookieData,
                                         responseData,
                                         self.response,
                                         errorMessage=conf.NOT_OWNER)
        if not requestForProposalsRec.allowEdit:
            return httpServer.outputJson(cookieData,
                                         responseData,
                                         self.response,
                                         errorMessage=conf.HAS_RESPONSES)
        if requestForProposalsRec.freezeUserInput:
            return httpServer.outputJson(cookieData,
                                         responseData,
                                         self.response,
                                         errorMessage=conf.FROZEN)

        # Update request record.
        requestForProposalsRec.title = title
        requestForProposalsRec.detail = detail
        requestForProposalsRec.put()

        linkKeyDisplay = httpServer.linkKeyToDisplay(linkKeyRec)
        requestDisplay = httpServer.requestToDisplay(requestForProposalsRec,
                                                     userId)
        responseData.update({
            'success': True,
            'linkKey': linkKeyDisplay,
            'request': requestDisplay
        })
        httpServer.outputJson(cookieData, responseData, self.response)
Example #4
0
    def post(self):
        logging.debug(
            LogMessage('SubmitFreezeRequest', 'request.body=',
                       self.request.body))

        # Collect inputs
        requestLogId = os.environ.get(conf.REQUEST_LOG_ID)
        inputData = json.loads(self.request.body)
        logging.debug(
            LogMessage('SubmitFreezeRequest', 'inputData=', inputData))

        freeze = bool(inputData.get('freezeUserInput', False))
        linkKeyString = inputData.get('linkKey', None)
        logging.debug(
            LogMessage('SubmitFreezeRequest', 'freeze=', freeze,
                       'linkKeyString=', linkKeyString))

        # User id from cookie, crumb...
        responseData = {'success': False, 'requestLogId': requestLogId}
        cookieData = httpServer.validate(self.request, inputData, responseData,
                                         self.response)
        if not cookieData.valid(): return
        userId = cookieData.id()

        # Retrieve link-key record
        linkKeyRec = linkKey.LinkKey.get_by_id(linkKeyString)
        logging.debug(
            LogMessage('SubmitFreezeRequest', 'linkKeyRec=', linkKeyRec))

        if linkKeyRec is None:
            return httpServer.outputJson(cookieData,
                                         responseData,
                                         self.response,
                                         errorMessage='linkKey not found')
        if linkKeyRec.destinationType != conf.REQUEST_CLASS_NAME:
            return httpServer.outputJson(cookieData,
                                         responseData,
                                         self.response,
                                         errorMessage='linkKey not a request')
        requestId = int(linkKeyRec.destinationId)
        logging.debug(
            LogMessage('SubmitFreezeRequest', 'requestId=', requestId))

        if linkKeyRec.loginRequired and not cookieData.loginId:
            return httpServer.outputJson(cookieData,
                                         responseData,
                                         self.response,
                                         errorMessage=conf.NO_LOGIN)

        # Retrieve request record
        requestForProposalsRec = requestForProposals.RequestForProposals.get_by_id(
            int(requestId))
        logging.debug(
            LogMessage('SubmitFreezeRequest', 'requestForProposalsRec=',
                       requestForProposalsRec))
        if requestForProposalsRec is None:
            return httpServer.outputJson(
                cookieData,
                responseData,
                self.response,
                errorMessage='requestForProposalsRec not found')

        # Verify that user is authorized
        if userId != requestForProposalsRec.creator:
            return httpServer.outputJson(cookieData,
                                         responseData,
                                         self.response,
                                         errorMessage=conf.NOT_OWNER)

        # Update request record
        requestForProposalsRec.freezeUserInput = freeze
        requestForProposalsRec.put()

        linkKeyDisplay = httpServer.linkKeyToDisplay(linkKeyRec)
        requestDisplay = httpServer.requestToDisplay(requestForProposalsRec,
                                                     userId)
        responseData.update({
            'success': True,
            'linkKey': linkKeyDisplay,
            'request': requestDisplay
        })
        httpServer.outputJson(cookieData, responseData, self.response)
Example #5
0
    def post(
        self
    ):  # Not a transaction, because it is ok to fail link creation, and orphan the request.

        logging.debug(
            LogMessage('SubmitNewRequest', 'request.body=', self.request.body))

        # Collect inputs
        requestLogId = os.environ.get(conf.REQUEST_LOG_ID)
        inputData = json.loads(self.request.body)
        logging.debug(LogMessage('SubmitNewRequest', 'inputData=', inputData))

        title = text.formTextToStored(inputData.get('title', ''))
        detail = text.formTextToStored(inputData.get('detail', ''))
        loginRequired = bool(inputData.get('loginRequired', False))
        experimentalPassword = inputData.get('experimentalPassword', None)
        hideReasons = bool(inputData.get('hideReasons', False))
        browserCrumb = inputData.get('crumb', '')
        loginCrumb = inputData.get('crumbForLogin', '')
        logging.debug(
            LogMessage('SubmitNewRequest', 'title=', title, 'detail=', detail,
                       'browserCrumb=', browserCrumb, 'loginCrumb=',
                       loginCrumb, 'loginRequired=', loginRequired,
                       'hideReasons=', hideReasons))

        # User id from cookie, crumb...
        responseData = {'success': False, 'requestLogId': requestLogId}
        cookieData = httpServer.validate(self.request,
                                         inputData,
                                         responseData,
                                         self.response,
                                         loginRequired=loginRequired)
        if not cookieData.valid(): return
        userId = cookieData.id()

        # Check request length
        if not httpServer.isLengthOk(title, detail, conf.minLengthRequest):
            return httpServer.outputJson(cookieData,
                                         responseData,
                                         self.response,
                                         errorMessage=conf.TOO_SHORT)

        # Check experimental password (low-risk secret)
        if (hideReasons or loginRequired or experimentalPassword) and (
                experimentalPassword != secrets.experimentalPassword):
            return httpServer.outputJson(
                cookieData,
                responseData,
                self.response,
                errorMessage=conf.EXPERIMENT_NOT_AUTHORIZED)

        # Construct new request record
        requestRecord = requestForProposals.RequestForProposals(
            creator=userId,
            title=title,
            detail=detail,
            allowEdit=True,
            hideReasons=hideReasons)
        # Store request record
        requestRecordKey = requestRecord.put()
        logging.debug(
            LogMessage('SubmitNewRequest', 'requestRecordKey.id=',
                       requestRecordKey.id()))

        # Construct and store link key.
        requestId = str(requestRecordKey.id())
        linkKeyRecord = httpServer.createAndStoreLinkKey(
            conf.REQUEST_CLASS_NAME, requestId, loginRequired, cookieData)

        # Send response data.
        linkKeyDisplay = httpServer.linkKeyToDisplay(linkKeyRecord)
        requestDisplay = httpServer.requestToDisplay(requestRecord, userId)
        responseData.update({
            'success': True,
            'linkKey': linkKeyDisplay,
            'request': requestDisplay
        })
        httpServer.outputJson(cookieData, responseData, self.response)
Example #6
0
    def post(
        self
    ):  # Not a transaction, because it is ok to fail link creation, and orphan the request.

        logging.debug('SubmitNewRequest.post() request.body=' +
                      self.request.body)

        # Collect inputs
        requestLogId = os.environ.get(conf.REQUEST_LOG_ID)
        inputData = json.loads(self.request.body)
        logging.debug('SubmitNewRequest.post() inputData=' + str(inputData))

        title = text.formTextToStored(inputData.get('title', ''))
        detail = text.formTextToStored(inputData.get('detail', ''))
        loginRequired = inputData.get('loginRequired', False)
        browserCrumb = inputData.get('crumb', '')
        loginCrumb = inputData.get('crumbForLogin', '')
        logging.debug('SubmitNewRequest.post() title=' + str(title) +
                      ' detail=' + str(detail) + ' browserCrumb=' +
                      str(browserCrumb) + ' loginCrumb=' + str(loginCrumb) +
                      ' loginRequired=' + str(loginRequired))

        # User id from cookie, crumb...
        responseData = {'success': False, 'requestLogId': requestLogId}
        cookieData = httpServer.validate(self.request,
                                         inputData,
                                         responseData,
                                         self.response,
                                         loginRequired=loginRequired)
        if not cookieData.valid(): return
        userId = cookieData.id()

        # Check request length
        if not httpServer.isLengthOk(title, detail, conf.minLengthRequest):
            return httpServer.outputJson(cookieData,
                                         responseData,
                                         self.response,
                                         errorMessage=conf.TOO_SHORT)

        # Construct new request record
        requestRecord = requestForProposals.RequestForProposals(
            creator=userId,
            title=title,
            detail=detail,
            allowEdit=True,
        )
        # Store request record
        requestRecordKey = requestRecord.put()
        logging.debug('requestRecordKey.id={}'.format(requestRecordKey.id()))

        # Construct and store link key.
        requestId = str(requestRecordKey.id())
        linkKeyRecord = httpServer.createAndStoreLinkKey(
            conf.REQUEST_CLASS_NAME, requestId, loginRequired, cookieData)

        # Send response data.
        linkKeyDisplay = httpServer.linkKeyToDisplay(linkKeyRecord)
        requestDisplay = httpServer.requestToDisplay(requestRecord, userId)
        responseData.update({
            'success': True,
            'linkKey': linkKeyDisplay,
            'request': requestDisplay
        })
        httpServer.outputJson(cookieData, responseData, self.response)