def db_load(self, store):
        not_notified_rfiles = store.find(models.ReceiverFile,
                                         models.ReceiverFile.new == True)

        if not_notified_rfiles.count():
            log.debug("new Files found to be notified: %d" % not_notified_rfiles.count())

        for rfile in not_notified_rfiles:
            context_desc = admin.admin_serialize_context(store,
                                                         rfile.internalfile.internaltip.context,
                                                         self.language)

            steps_desc = admin.db_get_context_steps(store,
                                                    context_desc['id'],
                                                    self.language)

            tip_desc = serialize_receivertip(rfile.receivertip)
            file_desc = serialize_internalfile(rfile.internalfile, rfile.id)
            do_mail, receiver_desc = self.import_receiver(rfile.receiver)

            self.events.append(Event(type=self.template_type,
                                     trigger=self.trigger,
                                     node_info={},
                                     receiver_info=receiver_desc,
                                     context_info=context_desc,
                                     steps_info=steps_desc,
                                     tip_info=tip_desc,
                                     subevent_info=file_desc,
                                     do_mail=do_mail))

            rfile.new = False
Exemple #2
0
def db_archive_questionnaire_schema(store, submission):
    if (store.find(ArchivedSchema, ArchivedSchema.hash
                   == submission.questionnaire_hash).count() <= 0):

        for lang in GLSettings.memory_copy.languages_enabled:
            aqs = ArchivedSchema()
            aqs.hash = submission.questionnaire_hash
            aqs.type = u'questionnaire'
            aqs.language = lang
            aqs.schema = db_get_context_steps(store, submission.context_id,
                                              lang)
            store.add(aqs)

            preview = []
            for s in aqs.schema:
                for f in s['children']:
                    if f['preview']:
                        preview.append(f)

            aqsp = ArchivedSchema()
            aqsp.hash = submission.questionnaire_hash
            aqsp.type = u'preview'
            aqsp.language = lang
            aqsp.schema = preview
            store.add(aqsp)
    def process_event(self, store, message):
        message_desc = rtip.receiver_serialize_message(message)

        # message.type can be 'receiver' or 'wb' at the moment, we care of the latter
        if message.type == u"receiver":
            return

        tip_desc = serialize_receivertip(message.receivertip)

        context_desc = admin.admin_serialize_context(store,
                                                     message.receivertip.internaltip.context,
                                                     self.language)

        steps_desc = admin.db_get_context_steps(store,
                                                context_desc['id'],
                                                self.language)

        do_mail, receiver_desc = self.import_receiver(message.receivertip.receiver)

        self.events.append(Event(type=self.template_type,
                                 trigger=self.trigger,
                                 node_info={},
                                 receiver_info=receiver_desc,
                                 context_info=context_desc,
                                 steps_info=steps_desc,
                                 tip_info=tip_desc,
                                 subevent_info=message_desc,
                                 do_mail=do_mail))
Exemple #4
0
    def load_files(self, store):

        not_notified_rfiles = store.find(models.ReceiverFile,
            models.ReceiverFile.mark == u'not notified')

        if not_notified_rfiles.count():
            log.debug("new [Files✖Receiver] found to be notified: %d" % not_notified_rfiles.count())

        for rfile in not_notified_rfiles:

            if not self.context_desc.has_key('id') or \
                            self.context_desc['id'] != rfile.internalfile.internaltip.context_id:
                self.context_desc = admin.admin_serialize_context(store,
                                                                  rfile.internalfile.internaltip.context,
                                                                  self.language)

                self.steps_info_desc = admin.db_get_context_steps(store,
                                                                  self.context_desc['id'],
                                                                  self.language)

            file_desc = serialize_internalfile(rfile.internalfile, rfile.id)
            tip_desc = serialize_receivertip(rfile.receiver_tip)
            rfile.mark = u'notified'

            self.do_mail = self.import_receiver(rfile.receiver)

            self.append_event(tip_info=tip_desc,
                              subevent_info=file_desc)
Exemple #5
0
    def load_messages(self, store):

        not_notified_messages = store.find(models.Message,
                                           models.Message.mark == u'not notified')

        if not_notified_messages.count():
            log.debug("Messages found to be notified: %d" % not_notified_messages.count())

        for message in not_notified_messages:

            message_desc = rtip.receiver_serialize_message(message)
            message.mark = u'notified'

            # message.type can be 'receiver' or 'wb' at the moment, we care of the 2nd
            if message.type == u"receiver":
                continue

            tip_desc = serialize_receivertip(message.receivertip)

            self.do_mail = self.import_receiver(message.receivertip.receiver)

            # this check is to avoid ask continuously the same context:
            if not self.context_desc.has_key('id') or \
                            self.context_desc['id'] != message.receivertip.internaltip.context_id:
                self.context_desc = admin.admin_serialize_context(store,
                                                                  message.receivertip.internaltip.context,
                                                                  self.language)
                self.steps_info_desc = admin.db_get_context_steps(store,
                                                                  self.context_desc['id'],
                                                                  self.language)

            # append the event based on the self.* and the iteration serialization:
            self.append_event(tip_info=tip_desc,
                              subevent_info=message_desc)
Exemple #6
0
    def load_tips(self, store):
        not_notified_tips = store.find(models.ReceiverTip,
                                       models.ReceiverTip.mark == u'not notified')

        if not_notified_tips.count():
            log.debug("Receiver Tips found to be notified: %d" % not_notified_tips.count())

        for receiver_tip in not_notified_tips:

            self.do_mail = self.import_receiver(receiver_tip.receiver)

            tip_desc = serialize_receivertip(receiver_tip)
            receiver_tip.mark = u'notified'

            # this check is to avoid ask continuously the same context:
            if not self.context_desc.has_key('id') or \
                            self.context_desc['id'] != receiver_tip.internaltip.context_id:
                self.context_desc = admin.admin_serialize_context(store,
                                                                  receiver_tip.internaltip.context,
                                                                  self.language)

                self.steps_info_desc = admin.db_get_context_steps(store,
                                                                  self.context_desc['id'],
                                                                  self.language)

            # append the event (use the self.* and the iteration serialization):
            self.append_event(tip_info=tip_desc,
                              subevent_info=None)
Exemple #7
0
def db_update_submission(store, submission_id, request, finalize, language):
    context = store.find(Context,
                         Context.id == unicode(request['context_id'])).one()
    if not context:
        log.err("Context requested: [%s] not found!" % request['context_id'])
        raise errors.ContextIdNotFound

    submission = store.find(InternalTip,
                            InternalTip.id == unicode(submission_id)).one()
    if not submission:
        log.err("Invalid Submission requested %s in PUT" % submission_id)
        raise errors.SubmissionIdNotFound

    # this may happen if a submission try to update a context
    if submission.context_id != context.id:
        log.err("Can't be changed context in a submission update")
        raise errors.ContextIdNotFound()

    if submission.mark != u'submission':
        log.err("Submission %s do not permit update (status %s)" %
                (submission_id, submission.mark))
        raise errors.SubmissionConcluded

    try:
        import_files(store, submission, request['files'])
    except Exception as excep:
        log.err("Submission update: files import fail: %s" % excep)
        log.exception(excep)
        raise excep

    try:
        wb_steps = request['wb_steps']
        if finalize:
            steps = db_get_context_steps(store, context.id, language)
            verify_steps(steps, wb_steps)

        submission.wb_steps = wb_steps
    except Exception as excep:
        log.err("Submission update: fields validation fail: %s" % excep)
        log.exception(excep)
        raise excep

    try:
        import_receivers(store,
                         submission,
                         request['receivers'],
                         required=finalize)
    except Exception as excep:
        log.err("Submission update: receiver import fail: %s" % excep)
        log.exception(excep)
        raise excep

    if finalize:
        submission.mark = u'finalize'  # Finalized
    else:
        submission.mark = u'submission'  # Submission

    submission_dict = wb_serialize_internaltip(submission)
    return submission_dict
Exemple #8
0
def db_create_submission(store, request, finalize, language):
    context = store.find(Context,
                         Context.id == unicode(request['context_id'])).one()
    if not context:
        log.err("Context requested: [%s] not found!" % request['context_id'])
        raise errors.ContextIdNotFound

    submission = InternalTip()

    submission.access_limit = context.tip_max_access
    submission.download_limit = context.file_max_download
    submission.expiration_date = utc_future_date(
        seconds=context.tip_timetolive)
    submission.context_id = context.id
    submission.creation_date = datetime_now()

    if finalize:
        submission.mark = u'finalize'  # Finalized
    else:
        submission.mark = u'submission'  # Submission

    try:
        store.add(submission)
    except Exception as excep:
        log.err("Storm/SQL Error: %s (create_submission)" % excep)
        raise errors.InternalServerError("Unable to commit on DB")

    try:
        import_files(store, submission, request['files'])
    except Exception as excep:
        log.err("Submission create: files import fail: %s" % excep)
        raise excep

    try:
        wb_steps = request['wb_steps']

        if finalize:
            steps = db_get_context_steps(store, context.id, language)
            verify_steps(steps, wb_steps)

        submission.wb_steps = wb_steps
    except Exception as excep:
        log.err("Submission create: fields validation fail: %s" % excep)
        raise excep

    try:
        import_receivers(store,
                         submission,
                         request['receivers'],
                         required=finalize)
    except Exception as excep:
        log.err("Submission create: receivers import fail: %s" % excep)
        raise excep

    submission_dict = wb_serialize_internaltip(submission)
    return submission_dict
Exemple #9
0
def fill_random_fields(store, context_id, value=None):
    """
    return randomly populated contexts associated to specified context
    """
    steps = db_get_context_steps(store, context_id, 'en')

    for step in steps:
        for field in step['children']:
            fill_random_field_recursively(field)

    return steps
Exemple #10
0
def update_submission(store, submission_id, request, finalize, language=GLSetting.memory_copy.default_language):

    context = store.find(Context, Context.id == unicode(request['context_id'])).one()
    if not context:
        log.err("Context requested: [%s] not found!" % request['context_id'])
        raise errors.ContextIdNotFound

    submission = store.find(InternalTip, InternalTip.id == unicode(submission_id)).one()
    if not submission:
        log.err("Invalid Submission requested %s in PUT" % submission_id)
        raise errors.SubmissionIdNotFound

    # this may happen if a submission try to update a context
    if submission.context_id != context.id:
        log.err("Can't be changed context in a submission update")
        raise errors.ContextIdNotFound("Context are immutable")

    if submission.mark != u'submission':
        log.err("Submission %s do not permit update (status %s)" % (submission_id, submission.mark))
        raise errors.SubmissionConcluded

    try:
        import_files(store, submission, request['files'], finalize)
    except Exception as excep:
        log.err("Submission update: files import fail: %s" % excep)
        log.exception(excep)
        raise excep

    try:
        wb_steps = request['wb_steps']
        if finalize:
            steps = db_get_context_steps(store, context.id, language)
            verify_steps(steps, wb_steps)

        submission.wb_steps = wb_steps
    except Exception as excep:
        log.err("Submission update: fields validation fail: %s" % excep)
        log.exception(excep)
        raise excep

    try:
        import_receivers(store, submission, request['receivers'], required=finalize)
    except Exception as excep:
        log.err("Submission update: receiver import fail: %s" % excep)
        log.exception(excep)
        raise excep

    if finalize:
        submission.mark = u'finalize'  # Finalized
    else:
        submission.mark = u'submission' # Submission

    submission_dict = wb_serialize_internaltip(submission)
    return submission_dict
Exemple #11
0
def fill_random_fields(store, context_id, value=None):
    """
    return randomly populated contexts associated to specified context
    """
    steps = db_get_context_steps(store, context_id)

    for step in steps:
        for field in step['children']:
            fill_random_field_recursively(field)

    return steps
Exemple #12
0
def db_create_submission(store, token, request, language):
    context = store.find(Context, Context.id == token.context_associated).one()
    if not context:
        # this can happen only if the context is removed
        # between submission POST and PUT.. :) that's why is better just
        # ignore this check, take che cached and wait the reference below fault
        log.err("Context requested: [%s] not found!" % token.context_associated)
        raise errors.ContextIdNotFound

    submission = InternalTip()

    submission.expiration_date = utc_future_date(seconds=context.tip_timetolive)
    submission.context_id = context.id
    submission.creation_date = datetime_now()

    store.add(submission)

    try:
        for filedesc in token.uploaded_files:
            associated_f = InternalFile()
            associated_f.name = filedesc['filename']
            # aio, when we are going to implement file.description ?
            associated_f.description = ""
            associated_f.content_type = filedesc['content_type']
            associated_f.size = filedesc['body_len']
            associated_f.internaltip_id = submission.id
            associated_f.file_path = filedesc['encrypted_path']
            store.add(associated_f)

            log.debug("=> file associated %s|%s (%d bytes)" % (
                associated_f.name, associated_f.content_type, associated_f.size))

    except Exception as excep:
        log.err("Unable to create a DB entry for file! %s" % excep)
        raise excep

    try:
        wb_steps = request['wb_steps']
        steps = db_get_context_steps(store, context.id, language)
        verify_steps(steps, wb_steps)
        submission.wb_steps = wb_steps
    except Exception as excep:
        log.err("Submission create: fields validation fail: %s" % excep)
        raise excep

    try:
        import_receivers(store, submission, request['receivers'])
    except Exception as excep:
        log.err("Submission create: receivers import fail: %s" % excep)
        raise excep

    submission_dict = wb_serialize_internaltip(submission)
    return submission_dict
Exemple #13
0
    def fill_random_answers(self, store, context_id, value=None):
        """
        return randomly populated contexts associated to specified context
        """
        answers = {}

        steps = db_get_context_steps(store, context_id, 'en')

        for step in steps:
            for field in step['children']:
                self.fill_random_field_recursively(answers, field)

        return answers
Exemple #14
0
def create_submission(store, request, finalize, language=GLSetting.memory_copy.default_language):
    context = store.find(Context, Context.id == unicode(request['context_id'])).one()
    if not context:
        log.err("Context requested: [%s] not found!" % request['context_id'])
        raise errors.ContextIdNotFound

    submission = InternalTip()

    submission.access_limit = context.tip_max_access
    submission.download_limit = context.file_max_download
    submission.expiration_date = utc_future_date(seconds=context.tip_timetolive)
    submission.context_id = context.id
    submission.creation_date = datetime_now()

    if finalize:
        submission.mark = u'finalize'  # Finalized
    else:
        submission.mark = u'submission' # Submission

    try:
        store.add(submission)
    except Exception as excep:
        log.err("Storm/SQL Error: %s (create_submission)" % excep)
        raise errors.InternalServerError("Unable to commit on DB")

    try:
        import_files(store, submission, request['files'], finalize)
    except Exception as excep:
        log.err("Submission create: files import fail: %s" % excep)
        raise excep

    try:
        wb_steps = request['wb_steps']

        if finalize:
            steps = db_get_context_steps(store, context.id, language)
            verify_steps(steps, wb_steps)

        submission.wb_steps = wb_steps
    except Exception as excep:
        log.err("Submission create: fields validation fail: %s" % excep)
        raise excep

    try:
        import_receivers(store, submission, request['receivers'], required=finalize)
    except Exception as excep:
        log.err("Submission create: receivers import fail: %s" % excep)
        raise excep

    submission_dict = wb_serialize_internaltip(submission)
    return submission_dict
    def db_load(self, store):
        not_notified_comments = store.find(models.Comment,
                                           models.Comment.new == True)

        if not_notified_comments.count():
            log.debug("Comments found to be notified: %d" %
                      not_notified_comments.count())

        for comment in not_notified_comments:
            comment_desc = rtip.receiver_serialize_comment(comment)

            context_desc = admin.admin_serialize_context(store,
                                                         comment.internaltip.context,
                                                         self.language)

            steps_desc = admin.db_get_context_steps(store,
                                                    context_desc['id'],
                                                    self.language)

            # for every comment, iterate on the associated receiver(s)
            log.debug("Comments from %s - Receiver(s) %d" % \
                      (comment.author, comment.internaltip.receivers.count()))

            for receiver in comment.internaltip.receivers:
                if comment.type == u'receiver' and comment.author == receiver.name:
                    log.debug("Receiver is the Author (%s): skipped" % receiver.user.username)
                    continue

                receivertip = store.find(models.ReceiverTip,
                                         (models.ReceiverTip.internaltip_id == comment.internaltip_id,
                                         models.ReceiverTip.receiver_id == receiver.id)).one()

                tip_desc = serialize_receivertip(receivertip)

                do_mail, receiver_desc = self.import_receiver(receiver)

                self.events.append(Event(type=self.template_type,
                                         trigger=self.trigger,
                                         node_info={},
                                         receiver_info=receiver_desc,
                                         context_info=context_desc,
                                         steps_info=steps_desc,
                                         tip_info=tip_desc,
                                         subevent_info=comment_desc,
                                         do_mail=do_mail))

            comment.new = False
Exemple #16
0
    def load_comments(self, store):

        not_notified_comments = store.find(models.Comment,
            models.Comment.mark == u'not notified'
        )

        if not_notified_comments.count():
            log.debug("Comments found to be notified: %d" %
                      not_notified_comments.count())

        for comment in not_notified_comments:

            if not self.context_desc.has_key('id') or \
                            self.context_desc['id'] != comment.internaltip.context_id:
                self.context_desc = admin.admin_serialize_context(store,
                                                                  comment.internaltip.context,
                                                                  self.language)

                self.steps_info_desc = admin.db_get_context_steps(store,
                                                                  self.context_desc['id'],
                                                                  self.language)

            comment_desc = rtip.receiver_serialize_comment(comment)
            comment.mark = u'notified'

            # for every comment, iterate on the associated receiver(s)
            log.debug("Comments from %s - Receiver(s) %d" % \
                      (comment.author, comment.internaltip.receivers.count()))

            for receiver in comment.internaltip.receivers:

                self.do_mail = self.import_receiver(receiver)

                if comment.type == u'receiver' and comment.author == receiver.name:
                    log.debug("Receiver is the Author (%s): skipped" % receiver.user.username)
                    continue

                receivertip = store.find(models.ReceiverTip,
                    (models.ReceiverTip.internaltip_id == comment.internaltip_id,
                     models.ReceiverTip.receiver_id == receiver.id)).one()

                tip_desc = serialize_receivertip(receivertip)

                self.append_event(tip_info=tip_desc,
                                  subevent_info=comment_desc)
    def process_event(self, store, rfile):
        context_desc = admin.admin_serialize_context(store,
                                                     rfile.internalfile.internaltip.context,
                                                     self.language)

        steps_desc = admin.db_get_context_steps(store,
                                                context_desc['id'],
                                                self.language)

        tip_desc = serialize_receivertip(rfile.receivertip)
        file_desc = serialize_internalfile(rfile.internalfile, rfile.id)
        do_mail, receiver_desc = self.import_receiver(rfile.receiver)

        self.events.append(Event(type=self.template_type,
                                 trigger=self.trigger,
                                 node_info={},
                                 receiver_info=receiver_desc,
                                 context_info=context_desc,
                                 steps_info=steps_desc,
                                 tip_info=tip_desc,
                                 subevent_info=file_desc,
                                 do_mail=do_mail))
    def db_load(self, store):
        not_notified_messages = store.find(models.Message,
                                           models.Message.new == True)

        if not_notified_messages.count():
            log.debug("Messages found to be notified: %d" % not_notified_messages.count())

        for message in not_notified_messages:
            message_desc = rtip.receiver_serialize_message(message)

            # message.type can be 'receiver' or 'wb' at the moment, we care of the latter
            if message.type == u"receiver":
                continue

            tip_desc = serialize_receivertip(message.receivertip)

            context_desc = admin.admin_serialize_context(store,
                                                         message.receivertip.internaltip.context,
                                                         self.language)

            steps_desc = admin.db_get_context_steps(store,
                                                    context_desc['id'],
                                                    self.language)

            do_mail, receiver_desc = self.import_receiver(message.receivertip.receiver)

            self.events.append(Event(type=self.template_type,
                                     trigger=self.trigger,
                                     node_info={},
                                     receiver_info=receiver_desc,
                                     context_info=context_desc,
                                     steps_info=steps_desc,
                                     tip_info=tip_desc,
                                     subevent_info=message_desc,
                                     do_mail=do_mail))

            message.new = False
Exemple #19
0
def db_archive_questionnaire_schema(store, submission):
    if (store.find(ArchivedSchema, 
                   ArchivedSchema.hash == submission.questionnaire_hash).count() <= 0):

        for lang in GLSettings.memory_copy.languages_enabled:
            aqs = ArchivedSchema()
            aqs.hash = submission.questionnaire_hash
            aqs.type = u'questionnaire'
            aqs.language = lang
            aqs.schema = db_get_context_steps(store, submission.context_id, lang)
            store.add(aqs)

            preview = []
            for s in aqs.schema:
                for f in s['children']:
                    if f['preview']:
                        preview.append(f)

            aqsp = ArchivedSchema()
            aqsp.hash = submission.questionnaire_hash
            aqsp.type = u'preview'
            aqsp.language = lang
            aqsp.schema = preview
            store.add(aqsp)
    def notify(self, store, tip_id):
        expiring_rtips = store.find(ReceiverTip, ReceiverTip.internaltip_id == tip_id)

        for ertip in expiring_rtips:
            do_mail, receiver_desc = self.import_receiver(ertip.receiver)

            context_desc = admin.admin_serialize_context(store,
                                                         ertip.internaltip.context,
                                                         self.language)
            steps_desc = admin.db_get_context_steps(store,
                                                    context_desc['id'],
                                                    self.language)

            expiring_tip_desc = serialize_receivertip(ertip)

            self.events.append(Event(type=self.template_type,
                                     trigger=self.trigger,
                                     node_info={},
                                     receiver_info=receiver_desc,
                                     context_info=context_desc,
                                     steps_info=steps_desc,
                                     tip_info=expiring_tip_desc,
                                     subevent_info=None,
                                     do_mail=do_mail))
Exemple #21
0
def db_create_submission(store, token_id, request, t2w, language):
    # the .get method raise an exception if the token is invalid
    token = TokenList.get(token_id)

    if not token.context_associated == request['context_id']:
        raise errors.InvalidInputFormat("Token context does not match the one specified in submission payload")

    token.validate(request)

    TokenList.delete(token_id)

    answers = request['answers']

    context = store.find(Context, Context.id == token.context_associated).one()
    if not context:
        # this can happen only if the context is removed
        # between submission POST and PUT.. :) that's why is better just
        # ignore this check, take che cached and wait the reference below fault
        log.err("Context requested: [%s] not found!" % token.context_associated)
        raise errors.ContextIdNotFound

    submission = InternalTip()

    submission.expiration_date = utc_future_date(seconds=context.tip_timetolive)
    submission.context_id = context.id
    submission.creation_date = datetime_now()

    # Tor2Web is spot in the handler and passed here, is done to keep track of the
    # security level adopted by the whistleblower
    submission.tor2web = t2w

    try:
        questionnaire = db_get_context_steps(store, context.id, GLSettings.memory_copy.default_language)
        questionnaire_hash = sha256(json.dumps(questionnaire))

        submission.questionnaire_hash = questionnaire_hash
        submission.preview = extract_answers_preview(questionnaire, answers)

        store.add(submission)

        db_archive_questionnaire_schema(store, submission)

        db_save_questionnaire_answers(store, submission, answers)
    except Exception as excep:
        log.err("Submission create: fields validation fail: %s" % excep)
        raise excep

    try:
        import_receivers(store, submission, request['receivers'])
    except Exception as excep:
        log.err("Submission create: receivers import fail: %s" % excep)
        raise excep

    try:
        for filedesc in token.uploaded_files:
            associated_f = InternalFile()
            associated_f.name = filedesc['filename']
            associated_f.description = ""
            associated_f.content_type = filedesc['content_type']
            associated_f.size = filedesc['body_len']
            associated_f.internaltip_id = submission.id
            associated_f.file_path = filedesc['encrypted_path']
            store.add(associated_f)

            log.debug("=> file associated %s|%s (%d bytes)" % (
                associated_f.name, associated_f.content_type, associated_f.size))

    except Exception as excep:
        log.err("Unable to create a DB entry for file! %s" % excep)
        raise excep

    receipt = db_create_whistleblower_tip(store, submission)

    submission_dict = wb_serialize_internaltip(store, submission)

    submission_dict.update({'receipt': receipt})

    return submission_dict
Exemple #22
0
def db_create_submission(store, token_id, request, t2w, language):
    # the .get method raise an exception if the token is invalid
    token = TokenList.get(token_id)

    if not token.context_associated == request['context_id']:
        raise errors.InvalidInputFormat(
            "Token context does not match the one specified in submission payload"
        )

    token.validate(request)

    TokenList.delete(token_id)

    answers = request['answers']

    context = store.find(Context, Context.id == token.context_associated).one()
    if not context:
        # this can happen only if the context is removed
        # between submission POST and PUT.. :) that's why is better just
        # ignore this check, take che cached and wait the reference below fault
        log.err("Context requested: [%s] not found!" %
                token.context_associated)
        raise errors.ContextIdNotFound

    submission = InternalTip()

    submission.expiration_date = utc_future_date(
        seconds=context.tip_timetolive)
    submission.context_id = context.id
    submission.creation_date = datetime_now()

    # Tor2Web is spot in the handler and passed here, is done to keep track of the
    # security level adopted by the whistleblower
    submission.tor2web = t2w

    try:
        questionnaire = db_get_context_steps(
            store, context.id, GLSettings.memory_copy.default_language)
        questionnaire_hash = sha256(json.dumps(questionnaire))

        submission.questionnaire_hash = questionnaire_hash
        submission.preview = extract_answers_preview(questionnaire, answers)

        store.add(submission)

        db_archive_questionnaire_schema(store, submission)

        db_save_questionnaire_answers(store, submission, answers)
    except Exception as excep:
        log.err("Submission create: fields validation fail: %s" % excep)
        raise excep

    try:
        import_receivers(store, submission, request['receivers'])
    except Exception as excep:
        log.err("Submission create: receivers import fail: %s" % excep)
        raise excep

    try:
        for filedesc in token.uploaded_files:
            associated_f = InternalFile()
            associated_f.name = filedesc['filename']
            associated_f.description = ""
            associated_f.content_type = filedesc['content_type']
            associated_f.size = filedesc['body_len']
            associated_f.internaltip_id = submission.id
            associated_f.file_path = filedesc['encrypted_path']
            store.add(associated_f)

            log.debug("=> file associated %s|%s (%d bytes)" %
                      (associated_f.name, associated_f.content_type,
                       associated_f.size))

    except Exception as excep:
        log.err("Unable to create a DB entry for file! %s" % excep)
        raise excep

    receipt = db_create_whistleblower_tip(store, submission)

    submission_dict = wb_serialize_internaltip(store, submission)

    submission_dict.update({'receipt': receipt})

    return submission_dict
    def create_message_notification_events(self, store, notification_counter):
        """
        Creates events for performing notification of newly added messages.

        Returns:
            events: a list of tuples containing ((message_id, receiver_id), an instance of
                :class:`globaleaks.plugins.base.Event`).


        """
        language = GLSetting.memory_copy.default_language
        events = []
        cplugin = GLSetting.notification_plugins[0]

        plugin = getattr(notification, cplugin)()

        not_notified_messages = store.find(models.Message,
                                           models.Message.mark == models.Message._marker[0]
        )

        node_desc = admin.db_admin_serialize_node(store, language)

        if not_notified_messages.count():
            log.debug("Messages found to be notified: %d" % not_notified_messages.count() )

        for message in not_notified_messages:

            notification_counter += 1
            if notification_counter >= GLSetting.notification_limit:
                log.debug("Notification counter has reached the suggested limit: %d (messages)" %
                          notification_counter)
                store.remove(message)
                break

            if message.receivertip is None:
                log.err("Message %s has ReceiverTip broken reference" % message.id)
                message.mark = models.Message._marker[2] # 'unable to notify'
                continue

            tip_desc = serialize_receivertip(message.receivertip)

            receiver = models.Receiver.get(store, message.receivertip.receiver_id)
            if not receiver:
                log.err("Message %s do not find receiver!?" % message.id)

            if not receiver.mail_address:
                log.err("Receiver %s lack of email address!" % receiver.name)
                continue

            receiver_desc = admin.admin_serialize_receiver(receiver, language)
            log.debug("Messages receiver: %s" % message.receivertip.receiver.name)

            context = message.receivertip.internaltip.context
            if not context:
                log.err("Reference chain fail!")
                continue

            context_desc = admin.admin_serialize_context(store, context, language)

            message_desc = rtip.receiver_serialize_message(message)
            message.mark = u'notified' # models.Message._marker[1]

            if message.type == u"receiver":
                log.debug("Receiver is the Author (%s): skipped" % receiver.user.username)
                continue

            # check if the receiver has the Message notification enabled or not
            if not receiver.message_notification:
                log.debug("Receiver %s has message notification disabled: skipped [source: %s]" % (
                    receiver.user.username, message.author))
                continue

            if  receiver_desc['gpg_key_status'] == u'Enabled': # Receiver._gpg_types[1]
                template_type = u'encrypted_message'
            else:
                template_type = u'plaintext_message'

            notification_settings = self._get_notification_settings(store, receiver_desc['language'])

            event = Event(type=template_type, trigger='Message',
                          notification_settings=notification_settings,
                          trigger_info=message_desc,
                          trigger_parent=tip_desc,
                          node_info=node_desc,
                          receiver_info=receiver_desc,
                          context_info=context_desc,
                          steps_info = admin.db_get_context_steps(store,
                                                                  context_desc['id'],
                                                                  language),
                          plugin=plugin)

            events.append(((unicode(message.id), unicode(receiver.id)), event))

        return events, notification_counter
    def create_comment_notification_events(self, store, notification_counter):
        """
        Creates events for performing notification of newly added comments.

        Returns:
            events: a list of tuples containing ((comment_id, receiver_id), an instance of
                :class:`globaleaks.plugins.base.Event`).


        """
        language = GLSetting.memory_copy.default_language
        events = []
        cplugin = GLSetting.notification_plugins[0]

        plugin = getattr(notification, cplugin)()

        not_notified_comments = store.find(models.Comment,
            models.Comment.mark == models.Comment._marker[0]
        )

        node_desc = admin.db_admin_serialize_node(store, language)

        if not_notified_comments.count():
            log.debug("Comments found to be notified: %d" % not_notified_comments.count() )

        for comment in not_notified_comments:

            notification_counter += 1
            if notification_counter >= GLSetting.notification_limit:
                log.debug("Notification counter has reached the suggested limit: %d (comment)" %
                          notification_counter)
                store.remove(comment)
                break

            if comment.internaltip is None or comment.internaltip.receivers is None:
                log.err("Comment %s has internaltip or receivers broken reference" % comment.id)
                comment.mark = models.Comment._marker[2] # 'unable to notify'
                continue

            # for every comment, iter on the associated receiver
            log.debug("Comments receiver: %d" % comment.internaltip.receivers.count())

            comment_desc = rtip.receiver_serialize_comment(comment)

            if not comment.internaltip.context:
                log.err("(comment_notification) Integrity check failure Context")
                store.remove(comment)
                continue

            context_desc = admin.admin_serialize_context(store, comment.internaltip.context, language)

            # XXX BUG! All notification is marked as correctly send,
            # This can't be managed by callback, and can't be managed by actual DB design
            comment.mark = models.Comment._marker[1] # 'notified'

            for receiver in comment.internaltip.receivers:

                receiver_desc = admin.admin_serialize_receiver(receiver, language)
                if not receiver_desc.has_key('mail_address'):
                    log.err("Receiver %s lack of email address!" % receiver.name)
                    continue

                # if the comment author is the one to be notified: skip the notification
                # ----- BUG, remind,
                # if two receiver has the same name, and one has notification disabled
                # also the homonymous would get the notification dropped.
                if comment.type == models.Comment._types[0] and comment.author == receiver.name:
                    log.debug("Receiver is the Author (%s): skipped" % receiver.user.username)
                    continue

                # check if the receiver has the Comment notification enabled or not
                if not receiver.comment_notification:
                    log.debug("Receiver %s has comment notification disabled: skipped [source: %s]" % (
                        receiver.user.username, comment.author))
                    continue

                receivertip = store.find(models.ReceiverTip,
                    (models.ReceiverTip.internaltip_id == comment.internaltip_id,
                     models.ReceiverTip.receiver_id == receiver.id)).one()

                tip_desc = serialize_receivertip(receivertip)

                if  receiver_desc['gpg_key_status'] == u'Enabled': # Receiver._gpg_types[1]
                    template_type = u'encrypted_comment'
                else:
                    template_type = u'plaintext_comment'

                notification_settings = self._get_notification_settings(store, receiver_desc['language'])

                event = Event(type=template_type, trigger='Comment',
                    notification_settings=notification_settings,
                    trigger_info=comment_desc,
                    trigger_parent=tip_desc,
                    node_info=node_desc,
                    receiver_info=receiver_desc,
                    context_info=context_desc,
                    steps_info = admin.db_get_context_steps(store,
                                                            context_desc['id'],
                                                            language),
                    plugin=plugin)

                events.append(((unicode(comment.id), unicode(receiver.id)), event))

        return events, notification_counter
    def create_file_notification_events(self, store, notification_counter):
        """
        Creates events for performing notification of newly added files..

        Returns:
            events: a list of tuples containing ((receiverfile_id, receiver_id), an instance of
                :class:`globaleaks.plugins.base.Event`).

        """
        language = GLSetting.memory_copy.default_language
        events = []
        cplugin = GLSetting.notification_plugins[0]

        plugin = getattr(notification, cplugin)()

        not_notified_rfiles = store.find(models.ReceiverFile,
            models.ReceiverFile.mark == models.ReceiverFile._marker[0]
        )

        node_desc = admin.db_admin_serialize_node(store, language)

        if not_notified_rfiles.count():
            log.debug("Receiverfiles found to be notified: %d" % not_notified_rfiles.count() )

        for rfile in not_notified_rfiles:

            notification_counter += 1
            if notification_counter >= GLSetting.notification_limit:
                log.debug("Notification counter has reached the suggested limit: %d (files)" %
                          notification_counter)
                store.remove(rfile)
                break

            if not rfile.internalfile:
                log.err("(file_notification) Integrity check failure (InternalFile)")
                store.remove(rfile)
                continue

            file_desc = serialize_internalfile(rfile.internalfile)

            if not rfile.internalfile.internaltip or \
                not rfile.internalfile.internaltip.context:
                log.err("(file_notification) Integrity check failure (InternalTip/Context)")
                store.remove(rfile)
                continue

            context_desc = admin.admin_serialize_context(store,
                                                         rfile.internalfile.internaltip.context,
                                                         language)

            receiver_desc = admin.admin_serialize_receiver(rfile.receiver, language)
            if not receiver_desc.has_key('mail_address'):
                log.err("Receiver %s lack of email address!" % rfile.receiver.user.name)
                continue

            # check if the receiver has the File notification enabled or not
            if not rfile.receiver.file_notification:
                log.debug("Receiver %s has file notification disabled: %s skipped" % (
                    rfile.receiver.user.username, rfile.internalfile.name ))
                rfile.mark = models.ReceiverFile._marker[3] # 'disabled'
                store.commit()
                continue

            # by ticket https://github.com/globaleaks/GlobaLeaks/issues/444
            # send notification of file only if notification of tip is already on send status
            if rfile.receiver_tip.mark == models.ReceiverTip._marker[0]: # 'not notified'
                rfile.mark = models.ReceiverFile._marker[4] # 'skipped'
                log.debug("Skipped notification of %s (for %s) because Tip not yet notified" %
                          (rfile.internalfile.name, rfile.receiver.name) )
                store.commit()
                continue

            tip_desc = serialize_receivertip(rfile.receiver_tip)

            if  receiver_desc['gpg_key_status'] == u'Enabled': # Receiver._gpg_types[1]
                template_type = u'encrypted_file'
            else:
                template_type = u'plaintext_file'

            notification_settings = self._get_notification_settings(store, receiver_desc['language'])

            event = Event(type=template_type, trigger='File',
                notification_settings=notification_settings,
                trigger_info=file_desc,
                trigger_parent=tip_desc,
                node_info=node_desc,
                receiver_info=receiver_desc,
                context_info=context_desc,
                steps_info = admin.db_get_context_steps(store,
                                                        context_desc['id'],
                                                        language),
                plugin=plugin)

            events.append(((unicode(rfile.id), unicode(rfile.receiver.id)), event))

        return events, notification_counter
    def create_tip_notification_events(self, store, notification_counter):
        """
        This transaction will return all a list of tuples containing the tips
        for which the notification event has not been run.

        Returns:

            events: a list of tuples containing (tip_id, an instance of
                :class:`globaleaks.plugins.base.Event`).

        """
        language = GLSetting.memory_copy.default_language
        events = []

        # settings.notification_plugins contain a list of supported plugin
        # at the moment only 1. so [0] is used. but different context/receiver
        # may use different code-plugin:
        cplugin = GLSetting.notification_plugins[0]

        plugin = getattr(notification, cplugin)()

        not_notified_tips = store.find(models.ReceiverTip,
            models.ReceiverTip.mark == models.ReceiverTip._marker[0]
        )

        node_desc = admin.db_admin_serialize_node(store, language)

        if not_notified_tips.count():
            log.debug("Receiver Tips found to be notified: %d" % not_notified_tips.count() )

        for receiver_tip in not_notified_tips:

            notification_counter += 1
            if notification_counter >= GLSetting.notification_limit:
                log.debug("Notification counter has reached the suggested limit: %d (tip)" %
                          notification_counter)
                break

            if not receiver_tip.internaltip or not receiver_tip.internaltip.context:
                log.err("(tip_notification) Integrity failure: missing (InternalTip/Context)")
                store.remove(receiver_tip)
                continue

            context_desc = admin.admin_serialize_context(store, receiver_tip.internaltip.context, language)

            receiver_desc = admin.admin_serialize_receiver(receiver_tip.receiver, language)
            if not receiver_desc.has_key('mail_address'):
                log.err("Receiver %s lack of email address!" % receiver_tip.receiver.name)
                continue

            # check if the receiver has the Tip notification enabled or not
            if not receiver_desc['tip_notification']:
                log.debug("Receiver %s has tip notification disabled" % receiver_tip.receiver.user.username)
                receiver_tip.mark = models.ReceiverTip._marker[3] # 'disabled'
                store.commit()
                continue

            tip_desc = serialize_receivertip(receiver_tip)

            if  receiver_desc['gpg_key_status'] == u'Enabled': # Receiver._gpg_types[1]
                template_type = u'encrypted_tip'
            else:
                template_type = u'plaintext_tip'

            notification_settings = self._get_notification_settings(store, receiver_desc['language'])

            event = Event(type=template_type, trigger='Tip',
                            notification_settings=notification_settings,
                            trigger_info=tip_desc,
                            trigger_parent=None,
                            node_info=node_desc,
                            receiver_info=receiver_desc,
                            context_info=context_desc,
                            steps_info = admin.db_get_context_steps(store,
                                                                    context_desc['id'],
                                                                    language),
                            plugin=plugin)

            events.append((unicode(receiver_tip.id), event))

        return events, notification_counter