def test_emeritus(self): op = ops.ChangeStatus(audit_author=self.persons.fd, audit_notes="test emeritus", audit_time=self.audit_time, person=self.persons.dd_u, status=const.STATUS_EMERITUS_DD, rt_ticket=111) op.execute() person = self.persons.dd_u person.refresh_from_db() self.assertEqual(person.status, const.STATUS_EMERITUS_DD) self.assertEqual(person.status_changed, self.audit_time) from process.models import Process process = Process.objects.get(person=person) self.assertEqual(process.applying_for, const.STATUS_EMERITUS_DD) self.assertEqual(process.frozen_by, self.persons.fd) self.assertEqual(process.frozen_time, self.audit_time) self.assertEqual(process.approved_by, self.persons.fd) self.assertEqual(process.approved_time, self.audit_time) self.assertEqual(process.rt_ticket, 111) self.assertEqual(process.closed_by, self.persons.fd) self.assertEqual(process.closed_time, self.audit_time) self.assertFalse(process.requirements.exists()) log = process.log.get() self.assertEqual(log.changed_by, self.persons.fd) self.assertEqual(log.logtext, "test emeritus") self.assertFalse(log.is_public) self.assertEqual(log.action, "proc_approve") self.assertEqual(log.logdate, self.audit_time)
def ops(self): # Check for existing records in the database person = self._get_person() # If it is all new, create and we are done if person is None: if self.rt: audit_notes = "Created DM entry, RT #{}".format(self.rt) else: audit_notes = "Created DM entry, RT unknown" yield bops.CreatePerson( audit_author=self.author, audit_notes=audit_notes, audit_time=self.log_entry.dt, # Dummy username used to avoid unique entry conflicts username="******".format(self.fpr), cn=self.cn, mn=self.mn, sn=self.sn, email=self.email, status=const.STATUS_DM, fpr=self.fpr, ) return if person.status in (const.STATUS_DM, const.STATUS_DM_GA): # Already a DM, nothing to do #log.info("%s: %s is already a DM: skipping duplicate entry", self.logtag, self.person_link(person)) return if person.status in (const.STATUS_DD_U, const.STATUS_DD_NU, const.STATUS_EMERITUS_DD, const.STATUS_REMOVED_DD): raise OperationError( self.log_entry, "commit is for a new DM, but it corresponds to {} who has status {}" .format(person.lookup_key, person.status)) if person.status == const.STATUS_DC_GA: status = const.STATUS_DM_GA else: status = const.STATUS_DM if self.rt: audit_notes = "Set status to {}, RT #{}".format( const.ALL_STATUS_DESCS[status], self.rt) else: audit_notes = "Set status to {}, RT unknown".format( const.ALL_STATUS_DESCS[status]) yield bops.ChangeStatus(person=person, status=status, audit_time=self.log_entry.dt, audit_author=self.author, audit_notes=audit_notes)
def test_op(self): def check_contents(o): self.assertEqual(o.audit_author, self.persons.fd) self.assertEqual(o.audit_notes, "test message") self.assertEqual(o.audit_time, self.audit_time) self.assertEqual(o.person, self.persons.dc) self.assertEqual(o.status, const.STATUS_DD_NU) self.assertEqual(o.rt_ticket, 123) o = ops.ChangeStatus(audit_author=self.persons.fd, audit_notes="test message", audit_time=self.audit_time, person=self.persons.dc, status=const.STATUS_DD_NU, rt_ticket=123) self.check_op(o, check_contents)
def ops(self): persons = {} if self.uid: try: persons["uid"] = bmodels.Person.objects.get(uid=self.uid) except bmodels.Person.DoesNotExist: pass try: persons["fpr"] = bmodels.Person.objects.get(fprs__fpr=self.fpr) except bmodels.Person.DoesNotExist: pass person = self._get_consistent_person(persons) if not person: raise OperationError( self.log_entry, "commit references a person that is not known to the site") if person.status in (const.STATUS_DM, const.STATUS_DM_GA): if self.rt: audit_notes = "Moved to contributor status, RT #{}".format( self.rt) else: audit_notes = "Moved to contributor status, RT unknown" if person.status == const.STATUS_DM: new_status = const.STATUS_DC else: new_status = const.STATUS_DC_GA yield bops.ChangeStatus(person=person, status=new_status, audit_time=self.log_entry.dt, audit_author=self.author, audit_notes=audit_notes) return return
def handle(self, **opts): FORMAT = "%(asctime)-15s %(levelname)s %(message)s" if opts["quiet"]: logging.basicConfig(level=logging.WARNING, stream=sys.stderr, format=FORMAT) else: logging.basicConfig(level=logging.INFO, stream=sys.stderr, format=FORMAT) status = opts["status"] author = bmodels.Person.lookup(opts["author"]) if author is None: raise RuntimeError("Author {} not found".format(opts["author"])) person = bmodels.Person.lookup(opts["person"]) if person is None: raise RuntimeError("Person {} not found".format(opts["person"])) message = opts["message"] if not message: message = "Set status to {}".format(status) if opts["rt"]: message += " RT#{}".format(opts["rt"]) if opts["date"]: date = dateutil.parser.parse(opts["date"]).replace(tzinfo=utc) else: date = now() op = bops.ChangeStatus( audit_author=author, audit_notes=message, audit_time=date, person=person, status=status, rt=opts["rt"], ) print(op.to_json(indent=1)) if opts["execute"]: with transaction.atomic(): op.execute()
def ops(self): persons = {} if self.uid: try: persons["uid"] = bmodels.Person.objects.get(uid=self.uid) except bmodels.Person.DoesNotExist: pass try: persons["fpr"] = bmodels.Person.objects.get(fprs__fpr=self.fpr) except bmodels.Person.DoesNotExist: pass person = self._get_consistent_person(persons) if not person: raise OperationError( self.log_entry, "commit references a person that is not known to the site") if person.status in (const.STATUS_DD_U, const.STATUS_DD_NU): if self.rt: audit_notes = "Moved to emeritus keyring, RT #{}".format( self.rt) else: audit_notes = "Moved to emeritus keyring, RT unknown" yield bops.ChangeStatus(person=person, status=const.STATUS_EMERITUS_DD, audit_time=self.log_entry.dt, audit_author=self.author, audit_notes=audit_notes) #log.info("%s: %s: %s", self.logtag, self.person_link(person), audit_notes) return if person.status == const.STATUS_EMERITUS_DD: # Already moved to DD #log.info("%s: %s is already emeritus: skipping key removal", self.logtag, self.person_link(person)) return
def run_main(self, stage): for entry in dmodels.list_people(): # Skip DDs if entry.is_dd and entry.single("keyFingerPrint") is not None: continue fpr = entry.single("keyFingerPrint") # Skip people without fingerprints if fpr is None: continue email = entry.single("emailForward") # Skip entries without emails (happens when running outside of the Debian network) if email is None: continue # Find the corresponding person in our database person = bmodels.Person.objects.get_from_other_db( "LDAP", uid=entry.uid, fpr=fpr, email=email, format_person=self.hk.link, ) if not person: # New DC_GA audit_notes = "created new guest account entry from LDAP" person = bmodels.Person.objects.create_user( cn=entry.single("cn"), mn=entry.single("mn") or "", sn=entry.single("sn") or "", email=email, email_ldap=email, uid=entry.uid, fpr=fpr, status=const.STATUS_DC_GA, username="******".format(entry.uid), audit_author=self.hk.housekeeper.user, audit_notes=audit_notes, ) log.warn("%s: %s %s", self.IDENTIFIER, self.hk.link(person), audit_notes) else: # Validate fields if person.uid is not None and person.uid != entry.uid: log.warn( "%s: LDAP has uid %s for person %s, but uid is %s in our database", self.IDENTIFIER, entry.uid, self.hk.link(person), person.uid) continue if person.fpr is not None and person.fpr != fpr: log.warn( "%s: LDAP has fingerprint %s for person %s, but fingerprint is %s in our database", self.IDENTIFIER, fpr, self.hk.link(person), person.fpr) continue audit_notes = ["entry found in LDAP"] # Ignore differences in email forward: they are caught by # CheckLDAPConsistency if person.status in (const.STATUS_DC_GA, const.STATUS_DM_GA): # We already know about it: nothing to do pass elif person.status in (const.STATUS_DC, const.STATUS_DM): if person.status == const.STATUS_DM: # DM that becomes DM_GA (acquires uid) new_status = const.STATUS_DM_GA else: # DC that becomes DC_GA (acquires uid) new_status = const.STATUS_DC_GA audit_notes = "entry found in LDAP, adding 'guest account' status" try: process = pmodels.Process.objects.get( person=person, closed_by__isnull=True, applying_for=new_status) except pmodels.Process.DoesNotExist: process = None if process is None: op = bops.ChangeStatus( audit_author=self.hk.housekeeper.user, audit_notes=audit_notes, person=person, status=new_status) op.execute() else: op = pops.ProcessClose( audit_author=self.hk.housekeeper.user, audit_notes=audit_notes, process=process, ) op.execute() log.info("%s: %s %s", self.IDENTIFIER, self.hk.link(person), audit_notes) else: # New uid on a status that is not supposed to have one: # just warn about it log.warn( "%s: LDAP has new uid %s for person %s, which already has status %s in our database", self.IDENTIFIER, entry.uid, self.hk.link(person), const.ALL_STATUS_DESCS[person.status])