def full_receiver_align(self, context_gus, un_receiver_selected): """ Called by Context handlers (PUT|POST), roll in all the receiver and delete|add|skip with the presence of context_gus """ store = self.getStore() receiver_selected = [] for r in un_receiver_selected: receiver_selected.append(str(r)) presents_receiver = store.find(Receiver) debug_counter = 0 for r in presents_receiver: # if is not present in receiver.contexts and is requested: add if not context_gus in r.contexts: if r.receiver_gus in receiver_selected: debug_counter += 1 r.contexts.append(str(context_gus)) r.update_date = gltime.utcTimeNow() # if is present in context.receiver and is not selected: remove if context_gus in r.contexts: if not r.receiver_gus in receiver_selected: debug_counter += 1 r.contexts.remove(str(context_gus)) r.update_date = gltime.utcTimeNow() log.debug(" **** full_receiver_align in all receivers after %s has been set with %s: %d mods" % ( context_gus, str(receiver_selected), debug_counter ) )
def context_align(self, context_gus, receiver_selected): """ Called by Context handler, (PUT|POST), just take the context and update the associated receivers, checks the receiver existence, and return an exception if do not exist. """ from globaleaks.models.receiver import Receiver from globaleaks.rest.errors import ReceiverGusNotFound try: requested_c = self.store.find(Context, Context.context_gus == unicode(context_gus)).one() except NotOneError: raise ContextGusNotFound if requested_c is None: raise ContextGusNotFound requested_c.receivers = [] for r in receiver_selected: try: selected = self.store.find(Receiver, Receiver.receiver_gus == unicode(r)).one() except NotOneError: raise ReceiverGusNotFound if selected is None: raise ReceiverGusNotFound requested_c.receivers.append(str(r)) requested_c.update_date = gltime.utcTimeNow() log.debug(" ++++ context_align in receiver %s with receivers %s" % (context_gus, str(receiver_selected)))
def align_context_delete(self, receivers_gus_list, removed_context_gus): """ @param receivers_gus_list: a list of receiver_gus target of the ops @param context_gus: context being removed @return: None """ store = self.getStore() aligned_counter = 0 for receiver_gus in receivers_gus_list: try: requested_r = store.find(Receiver, Receiver.receiver_gus == unicode(receiver_gus)).one() except NotOneError: raise ReceiverGusNotFound if requested_r is None: raise ReceiverGusNotFound if str(removed_context_gus) in requested_r.contexts: requested_r.contexts.remove(str(removed_context_gus)) requested_r.update_date = gltime.utcTimeNow() aligned_counter += 1 else: raise AssertionError # Just for debug # TODO XXX Applicative log about aligned_counter return aligned_counter
def receiver_align(self, receiver_gus, context_selected): """ Called by Receiver handler, (PUT|POST), just take the receiver and update the associated contexts """ from globaleaks.models.context import Context from globaleaks.rest.errors import ContextGusNotFound store = self.getStore() try: requested_r = store.find(Receiver, Receiver.receiver_gus == unicode(receiver_gus)).one() except NotOneError: raise ReceiverGusNotFound if requested_r is None: raise ReceiverGusNotFound requested_r.contexts = [] for c in context_selected: try: selected = store.find(Context, Context.context_gus == unicode(c)).one() except NotOneError: raise ContextGusNotFound if selected is None: raise ContextGusNotFound requested_r.contexts.append(str(c)) requested_r.update_date = gltime.utcTimeNow() log.debug(" ++++ receiver_align in receiver %s with contexts %s" % ( receiver_gus, str(context_selected) ) )
def new(self, itip_id, comment, source, author_gus=None): """ @param itip_id: InternalTip.id of reference, need to be addressed @param comment: the unicode text expected to be recorded @param source: the source kind of the comment (receiver, wb, system) @param name: the Comment wb_r name to be show and recorded, can be absent if source is enough @return: None """ if not source in [ u'receiver', u'whistleblower', u'system' ]: raise NotImplemented try: itip = self.store.find(InternalTip, InternalTip.id == int(itip_id)).one() except NotOneError: # This can't actually happen raise Exception if itip is None: # This can't actually happen raise Exception # this approach is a little different from the other classes in ExternalTip # they use a new Object() in the caller method, and then Object.initialize # to fill with data. try: self.creation_time = gltime.utcTimeNow() self.source = source self.content = comment self.author_gus = author_gus self.internaltip = itip self.internaltip_id = int(itip_id) except TypeError, e: raise InvalidInputFormat("Unable to create comment: (wrong %s)" % e )
def add_comment(self, itip_id, comment, source, author_gus=None): """ @param itip_id: InternalTip.id of reference, need to be addressed @param comment: the unicode text expected to be recorded @param source: the source kind of the comment (receiver, wb, system) @param name: the Comment author name to be show and recorded, can be absent if source is enough @return: None """ log.debug("[D] %s %s " % (__file__, __name__), "InternalTip class", "add_comment", "itip_id", itip_id, "source", source, "author_gus", author_gus) if not source in [ u'receiver', u'whistleblower', u'system' ]: raise Exception("Invalid developer brain status", source) store = self.getStore('add_comment') # this approach is a little different from the other classes in ExternalTip # they use a new Object() in the caller method, and then Object.initialize # to fill with data. # XXX this would be refactored when TaskQueue would be engineered newcomment = Comment() newcomment.creation_time = gltime.utcTimeNow() newcomment.source = source newcomment.content = comment newcomment.author_gus = author_gus newcomment.notification_mark = u'not notified' newcomment.internaltip_id = itip_id store.add(newcomment) retVal = newcomment._description_dict() store.commit() store.close() return retVal
def get_single(self, tip_gus): """ This is the method called when a receiver is accessing to Tip. It return InternalTip details and update the last_access date. """ store = self.getStore() try: requested_t = store.find(ReceiverTip, ReceiverTip.tip_gus == tip_gus).one() except NotOneError: raise TipGusNotFound if not requested_t: raise TipGusNotFound # Access counter is incremented before the data extraction, # last_access is incremented after (because the receiver want know # if someone has accesses in his place) requested_t.access_counter += 1 # The single tip dump is composed by InternalTip + ReceiverTip details tip_details = requested_t.internaltip._description_dict() tip_details.update(requested_t._description_dict()) requested_t.last_access = gltime.utcTimeNow() # every time the name 'id' is misused, a kitten die :( tip_details.update({ 'id' : requested_t.tip_gus }) # XXX verifiy why need to be echoed back return dict(tip_details)
def update_notification_date(self, tip_gus): store = self.getStore() requested_t = store.find(ReceiverTip, ReceiverTip.tip_gus == tip_gus).one() requested_t.notification_date = gltime.utcTimeNow() return requested_t._description_dict()
def new(self, context_dict): """ @param context_dict: a dictionary containing the expected field of a context, is called and define as contextDescriptionDict @return: context_gus, the universally unique identifier of the context """ self.context_gus = idops.random_context_gus() self.creation_date = gltime.utcTimeNow() self.update_date = gltime.utcTimeNow() self.last_activity = gltime.utcTimeNow() self.receivers = [] try: self._import_dict(context_dict) except KeyError, e: raise InvalidInputFormat("Context Import failed (missing %s)" % e)
def add_comment(self, itip_id, comment, source, author_gus=None): """ @param itip_id: InternalTip.id of reference, need to be addressed @param comment: the unicode text expected to be recorded @param source: the source kind of the comment (receiver, wb, system) @param name: the Comment wb_r name to be show and recorded, can be absent if source is enough @return: None """ if not source in [ u'receiver', u'whistleblower', u'system' ]: raise NotImplemented store = self.getStore() try: itip = store.find(InternalTip, InternalTip.id == int(itip_id)).one() except NotOneError: # This can't actually happen raise Exception if itip is None: # This can't actually happen raise Exception # this approach is a little different from the other classes in ExternalTip # they use a new Object() in the caller method, and then Object.initialize # to fill with data. newcomment = Comment() newcomment.creation_time = gltime.utcTimeNow() newcomment.source = source newcomment.content = comment newcomment.author_gus = author_gus newcomment.internaltip = itip newcomment.internaltip_id = int(itip_id) # TODO |need to be reeingineered, only with the queue task # TODO |manager can be digest and track the single notification. # TODO | newcomment.notification_mark = u'not notified' store.add(newcomment) return newcomment._description_dict()
def new(self, profile_dict): """ @profile_dict need to contain the keys: 'plugin_type', 'plugin_name', 'admin_settings', """ try: # below, before _import_dict, are checked profile_type, and plugin_name # both of them can't be updated, are chosen at creation time, if not unicode(profile_dict['plugin_type']) in valid_plugin_types: raise InvalidInputFormat("plugin_type not recognized") if not PluginManager.plugin_exists(profile_dict['plugin_name']): raise InvalidInputFormat("plugin_name not recognized between available plugins") self._import_dict(profile_dict) self.profile_gus = idops.random_plugin_gus() self.creation_time = gltime.utcTimeNow() # the name can be updated, but need to be checked to be UNIQUE if self.store.find(PluginProfiles, PluginProfiles.profile_name == self.profile_name).count() >= 1: raise ProfileNameConflict plugin_info = PluginManager.get_plugin(profile_dict['plugin_name']) # initialize the three plugin_* fields, inherit by Plugin code self.plugin_name = unicode(plugin_info['plugin_name']) self.plugin_type = unicode(plugin_info['plugin_type']) self.plugin_description = unicode(plugin_info['plugin_description']) self.admin_fields = dict(plugin_info['admin_fields']) # Admin-only plugins are listed here, and they have not receiver_fields if self.plugin_type in [ u'fileprocess' ]: self.receiver_fields = [] else: self.receiver_fields = plugin_info['receiver_fields'] except KeyError, e: raise InvalidInputFormat("Profile creation failed (missing %s)" % e)
def self_update(self, receiver_gus, receiver_dict): """ This is the method called by a receiver for change/set their preference """ try: requested_r = self.store.find(Receiver, Receiver.receiver_gus == unicode(receiver_gus)).one() except NotOneError: raise ReceiverGusNotFound if requested_r is None: raise ReceiverGusNotFound try: requested_r.name = receiver_dict['name'] requested_r.description = receiver_dict['description'] requested_r.tags = receiver_dict['tags'] requested_r.know_languages = receiver_dict['languages'] requested_r.update_date = gltime.utcTimeNow() except KeyError, e: raise InvalidInputFormat("self update failed (missing %s)" % e)
def pertinence_vote(self, tip_gus, vote): """ check if the receiver has already voted. if YES: raise an exception, if NOT mark the expressed vote and call the internaltip to register the fact. @vote would be True or False, default is "I'm not expressed". return the actual vote expressed by all the receivers, to the same iTip. """ store = self.getStore() try: requested_t = store.find(ReceiverTip, ReceiverTip.tip_gus == tip_gus).one() except NotOneError: raise TipGusNotFound if not requested_t: raise TipGusNotFound if requested_t.expressed_pertinence: raise TipPertinenceExpressed # expressed_pertinence has these meanings: # 0 = unassigned # 1 = negative vote # 2 = positive vote requested_t.expressed_pertinence = 2 if vote else 1 requested_t.last_access = gltime.utcTimeNow() expressed_t = store.find(ReceiverTip, (ReceiverTip.internaltip_id == requested_t.internaltip_id, ReceiverTip.expressed_pertinence != 0)) vote_sum = 0 for et in expressed_t: if et.expressed_pertinence == 1: vote_sum -= 1 else: vote_sum += 1 itip_id_copy = requested_t.internaltip_id return (itip_id_copy, vote_sum)
def get_single(self, receipt): try: requested_t = self.store.find(WhistleblowerTip, WhistleblowerTip.receipt == unicode(receipt)).one() except NotOneError: raise TipReceiptNotFound if not requested_t: raise TipReceiptNotFound requested_t.access_counter += 1 # The single tip dump is composed by InternalTip + WBTip details tip_details = requested_t.internaltip._description_dict() tip_details.update(requested_t._description_dict()) requested_t.last_access = gltime.utcTimeNow() # every time the name 'id' is misused, a kitten die :( tip_details.update({ 'id' : requested_t.receipt }) # XXX verifiy why need to be echoed back return dict(tip_details)
def newprofile(self, plugtype, plugname, profname, plugreq, desc=None, settings=None): """ @param plugtype: notification|delivery|inputfilter, already checked by the caller @param plugname: plugin name, already checked the existence using GLPluginManager @param profname: a profile name, used to recognize a unique profile in a list @param plugreq: the plugins required fields for admin and receiver. @param desc: a descriptive string that would be presented to the receiver @param settings: the admin side configuration fields for the plugin. @return: """ log.debug("[D] %s %s " % (__file__, __name__), "Class PluginConf", "newprofile", ptype, pname) store = self.getStore('newprofile') if store.find(PluginProfiles, PluginProfiles.profile_name == profname).count() >= 1: store.close() raise ProfileNameConflict newone = PluginProfiles() newone.profile_gus = idops.random_plugin_gus() newone.profile_name = profname newone.creation_time = gltime.utcTimeNow() newone.plugin_type = plugtype newone.plugin_name = plugname newone.required_fields = plugreq if settings: newone.admin_fields = settings if desc: newone.external_description = desc store.add(newone) store.commit() store.close()
newone.admin_fields = dict(plugin_info['admin_fields']) # Admin-only plugins are listed here, and they have not receiver_fields if newone.plugin_type in [ u'fileprocess' ]: newone.receiver_fields = [] else: newone.receiver_fields = plugin_info['receiver_fields'] except KeyError, e: raise InvalidInputFormat("Profile creation failed (missing %s)" % e) except TypeError, e: raise InvalidInputFormat("Profile creation failed (wrong %s)" % e) newone.profile_gus = idops.random_plugin_gus() newone.creation_time = gltime.utcTimeNow() store.add(newone) # build return value for the handler return newone._description_dict() @transact def update(self, profile_gus, profile_dict): store = self.getStore() try: looked_p = store.find(PluginProfiles, PluginProfiles.profile_gus == profile_gus).one() except NotOneError:
One that want review the whistles blowed documents. It's a sort of transparency baptism: here you get your GlobaLeaks Unique String, sir! """ store = self.getStore() try: self._import_dict(receiver_dict) except KeyError, e: raise InvalidInputFormat("initialization failed (missing %s)" % e) except TypeError, e: raise InvalidInputFormat("initialization failed (wrong %s)" % e) self.receiver_gus = idops.random_receiver_gus() self.creation_date = gltime.utcTimeNow() self.update_date = gltime.utcTimeNow() store.add(self) return self._description_dict() @transact def update(self, receiver_gus, receiver_dict): """ This is the method called by the admin for change receiver preferences. may edit more elements than the next method (self_update) the dict need to be already validated """
raise ContextGusNotFound if requested_c is None: raise ContextGusNotFound try: requested_c._import_dict(context_dict) except KeyError, e: raise InvalidInputFormat("Context update failed (missing %s)" % e) except TypeError, e: raise InvalidInputFormat("Context update failed (wrong %s)" % e) if requested_c.selectable_receiver and requested_c.escalation_threshold: raise InvalidInputFormat("selectable_receiver and escalation_threshold are mutually exclusive") requested_c.update_date = gltime.utcTimeNow() log.msg( "Updated context %s in %s, created in %s" % (requested_c.name, requested_c.update_date, requested_c.creation_date) ) return requested_c._description_dict() def delete_context(self, context_gus): """ @param context_gus: the universal unique identifier of the context @return: None if is deleted correctly, or raise an exception if something is wrong. """ # Handler Guarantee these operations *before*:
raise InvalidInputFormat("Receiver and Context do not fit") # TODO check in a strongest way if newcfg.receiver_setting fit with newcfg.profile.receiver_fields key_expectation_fail = None for expected_k in self.profile.receiver_fields.iterkeys(): if not self.receiver_settings.has_key(expected_k): key_expectation_fail = expected_k break if key_expectation_fail: raise InvalidInputFormat("Expected field %s" % key_expectation_fail) # End of temporary check: why I'm not put the raise exception inside # of the for+if ? because otherwise Storm results locked in the future operations :( self.plugin_type = self.profile.plugin_type self.creation_time = gltime.utcTimeNow() self.last_update = gltime.utcTimeNow() self.store.add(self) return self._description_dict() def update(self, conf_id, receiver_authorized, received_dict): try: looked_cfg = self.store.find(ReceiverConfs, ReceiverConfs.id == int(conf_id)).one() except NotOneError: raise ReceiverConfNotFound if not looked_cfg: raise ReceiverConfNotFound
except KeyError, e: raise InvalidInputFormat("File import failed (missing %s)" % e) except TypeError, e: raise InvalidInputFormat("File import failed (wrong %s)" % e) try: self.context = store.find(Context, Context.context_gus == self.context_gus).one() except NotOneError: # This can never happen raise Exception("Internal Impossible Error") self.mark = self._marker[0] # not processed self.completed = False self.uploaded_date = gltime.utcTimeNow() self.file_gus = unicode(idops.random_file_gus()) # When the file is 'not processed', this value stay to 0 self.internaltip_id = 0 store.add(self) return self._description_dict() # update in short modify only filename and description, at the moment API is missing # Remind open ticket with GLClient @transact def update(self, file_gus, received_dict):