def stream_delegates(request, stream_name): stream = get_object_or_404(Stream, name=stream_name) if not is_chair_of_stream(request.user, stream): return HttpResponseForbidden('You have no permission to access this view') chairs = stream.get_chairs() form = StreamDelegatesForm(stream=stream) if request.method == 'POST': if request.POST.get('delete', False): pk_list = request.POST.getlist('remove_delegate') if settings.USE_DB_REDESIGN_PROXY_CLASSES: stream_group = Group.objects.get(acronym=stream.slug) save_group_in_history(stream_group) Role.objects.filter(person__in=pk_list, group=stream_group, name="delegate").delete() else: StreamDelegate.objects.filter(stream=stream, person__pk__in=pk_list).delete() else: form = StreamDelegatesForm(request.POST, stream=stream) if form.is_valid(): form.save() form = StreamDelegatesForm(stream=stream) delegates = stream.get_delegates() return render_to_response('ietfworkflows/stream_delegates.html', {'stream': stream, 'chairs': chairs, 'delegates': delegates, 'form': form, }, context_instance=RequestContext(request))
def create_delegate(self, person): if settings.USE_DB_REDESIGN_PROXY_CLASSES: created = False e = Email.objects.get(address=self.cleaned_data.get('email')) if not Role.objects.filter( name="delegate", group=self.wg, person=person, email=e): created = True save_group_in_history(Group.objects.get(pk=self.wg.pk)) delegate, _ = Role.objects.get_or_create( name=RoleName.objects.get(slug="delegate"), group=self.wg, person=e.person, email=e) else: (delegate, created) = WGDelegate.objects.get_or_create(wg=self.wg, person=person) if not created: self.set_message( 'error', 'The email belongs to a person who is already a delegate') else: self.next_form = AddDelegateForm(wg=self.wg, user=self.user) self.next_form.set_message('success', 'A new delegate has been added')
def stream_delegates(request, stream_name): stream = get_object_or_404(Stream, name=stream_name) if not is_chair_of_stream(request.user, stream): return HttpResponseForbidden( 'You have no permission to access this view') chairs = stream.get_chairs() form = StreamDelegatesForm(stream=stream) if request.method == 'POST': if request.POST.get('delete', False): pk_list = request.POST.getlist('remove_delegate') if settings.USE_DB_REDESIGN_PROXY_CLASSES: stream_group = Group.objects.get(acronym=stream.slug) save_group_in_history(stream_group) Role.objects.filter(person__in=pk_list, group=stream_group, name="delegate").delete() else: StreamDelegate.objects.filter(stream=stream, person__pk__in=pk_list).delete() else: form = StreamDelegatesForm(request.POST, stream=stream) if form.is_valid(): form.save() form = StreamDelegatesForm(stream=stream) delegates = stream.get_delegates() return render_to_response('ietfworkflows/stream_delegates.html', { 'stream': stream, 'chairs': chairs, 'delegates': delegates, 'form': form, }, context_instance=RequestContext(request))
def modify(request, name): """ Handle state changes of Area Directors (enable voting, retire) # Legacy -------------------------- Enable Voting actions - user_level = 1 - create TelechatUser object Per requirements, the Retire button shall perform the following DB updates - update iesg_login row, user_level = 2 (per Matt Feb 7, 2011) - remove telechat_user row (to revoke voting rights) - update IETFWG(groups) set area_director = TBD - remove area_director row # New ------------------------------ Enable Voting: change Role from 'pre-ad' to 'ad' Retire: save in history, delete role record, set group assn to TBD **Templates:** * none Redirects to view page on success. """ area = get_object_or_404(Group, type='area', acronym=name) # should only get here with POST method if request.method == 'POST': # setup common request variables tag = request.POST.get('tag', '') person = Person.objects.get(id=tag) # save group save_group_in_history(area) # handle retire request if request.POST.get('submit', '') == "Retire": role = Role.objects.get(group=area,name__in=('ad','pre-ad'),person=person) role.delete() # update groups that have this AD as primary AD for group in Group.objects.filter(ad=person,type='wg',state__in=('active','bof')): group.ad = None group.save() messages.success(request, 'The Area Director has been retired successfully!') # handle voting request if request.POST.get('submit', '') == "Enable Voting": role = Role.objects.get(group=area,name__slug='pre-ad',person=person) role.name_id = 'ad' role.save() messages.success(request, 'Voting rights have been granted successfully!') url = reverse('areas_view', kwargs={'name':name}) return HttpResponseRedirect(url)
def save(self): if settings.USE_DB_REDESIGN_PROXY_CLASSES: stream_group = Group.objects.get(acronym=self.stream.slug) save_group_in_history(stream_group) Role.objects.get_or_create(person=self.person, group=stream_group, name=RoleName.objects.get(slug="delegate"), email=Email.objects.get(address=self.cleaned_data.get('email'))) return StreamDelegate.objects.get_or_create( person=self.person, stream=self.stream)
def main(request): ''' Main view for generic Roles App ''' groups = Group.objects.filter(type__in=('sdo', 'ietf')).order_by('acronym') choices = build_choices(groups) choices.insert(0, ('', '------------')) group_form = GroupSelectForm(choices=choices) # prime form with random sdo group so all roles are available group = Group.objects.filter(type='sdo')[0] if request.method == 'POST': role_form = RoleForm(request.POST, group=group) if role_form.is_valid(): name = role_form.cleaned_data['name'] person = role_form.cleaned_data['person'] email = role_form.cleaned_data['email'] acronym = role_form.cleaned_data['group_acronym'] group = Group.objects.get(acronym=acronym) # save group save_group_in_history(group) Role.objects.create(name=name, person=person, email=email, group=group) messages.success(request, 'New %s added successfully!' % name) url = reverse( 'ietf.secr.roles.views.main') + '?group=%s' % group.acronym return HttpResponseRedirect(url) else: role_form = RoleForm(initial={'name': 'chair'}, group=group) # accept get argument to select group if we're returning after a change if 'group' in request.GET: group_form = GroupSelectForm( choices=choices, initial={'group': request.GET['group']}) return render( request, 'roles/main.html', { 'group_form': group_form, 'role_form': role_form }, )
def save(self): if settings.USE_DB_REDESIGN_PROXY_CLASSES: stream_group = Group.objects.get(acronym=self.stream.slug) save_group_in_history(stream_group) Role.objects.get_or_create( person=self.person, group=stream_group, name=RoleName.objects.get(slug="delegate"), email=Email.objects.get( address=self.cleaned_data.get('email'))) return StreamDelegate.objects.get_or_create(person=self.person, stream=self.stream)
def people(request, acronym): """ Edit Group Roles (Chairs, Secretary, etc) **Templates:** * ``groups/people.html`` **Template Variables:** * form, group """ group = get_object_or_404(Group, acronym=acronym) if request.method == 'POST': # we need to pass group for form validation form = RoleForm(request.POST, group=group) if form.is_valid(): name = form.cleaned_data['name'] person = form.cleaned_data['person'] email = form.cleaned_data['email'] # save group save_group_in_history(group) Role.objects.create(name=name, person=person, email=email, group=group) messages.success(request, 'New %s added successfully!' % name) return redirect('ietf.secr.groups.views.people', acronym=group.acronym) else: form = RoleForm(initial={ 'name': 'chair', 'group_acronym': group.acronym }, group=group) return render( request, 'groups/people.html', { 'form': form, 'group': group }, )
def people(request, name): """ Edit People associated with Areas, Area Directors. # Legacy ------------------ When a new Director is first added they get a user_level of 4, read-only. Then, when Director is made active (Enable Voting) user_level = 1. # New --------------------- First Director's are assigned the Role 'pre-ad' Incoming Area director Then they get 'ad' role **Templates:** * ``areas/people.html`` **Template Variables:** * directors, area """ area = get_object_or_404(Group, type='area', acronym=name) if request.method == 'POST': if request.POST.get('submit', '') == "Add": form = AreaDirectorForm(request.POST) if form.is_valid(): email = form.cleaned_data['email'] person = form.cleaned_data['ad_name'] # save group save_group_in_history(area) # create role Role.objects.create(name_id='pre-ad',group=area,email=email,person=person) messages.success(request, 'New Area Director added successfully!') url = reverse('areas_view', kwargs={'name':name}) return HttpResponseRedirect(url) else: form = AreaDirectorForm() directors = area.role_set.filter(name__slug__in=('ad','pre-ad')) return render_to_response('areas/people.html', { 'area': area, 'form': form, 'directors': directors}, RequestContext(request, {}), )
def create_delegate(self, person): if settings.USE_DB_REDESIGN_PROXY_CLASSES: created = False e = Email.objects.get(address=self.cleaned_data.get('email')) if not Role.objects.filter(name="delegate", group=self.wg, person=person, email=e): created = True save_group_in_history(Group.objects.get(pk=self.wg.pk)) delegate, _ = Role.objects.get_or_create( name=RoleName.objects.get(slug="delegate"), group=self.wg, person=e.person, email=e) else: (delegate, created) = WGDelegate.objects.get_or_create(wg=self.wg, person=person) if not created: self.set_message('error', 'The email belongs to a person who is already a delegate') else: self.next_form = AddDelegateForm(wg=self.wg, user=self.user) self.next_form.set_message('success', 'A new delegate has been added')
def main(request): ''' Main view for generic Roles App ''' groups = Group.objects.filter(type__in=('sdo','ietf')).order_by('acronym') choices=build_choices(groups) choices.insert(0,('','------------')) group_form = GroupSelectForm(choices=choices) # prime form with random sdo group so all roles are available group = Group.objects.filter(type='sdo')[0] if request.method == 'POST': role_form = RoleForm(request.POST,group=group) if role_form.is_valid(): name = role_form.cleaned_data['name'] person = role_form.cleaned_data['person'] email = role_form.cleaned_data['email'] acronym = role_form.cleaned_data['group_acronym'] group = Group.objects.get(acronym=acronym) # save group save_group_in_history(group) Role.objects.create(name=name, person=person, email=email, group=group) messages.success(request, 'New %s added successfully!' % name) url = reverse('roles') + '?group=%s' % group.acronym return HttpResponseRedirect(url) else: role_form = RoleForm(initial={'name':'chair'},group=group) # accept get argument to select group if we're returning after a change if 'group' in request.GET: group_form = GroupSelectForm(choices=choices,initial={'group':request.GET['group']}) return render_to_response('roles/main.html', { 'group_form': group_form, 'role_form': role_form}, RequestContext(request, {}), )
def change_group_state_after_charter_approval(group, by): new_state = GroupStateName.objects.get(slug="active") if group.state == new_state: return None save_group_in_history(group) group.state = new_state group.time = datetime.datetime.now() group.save() # create an event for the group state change, too e = ChangeStateGroupEvent(group=group, type="changed_state") e.time = group.time e.by = by e.state_id = "active" e.desc = "Charter approved, group active" e.save() return e
def people(request, acronym): """ Edit Group Roles (Chairs, Secretary, etc) **Templates:** * ``groups/people.html`` **Template Variables:** * form, group """ group = get_object_or_404(Group, acronym=acronym) if request.method == 'POST': # we need to pass group for form validation form = RoleForm(request.POST,group=group) if form.is_valid(): name = form.cleaned_data['name'] person = form.cleaned_data['person'] email = form.cleaned_data['email'] # save group save_group_in_history(group) Role.objects.create(name=name, person=person, email=email, group=group) messages.success(request, 'New %s added successfully!' % name) url = reverse('groups_people', kwargs={'acronym':group.acronym}) return HttpResponseRedirect(url) else: form = RoleForm(initial={'name':'chair'},group=group) return render_to_response('groups/people.html', { 'form':form, 'group':group}, RequestContext(request, {}), )
def people(request, acronym): """ Edit Group Roles (Chairs, Secretary, etc) **Templates:** * ``groups/people.html`` **Template Variables:** * form, group """ group = get_object_or_404(Group, acronym=acronym) if request.method == 'POST': # we need to pass group for form validation form = RoleForm(request.POST,group=group) if form.is_valid(): name = form.cleaned_data['name'] person = form.cleaned_data['person'] email = form.cleaned_data['email'] # save group save_group_in_history(group) Role.objects.create(name=name, person=person, email=email, group=group) messages.success(request, 'New %s added successfully!' % name) return redirect('groups_people', acronym=group.acronym) else: form = RoleForm(initial={'name':'chair'},group=group) return render_to_response('groups/people.html', { 'form':form, 'group':group}, RequestContext(request, {}), )
def delete_role(request, acronym, id): """ Handle deleting roles **Templates:** * none """ role = get_object_or_404(Role, id=id) group = get_object_or_404(Group, acronym=acronym) # save group save_group_in_history(role.group) role.delete() messages.success(request, 'The entry was deleted successfully') url = reverse('roles') + '?group=%s' % group.acronym return HttpResponseRedirect(url)
def delete_role(request, acronym, id): """ Handle deleting roles for groups (chair, editor, advisor, secretary) **Templates:** * none Redirects to people page on success. """ group = get_object_or_404(Group, acronym=acronym) role = get_object_or_404(Role, id=id) # save group save_group_in_history(group) role.delete() messages.success(request, 'The entry was deleted successfully') return redirect('groups_people', acronym=acronym)
def delete_role(request, acronym, id): """ Handle deleting roles **Templates:** * none """ role = get_object_or_404(Role, id=id) group = get_object_or_404(Group, acronym=acronym) if request.method == 'POST' and request.POST['post'] == 'yes': # save group save_group_in_history(group) role.delete() messages.success(request, 'The entry was deleted successfully') return redirect('ietf.secr.roles.views.main') return render(request, 'confirm_delete.html', {'object': role})
def stream_edit(request, acronym): group = get_object_or_404(Group, acronym=acronym) if not (has_role(request.user, "Secretariat") or group.has_role(request.user, "chair")): return HttpResponseForbidden("You don't have permission to access this page.") chairs = Email.objects.filter(role__group=group, role__name="chair").select_related("person") if request.method == 'POST': form = StreamEditForm(request.POST) if form.is_valid(): save_group_in_history(group) # update roles attr, slug, title = ('delegates', 'delegate', "Delegates") new = form.cleaned_data[attr] old = Email.objects.filter(role__group=group, role__name=slug).select_related("person") if set(new) != set(old): desc = "%s changed to <b>%s</b> from %s" % ( title, ", ".join(x.get_name() for x in new), ", ".join(x.get_name() for x in old)) GroupEvent.objects.create(group=group, by=request.user.person, type="info_changed", desc=desc) group.role_set.filter(name=slug).delete() for e in new: Role.objects.get_or_create(name_id=slug, email=e, group=group, person=e.person) return redirect("ietf.group.views.streams") else: form = StreamEditForm(initial=dict(delegates=Email.objects.filter(role__group=group, role__name="delegate"))) return render_to_response('group/stream_edit.html', {'group': group, 'chairs': chairs, 'form': form, }, context_instance=RequestContext(request))
def delete_role(request, acronym, id): """ Handle deleting roles for groups (chair, editor, advisor, secretary) **Templates:** * none Redirects to people page on success. """ group = get_object_or_404(Group, acronym=acronym) role = get_object_or_404(Role, id=id) # save group save_group_in_history(group) role.delete() messages.success(request, 'The entry was deleted successfully') url = reverse('groups_people', kwargs={'acronym':acronym}) return HttpResponseRedirect(url)
def delete_role(request, acronym, id): """ Handle deleting roles for groups (chair, editor, advisor, secretary) **Templates:** * none Redirects to people page on success. """ group = get_object_or_404(Group, acronym=acronym) role = get_object_or_404(Role, id=id) if request.method == 'POST' and request.POST['post'] == 'yes': # save group save_group_in_history(group) role.delete() messages.success(request, 'The entry was deleted successfully') return redirect('ietf.secr.groups.views.people', acronym=acronym) return render(request, 'confirm_delete.html', {'object': role})
def edit(request, name): """ Edit IETF Areas **Templates:** * ``areas/edit.html`` **Template Variables:** * acronym, area_formset, awp_formset, acronym_form """ area = get_object_or_404(Group, acronym=name, type='area') AWPFormSet = inlineformset_factory(Group, GroupURL, form=AWPForm, max_num=2) if request.method == 'POST': button_text = request.POST.get('submit', '') if button_text == 'Save': form = AreaForm(request.POST, instance=area) awp_formset = AWPFormSet(request.POST, instance=area) if form.is_valid() and awp_formset.is_valid(): state = form.cleaned_data['state'] # save group save_group_in_history(area) new_area = form.save() new_area.time = datetime.datetime.now() new_area.save() awp_formset.save() # create appropriate GroupEvent if 'state' in form.changed_data: ChangeStateGroupEvent.objects.create(group=new_area, type='changed_state', by=request.user.get_profile(), state=state, time=new_area.time) form.changed_data.remove('state') # if anything else was changed if form.changed_data: GroupEvent.objects.create(group=new_area, type='info_changed', by=request.user.get_profile(), time=new_area.time) messages.success(request, 'The Area entry was changed successfully') url = reverse('areas_view', kwargs={'name':name}) return HttpResponseRedirect(url) else: url = reverse('areas_view', kwargs={'name':name}) return HttpResponseRedirect(url) else: form = AreaForm(instance=area) awp_formset = AWPFormSet(instance=area) return render_to_response('areas/edit.html', { 'area': area, 'form': form, 'awp_formset': awp_formset, }, RequestContext(request,{}), )
def submit(request, name=None, option=None): if not name.startswith('charter-'): raise Http404 charter = get_object_or_404(Document, type="charter", name=name) group = charter.group if not can_manage_group_type(request.user, group.type_id): return HttpResponseForbidden("You don't have permission to access this view") path = os.path.join(settings.CHARTER_PATH, '%s-%s.txt' % (charter.canonical_name(), charter.rev)) not_uploaded_yet = charter.rev.endswith("-00") and not os.path.exists(path) if not_uploaded_yet: # this case is special - we recently chartered or rechartered and have no file yet next_rev = charter.rev else: # search history for possible collisions with abandoned efforts prev_revs = list(charter.history_set.order_by('-time').values_list('rev', flat=True)) next_rev = next_revision(charter.rev) while next_rev in prev_revs: next_rev = next_revision(next_rev) if request.method == 'POST': form = UploadForm(request.POST, request.FILES) if form.is_valid(): save_document_in_history(charter) # Also save group history so we can search for it save_group_in_history(group) charter.rev = next_rev e = NewRevisionDocEvent(doc=charter, by=request.user.person, type="new_revision") e.desc = "New version available: <b>%s-%s.txt</b>" % (charter.canonical_name(), charter.rev) e.rev = charter.rev e.save() # Save file on disk form.save(group, charter.rev) if option in ['initcharter','recharter'] and charter.ad == None: charter.ad = getattr(group.ad_role(),'person',None) charter.time = datetime.datetime.now() charter.save() if option: return redirect('charter_startstop_process', name=charter.name, option=option) else: return redirect("doc_view", name=charter.name) else: init = { "content": ""} c = charter if not_uploaded_yet: # use text from last approved revision last_approved = charter.rev.split("-")[0] h = charter.history_set.filter(rev=last_approved).order_by("-time", "-id") if h: c = h[0] filename = os.path.join(settings.CHARTER_PATH, '%s-%s.txt' % (c.canonical_name(), c.rev)) try: with open(filename, 'r') as f: init["content"] = f.read() except IOError: pass form = UploadForm(initial=init) return render_to_response('doc/charter/submit.html', {'form': form, 'next_rev': next_rev, 'group': group, 'name': name }, context_instance=RequestContext(request))
def save(self): delegates = self.cleaned_data.get('delete') save_group_in_history(Group.objects.get(pk=self.wg.pk)) WGDelegate.objects.filter(pk__in=delegates).delete() self.set_message('success', 'Delegates removed')
def approve(request, name): """Approve charter, changing state, fixing revision, copying file to final location.""" charter = get_object_or_404(Document, type="charter", name=name) group = charter.group login = request.user.get_profile() e = charter.latest_event(WriteupDocEvent, type="changed_action_announcement") if not e: announcement = default_action_text(group, charter, login).text else: announcement = e.text if request.method == 'POST': new_charter_state = State.objects.get(used=True, type="charter", slug="approved") prev_charter_state = charter.get_state() save_document_in_history(charter) charter.set_state(new_charter_state) close_open_ballots(charter, login) # approve e = DocEvent(doc=charter, by=login) e.type = "iesg_approved" e.desc = "IESG has approved the charter" e.save() change_description = e.desc new_state = GroupStateName.objects.get(slug="active") if group.state != new_state: save_group_in_history(group) prev_state = group.state group.state = new_state group.time = e.time group.save() # create an event for the wg state change, too e = ChangeStateGroupEvent(group=group, type="changed_state") e.time = group.time e.by = login e.state_id = "active" e.desc = "Charter approved, group active" e.save() change_description += " and %s state has been changed to %s" % ( group.type.name, new_state.name) e = log_state_changed(request, charter, login, prev_charter_state) # according to spec, 00-02 becomes 01, so copy file and record new revision try: old = os.path.join( charter.get_file_path(), '%s-%s.txt' % (charter.canonical_name(), charter.rev)) new = os.path.join( charter.get_file_path(), '%s-%s.txt' % (charter.canonical_name(), next_approved_revision(charter.rev))) shutil.copy(old, new) except IOError: return HttpResponse( "There was an error copying %s to %s" % ('%s-%s.txt' % (charter.canonical_name(), charter.rev), '%s-%s.txt' % (charter.canonical_name(), next_approved_revision( charter.rev)))) e = NewRevisionDocEvent(doc=charter, by=login, type="new_revision") e.rev = next_approved_revision(charter.rev) e.desc = "New version available: <b>%s-%s.txt</b>" % ( charter.canonical_name(), e.rev) e.save() charter.rev = e.rev charter.time = e.time charter.save() email_secretariat(request, group, "state-%s" % new_charter_state.slug, change_description) # move milestones over milestones_to_delete = list( group.groupmilestone_set.filter(state__in=("active", "review"))) for m in group.groupmilestone_set.filter(state="charter"): # see if we got this milestone already (i.e. it was copied # verbatim to the charter) found = False for i, o in enumerate(milestones_to_delete): if o.desc == m.desc and o.due == m.due and set( o.docs.all()) == set(m.docs.all()): found = True break if found: # keep existing, whack charter milestone if not o.state_id == "active": save_milestone_in_history(o) o.state_id = "active" o.save() MilestoneGroupEvent.objects.create( group=group, type="changed_milestone", by=login, desc= "Changed milestone \"%s\", set state to active from review" % o.desc, milestone=o) del milestones_to_delete[i] # don't generate a DocEvent for this, it's implicit in the approval event save_milestone_in_history(m) m.state_id = "deleted" m.save() else: # move charter milestone save_milestone_in_history(m) m.state_id = "active" m.save() MilestoneGroupEvent.objects.create( group=group, type="changed_milestone", by=login, desc="Added milestone \"%s\", due %s, from approved charter" % (m.desc, m.due), milestone=m) for m in milestones_to_delete: save_milestone_in_history(m) m.state_id = "deleted" m.save() MilestoneGroupEvent.objects.create( group=group, type="changed_milestone", by=login, desc="Deleted milestone \"%s\", not present in approved charter" % m.desc, milestone=m) # send announcement send_mail_preformatted(request, announcement) return HttpResponseRedirect(charter.get_absolute_url()) return render_to_response('wgcharter/approve.html', dict(charter=charter, announcement=announcement), context_instance=RequestContext(request))
def submit(request, name=None, acronym=None, option=None): if name: if not name.startswith('charter-'): name = "charter-ietf-" + name elif acronym: name = "charter-ietf-" + acronym charter = get_object_or_404(Document, type="charter", name=name) group = charter.group login = request.user.get_profile() path = os.path.join(settings.CHARTER_PATH, '%s-%s.txt' % (charter.canonical_name(), charter.rev)) not_uploaded_yet = charter.rev.endswith("-00") and not os.path.exists(path) if not_uploaded_yet: # this case is special - we recently chartered or rechartered and have no file yet next_rev = charter.rev else: # search history for possible collisions with abandoned efforts prev_revs = list( charter.history_set.order_by('-time').values_list('rev', flat=True)) next_rev = next_revision(charter.rev) while next_rev in prev_revs: next_rev = next_revision(next_rev) if request.method == 'POST': form = UploadForm(request.POST, request.FILES) if form.is_valid(): save_document_in_history(charter) # Also save group history so we can search for it save_group_in_history(group) charter.rev = next_rev e = NewRevisionDocEvent(doc=charter, by=login, type="new_revision") e.desc = "New version available: <b>%s-%s.txt</b>" % ( charter.canonical_name(), charter.rev) e.rev = charter.rev e.save() # Save file on disk form.save(group, charter.rev) charter.time = datetime.datetime.now() charter.save() if option: return redirect('charter_startstop_process', name=charter.name, option=option) else: return redirect("doc_view", name=charter.name) else: init = {"content": ""} c = charter if not_uploaded_yet: # use text from last approved revision last_approved = charter.rev.split("-")[0] h = charter.history_set.filter(rev=last_approved).order_by( "-time", "-id") if h: c = h[0] filename = os.path.join(settings.CHARTER_PATH, '%s-%s.txt' % (c.canonical_name(), c.rev)) try: with open(filename, 'r') as f: init["content"] = f.read() except IOError: pass form = UploadForm(initial=init) return render_to_response('wgcharter/submit.html', { 'form': form, 'next_rev': next_rev, 'group': group }, context_instance=RequestContext(request))
def test_edit_info(self): make_test_data() group = Group.objects.get(acronym="mars") url = urlreverse('group_edit', kwargs=dict(group_type=group.type_id, acronym=group.acronym)) login_testing_unauthorized(self, "secretary", url) # normal get r = self.client.get(url) self.assertEqual(r.status_code, 200) q = PyQuery(r.content) self.assertEqual(len(q('form select[name=parent]')), 1) self.assertEqual(len(q('form input[name=acronym]')), 1) # faulty post Group.objects.create(name="Collision Test Group", acronym="collide") r = self.client.post(url, dict(acronym="collide")) self.assertEqual(r.status_code, 200) q = PyQuery(r.content) self.assertTrue(len(q('form ul.errorlist')) > 0) # create old acronym group.acronym = "oldmars" group.save() save_group_in_history(group) group.acronym = "mars" group.save() # post with warning r = self.client.post(url, dict(acronym="oldmars")) self.assertEqual(r.status_code, 200) q = PyQuery(r.content) self.assertTrue(len(q('form ul.errorlist')) > 0) # edit info with open(os.path.join(self.charter_dir, "%s-%s.txt" % (group.charter.canonical_name(), group.charter.rev)), "w") as f: f.write("This is a charter.") area = group.parent ad = Person.objects.get(name="Aread Irector") state = GroupStateName.objects.get(slug="bof") r = self.client.post(url, dict(name="Mars Not Special Interest Group", acronym="mars", parent=area.pk, ad=ad.pk, state=state.pk, chairs="[email protected], [email protected]", secretaries="[email protected], [email protected], [email protected]", techadv="*****@*****.**", delegates="*****@*****.**", list_email="mars@mail", list_subscribe="subscribe.mars", list_archive="archive.mars", urls="http://mars.mars (MARS site)" )) self.assertEqual(r.status_code, 302) group = Group.objects.get(acronym="mars") self.assertEqual(group.name, "Mars Not Special Interest Group") self.assertEqual(group.parent, area) self.assertEqual(group.ad, ad) for k in ("chair", "secr", "techadv"): self.assertTrue(group.role_set.filter(name=k, email__address="*****@*****.**")) self.assertTrue(group.role_set.filter(name="delegate", email__address="*****@*****.**")) self.assertEqual(group.list_email, "mars@mail") self.assertEqual(group.list_subscribe, "subscribe.mars") self.assertEqual(group.list_archive, "archive.mars") self.assertEqual(group.groupurl_set.all()[0].url, "http://mars.mars") self.assertEqual(group.groupurl_set.all()[0].name, "MARS site") self.assertTrue(os.path.exists(os.path.join(self.charter_dir, "%s-%s.txt" % (group.charter.canonical_name(), group.charter.rev))))
def edit(request, acronym): """ Edit Group details **Templates:** * ``groups/edit.html`` **Template Variables:** * group, form, awp_formset """ group = get_object_or_404(Group, acronym=acronym) AWPFormSet = inlineformset_factory(Group, GroupURL, form=AWPForm, max_num=2) if request.method == 'POST': button_text = request.POST.get('submit', '') if button_text == 'Cancel': url = reverse('groups_view', kwargs={'acronym':acronym}) return HttpResponseRedirect(url) form = GroupModelForm(request.POST, instance=group) awp_formset = AWPFormSet(request.POST, instance=group) if form.is_valid() and awp_formset.is_valid(): awp_formset.save() if form.changed_data: state = form.cleaned_data['state'] # save group save_group_in_history(group) form.save() # create appropriate GroupEvent if 'state' in form.changed_data: if state.name == 'Active': desc = 'Started group' else: desc = state.name + ' group' ChangeStateGroupEvent.objects.create(group=group, type='changed_state', by=request.user.get_profile(), state=state, desc=desc) form.changed_data.remove('state') # if anything else was changed if form.changed_data: GroupEvent.objects.create(group=group, type='info_changed', by=request.user.get_profile(), desc='Info Changed') # if the acronym was changed we'll want to redirect using the new acronym below if 'acronym' in form.changed_data: acronym = form.cleaned_data['acronym'] messages.success(request, 'The Group was changed successfully') url = reverse('groups_view', kwargs={'acronym':acronym}) return HttpResponseRedirect(url) else: form = GroupModelForm(instance=group) awp_formset = AWPFormSet(instance=group) return render_to_response('groups/edit.html', { 'group': group, 'awp_formset': awp_formset, 'form': form}, RequestContext(request, {}), )
def edit(request, acronym): """ Edit Group details **Templates:** * ``groups/edit.html`` **Template Variables:** * group, form, awp_formset """ group = get_object_or_404(Group, acronym=acronym) AWPFormSet = inlineformset_factory(Group, GroupURL, form=AWPForm, max_num=2) if request.method == 'POST': button_text = request.POST.get('submit', '') if button_text == 'Cancel': return redirect('groups_view', acronym=acronym) form = GroupModelForm(request.POST, instance=group) awp_formset = AWPFormSet(request.POST, instance=group) if form.is_valid() and awp_formset.is_valid(): awp_formset.save() if form.changed_data: state = form.cleaned_data['state'] # save group save_group_in_history(group) form.save() # create appropriate GroupEvent if 'state' in form.changed_data: if state.name == 'Active': desc = 'Started group' else: desc = state.name + ' group' ChangeStateGroupEvent.objects.create(group=group, type='changed_state', by=request.user.person, state=state, desc=desc) form.changed_data.remove('state') # if anything else was changed if form.changed_data: GroupEvent.objects.create(group=group, type='info_changed', by=request.user.person, desc='Info Changed') # if the acronym was changed we'll want to redirect using the new acronym below if 'acronym' in form.changed_data: acronym = form.cleaned_data['acronym'] messages.success(request, 'The Group was changed successfully') return redirect('groups_view', acronym=acronym) else: form = GroupModelForm(instance=group) awp_formset = AWPFormSet(instance=group) messages.warning(request, "WARNING: don't use this tool to change group names. Use Datatracker when possible.") return render_to_response('groups/edit.html', { 'group': group, 'awp_formset': awp_formset, 'form': form}, RequestContext(request, {}), )
def edit(request, acronym=None, action="edit"): """Edit or create a WG, notifying parties as necessary and logging changes as group events.""" if action == "edit": wg = get_object_or_404(Group, acronym=acronym) new_wg = False elif action in ("create","charter"): wg = None new_wg = True else: raise Http404 login = request.user.get_profile() if request.method == 'POST': form = WGForm(request.POST, wg=wg, confirmed=request.POST.get("confirmed", False)) if form.is_valid(): clean = form.cleaned_data if new_wg: try: wg = Group.objects.get(acronym=clean["acronym"]) save_group_in_history(wg) wg.time = datetime.datetime.now() wg.save() except Group.DoesNotExist: wg = Group.objects.create(name=clean["name"], acronym=clean["acronym"], type=GroupTypeName.objects.get(slug="wg"), state=clean["state"] ) e = ChangeStateGroupEvent(group=wg, type="changed_state") e.time = wg.time e.by = login e.state_id = clean["state"].slug e.desc = "Group created in state %s" % clean["state"].name e.save() else: save_group_in_history(wg) if action=="charter" and not wg.charter: # make sure we have a charter wg.charter = get_or_create_initial_charter(wg) changes = [] def desc(attr, new, old): entry = "%(attr)s changed to <b>%(new)s</b> from %(old)s" if new_wg: entry = "%(attr)s changed to <b>%(new)s</b>" return entry % dict(attr=attr, new=new, old=old) def diff(attr, name): v = getattr(wg, attr) if clean[attr] != v: changes.append(desc(name, clean[attr], v)) setattr(wg, attr, clean[attr]) prev_acronym = wg.acronym # update the attributes, keeping track of what we're doing diff('name', "Name") diff('acronym', "Acronym") diff('state', "State") diff('ad', "Shepherding AD") diff('parent', "IETF Area") diff('list_email', "Mailing list email") diff('list_subscribe', "Mailing list subscribe address") diff('list_archive', "Mailing list archive") if not new_wg and wg.acronym != prev_acronym and wg.charter: save_document_in_history(wg.charter) DocAlias.objects.get_or_create( name="charter-ietf-%s" % wg.acronym, document=wg.charter, ) old = os.path.join(wg.charter.get_file_path(), 'charter-ietf-%s-%s.txt' % (prev_acronym, wg.charter.rev)) if os.path.exists(old): new = os.path.join(wg.charter.get_file_path(), 'charter-ietf-%s-%s.txt' % (wg.acronym, wg.charter.rev)) shutil.copy(old, new) # update roles for attr, slug, title in [('chairs', 'chair', "Chairs"), ('secretaries', 'secr', "Secretaries"), ('techadv', 'techadv', "Tech Advisors")]: new = clean[attr] old = Email.objects.filter(role__group=wg, role__name=slug).select_related("person") if set(new) != set(old): changes.append(desc(title, ", ".join(x.get_name() for x in new), ", ".join(x.get_name() for x in old))) wg.role_set.filter(name=slug).delete() for e in new: Role.objects.get_or_create(name_id=slug, email=e, group=wg, person=e.person) # update urls new_urls = clean['urls'] old_urls = format_urls(wg.groupurl_set.order_by('url'), ", ") if ", ".join(sorted(new_urls)) != old_urls: changes.append(desc('Urls', ", ".join(sorted(new_urls)), old_urls)) wg.groupurl_set.all().delete() # Add new ones for u in new_urls: m = re.search('(?P<url>[\w\d:#@%/;$()~_?\+-=\\\.&]+)( \((?P<name>.+)\))?', u) if m: if m.group('name'): url = GroupURL(url=m.group('url'), name=m.group('name'), group=wg) else: url = GroupURL(url=m.group('url'), name='', group=wg) url.save() wg.time = datetime.datetime.now() if changes and not new_wg: for c in changes: GroupEvent.objects.create(group=wg, by=login, type="info_changed", desc=c) wg.save() if action=="charter": return redirect('charter_submit', name=wg.charter.name, option="initcharter") return redirect('wg_charter', acronym=wg.acronym) else: # form.is_valid() if not new_wg: from ietf.person.forms import json_emails init = dict(name=wg.name, acronym=wg.acronym, state=wg.state, chairs=Email.objects.filter(role__group=wg, role__name="chair"), secretaries=Email.objects.filter(role__group=wg, role__name="secr"), techadv=Email.objects.filter(role__group=wg, role__name="techadv"), ad=wg.ad_id if wg.ad else None, parent=wg.parent.id if wg.parent else None, list_email=wg.list_email if wg.list_email else None, list_subscribe=wg.list_subscribe if wg.list_subscribe else None, list_archive=wg.list_archive if wg.list_archive else None, urls=format_urls(wg.groupurl_set.all()), ) else: init = dict(ad=login.id if has_role(request.user, "Area Director") else None, ) form = WGForm(initial=init, wg=wg) return render_to_response('wginfo/edit.html', dict(wg=wg, form=form, action=action, user=request.user, login=login), context_instance=RequestContext(request))
def submit(request, name, option=None): if not name.startswith('charter-'): raise Http404 charter = Document.objects.filter(type="charter", name=name).first() if charter: group = charter.group charter_canonical_name = charter.canonical_name() charter_rev = charter.rev else: top_org, group_acronym = split_charter_name(name) group = get_object_or_404(Group, acronym=group_acronym) charter_canonical_name = name charter_rev = "00-00" if not can_manage_group_type( request.user, group) or not group.features.has_chartering_process: return HttpResponseForbidden( "You don't have permission to access this view") path = os.path.join(settings.CHARTER_PATH, '%s-%s.txt' % (charter_canonical_name, charter_rev)) not_uploaded_yet = charter_rev.endswith("-00") and not os.path.exists(path) if not_uploaded_yet or not charter: # this case is special - we recently chartered or rechartered and have no file yet next_rev = charter_rev else: # search history for possible collisions with abandoned efforts prev_revs = list( charter.history_set.order_by('-time').values_list('rev', flat=True)) next_rev = next_revision(charter.rev) while next_rev in prev_revs: next_rev = next_revision(next_rev) if request.method == 'POST': form = UploadForm(request.POST, request.FILES) if form.is_valid(): # Also save group history so we can search for it save_group_in_history(group) if not charter: charter = Document.objects.create( name=name, type_id="charter", title=group.name, group=group, abstract=group.name, rev=next_rev, ) DocAlias.objects.create(name=charter.name, document=charter) charter.set_state( State.objects.get(used=True, type="charter", slug="notrev")) group.charter = charter group.save() else: charter.rev = next_rev events = [] e = NewRevisionDocEvent(doc=charter, by=request.user.person, type="new_revision") e.desc = "New version available: <b>%s-%s.txt</b>" % ( charter.canonical_name(), charter.rev) e.rev = charter.rev e.save() events.append(e) # Save file on disk filename = os.path.join( settings.CHARTER_PATH, '%s-%s.txt' % (charter.canonical_name(), charter.rev)) with open(filename, 'wb') as destination: if form.cleaned_data['txt']: destination.write(form.cleaned_data['txt']) else: destination.write( form.cleaned_data['content'].encode("utf-8")) if option in ['initcharter', 'recharter'] and charter.ad == None: charter.ad = getattr(group.ad_role(), 'person', None) charter.save_with_history(events) if option: return redirect('ietf.doc.views_charter.change_state', name=charter.name, option=option) else: return redirect("ietf.doc.views_doc.document_main", name=charter.name) else: init = {"content": ""} if not_uploaded_yet and charter: # use text from last approved revision last_approved = charter.rev.split("-")[0] h = charter.history_set.filter(rev=last_approved).order_by( "-time", "-id").first() if h: charter_canonical_name = h.canonical_name() charter_rev = h.rev filename = os.path.join( settings.CHARTER_PATH, '%s-%s.txt' % (charter_canonical_name, charter_rev)) try: with open(filename, 'r') as f: init["content"] = f.read() except IOError: pass form = UploadForm(initial=init) fill_in_charter_info(group) return render(request, 'doc/charter/submit.html', { 'form': form, 'next_rev': next_rev, 'group': group, 'name': name, })
def edit(request, acronym): """ Edit Group details **Templates:** * ``groups/edit.html`` **Template Variables:** * group, form, awp_formset """ group = get_object_or_404(Group, acronym=acronym) AWPFormSet = inlineformset_factory(Group, GroupURL, form=AWPForm, max_num=2) if request.method == 'POST': button_text = request.POST.get('submit', '') if button_text == 'Cancel': return redirect('ietf.secr.groups.views.view', acronym=acronym) form = GroupModelForm(request.POST, instance=group) awp_formset = AWPFormSet(request.POST, instance=group) if form.is_valid() and awp_formset.is_valid(): awp_formset.save() if form.changed_data: state = form.cleaned_data['state'] # save group save_group_in_history(group) form.save() # create appropriate GroupEvent if 'state' in form.changed_data: if state.name == 'Active': desc = 'Started group' else: desc = state.name + ' group' ChangeStateGroupEvent.objects.create( group=group, type='changed_state', by=request.user.person, state=state, desc=desc) form.changed_data.remove('state') # if anything else was changed if form.changed_data: GroupEvent.objects.create(group=group, type='info_changed', by=request.user.person, desc='Info Changed') # if the acronym was changed we'll want to redirect using the new acronym below if 'acronym' in form.changed_data: acronym = form.cleaned_data['acronym'] messages.success(request, 'The Group was changed successfully') return redirect('ietf.secr.groups.views.view', acronym=acronym) else: form = GroupModelForm(instance=group) awp_formset = AWPFormSet(instance=group) messages.warning( request, "WARNING: don't use this tool to change group names. Use Datatracker when possible." ) return render( request, 'groups/edit.html', { 'group': group, 'awp_formset': awp_formset, 'form': form }, )
def edit(request, acronym=None, action="edit"): """Edit or create a WG, notifying parties as necessary and logging changes as group events.""" if action == "edit": wg = get_object_or_404(Group, acronym=acronym) new_wg = False elif action in ("create", "charter"): wg = None new_wg = True else: raise Http404 login = request.user.get_profile() if request.method == 'POST': form = WGForm(request.POST, wg=wg, confirmed=request.POST.get("confirmed", False)) if form.is_valid(): clean = form.cleaned_data if new_wg: try: wg = Group.objects.get(acronym=clean["acronym"]) save_group_in_history(wg) wg.time = datetime.datetime.now() wg.save() except Group.DoesNotExist: wg = Group.objects.create( name=clean["name"], acronym=clean["acronym"], type=GroupTypeName.objects.get(slug="wg"), state=clean["state"]) e = ChangeStateGroupEvent(group=wg, type="changed_state") e.time = wg.time e.by = login e.state_id = clean["state"].slug e.desc = "Group created in state %s" % clean["state"].name e.save() else: save_group_in_history(wg) if action == "charter" and not wg.charter: # make sure we have a charter wg.charter = get_or_create_initial_charter(wg) changes = [] def desc(attr, new, old): entry = "%(attr)s changed to <b>%(new)s</b> from %(old)s" if new_wg: entry = "%(attr)s changed to <b>%(new)s</b>" return entry % dict(attr=attr, new=new, old=old) def diff(attr, name): v = getattr(wg, attr) if clean[attr] != v: changes.append(desc(name, clean[attr], v)) setattr(wg, attr, clean[attr]) prev_acronym = wg.acronym # update the attributes, keeping track of what we're doing diff('name', "Name") diff('acronym', "Acronym") diff('state', "State") diff('ad', "Shepherding AD") diff('parent', "IETF Area") diff('list_email', "Mailing list email") diff('list_subscribe', "Mailing list subscribe address") diff('list_archive', "Mailing list archive") if not new_wg and wg.acronym != prev_acronym and wg.charter: save_document_in_history(wg.charter) DocAlias.objects.get_or_create( name="charter-ietf-%s" % wg.acronym, document=wg.charter, ) old = os.path.join( wg.charter.get_file_path(), 'charter-ietf-%s-%s.txt' % (prev_acronym, wg.charter.rev)) if os.path.exists(old): new = os.path.join( wg.charter.get_file_path(), 'charter-ietf-%s-%s.txt' % (wg.acronym, wg.charter.rev)) shutil.copy(old, new) # update roles for attr, slug, title in [('chairs', 'chair', "Chairs"), ('secretaries', 'secr', "Secretaries"), ('techadv', 'techadv', "Tech Advisors")]: new = clean[attr] old = Email.objects.filter( role__group=wg, role__name=slug).select_related("person") if set(new) != set(old): changes.append( desc(title, ", ".join(x.get_name() for x in new), ", ".join(x.get_name() for x in old))) wg.role_set.filter(name=slug).delete() for e in new: Role.objects.get_or_create(name_id=slug, email=e, group=wg, person=e.person) # update urls new_urls = clean['urls'] old_urls = format_urls(wg.groupurl_set.order_by('url'), ", ") if ", ".join(sorted(new_urls)) != old_urls: changes.append( desc('Urls', ", ".join(sorted(new_urls)), old_urls)) wg.groupurl_set.all().delete() # Add new ones for u in new_urls: m = re.search( '(?P<url>[\w\d:#@%/;$()~_?\+-=\\\.&]+)( \((?P<name>.+)\))?', u) if m: if m.group('name'): url = GroupURL(url=m.group('url'), name=m.group('name'), group=wg) else: url = GroupURL(url=m.group('url'), name='', group=wg) url.save() wg.time = datetime.datetime.now() if changes and not new_wg: for c in changes: GroupEvent.objects.create(group=wg, by=login, type="info_changed", desc=c) wg.save() if action == "charter": return redirect('charter_submit', name=wg.charter.name, option="initcharter") return redirect('wg_charter', acronym=wg.acronym) else: # form.is_valid() if not new_wg: from ietf.person.forms import json_emails init = dict( name=wg.name, acronym=wg.acronym, state=wg.state, chairs=Email.objects.filter(role__group=wg, role__name="chair"), secretaries=Email.objects.filter(role__group=wg, role__name="secr"), techadv=Email.objects.filter(role__group=wg, role__name="techadv"), ad=wg.ad_id if wg.ad else None, parent=wg.parent.id if wg.parent else None, list_email=wg.list_email if wg.list_email else None, list_subscribe=wg.list_subscribe if wg.list_subscribe else None, list_archive=wg.list_archive if wg.list_archive else None, urls=format_urls(wg.groupurl_set.all()), ) else: init = dict(ad=login.id if has_role(request.user, "Area Director") else None, ) form = WGForm(initial=init, wg=wg) return render_to_response('wginfo/edit.html', dict(wg=wg, form=form, action=action, user=request.user, login=login), context_instance=RequestContext(request))
def edit(request, group_type=None, acronym=None, action="edit"): """Edit or create a group, notifying parties as necessary and logging changes as group events.""" if not can_manage_group_type(request.user, group_type): return HttpResponseForbidden("You don't have permission to access this view") if action == "edit": group = get_object_or_404(Group, acronym=acronym) new_group = False elif action in ("create","charter"): group = None new_group = True else: raise Http404 if not group_type and group: group_type = group.type_id if request.method == 'POST': form = GroupForm(request.POST, group=group, group_type=group_type) if form.is_valid(): clean = form.cleaned_data if new_group: try: group = Group.objects.get(acronym=clean["acronym"]) save_group_in_history(group) group.time = datetime.datetime.now() group.save() except Group.DoesNotExist: group = Group.objects.create(name=clean["name"], acronym=clean["acronym"], type=GroupTypeName.objects.get(slug=group_type), state=clean["state"] ) e = ChangeStateGroupEvent(group=group, type="changed_state") e.time = group.time e.by = request.user.person e.state_id = clean["state"].slug e.desc = "Group created in state %s" % clean["state"].name e.save() else: save_group_in_history(group) if action == "charter" and not group.charter: # make sure we have a charter group.charter = get_or_create_initial_charter(group, group_type) changes = [] def desc(attr, new, old): entry = "%(attr)s changed to <b>%(new)s</b> from %(old)s" if new_group: entry = "%(attr)s changed to <b>%(new)s</b>" return entry % dict(attr=attr, new=new, old=old) def diff(attr, name): v = getattr(group, attr) if clean[attr] != v: changes.append((attr, clean[attr], desc(name, clean[attr], v))) setattr(group, attr, clean[attr]) # update the attributes, keeping track of what we're doing diff('name', "Name") diff('acronym', "Acronym") diff('state', "State") diff('parent', "IETF Area" if group.type=="wg" else "Group parent") diff('list_email', "Mailing list email") diff('list_subscribe', "Mailing list subscribe address") diff('list_archive', "Mailing list archive") personnel_change_text="" changed_personnel = set() # update roles for attr, slug, title in [('ad','ad','Shepherding AD'), ('chairs', 'chair', "Chairs"), ('secretaries', 'secr', "Secretaries"), ('techadv', 'techadv', "Tech Advisors"), ('delegates', 'delegate', "Delegates")]: new = clean[attr] if attr == 'ad': new = [ new.role_email('ad'),] if new else [] old = Email.objects.filter(role__group=group, role__name=slug).select_related("person") if set(new) != set(old): changes.append((attr, new, desc(title, ", ".join(x.get_name() for x in new), ", ".join(x.get_name() for x in old)))) group.role_set.filter(name=slug).delete() for e in new: Role.objects.get_or_create(name_id=slug, email=e, group=group, person=e.person) added = set(new) - set(old) deleted = set(old) - set(new) if added: change_text=title + ' added: ' + ", ".join(x.formatted_email() for x in added) personnel_change_text+=change_text+"\n" if deleted: change_text=title + ' deleted: ' + ", ".join(x.formatted_email() for x in deleted) personnel_change_text+=change_text+"\n" changed_personnel.update(set(old)^set(new)) if personnel_change_text!="": email_personnel_change(request, group, personnel_change_text, changed_personnel) # update urls new_urls = clean['urls'] old_urls = format_urls(group.groupurl_set.order_by('url'), ", ") if ", ".join(sorted(new_urls)) != old_urls: changes.append(('urls', new_urls, desc('Urls', ", ".join(sorted(new_urls)), old_urls))) group.groupurl_set.all().delete() # Add new ones for u in new_urls: m = re.search('(?P<url>[\w\d:#@%/;$()~_?\+-=\\\.&]+)( \((?P<name>.+)\))?', u) if m: if m.group('name'): url = GroupURL(url=m.group('url'), name=m.group('name'), group=group) else: url = GroupURL(url=m.group('url'), name='', group=group) url.save() group.time = datetime.datetime.now() if changes and not new_group: for attr, new, desc in changes: if attr == 'state': ChangeStateGroupEvent.objects.create(group=group, time=group.time, state=new, by=request.user.person, type="changed_state", desc=desc) else: GroupEvent.objects.create(group=group, time=group.time, by=request.user.person, type="info_changed", desc=desc) group.save() if action=="charter": return redirect('charter_submit', name=group.charter.name, option="initcharter") return HttpResponseRedirect(group.about_url()) else: # form.is_valid() if not new_group: ad_role = group.ad_role() init = dict(name=group.name, acronym=group.acronym, state=group.state, chairs=Email.objects.filter(role__group=group, role__name="chair"), secretaries=Email.objects.filter(role__group=group, role__name="secr"), techadv=Email.objects.filter(role__group=group, role__name="techadv"), delegates=Email.objects.filter(role__group=group, role__name="delegate"), ad=ad_role and ad_role.person and ad_role.person.id, parent=group.parent.id if group.parent else None, list_email=group.list_email if group.list_email else None, list_subscribe=group.list_subscribe if group.list_subscribe else None, list_archive=group.list_archive if group.list_archive else None, urls=format_urls(group.groupurl_set.all()), ) else: init = dict(ad=request.user.person.id if group_type == "wg" and has_role(request.user, "Area Director") else None, ) form = GroupForm(initial=init, group=group, group_type=group_type) return render(request, 'group/edit.html', dict(group=group, form=form, action=action))
def approve(request, name): """Approve charter, changing state, fixing revision, copying file to final location.""" charter = get_object_or_404(Document, type="charter", name=name) group = charter.group login = request.user.get_profile() e = charter.latest_event(WriteupDocEvent, type="changed_action_announcement") if not e: announcement = default_action_text(group, charter, login).text else: announcement = e.text if request.method == 'POST': new_charter_state = State.objects.get(used=True, type="charter", slug="approved") prev_charter_state = charter.get_state() save_document_in_history(charter) charter.set_state(new_charter_state) close_open_ballots(charter, login) # approve e = DocEvent(doc=charter, by=login) e.type = "iesg_approved" e.desc = "IESG has approved the charter" e.save() change_description = e.desc new_state = GroupStateName.objects.get(slug="active") if group.state != new_state: save_group_in_history(group) prev_state = group.state group.state = new_state group.time = e.time group.save() # create an event for the wg state change, too e = ChangeStateGroupEvent(group=group, type="changed_state") e.time = group.time e.by = login e.state_id = "active" e.desc = "Charter approved, group active" e.save() change_description += " and %s state has been changed to %s" % (group.type.name, new_state.name) e = log_state_changed(request, charter, login, prev_charter_state) # according to spec, 00-02 becomes 01, so copy file and record new revision try: old = os.path.join(charter.get_file_path(), '%s-%s.txt' % (charter.canonical_name(), charter.rev)) new = os.path.join(charter.get_file_path(), '%s-%s.txt' % (charter.canonical_name(), next_approved_revision(charter.rev))) shutil.copy(old, new) except IOError: return HttpResponse("There was an error copying %s to %s" % ('%s-%s.txt' % (charter.canonical_name(), charter.rev), '%s-%s.txt' % (charter.canonical_name(), next_approved_revision(charter.rev)))) e = NewRevisionDocEvent(doc=charter, by=login, type="new_revision") e.rev = next_approved_revision(charter.rev) e.desc = "New version available: <b>%s-%s.txt</b>" % (charter.canonical_name(), e.rev) e.save() charter.rev = e.rev charter.time = e.time charter.save() email_secretariat(request, group, "state-%s" % new_charter_state.slug, change_description) # move milestones over milestones_to_delete = list(group.groupmilestone_set.filter(state__in=("active", "review"))) for m in group.groupmilestone_set.filter(state="charter"): # see if we got this milestone already (i.e. it was copied # verbatim to the charter) found = False for i, o in enumerate(milestones_to_delete): if o.desc == m.desc and o.due == m.due and set(o.docs.all()) == set(m.docs.all()): found = True break if found: # keep existing, whack charter milestone if not o.state_id == "active": save_milestone_in_history(o) o.state_id = "active" o.save() MilestoneGroupEvent.objects.create( group=group, type="changed_milestone", by=login, desc="Changed milestone \"%s\", set state to active from review" % o.desc, milestone=o) del milestones_to_delete[i] # don't generate a DocEvent for this, it's implicit in the approval event save_milestone_in_history(m) m.state_id = "deleted" m.save() else: # move charter milestone save_milestone_in_history(m) m.state_id = "active" m.save() MilestoneGroupEvent.objects.create( group=group, type="changed_milestone", by=login, desc="Added milestone \"%s\", due %s, from approved charter" % (m.desc, m.due), milestone=m) for m in milestones_to_delete: save_milestone_in_history(m) m.state_id = "deleted" m.save() MilestoneGroupEvent.objects.create( group=group, type="changed_milestone", by=login, desc="Deleted milestone \"%s\", not present in approved charter" % m.desc, milestone=m) # send announcement send_mail_preformatted(request, announcement) return HttpResponseRedirect(charter.get_absolute_url()) return render_to_response('wgcharter/approve.html', dict(charter=charter, announcement=announcement), context_instance=RequestContext(request))