def post(self, tip_token, *uriargs): """ Request: actorsCommentDesc Response: actorsCommentDesc Errors: InvalidTipAuthToken, InvalidInputFormat, TipGusNotFound, TipReceiptNotFound """ comment_iface = Comment() try: request = validateMessage(self.request.body, requests.actorsCommentDesc) if is_receiver_token(tip_token): requested_t = ReceiverTip() tip_description = yield requested_t.get_single(tip_token) comment_stored = yield comment_iface.add_comment(tip_description['internaltip_id'], request['content'], u"receiver", tip_description['receiver_gus']) else: requested_t = WhistleblowerTip() tip_description = yield requested_t.get_single(tip_token) comment_stored = yield comment_iface.add_comment(tip_description['internaltip_id'], request['content'], u"whistleblower") self.set_status(200) self.write(json.dumps(comment_stored)) except TipGusNotFound, e: self.set_status(e.http_status) self.write({'error_message' : e.error_message, 'error_code' : e.error_code})
def delete(self, context_gus, *uriargs): """ Request: adminContextDesc Response: None Errors: InvalidInputFormat, ContextGusNotFound """ context_iface = Context() receivertip_iface = ReceiverTip() internaltip_iface = InternalTip() whistlebtip_iface = WhistleblowerTip() comment_iface = Comment() receiver_iface = Receiver() file_iface = File() # This DELETE operation, its permanent, and remove all the reference # a Context has within the system (in example: remove associated Tip, # remove try: context_desc = yield context_iface.get_single(context_gus) tips_related_blocks = yield receivertip_iface.get_tips_by_context(context_gus) print "Tip that need to be deleted, associated with the context",\ context_gus, ":", len(tips_related_blocks) for tip_block in tips_related_blocks: internaltip_id = tip_block.get('internaltip')['internaltip_id'] yield whistlebtip_iface.delete_access_by_itip(internaltip_id) yield receivertip_iface.massive_delete(internaltip_id) yield comment_iface.delete_comment_by_itip(internaltip_id) yield file_iface.delete_file_by_itip(internaltip_id) # and finally, delete the InternalTip yield internaltip_iface.tip_delete(internaltip_id) # (Just consistency check) receivers_associated = yield receiver_iface.get_receivers_by_context(context_gus) print "receiver associated by context POV:", len(receivers_associated),\ "receiver associated by context DB-field:", len(context_desc['receivers']) # Align all the receiver associated to the context, that the context cease to exist yield receiver_iface.align_context_delete(context_desc['receivers'], context_gus) # TODO delete stats associated with context ? # TODO delete profile associated with the context # Finally, delete the context yield context_iface.delete_context(context_gus) self.set_status(200) except ContextGusNotFound, e: self.set_status(e.http_status) self.write({'error_message': e.error_message, 'error_code' : e.error_code})
def get(self, tip_token, *uriargs): """ Parameters: None (TODO start/end, date) Response: actorsCommentList Errors: InvalidTipAuthToken """ try: if is_receiver_token(tip_token): requested_t = ReceiverTip() tip_description = yield requested_t.get_single(tip_token) else: requested_t = WhistleblowerTip() tip_description = yield requested_t.get_single(tip_token) comment_iface = Comment() comment_list = yield comment_iface.get_comment_by_itip(tip_description['internaltip_id']) self.set_status(200) self.write(json.dumps(comment_list)) except TipGusNotFound, e: self.set_status(e.http_status) self.write({'error_message' : e.error_message, 'error_code' : e.error_code})
def delete_context(self, context_gus): """ This DELETE operation, its permanent, and remove all the reference a Context has within the system (Tip, File, submission...) """ store = self.getStore() # Get context description, just to verify that context_gus is valid context_iface = Context(store) context_desc = context_iface.get_single(context_gus) # Collect tip by context and iter on the list receivertip_iface = ReceiverTip(store) tips_related_blocks = receivertip_iface.get_tips_by_context(context_gus) internaltip_iface = InternalTip(store) whistlebtip_iface = WhistleblowerTip(store) file_iface = File(store) comment_iface = Comment(store) # For every InternalTip, delete comment, wTip, rTip and Files for tip_block in tips_related_blocks: internaltip_id = tip_block.get('internaltip')['internaltip_id'] whistlebtip_iface.delete_access_by_itip(internaltip_id) receivertip_iface.massive_delete(internaltip_id) comment_iface.delete_comment_by_itip(internaltip_id) file_iface.delete_file_by_itip(internaltip_id) # and finally, delete the InternalTip internaltip_iface.tip_delete(internaltip_id) # (Just a consistency check - need to be removed) receiver_iface = Receiver(store) receivers_associated = receiver_iface.get_receivers_by_context(context_gus) print "receiver associated by context POV:", len(receivers_associated),\ "receiver associated by context DB-field:", len(context_desc['receivers']) # Align all the receiver associated to the context, that the context cease to exist receiver_iface.align_context_delete(context_desc['receivers'], context_gus) # Get the profile list related to context_gus and delete all of them profile_iface = PluginProfiles(store) profile_list = profile_iface.get_profiles_by_contexts([ context_gus ]) for prof in profile_list: profile_iface.delete_profile(prof['profile_gus']) # Get the submission list under the context, and delete all of them submission_iface = Submission(store) submission_list = submission_iface.get_all() for single_sub in submission_list: submission_iface.submission_delete(single_sub['submission_gus'], wb_request=False) # Finally, delete the context context_iface.delete_context(context_gus) self.returnData(context_desc) self.returnCode(200) return self.prepareRetVals()
def get(self, what, *uriargs): """ Parameters: None Response: Unknown Errors: None /admin/overview GET should return up to all the tables of GLBackend """ from globaleaks.models.externaltip import ReceiverTip, WhistleblowerTip, Comment from globaleaks.models.options import PluginProfiles, ReceiverConfs from globaleaks.models.internaltip import InternalTip from globaleaks.models.receiver import Receiver expected = [ 'itip', 'wtip', 'rtip', 'receivers', 'comment', 'profiles', 'rcfg', 'all' ] if what == 'receivers' or what == 'all': receiver_iface = Receiver() receiver_list = yield receiver_iface.admin_get_all() self.write({ 'elements' : len(receiver_list), 'receivers' : receiver_list}) if what == 'itip' or what == 'all': itip_iface = InternalTip() itip_list = yield itip_iface.admin_get_all() self.write({ 'elements' : len(itip_list), 'internaltips' : itip_list }) if what == 'rtip' or what == 'all': rtip_iface = ReceiverTip() rtip_list = yield rtip_iface.admin_get_all() self.write({ 'elements' : len(rtip_list), 'receivers_tips' : rtip_list }) if what == 'wtip' or what == 'all': wtip_iface = WhistleblowerTip() wtip_list = yield wtip_iface.admin_get_all() self.write({ 'elements' : len(wtip_list), 'whistleblower_tips' : wtip_list }) if what == 'comment' or what == 'all': comment_iface = Comment() comment_list = yield comment_iface.admin_get_all() self.write({ 'elements' : len(comment_list), 'comments' : comment_list }) if what == 'profiles' or what == 'all': profile_iface = PluginProfiles() profile_list = yield profile_iface.admin_get_all() self.write({ 'elements' : len(profile_list), 'profiles' : profile_list }) if what == 'rcfg' or what == 'all': rconf_iface = ReceiverConfs() rconf_list = yield rconf_iface.admin_get_all() self.write({ 'elements' : len(rconf_list), 'settings' : rconf_list }) if not what in expected: self.set_status(405) else: self.set_status(200) self.finish()
def delete(self, tip_token, *uriargs): """ Request: None Response: None Errors: ForbiddenOperation, TipGusNotFound When an uber-receiver decide to "total delete" a Tip, is handled by this call. """ try: if not is_receiver_token(tip_token): raise ForbiddenOperation receivertip_iface = ReceiverTip() receivers_map = yield receivertip_iface.get_receivers_by_tip(tip_token) if not receivers_map['actor']['can_delete_submission']: raise ForbiddenOperation # sibilings_tips has the keys: 'sibilings': [$] 'requested': $ sibilings_tips = yield receivertip_iface.get_sibiligs_by_tip(tip_token) # delete all the related tip for sibiltip in sibilings_tips['sibilings']: yield receivertip_iface.personal_delete(sibiltip['tip_gus']) # and the tip of the called yield receivertip_iface.personal_delete(sibilings_tips['requested']['tip_gus']) # extract the internaltip_id, we need for the next operations itip_id = sibilings_tips['requested']['internaltip_id'] file_iface = File() # remove all the files: XXX think if delivery method need to be inquired files_list = yield file_iface.get_files_by_itip(itip_id) print "TODO remove file_list", files_list comment_iface = Comment() # remove all the comments based on a specific itip_id comments_list = yield comment_iface.delete_comment_by_itip(itip_id) internaltip_iface = InternalTip() # finally, delete the internaltip internaltip_iface.tip_delete(sibilings_tips['requested']['internaltip_id']) self.set_status(200) except ForbiddenOperation, e: self.set_status(e.http_status) self.write({'error_message' : e.error_message, 'error_code' : e.error_code})
def get_comment_list_by_wb(self, receipt): store = self.getStore() requested_t = WhistleblowerTip(store) tip_description = requested_t.get_single(receipt) comment_iface = Comment(store) comment_list = comment_iface.get_comment_by_itip(tip_description['internaltip_id']) self.returnData(comment_list) self.returnCode(200) return self.prepareRetVals()
def new_comment_by_wb(self, receipt, request): store = self.getStore() requested_t = WhistleblowerTip(store) tip_description = requested_t.get_single(receipt) comment_iface = Comment(store) comment_stored = comment_iface.new(tip_description['internaltip_id'], request['content'], u"whistleblower") self.returnData(comment_stored) self.returnCode(201) return self.prepareRetVals()
def new_comment_by_receiver(self, tip_gus, request): store = self.getStore() requested_t = ReceiverTip(store) tip_description = requested_t.get_single(tip_gus) comment_iface = Comment(store) comment_stored = comment_iface.new(tip_description['internaltip_id'], request['content'], u"receiver", tip_description['receiver_gus']) # XXX here can be put the name of the Receiver self.returnData(comment_stored) self.returnCode(201) return self.prepareRetVals()
def comment_notification(self): plugin_type = u'notification' store = self.getStore() comment_iface = Comment(store) internaltip_iface = InternalTip(store) receivercfg_iface = ReceiverConfs(store) profile_iface = PluginProfiles(store) not_notified_comments = comment_iface.get_comment_by_mark(marker=u'not notified') for comment in not_notified_comments: receivers_list = internaltip_iface.get_receivers_by_itip(comment['internaltip_id']) # needed to obtain context! itip_info = internaltip_iface.get_single(comment['internaltip_id']) for receiver_info in receivers_list: receiver_conf = receivercfg_iface.get_active_conf(receiver_info['receiver_gus'], itip_info['context_gus'], plugin_type) if receiver_conf is None: # TODO applicative log, database tracking of queue continue # Ok, we had a valid an appropriate receiver configuration for the notification task related_profile = profile_iface.get_single(receiver_conf['profile_gus']) settings_dict = { 'admin_settings' : related_profile['admin_settings'], 'receiver_settings' : receiver_conf['receiver_settings']} plugin = PluginManager.instance_plugin(related_profile['plugin_name']) return_code = plugin.do_notify(settings_dict, u'comment', comment) if return_code: print "Notification of comment successful for user", receiver_conf['receiver_gus'] else: print "Notification of comment failed for user", receiver_conf['receiver_gus'] # remind: comment are not guarantee until Task manager is not developed comment_iface.flip_mark(comment['comment_id'], u'notified')
def delete_tip(self, tip_gus): store = self.getStore() receivertip_iface = ReceiverTip(store) receivers_map = receivertip_iface.get_receivers_by_tip(tip_gus) if not receivers_map['actor']['can_delete_submission']: raise ForbiddenOperation # sibilings_tips has the keys: 'sibilings': [$] 'requested': $ sibilings_tips = receivertip_iface.get_sibiligs_by_tip(tip_gus) # delete all the related tip for sibiltip in sibilings_tips['sibilings']: receivertip_iface.personal_delete(sibiltip['tip_gus']) # and the tip of the called receivertip_iface.personal_delete(sibilings_tips['requested']['tip_gus']) # extract the internaltip_id, we need for the next operations itip_id = sibilings_tips['requested']['internaltip_id'] # remove all the files: XXX think if delivery method need to be inquired file_iface = File(store) files_list = file_iface.get_files_by_itip(itip_id) # remove all the comments based on a specific itip_id comment_iface = Comment(store) comments_list = comment_iface.delete_comment_by_itip(itip_id) internaltip_iface = InternalTip(store) # finally, delete the internaltip internaltip_iface.tip_delete(sibilings_tips['requested']['internaltip_id']) # XXX Notify Tip removal to the receivers ? # XXX ask to the deleter a comment about the action, notifiy this comment ? self.returnCode(200) return self.prepareRetVals()
def get(self, what, *uriargs): """ Parameters: None Response: Unknown Errors: None /dump/overview GET should return up to all the tables of GLBackend """ expected = [ 'itip', 'wtip', 'rtip', 'receivers', 'comment', 'profiles', 'rcfg', 'file', 'submission', 'contexts', 'plugins', 'all', 'count' ] outputDict = {} if what == 'receivers' or what == 'all' or what == 'count': receiver_iface = Receiver() receiver_list = yield receiver_iface.get_all() if what != 'count': outputDict.update({ 'receivers_elements' : len(receiver_list), 'receivers' : receiver_list}) else: outputDict.update({ 'receivers_elements' : len(receiver_list)}) if what == 'itip' or what == 'all' or what == 'count': itip_iface = InternalTip() itip_list = yield itip_iface.get_all() if what != 'count': outputDict.update({ 'internaltips_elements' : len(itip_list), 'internaltips' : itip_list }) else: outputDict.update({ 'internaltips_elements' : len(itip_list)}) if what == 'rtip' or what == 'all' or what == 'count': rtip_iface = ReceiverTip() rtip_list = yield rtip_iface.get_all() if what != 'count': outputDict.update({ 'rtip_elements' : len(rtip_list), 'receivers_tips' : rtip_list }) else: outputDict.update({ 'rtip_elements' : len(rtip_list)}) if what == 'wtip' or what == 'all' or what == 'count': wtip_iface = WhistleblowerTip() wtip_list = yield wtip_iface.get_all() if what != 'count': outputDict.update({ 'wtip_elements' : len(wtip_list), 'whistleblower_tips' : wtip_list }) else: outputDict.update({ 'wtip_elements' : len(wtip_list)}) if what == 'comment' or what == 'all' or what == 'count': comment_iface = Comment() comment_list = yield comment_iface.get_all() if what != 'count': outputDict.update({ 'comment_elements' : len(comment_list), 'comments' : comment_list }) else: outputDict.update({ 'comment_elements' : len(comment_list)}) if what == 'profiles' or what == 'all' or what == 'count': profile_iface = PluginProfiles() profile_list = yield profile_iface.get_all() if what != 'count': outputDict.update({ 'profiles_elements' : len(profile_list), 'profiles' : profile_list }) else: outputDict.update({ 'profiles_elements' : len(profile_list)}) if what == 'plugins' or what == 'all' or what == 'count': plugin_list = yield PluginManager.get_all() if what != 'count': outputDict.update({ 'plugins_elements' : len(plugin_list), 'plugins' : plugin_list }) else: outputDict.update({ 'plugins_elements' : len(plugin_list) }) if what == 'rcfg' or what == 'all' or what == 'count': rconf_iface = ReceiverConfs() rconf_list = yield rconf_iface.get_all() if what != 'count': outputDict.update({ 'rcfg_elements' : len(rconf_list), 'settings' : rconf_list }) else: outputDict.update({ 'rcfg_elements' : len(rconf_list)}) if what == 'submission' or what == 'all' or what == 'count': submission_iface = Submission() submission_list = yield submission_iface.get_all() if what != 'count': outputDict.update({ 'submission_elements' : len(submission_list), 'submissions' : submission_list }) else: outputDict.update({ 'submission_elements' : len(submission_list)}) if what == 'file' or what == 'all' or what == 'count': file_iface = File() file_list = yield file_iface.get_all() if what != 'count': outputDict.update({ 'file_elements' : len(file_list), 'files' : file_list }) else: outputDict.update({ 'file_elements' : len(file_list)}) if what == 'contexts' or what == 'all' or what == 'count': context_iface = Context() context_list = yield context_iface.get_all() if what != 'count': outputDict.update({ 'contexts_elements' : len(context_list), 'contexts' : context_list }) else: outputDict.update({ 'contexts_elements' : len(context_list)}) if not what in expected: self.set_status(405) else: self.set_status(200) self.write(outputDict) self.finish()
def operation(self): """ Goal of this function is to check all the InternalTip and create the Tips for the receiver needing. Create the ReceiverTip only, because WhistleBlowerTip is created when submission is finalized, along with the receipt exchange. Only the Receiver marked as first tier receiver has a Tip now, the receiver marked as tier 2 (if configured in the context) had their Tip only when the escalation_threshold has reached the requested value. """ internaltip_iface = InternalTip() receivertip_iface = ReceiverTip() receiver_iface = Receiver() internal_tip_list = yield internaltip_iface.get_itips_by_maker(u'new', False) # TODO for each itip # TODO get file status if len(internal_tip_list): log.debug("TipSched: found %d new Tip" % len(internal_tip_list) ) for internaltip_desc in internal_tip_list: for receiver_gus in internaltip_desc['receivers']: receiver_desc = yield receiver_iface.get_single(receiver_gus) # check if the Receiver Tier is the first if int(receiver_desc['receiver_level']) != 1: continue receivertip_desc = yield receivertip_iface.new(internaltip_desc, receiver_desc) print "Created rTip", receivertip_desc['tip_gus'], "for", receiver_desc['name'] try: # switch the InternalTip.mark for the tier supplied yield internaltip_iface.flip_mark(internaltip_desc['internaltip_id'], internaltip_iface._marker[1]) except: # ErrorTheWorldWillEndSoon("Goodbye and thanks for all the fish") print "Internal error" raise # Escalation is not working at the moment, may be well engineered the function # before, permitting various layer of receivers. # # loops over the InternalTip and checks the escalation threshold # It may require the creation of second-step Tips escalated_itip_list = yield internaltip_iface.get_itips_by_maker(internaltip_iface._marker[1], True) if len(escalated_itip_list): log.debug("TipSched: %d Tip are escalated" % len(escalated_itip_list) ) # This event has to be notified as system Comment comment_iface = Comment() for itip in escalated_itip_list: itip_id = int(itip['internaltip_id']) yield comment_iface.add_comment(itip_id, u"Escalation threshold has been reached", u'system') # XXX missing part new yield internaltip_iface.flip_mark(itip_id, internaltip_iface._marker[2]) log.debug("TipSched: escalated %d ReceiverTip for the iTip %d" % (receivertip_created, itip_id))
def tip_creation(self): store = self.getStore() internaltip_iface = InternalTip(store) receiver_iface = Receiver(store) internal_tip_list = internaltip_iface.get_itips_by_maker(u'new', False) if len(internal_tip_list): print "TipSched: found %d new Tip" % len(internal_tip_list) for internaltip_desc in internal_tip_list: # TODO for each itip # TODO get file status, or 'continue' for receiver_gus in internaltip_desc['receivers']: try: receiver_desc = receiver_iface.get_single(receiver_gus) except ReceiverGusNotFound: # Log error, a receiver has been removed before get the Tip continue # check if the Receiver Tier is the first if int(receiver_desc['receiver_level']) != 1: continue receivertip_obj = ReceiverTip(store) receivertip_desc = receivertip_obj.new(internaltip_desc, receiver_desc) print "Created rTip", receivertip_desc['tip_gus'], "for", receiver_desc['name'], \ "in", internaltip_desc['context_gus'] internaltip_iface.flip_mark(internaltip_desc['internaltip_id'], internaltip_iface._marker[1]) # Escalation is not working at the moment, may be well engineered the function # before, permitting various layer of receivers. # # loops over the InternalTip and checks the escalation threshold # It may require the creation of second-step Tips escalated_itip_list = internaltip_iface.get_itips_by_maker(internaltip_iface._marker[1], True) if len(escalated_itip_list): print "TipSched: %d Tip are escalated" % len(escalated_itip_list) # This event has to be notified as system Comment comment_iface = Comment(store) for eitip in escalated_itip_list: eitip_id = int(eitip['internaltip_id']) comment_iface.new(eitip_id, u"Escalation threshold has been reached", u'system') for receiver_gus in eitip['receivers']: try: receiver_desc = receiver_iface.get_single(receiver_gus) except ReceiverGusNotFound: # Log error, a receiver has been removed before get the Tip continue # check if the Receiver Tier is the second if int(receiver_desc['receiver_level']) != 2: continue receivertip_obj = ReceiverTip(store) receivertip_desc = receivertip_obj.new(eitip, receiver_desc) print "Created 2nd tir rTip", receivertip_desc['tip_gus'], "for", receiver_desc['name'], \ "in", eitip['context_gus'] internaltip_iface.flip_mark(eitip_id, internaltip_iface._marker[2])
def operation(self): """ Goal of this function is to check all the: Tips Comment Folder System Event marked as 'not notified' and perform notification. Notification plugin chose if perform a communication or not, Then became marked as: 'notification ignored', or 'notified' Every notification plugin NEED have a checks to verify if notification has been correctly performed. If not (eg: wrong login/password, network errors) would be marked as: 'unable to be notified', and a retry logic is in TODO """ plugin_type = u'notification' log.debug("[D]", self.__class__, 'operation', datetime.today().ctime()) receivertip_iface = ReceiverTip() receivercfg_iface = ReceiverConfs() profile_iface = PluginProfiles() # TODO digest check missing it's required refactor the scheduler using a dedicated Storm table not_notified_tips = yield receivertip_iface.get_tips_by_notification_mark(u'not notified') for single_tip in not_notified_tips: # from a single tip, we need to extract the receiver, and then, having # context + receiver, find out which configuration setting has active receivers_map = yield receivertip_iface.get_receivers_by_tip(single_tip['tip_gus']) receiver_info = receivers_map['actor'] receiver_conf = yield receivercfg_iface.get_active_conf(receiver_info['receiver_gus'], single_tip['context_gus'], plugin_type) if receiver_conf is None: print "Receiver", receiver_info['receiver_gus'], \ "has not an active notification settings in context", single_tip['context_gus'], "for", plugin_type # TODO applicative log, database tracking of queue continue # Ok, we had a valid an appropriate receiver configuration for the notification task related_profile = yield profile_iface.get_single(receiver_conf['profile_gus']) settings_dict = { 'admin_settings' : related_profile['admin_settings'], 'receiver_settings' : receiver_conf['receiver_settings']} plugin = PluginManager.instance_plugin(related_profile['plugin_name']) updated_tip = yield receivertip_iface.update_notification_date(single_tip['tip_gus']) return_code = plugin.do_notify(settings_dict, u'tip', updated_tip) if return_code: yield receivertip_iface.flip_mark(single_tip['tip_gus'], u'notified') else: yield receivertip_iface.flip_mark(single_tip['tip_gus'], u'unable to notify') # Comment Notification here it's just an incomplete version, that never would supports # digest or retry, until Task manager queue is implemented comment_iface = Comment() internaltip_iface = InternalTip() not_notified_comments = yield comment_iface.get_comment_by_mark(marker=u'not notified') for comment in not_notified_comments: receivers_list = yield internaltip_iface.get_receivers_by_itip(comment['internaltip_id']) # needed to obtain context! itip_info = yield internaltip_iface.get_single(comment['internaltip_id']) for receiver_info in receivers_list: receiver_conf = yield receivercfg_iface.get_active_conf(receiver_info['receiver_gus'], itip_info['context_gus'], plugin_type) if receiver_conf is None: # TODO applicative log, database tracking of queue continue # Ok, we had a valid an appropriate receiver configuration for the notification task related_profile = yield profile_iface.get_single(receiver_conf['profile_gus']) settings_dict = { 'admin_settings' : related_profile['admin_settings'], 'receiver_settings' : receiver_conf['receiver_settings']} plugin = PluginManager.instance_plugin(related_profile['plugin_name']) return_code = plugin.do_notify(settings_dict, u'comment', comment) if return_code: print "Notification of comment successful for user", receiver_conf['receiver_gus'] else: print "Notification of comment failed for user", receiver_conf['receiver_gus'] # remind: comment are not guarantee until Task manager is not developed yield comment_iface.flip_mark(comment['comment_id'], u'notified')