Example #1
0
def make_revision_event(doc, system_person):
    try:
        e = NewRevisionDocEvent.objects.get(doc=doc, type="new_revision")
    except NewRevisionDocEvent.DoesNotExist:
        e = NewRevisionDocEvent(doc=doc, type="new_revision")
    e.rev = doc.rev
    e.time = doc.time
    e.by = system_person
    e.desc = "Added new revision"

    return e
Example #2
0
def fix_charter_revision_after_approval(charter, by):
    # 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=by, 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()
Example #3
0
def fix_charter_revision_after_approval(charter, by):
    # 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:
        log("There was an error copying %s to %s" % (old, new))

    events = []
    e = NewRevisionDocEvent(doc=charter, by=by, 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()
    events.append(e)

    charter.rev = e.rev
    charter.save_with_history(events)
Example #4
0
def edit_material(request, name=None, acronym=None, action=None, doc_type=None):
    # the materials process is not very developed, so at the moment we
    # handle everything through the same view/form

    if action == "new":
        group = get_object_or_404(Group, acronym=acronym)
        if not group.features.has_materials:
            raise Http404

        doc = None
        document_type = get_object_or_404(DocTypeName, slug=doc_type)
    else:
        doc = get_object_or_404(Document, name=name)
        group = doc.group
        document_type = doc.type

    if not can_manage_materials(request.user, group):
        return HttpResponseForbidden("You don't have permission to access this view")

    if request.method == 'POST':
        form = UploadMaterialForm(document_type, action, group, doc, request.POST, request.FILES)

        if form.is_valid():
            if action == "new":
                doc = Document()
                doc.type = document_type
                doc.group = group
                doc.rev = "00"
                doc.name = form.cleaned_data["name"]
                prev_rev = None
            else:
                save_document_in_history(doc)
                prev_rev = doc.rev

            prev_title = doc.title
            prev_state = doc.get_state()

            if "title" in form.cleaned_data:
                doc.title = form.cleaned_data["title"]

            if "abstract" in form.cleaned_data:
                doc.abstract = form.cleaned_data["abstract"]

            doc.time = datetime.datetime.now()

            if "material" in form.fields:
                if action != "new":
                    doc.rev = "%02d" % (int(doc.rev) + 1)

                f = form.cleaned_data["material"]
                file_ext = os.path.splitext(f.name)[1]

                with open(os.path.join(doc.get_file_path(), doc.name + "-" + doc.rev + file_ext), 'wb+') as dest:
                    for chunk in f.chunks():
                        dest.write(chunk)

            doc.save()

            if action == "new":
                DocAlias.objects.get_or_create(name=doc.name, document=doc)

            if prev_rev != doc.rev:
                e = NewRevisionDocEvent(type="new_revision", doc=doc, rev=doc.rev)
                e.time = doc.time
                e.by = request.user.person
                e.desc = "New version available: <b>%s-%s</b>" % (doc.name, doc.rev)
                e.save()
                
            if prev_title != doc.title:
                e = DocEvent(doc=doc, by=request.user.person, type='changed_document')
                e.desc = u"Changed title to <b>%s</b>" % doc.title
                if prev_title:
                    e.desc += u" from %s" % prev_title
                e.time = doc.time
                e.save()

            if "state" in form.cleaned_data and form.cleaned_data["state"] != prev_state:
                doc.set_state(form.cleaned_data["state"])
                add_state_change_event(doc, request.user.person, prev_state, form.cleaned_data["state"])

            return redirect("doc_view", name=doc.name)
    else:
        form = UploadMaterialForm(document_type, action, group, doc)

    return render(request, 'doc/material/edit_material.html', {
        'group': group,
        'form': form,
        'action': action,
        'document_type': document_type,
        'doc_name': doc.name if doc else "",
    })
Example #5
0
def submit(request, name):
    doc = get_object_or_404(Document, type="statchg", name=name)

    login = request.user.get_profile()

    path = os.path.join(settings.STATUS_CHANGE_PATH, '%s-%s.txt' % (doc.canonical_name(), doc.rev))
    not_uploaded_yet = doc.rev == "00" and not os.path.exists(path)

    if not_uploaded_yet:
        # this case is special - the status change text document doesn't actually exist yet
        next_rev = doc.rev
    else:
        next_rev = "%02d" % (int(doc.rev)+1) 

    if request.method == 'POST':
        if "submit_response" in request.POST:
            form = UploadForm(request.POST, request.FILES)
            if form.is_valid():
                save_document_in_history(doc)

                doc.rev = next_rev

                e = NewRevisionDocEvent(doc=doc, by=login, type="new_revision")
                e.desc = "New version available: <b>%s-%s.txt</b>" % (doc.canonical_name(), doc.rev)
                e.rev = doc.rev
                e.save()
            
                # Save file on disk
                form.save(doc)

                doc.time = datetime.datetime.now()
                doc.save()

                return HttpResponseRedirect(reverse('doc_view', kwargs={'name': doc.name}))

        elif "reset_text" in request.POST:

            init = { "content": render_to_string("doc/status_change/initial_template.txt",dict())}
            form = UploadForm(initial=init)

        # Protect against handcrufted malicious posts
        else:
            form = None

    else:
        form = None

    if not form:
        init = { "content": ""}

        if not_uploaded_yet:
            init["content"] = render_to_string("doc/status_change/initial_template.txt",
                                                dict(),
                                              )
        else:
            filename = os.path.join(settings.STATUS_CHANGE_PATH, '%s-%s.txt' % (doc.canonical_name(), doc.rev))
            try:
                with open(filename, 'r') as f:
                    init["content"] = f.read()
            except IOError:
                pass

        form = UploadForm(initial=init)

    return render_to_response('doc/status_change/submit.html',
                              {'form': form,
                               'next_rev': next_rev,
                               'doc' : doc,
                              },
                              context_instance=RequestContext(request))
Example #6
0
                                                name=review.name)
                        break

            review.set_state(State.objects.get(type="review", slug="active"))

            review.time = completion_time
            review.type = DocTypeName.objects.get(slug="review")
            review.rev = "00"
            review.title = "{} Review of {}-{}".format(review_req.type.name,
                                                       review_req.doc.name,
                                                       review_req.reviewed_rev)
            review.group = review_req.team
            review.external_url = reviewurl

            existing = NewRevisionDocEvent.objects.filter(
                doc=review).first() or NewRevisionDocEvent(doc=review)
            e.type = "new_revision"
            e.by = completion_by
            e.rev = review.rev
            e.desc = 'New revision available'
            e.time = completion_time
            e.skip_community_list_notification = True

            review.save_with_history([e])

            review_req.review = review
            review_req.save()

            print "imported review document", review_req.doc, review.name

        if review_req.state_id in ("requested",
Example #7
0
def submit(request, name):
    review = get_object_or_404(Document, type="conflrev", name=name)

    login = request.user.get_profile()

    path = os.path.join(settings.CONFLICT_REVIEW_PATH,
                        '%s-%s.txt' % (review.canonical_name(), review.rev))
    not_uploaded_yet = review.rev == "00" and not os.path.exists(path)

    if not_uploaded_yet:
        # this case is special - the conflict review text document doesn't actually exist yet
        next_rev = review.rev
    else:
        next_rev = "%02d" % (int(review.rev) + 1)

    if request.method == 'POST':
        if "submit_response" in request.POST:
            form = UploadForm(request.POST, request.FILES)
            if form.is_valid():
                save_document_in_history(review)

                review.rev = next_rev

                e = NewRevisionDocEvent(doc=review,
                                        by=login,
                                        type="new_revision")
                e.desc = "New version available: <b>%s-%s.txt</b>" % (
                    review.canonical_name(), review.rev)
                e.rev = review.rev
                e.save()

                # Save file on disk
                form.save(review)

                review.time = datetime.datetime.now()
                review.save()

                return HttpResponseRedirect(
                    reverse('doc_view', kwargs={'name': review.name}))

        elif "reset_text" in request.POST:

            init = {
                "content":
                render_to_string("doc/conflict_review/review_choices.txt",
                                 dict())
            }
            form = UploadForm(initial=init)

        # Protect against handcrufted malicious posts
        else:
            form = None

    else:
        form = None

    if not form:
        init = {"content": ""}

        if not_uploaded_yet:
            init["content"] = render_to_string(
                "doc/conflict_review/review_choices.txt",
                dict(),
            )
        else:
            filename = os.path.join(
                settings.CONFLICT_REVIEW_PATH,
                '%s-%s.txt' % (review.canonical_name(), review.rev))
            try:
                with open(filename, 'r') as f:
                    init["content"] = f.read()
            except IOError:
                pass

        form = UploadForm(initial=init)

    return render_to_response('doc/conflict_review/submit.html', {
        'form':
        form,
        'next_rev':
        next_rev,
        'review':
        review,
        'conflictdoc':
        review.relateddocument_set.get(
            relationship__slug='conflrev').target.document,
    },
                              context_instance=RequestContext(request))
Example #8
0
def submit(request, name):
    doc = get_object_or_404(Document, type="statchg", name=name)

    login = request.user.person

    path = os.path.join(settings.STATUS_CHANGE_PATH,
                        '%s-%s.txt' % (doc.canonical_name(), doc.rev))
    not_uploaded_yet = doc.rev == "00" and not os.path.exists(path)

    if not_uploaded_yet:
        # this case is special - the status change text document doesn't actually exist yet
        next_rev = doc.rev
    else:
        next_rev = "%02d" % (int(doc.rev) + 1)

    if request.method == 'POST':
        if "submit_response" in request.POST:
            form = UploadForm(request.POST, request.FILES)
            if form.is_valid():
                doc.rev = next_rev

                events = []
                e = NewRevisionDocEvent(doc=doc, by=login, type="new_revision")
                e.desc = "New version available: <b>%s-%s.txt</b>" % (
                    doc.canonical_name(), doc.rev)
                e.rev = doc.rev
                e.save()
                events.append(e)

                # Save file on disk
                form.save(doc)

                doc.save_with_history(events)

                return redirect('ietf.doc.views_doc.document_main',
                                name=doc.name)

        elif "reset_text" in request.POST:

            init = {
                "content":
                render_to_string("doc/status_change/initial_template.txt",
                                 dict())
            }
            form = UploadForm(initial=init)

        # Protect against handcrufted malicious posts
        else:
            form = None

    else:
        form = None

    if not form:
        init = {"content": ""}

        if not_uploaded_yet:
            init["content"] = render_to_string(
                "doc/status_change/initial_template.txt",
                dict(),
            )
        else:
            filename = os.path.join(
                settings.STATUS_CHANGE_PATH,
                '%s-%s.txt' % (doc.canonical_name(), doc.rev))
            try:
                with open(filename, 'r') as f:
                    init["content"] = f.read()
            except IOError:
                pass

        form = UploadForm(initial=init)

    return render(request, 'doc/status_change/submit.html', {
        'form': form,
        'next_rev': next_rev,
        'doc': doc,
    })
Example #9
0
def submit(request, name):
    review = get_object_or_404(Document, type="conflrev", name=name)

    login = request.user.person

    path = os.path.join(settings.CONFLICT_REVIEW_PATH, '%s-%s.txt' % (review.canonical_name(), review.rev))
    not_uploaded_yet = review.rev == "00" and not os.path.exists(path)

    if not_uploaded_yet:
        # this case is special - the conflict review text document doesn't actually exist yet
        next_rev = review.rev
    else:
        next_rev = "%02d" % (int(review.rev)+1) 

    if request.method == 'POST':
        if "submit_response" in request.POST:
            form = UploadForm(request.POST, request.FILES)
            if form.is_valid():
                save_document_in_history(review)

                review.rev = next_rev

                e = NewRevisionDocEvent(doc=review, by=login, type="new_revision")
                e.desc = "New version available: <b>%s-%s.txt</b>" % (review.canonical_name(), review.rev)
                e.rev = review.rev
                e.save()
            
                # Save file on disk
                form.save(review)

                review.time = datetime.datetime.now()
                review.save()

                return redirect('doc_view', name=review.name)

        elif "reset_text" in request.POST:

            init = { "content": render_to_string("doc/conflict_review/review_choices.txt",dict())}
            form = UploadForm(initial=init)

        # Protect against handcrufted malicious posts
        else:
            form = None

    else:
        form = None

    if not form:
        init = { "content": ""}

        if not_uploaded_yet:
            init["content"] = render_to_string("doc/conflict_review/review_choices.txt",
                                                dict(),
                                              )
        else:
            filename = os.path.join(settings.CONFLICT_REVIEW_PATH, '%s-%s.txt' % (review.canonical_name(), review.rev))
            try:
                with open(filename, 'r') as f:
                    init["content"] = f.read()
            except IOError:
                pass

        form = UploadForm(initial=init)

    return render_to_response('doc/conflict_review/submit.html',
                              {'form': form,
                               'next_rev': next_rev,
                               'review' : review,
                               'conflictdoc' : review.relateddocument_set.get(relationship__slug='conflrev').target.document,
                              },
                              context_instance=RequestContext(request))
Example #10
0
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))
Example #11
0
def post_submission(request, submission):
    system = Person.objects.get(name="(System)")

    try:
        draft = Document.objects.get(name=submission.name)
        save_document_in_history(draft)
    except Document.DoesNotExist:
        draft = Document(name=submission.name)
        draft.intended_std_level = None

    prev_rev = draft.rev

    draft.type_id = "draft"
    draft.time = datetime.datetime.now()
    draft.title = submission.title
    group = submission.group or Group.objects.get(type="individ")
    if not (group.type_id == "individ" and draft.group and draft.group.type_id == "area"):
        # don't overwrite an assigned area if it's still an individual
        # submission
        draft.group_id = group.pk
    draft.rev = submission.rev
    draft.pages = submission.pages
    draft.abstract = submission.abstract
    was_rfc = draft.get_state_slug() == "rfc"

    if not draft.stream:
        stream_slug = None
        if draft.name.startswith("draft-iab-"):
            stream_slug = "iab"
        elif draft.name.startswith("draft-irtf-"):
            stream_slug = "irtf"
        elif draft.name.startswith("draft-ietf-") and (draft.group.type_id != "individ" or was_rfc):
            stream_slug = "ietf"

        if stream_slug:
            draft.stream = StreamName.objects.get(slug=stream_slug)

    draft.expires = datetime.datetime.now() + datetime.timedelta(settings.INTERNET_DRAFT_DAYS_TO_EXPIRE)
    draft.save()

    submitter_parsed = submission.submitter_parsed()
    if submitter_parsed["name"] and submitter_parsed["email"]:
        submitter = ensure_person_email_info_exists(submitter_parsed["name"], submitter_parsed["email"]).person
        submitter_info = u'%s <%s>' % (submitter_parsed["name"], submitter_parsed["email"])
    else:
        submitter = system
        submitter_info = system.name

    draft.set_state(State.objects.get(used=True, type="draft", slug="active"))
    DocAlias.objects.get_or_create(name=submission.name, document=draft)

    update_authors(draft, submission)

    trouble = rebuild_reference_relations(draft, filename=os.path.join(settings.IDSUBMIT_STAGING_PATH, '%s-%s.txt' % (submission.name, submission.rev)))
    if trouble:
        log('Rebuild_reference_relations trouble: %s'%trouble)

    # new revision event
    e = NewRevisionDocEvent(type="new_revision", doc=draft, rev=draft.rev)
    e.time = draft.time #submission.submission_date
    e.by = submitter
    e.desc = "New version available: <b>%s-%s.txt</b>" % (draft.name, draft.rev)
    e.save()

    if draft.stream_id == "ietf" and draft.group.type_id == "wg" and draft.rev == "00":
        # automatically set state "WG Document"
        draft.set_state(State.objects.get(used=True, type="draft-stream-%s" % draft.stream_id, slug="wg-doc"))

    if draft.get_state_slug("draft-iana-review") in ("ok-act", "ok-noact", "not-ok"):
        prev_state = draft.get_state("draft-iana-review")
        next_state = State.objects.get(used=True, type="draft-iana-review", slug="changed")
        draft.set_state(next_state)
        add_state_change_event(draft, submitter, prev_state, next_state)

    # clean up old files
    if prev_rev != draft.rev:
        from ietf.doc.expire import move_draft_files_to_archive
        move_draft_files_to_archive(draft, prev_rev)

    # automatic state changes
    state_change_msg = ""

    if not was_rfc and draft.tags.filter(slug="need-rev"):
        draft.tags.remove("need-rev")
        draft.tags.add("ad-f-up")

        e = DocEvent(type="changed_document", doc=draft)
        e.desc = "Sub state has been changed to <b>AD Followup</b> from <b>Revised ID Needed</b>"
        e.by = system
        e.save()

        state_change_msg = e.desc

    move_files_to_repository(submission)
    submission.state = DraftSubmissionStateName.objects.get(slug="posted")

    new_replaces, new_possibly_replaces = update_replaces_from_submission(request, submission, draft)

    announce_to_lists(request, submission)
    announce_new_version(request, submission, draft, state_change_msg)
    announce_to_authors(request, submission)

    if new_possibly_replaces:
        send_review_possibly_replaces_request(request, draft, submitter_info)

    submission.save()
Example #12
0
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,
    })
Example #13
0
def edit_material(request,
                  name=None,
                  acronym=None,
                  action=None,
                  doc_type=None):
    # the materials process is not very developed, so at the moment we
    # handle everything through the same view/form

    if action == "new":
        group = get_object_or_404(Group, acronym=acronym)
        if not group.features.has_materials:
            raise Http404

        doc = None
        document_type = get_object_or_404(DocTypeName, slug=doc_type)
    else:
        doc = get_object_or_404(Document, name=name)
        group = doc.group
        document_type = doc.type

    if document_type not in DocTypeName.objects.filter(
            slug__in=group.features.material_types
    ) and document_type.slug not in [
            'minutes',
            'agenda',
            'bluesheets',
    ]:
        raise Http404

    if not can_manage_materials(request.user, group):
        return HttpResponseForbidden(
            "You don't have permission to access this view")

    if request.method == 'POST':
        form = UploadMaterialForm(document_type, action, group, doc,
                                  request.POST, request.FILES)

        if form.is_valid():
            events = []

            if action == "new":
                doc = Document.objects.create(type=document_type,
                                              group=group,
                                              rev="00",
                                              name=form.cleaned_data["name"])

                prev_rev = None
            else:
                prev_rev = doc.rev

            prev_title = doc.title
            prev_state = doc.get_state()
            prev_abstract = doc.abstract

            if "title" in form.cleaned_data:
                doc.title = form.cleaned_data["title"]

            if "abstract" in form.cleaned_data:
                doc.abstract = form.cleaned_data["abstract"]

            if "material" in form.fields:
                if action != "new":
                    doc.rev = "%02d" % (int(doc.rev) + 1)

                f = form.cleaned_data["material"]
                file_ext = os.path.splitext(f.name)[1]

                with open(
                        os.path.join(doc.get_file_path(),
                                     doc.name + "-" + doc.rev + file_ext),
                        'wb+') as dest:
                    for chunk in f.chunks():
                        dest.write(chunk)

            if action == "new":
                DocAlias.objects.get_or_create(name=doc.name, document=doc)

            if prev_rev != doc.rev:
                e = NewRevisionDocEvent(type="new_revision",
                                        doc=doc,
                                        rev=doc.rev)
                e.by = request.user.person
                e.desc = "New version available: <b>%s-%s</b>" % (doc.name,
                                                                  doc.rev)
                e.save()
                events.append(e)

            if prev_title != doc.title:
                e = DocEvent(doc=doc,
                             rev=doc.rev,
                             by=request.user.person,
                             type='changed_document')
                e.desc = u"Changed title to <b>%s</b>" % doc.title
                if prev_title:
                    e.desc += u" from %s" % prev_title
                e.save()
                events.append(e)

            if prev_abstract != doc.abstract:
                e = DocEvent(doc=doc,
                             rev=doc.rev,
                             by=request.user.person,
                             type='changed_document')
                e.desc = u"Changed abstract to <b>%s</b>" % doc.abstract
                if prev_abstract:
                    e.desc += u" from %s" % prev_abstract
                e.save()
                events.append(e)

            if "state" in form.cleaned_data and form.cleaned_data[
                    "state"] != prev_state:
                doc.set_state(form.cleaned_data["state"])
                e = add_state_change_event(doc, request.user.person,
                                           prev_state,
                                           form.cleaned_data["state"])
                events.append(e)

            if events:
                doc.save_with_history(events)

            return redirect("ietf.doc.views_doc.document_main", name=doc.name)
    else:
        form = UploadMaterialForm(document_type, action, group, doc)

    return render(
        request, 'doc/material/edit_material.html', {
            'group': group,
            'form': form,
            'action': action,
            'document_type': document_type,
            'doc_name': doc.name if doc else "",
        })