def handle_existing_account(request, users): if users.count() > 1: # There are only a few people in this situation, all of whom are # either editors themselves or definitely know how to easily get # in touch with an editor. return render_error(request, ('You already have multiple accounts with this email ' 'address. Please contact an editor to get your ' 'personal and/or shared accounts sorted out before ' 'adding a new one.')) user = users[0] if user.is_active: return render_error(request, 'You already have an active account with this email address. If ' 'you have forgotten your password, you may <a href="' + urlresolvers.reverse('forgot_password') + '">reset ' 'it</a>. If you feel you need a second account with this email, ' 'please <a href="mailto:%s">contact us</a>.' % settings.EMAIL_CONTACT, is_safe=True) elif not user.indexer.is_banned: # TODO: automatic reactivation, but have to merge fields? Complicated. return render_error(request, ('An account with this email address already exists, ' 'but is deactivated. Please ' '<a href="mailto:%s">contact us</a> ' 'if you would like to reactivate it.') % settings.EMAIL_CONTACT, is_safe=True) else: return render_error(request, 'A prior account with this email address has been ' 'shut down. Please contact an Editor if you believe ' 'this was done in error.')
def upload_cover(request, cover_id=None, issue_id=None): """ Handles uploading of covers be it - first upload - replacement upload - variant upload """ # this cannot actually happen if cover_id and issue_id: raise ValueError # if cover_id is present it is a replacement upload if cover_id: cover = get_object_or_404(Cover, id=cover_id) issue = cover.issue # no cover_id, therefore upload a cover to an issue (first or variant) else: issue = get_object_or_404(Issue, id=issue_id) if not issue.series.is_comics_publication: return render_error(request, 'No covers for non-comics publications.', redirect=False) cover = None # check if there is a pending issue deletion if IssueRevision.objects.filter(issue=issue, deleted=True, changeset__state__in=states.ACTIVE): revision = IssueRevision.objects.get(issue=issue, changeset__state__in=states.ACTIVE) return render_error(request, ('%s is <a href="%s">pending deletion</a>. Covers ' 'cannot be added or modified.') % (esc(issue), urlresolvers.reverse('compare', kwargs={'id': revision.changeset.id})), redirect=False, is_safe=True) # check if there is a pending change for the cover if cover_id and CoverRevision.objects.filter(cover=cover, changeset__state__in=states.ACTIVE): revision = CoverRevision.objects.get(cover=cover, changeset__state__in=states.ACTIVE) return render_error(request, ('There currently is a <a href="%s">pending replacement</a> ' 'for this cover of %s.') % (urlresolvers.reverse('compare', kwargs={'id': revision.changeset.id}), esc(cover.issue)), redirect=False, is_safe=True) # current request is an upload if request.method == 'POST': return handle_uploaded_cover(request, cover, issue) # request is a GET for the form else: if 'oi_file_source' in request.session: vars = {'source' : request.session['oi_file_source'], 'remember_source' : True} else: vars = None form = UploadScanForm(initial=vars) # display the form return _display_cover_upload_form(request, form, cover, issue)
def mentor_not_new(request, indexer_id): """ Marks a user as no longer needing a mentor and adjusts their limits accordingly. POST only, although a GET will redirect to the basic mentoring view. """ if not request.user.has_perm('gcd.can_mentor'): return render_error(request, 'You are not allowed to mentor new Indexers', redirect=False) indexer = get_object_or_404(Indexer, id=indexer_id) if indexer.mentor != request.user: return render_error( request, 'You are not allowed to change the state of this new Indexer', redirect=False) else: if request.method == 'POST': indexer.is_new = False indexer.max_reservations = max(settings.RESERVE_MAX_DEFAULT, indexer.max_reservations) indexer.max_ongoing = max(settings.RESERVE_MAX_ONGOING_DEFAULT, indexer.max_ongoing) indexer.save() return HttpResponseRedirect(urlresolvers.reverse('mentoring'))
def import_sequences_from_file(request, issue_id, changeset_id, use_csv = False): changeset = get_object_or_404(Changeset, id=changeset_id) if request.user != changeset.indexer: return render_error(request, 'Only the reservation holder may import stories.') try: # Process add form if this is a POST. if request.method == 'POST' and 'flatfile' in request.FILES: issue_revision = changeset.issuerevisions.get(issue=issue_id) if 'csv' in request.POST: use_csv = True else: use_csv = False lines, failure = _process_file(request, changeset, is_issue=False, use_csv=use_csv) if failure: return lines running_number = issue_revision.next_sequence_number() return _import_sequences(request, issue_id, changeset, lines, running_number) else: return HttpResponseRedirect(urlresolvers.reverse('edit', kwargs={ 'id': changeset.id })) except (Issue.DoesNotExist, Issue.MultipleObjectsReturned, IssueRevision.DoesNotExist): return render_error(request, 'Could not find issue for id %s and changeset %s' \ % (issue_id, changeset_id))
def mentor_not_new(request, indexer_id): """ Marks a user as no longer needing a mentor and adjusts their limits accordingly. POST only, although a GET will redirect to the basic mentoring view. """ if not request.user.has_perm('gcd.can_mentor'): return render_error(request, 'You are not allowed to mentor new Indexers', redirect=False) indexer = get_object_or_404(Indexer, id=indexer_id) if indexer.mentor != request.user: return render_error(request, 'You are not allowed to change the state of this new Indexer', redirect=False) else: if request.method == 'POST': indexer.is_new = False indexer.max_reservations = max(settings.RESERVE_MAX_DEFAULT, indexer.max_reservations) indexer.max_ongoing = max(settings.RESERVE_MAX_ONGOING_DEFAULT, indexer.max_ongoing) indexer.save() return HttpResponseRedirect(urlresolvers.reverse('mentoring'))
def confirm_account(request, key): try: indexer = Indexer.objects.get(registration_key=key) if date.today() > indexer.registration_expires: return render_error(request, 'Your confirmation key has expired. ' 'You may <a href="' + urlresolvers.reverse('register') + \ '">re-register</a>. ', is_safe=True ) indexer.user.is_active = True indexer.user.save() indexer.registration_key = None indexer.registration_expires = None indexer.save() email_body = u""" We have a new Indexer! Name: %s Email: %s Country: %s Languages: %s Interests: %s Mentor this indexer: %s """ % (indexer, indexer.user.email, indexer.country.name, ', '.join([lang.name for lang in indexer.languages.all()]), indexer.interests, 'http://' + request.get_host() + urlresolvers.reverse('mentor', kwargs={ 'indexer_id': indexer.id })) if settings.BETA: emailSubject = 'New BETA Indexer: %s' % indexer else: emailSubject = 'New Indexer: %s' % indexer send_mail(from_email=settings.EMAIL_NEW_ACCOUNTS_FROM, recipient_list=[settings.EMAIL_EDITORS], subject=emailSubject, message=email_body, fail_silently=(not settings.BETA)) return HttpResponseRedirect(urlresolvers.reverse('welcome')) except Indexer.DoesNotExist: return render_error(request, ('Invalid confirmation URL. Please make certain that you copied ' 'the URL from the email correctly. If it has been more than %d ' 'days, the confirmation code has expired and the account may have ' 'been deleted due to lack of confirmation.') % (settings.REGISTRATION_EXPIRATION_DELTA + 1)) except Indexer.MultipleObjectsReturned: return render_error(request, ('There is a problem with your confirmation key. Please email %s ' 'for assistance.') % settings.EMAIL_CONTACT)
def login(request, template_name): """ Do some pre-checking before handing off to the standard login view. If anything goes wrong just let the standard login handle it. """ if request.user.is_authenticated(): return HttpResponseRedirect(urlresolvers.reverse("default_profile")) try: if request.method == "POST": try: user = User.objects.get(email=request.POST["username"]) except (User.DoesNotExist, User.MultipleObjectsReturned): user = User.objects.get(username=request.POST["username"]) if user.indexer.registration_expires is not None: if date.today() > (user.indexer.registration_expires + timedelta(1)): return render_error( request, ( 'The account with the email "%s" was never confirmed ' 'and has expired. You may <a href="' + urlresolvers.reverse("register") + '">re-register</a>. ' ) % esc(user.email), is_safe=True, ) return render_error( request, ( 'The account with email "%s" has not yet been confirmed. ' "You should receive an email that gives you a URL to visit " "to confirm your account. After you have visited that URL " "you will be able to log in and use your account. Please " '<a href="mailto:%s">contact us</a> if you do not receive ' "the email within a few hours." ) % (esc(user.email), settings.EMAIL_CONTACT), is_safe=True, ) except User.DoesNotExist: pass if "next" in request.POST: next = request.POST["next"] if re.match(r"/accounts/confirm/", next, flags=re.I): post = request.POST.copy() post["next"] = urlresolvers.reverse("welcome") request.POST = post if re.match(r"/gcd-error/", next, flags=re.I): post = request.POST.copy() post["next"] = urlresolvers.reverse("home") request.POST = post return standard_login(request, template_name=template_name, authentication_form=LongUsernameAuthenticationForm)
def confirm_account(request, key): try: indexer = Indexer.objects.get(registration_key=key) if date.today() > indexer.registration_expires: return render_error(request, 'Your confirmation key has expired. ' 'You may <a href="' + urlresolvers.reverse('register') + \ '">re-register</a>. ', is_safe=True ) indexer.user.is_active = True indexer.user.save() indexer.registration_key = None indexer.registration_expires = None indexer.save() email_body = u""" We have a new Indexer! Name: %s Email: %s Country: %s Languages: %s Interests: %s Mentor this indexer: %s """ % (indexer, indexer.user.email, indexer.country.name, ', '.join( [lang.name for lang in indexer.languages.all()]), indexer.interests, 'http://' + request.get_host() + urlresolvers.reverse( 'mentor', kwargs={'indexer_id': indexer.id})) if settings.BETA: emailSubject = 'New BETA Indexer: %s' % indexer else: emailSubject = 'New Indexer: %s' % indexer send_mail(from_email=settings.EMAIL_NEW_ACCOUNTS_FROM, recipient_list=[settings.EMAIL_EDITORS], subject=emailSubject, message=email_body, fail_silently=(not settings.BETA)) return HttpResponseRedirect(urlresolvers.reverse('welcome')) except Indexer.DoesNotExist: return render_error(request, ( 'Invalid confirmation URL. Please make certain that you copied ' 'the URL from the email correctly. If it has been more than %d ' 'days, the confirmation code has expired and the account may have ' 'been deleted due to lack of confirmation.') % (settings.REGISTRATION_EXPIRATION_DELTA + 1)) except Indexer.MultipleObjectsReturned: return render_error( request, ('There is a problem with your confirmation key. Please email %s ' 'for assistance.') % settings.EMAIL_CONTACT)
def upload_cover(request, cover_id=None, issue_id=None): """ Handles uploading of covers be it - first upload - replacement upload - variant upload """ # this cannot actually happen if cover_id and issue_id: raise ValueError # if cover_id is present it is a replacement upload if cover_id: cover = get_object_or_404(Cover, id=cover_id) issue = cover.issue # no cover_id, therefore upload a cover to an issue (first or variant) else: issue = get_object_or_404(Issue, id=issue_id) cover = None # check if there is a pending issue deletion if IssueRevision.objects.filter(issue=issue, deleted=True, changeset__state__in=states.ACTIVE): revision = IssueRevision.objects.get(issue=issue, changeset__state__in=states.ACTIVE) return render_error(request, ('%s is <a href="%s">pending deletion</a>. Covers ' 'cannot be added or modified.') % (esc(issue), urlresolvers.reverse('compare', kwargs={'id': revision.changeset.id})), redirect=False, is_safe=True) # check if there is a pending change for the cover if cover_id and CoverRevision.objects.filter(cover=cover, changeset__state__in=states.ACTIVE): revision = CoverRevision.objects.get(cover=cover, changeset__state__in=states.ACTIVE) return render_error(request, ('There currently is a <a href="%s">pending replacement</a> ' 'for this cover of %s.') % (urlresolvers.reverse('compare', kwargs={'id': revision.changeset.id}), esc(cover.issue)), redirect=False, is_safe=True) # current request is an upload if request.method == 'POST': return handle_uploaded_cover(request, cover, issue) # request is a GET for the form else: if 'oi_file_source' in request.session: vars = {'source' : request.session['oi_file_source'], 'remember_source' : True} else: vars = None form = UploadScanForm(initial=vars) # display the form return _display_cover_upload_form(request, form, cover, issue)
def upload_image(request, model_name, id, image_type, image=None): from apps.oi.views import DISPLAY_CLASSES, REVISION_CLASSES """ Handles uploading of supporting images """ display_obj = get_object_or_404(DISPLAY_CLASSES[model_name], id=id, deleted=False) kwargs = None # replacement if image: if image.object != display_obj: return render_error(request, 'Image and object id do not match.', redirect=False, is_safe=True) kwargs = {'upload_type': 'replacement', 'current_image': image, 'current_image_tag': get_generic_image_tag(image, 'current image')} # check if there is an image if image_type.unique is set else: img_type = get_object_or_404(ImageType, name=image_type) if img_type.unique: if Image.objects.filter(content_type=\ ContentType.objects.get_for_model(display_obj), object_id=display_obj.id, type=img_type, deleted=False).count(): return render_error(request, ('%s has an image. Further images cannot be added, ' 'only replaced.') % (esc(display_obj)), redirect=False, is_safe=True) # check if there is a pending object deletion filter_dict = {model_name : display_obj, 'deleted' : True, 'changeset__state__in' : states.ACTIVE} revision = REVISION_CLASSES[model_name].objects.filter(**filter_dict) if revision: revision = revision.get() return render_error(request, ('%s is <a href="%s">pending deletion</a>. Images ' 'cannot be added or modified.') % (esc(display_obj), urlresolvers.reverse('compare', kwargs={'id': revision.changeset.id})), redirect=False, is_safe=True) # current request is an upload if request.method == 'POST': if image: return handle_uploaded_image(request, display_obj, model_name, image_type, current_image=image) else: return handle_uploaded_image(request, display_obj, model_name, image_type) # request is a GET for the form else: form = UploadImageForm() # display the form return _display_image_upload_form(request, form, display_obj, model_name, image_type, kwargs=kwargs)
def unmentor(request, indexer_id): indexer = get_object_or_404(Indexer, id=indexer_id) if indexer.mentor is None: return render_error(request, "This indexer does not have a mentor.") if request.user != indexer.mentor: return render_error(request, "You are not this indexer's mentor, so you may not un-mentor them.") if request.method == "POST": indexer.mentor = None indexer.save() return HttpResponseRedirect(urlresolvers.reverse("mentoring")) return render_error(request, "Please access this page through the proper form.")
def upload_variant(request, issue_id): """ Handles uploading of variant covers """ issue = get_object_or_404(Issue, id=issue_id) if issue.variant_of: return render_error( request, 'Variants can only be uploaded to the base issue.') # check if there is a pending issue deletion if IssueRevision.objects.filter(issue=issue, deleted=True, changeset__state__in=states.ACTIVE): revision = IssueRevision.objects.get( issue=issue, changeset__state__in=states.ACTIVE) return render_error( request, ('%s is <a href="%s">pending deletion</a>. Covers ' 'cannot be added or modified.') % (esc(issue), urlresolvers.reverse('compare', kwargs={'id': revision.changeset.id})), redirect=False, is_safe=True) # current request is an upload if request.method == 'POST': return handle_uploaded_cover(request, None, issue, variant=True) # request is a GET for the form else: if 'oi_file_source' in request.session: vars = { 'source': request.session['oi_file_source'], 'remember_source': True } else: vars = None form = UploadVariantScanForm(initial=vars) kwargs={'pending_variant_adds': Changeset.objects\ .filter(issuerevisions__variant_of=issue, #state__in=states.ACTIVE, state__in=[states.PENDING,states.REVIEWING], change_type__in=[CTYPES['issue_add'], CTYPES['variant_add']])} # display the form return _display_cover_upload_form(request, form, None, issue, variant=True, kwargs=kwargs)
def login(request, template_name, landing_view='default_profile'): """ Do some pre-checking before handing off to the standard login view. If anything goes wrong just let the standard login handle it. """ if request.user.is_authenticated(): return HttpResponseRedirect(urlresolvers.reverse(landing_view)) try: if request.method == "POST": try: user = User.objects.get(email=request.POST['username']) except (User.DoesNotExist, User.MultipleObjectsReturned): user = User.objects.get(username=request.POST['username']) if user.indexer.registration_expires is not None: if date.today() > (user.indexer.registration_expires + timedelta(1)): return render_error(request, ('The account with the email "%s" was never confirmed ' 'and has expired. You may <a href="' + \ urlresolvers.reverse('register') + \ '">re-register</a>. ') % esc(user.email), is_safe=True ) return render_error( request, ('The account with email "%s" has not yet been confirmed. ' 'You should receive an email that gives you a URL to visit ' 'to confirm your account. After you have visited that URL ' 'you will be able to log in and use your account. Please ' '<a href="mailto:%s">contact us</a> if you do not receive ' 'the email within a few hours.') % (esc(user.email), settings.EMAIL_CONTACT), is_safe=True) except User.DoesNotExist: pass if 'next' in request.POST: next = request.POST['next'] if re.match(r'/accounts/confirm/', next, flags=re.I): post = request.POST.copy() post['next'] = urlresolvers.reverse('welcome') request.POST = post if re.match(r'/gcd-error/', next, flags=re.I): post = request.POST.copy() post['next'] = urlresolvers.reverse('home') request.POST = post return standard_login(request, template_name=template_name, authentication_form=LongUsernameAuthenticationForm)
def unmentor(request, indexer_id): indexer = get_object_or_404(Indexer, id=indexer_id) if indexer.mentor is None: return render_error(request, "This indexer does not have a mentor.") if request.user != indexer.mentor: return render_error(request, "You are not this indexer's mentor, so you may not un-mentor them.") if request.method == 'POST': indexer.mentor = None indexer.save() return HttpResponseRedirect(urlresolvers.reverse('mentoring')) return render_error(request, 'Please access this page through the proper form.')
def handle_uploaded_image(request, display_obj, model_name, image_type, current_image=None): ''' process the uploaded file and generate ImageRevision ''' try: form = UploadImageForm(request.POST, request.FILES) except IOError: # sometimes uploads misbehave. connection dropped ? error_text = 'Something went wrong with the upload. ' + \ 'Please <a href="' + request.path + '">try again</a>.' return render_error(request, error_text, redirect=False, is_safe=True) if not form.is_valid(): return _display_image_upload_form(request, form, display_obj, model_name, image_type) # process form image = form.cleaned_data['image'] if current_image: from apps.oi.views import _is_reservable is_reservable = _is_reservable('image', current_image.id) if is_reservable == 0: return render_error(request, u'Cannot replace %s as it is already reserved.' % \ current_image.description()) # create OI records changeset = Changeset(indexer=request.user, state=states.OPEN, change_type=CTYPES['image']) changeset.save() revision = ImageRevision( changeset=changeset, content_type=ContentType.objects.get_for_model(display_obj), object_id=display_obj.id, type=ImageType.objects.get(name=image_type), marked=form.cleaned_data['marked']) if current_image: revision.image = current_image revision.is_replacement = True revision.save() revision.image_file.save(str(revision.id) + '.jpg', content=File(image)) revision.changeset.submit(form.cleaned_data['comments']) return HttpResponseRedirect(urlresolvers.reverse('editing'))
def logout(request): """ Handle logout. Prevent GET requests from having side effects (such as logging the user out). Don't leave the site on a user's error message after the user logs out. """ if request.method == "POST": next_page = request.POST["next"] if re.match(urlresolvers.reverse("error"), next_page): next_page = "/" return standard_logout(request, next_page=next_page) elif request.user.is_authenticated(): return render_error(request, "Please use the logout button to log out.") return render_error(request, "Cannot logout because you are not logged in.")
def mentor_not_new(request, indexer_id): if not request.user.has_perm("gcd.can_mentor"): return render_error(request, "You are not allowed to mentor new Indexers", redirect=False) indexer = get_object_or_404(Indexer, id=indexer_id) if indexer.mentor != request.user: return render_error(request, "You are not allowed to change the state of this new Indexer", redirect=False) else: if request.method == "POST": indexer.is_new = False indexer.max_reservations = max(settings.RESERVE_MAX_DEFAULT, indexer.max_reservations) indexer.max_ongoing = max(settings.RESERVE_MAX_ONGOING_DEFAULT, indexer.max_ongoing) indexer.save() return HttpResponseRedirect(urlresolvers.reverse("mentoring"))
def profile(request, user_id=None, edit=False): """ View method to display (with this method) or edit (using the update_profile method) the user's profile data. """ if request.method == 'POST': return update_profile(request, user_id) if not request.user.is_authenticated(): return HttpResponseRedirect(urlresolvers.reverse('login')) if user_id is None: return HttpResponseRedirect( urlresolvers.reverse('view_profile', kwargs={'user_id': request.user.id})) else: profile_user = get_object_or_404(User, id=user_id) context = {'profile_user': profile_user, 'settings': settings} if edit is True: if profile_user == request.user: form = ProfileForm( auto_id=True, initial={ 'email': profile_user.email, 'first_name': profile_user.first_name, 'last_name': profile_user.last_name, 'country': profile_user.indexer.country.id, 'languages': [lang.id for lang in profile_user.indexer.languages.all()], 'interests': profile_user.indexer.interests, 'from_where': profile_user.indexer.from_where, 'opt_in_email': profile_user.indexer.opt_in_email, 'issue_detail': profile_user.indexer.issue_detail, 'notify_on_approve': profile_user.indexer.notify_on_approve, 'collapse_compare_view': profile_user.indexer.collapse_compare_view, 'show_wiki_links': profile_user.indexer.show_wiki_links, }) context['form'] = form else: return render_error(request, "You may not edit other users' profiles") if profile_user == request.user: context['ranking'] = ranking(profile_user.indexer) return render_to_response('gcd/accounts/profile.html', context, context_instance=RequestContext(request))
def flip_artwork_flag(request, revision_id=None): """ flips the status in regard to variants with different cover artwork """ cover = get_object_or_404(CoverRevision, id=revision_id) changeset = cover.changeset if request.user != changeset.approver: return render_error( request, 'The variant artwork status may only be changed by the approver.') story = list(changeset.storyrevisions.all()) if len(story) == 1: for s in story: s.delete() elif len(story) == 0: story_revision = StoryRevision( changeset=changeset, type=StoryType.objects.get(name='cover'), pencils='?', inks='?', colors='?', sequence_number=0, page_count=2 if cover.is_wraparound else 1, ) story_revision.save() else: # this should never happen raise ValueError, 'More than one story sequence in a cover revision.' return HttpResponseRedirect( urlresolvers.reverse('compare', kwargs={'id': cover.changeset.id}))
def get_collection_for_owner(request, collection_id): collection = get_object_or_404(Collection, id=collection_id) if collection.collector.user != request.user: return render_error(request, 'Only the owner of a collection can add issues to it.', redirect=False) return collection
def profile(request, user_id=None, edit=False): if request.method == "POST": return update_profile(request, user_id) if not request.user.is_authenticated(): return HttpResponseRedirect(urlresolvers.reverse("login")) if user_id is None: return HttpResponseRedirect(urlresolvers.reverse("view_profile", kwargs={"user_id": request.user.id})) else: profile_user = get_object_or_404(User, id=user_id) context = {"profile_user": profile_user, "settings": settings} if edit is True: if profile_user == request.user: form = ProfileForm( auto_id=True, initial={ "email": profile_user.email, "first_name": profile_user.first_name, "last_name": profile_user.last_name, "country": profile_user.indexer.country.id, "languages": [lang.id for lang in profile_user.indexer.languages.all()], "interests": profile_user.indexer.interests, "notify_on_approve": profile_user.indexer.notify_on_approve, "collapse_compare_view": profile_user.indexer.collapse_compare_view, "show_wiki_links": profile_user.indexer.show_wiki_links, }, ) context["form"] = form else: return render_error(request, "You may not edit other users' profiles") return render_to_response("gcd/accounts/profile.html", context, context_instance=RequestContext(request))
def get_collection_for_owner(request, collection_id): collection = get_object_or_404(Collection, id=collection_id) if collection.collector.user != request.user: return None, render_error(request, 'Only the owner of a collection can add issues to it.', redirect=False) return collection, None
def replace_image(request, model_name, id, image_id): image = get_object_or_404(Image, id=image_id, deleted=False) if image.reserved: return render_error(request, ('%s is reserved.') % (image.description()), redirect=False, is_safe=True) return upload_image(request, model_name, id, image.type.name, image=image)
def mark_cover(request, cover_id): """ marks the cover of the issue for replacement """ # TODO: once we have permissions 'can_mark' should be one if request.user.is_authenticated() and \ request.user.groups.filter(name='editor'): # check for issue and cover cover = get_object_or_404(Cover, id=cover_id) cover.marked = True cover.save() # I kinda assume the HTTP_REFERER is always present, but just in case if request.META.has_key('HTTP_REFERER'): return HttpResponseRedirect(request.META['HTTP_REFERER']) else: cover_tag = get_image_tag(cover, "Cover Image", 2) return render_to_response('gcd/details/cover_marked.html', { 'issue': cover.issue, 'cover_tag': cover_tag, 'error_subject': '%s cover' % cover.issue, 'style': 'default', }, context_instance=RequestContext(request)) else: return render_error( request, 'You are not allowed to mark covers for replacement.', redirect=False)
def mentor(request, indexer_id): if not request.user.has_perm('gcd.can_mentor'): return render_error(request, 'You are not allowed to mentor new Indexers', redirect=False) indexer = get_object_or_404(Indexer, id=indexer_id) if request.method == 'POST' and indexer.mentor is None: indexer.mentor = request.user indexer.save() pending = indexer.user.changesets.filter(state=states.PENDING) for changeset in pending.all(): try: changeset.assign(approver=request.user, notes='') except ValueError: # Someone is already reviewing this. Unlikely, and just let it go. pass if pending.count(): return HttpResponseRedirect(urlresolvers.reverse('reviewing')) # I kinda assume the HTTP_REFERER is always present, but just in case if 'HTTP_REFERER' in request.META: return HttpResponseRedirect(request.META['HTTP_REFERER']) return render_to_response('gcd/accounts/mentor.html', {'indexer': indexer}, context_instance=RequestContext(request))
def mentor(request, indexer_id): if not request.user.has_perm('gcd.can_mentor'): return render_error(request, 'You are not allowed to mentor new Indexers', redirect=False) indexer = get_object_or_404(Indexer, id=indexer_id) if request.method == 'POST' and indexer.mentor is None: indexer.mentor = request.user indexer.save() pending = indexer.user.changesets.filter(state=states.PENDING) for changeset in pending.all(): try: changeset.assign(approver=request.user, notes='') except ValueError: # Someone is already reviewing this. Unlikely, and just let it go. pass if pending.count(): return HttpResponseRedirect(urlresolvers.reverse('reviewing')) # I kinda assume the HTTP_REFERER is always present, but just in case if 'HTTP_REFERER' in request.META: return HttpResponseRedirect(request.META['HTTP_REFERER']) return render_to_response('gcd/accounts/mentor.html', { 'indexer' : indexer }, context_instance=RequestContext(request))
def profile(request, user_id=None, edit=False): if request.method == 'POST': return update_profile(request, user_id) if not request.user.is_authenticated(): return HttpResponseRedirect(urlresolvers.reverse('login')) if user_id is None: return HttpResponseRedirect( urlresolvers.reverse('view_profile', kwargs={'user_id': request.user.id})) else: profile_user = get_object_or_404(User, id=user_id) context = { 'profile_user': profile_user } if edit is True: if profile_user == request.user: form = ProfileForm(auto_id=True, initial={ 'email': profile_user.email, 'first_name': profile_user.first_name, 'last_name': profile_user.last_name, 'country': profile_user.indexer.country.id, 'languages': [ lang.id for lang in profile_user.indexer.languages.all() ], 'interests': profile_user.indexer.interests, }) context['form'] = form else: return render_error(request, "You may not edit other users' profiles") return render_to_response('gcd/accounts/profile.html', context, context_instance=RequestContext(request))
def flip_artwork_flag(request, revision_id=None): """ flips the status in regard to variants with different cover artwork """ cover = get_object_or_404(CoverRevision, id=revision_id) changeset = cover.changeset if request.user != changeset.approver: return render_error(request, 'The variant artwork status may only be changed by the approver.') story = list(changeset.storyrevisions.all()) if len(story) == 1: for s in story: s.delete() elif len(story) == 0: story_revision = StoryRevision(changeset=changeset, type=StoryType.objects.get(name='cover'), pencils='?', inks='?', colors='?', sequence_number=0, page_count=2 if cover.is_wraparound else 1, ) story_revision.save() else: # this should never happen raise ValueError, 'More than one story sequence in a cover revision.' return HttpResponseRedirect(urlresolvers.reverse('compare', kwargs={'id': cover.changeset.id} ))
def mark_cover(request, cover_id): """ marks the cover of the issue for replacement """ # TODO: once we have permissions 'can_mark' should be one if request.user.is_authenticated() and \ request.user.groups.filter(name='editor'): # check for issue and cover cover = get_object_or_404(Cover, id=cover_id) cover.marked = True cover.save() # I kinda assume the HTTP_REFERER is always present, but just in case if request.META.has_key('HTTP_REFERER'): return HttpResponseRedirect(request.META['HTTP_REFERER']) else: cover_tag = get_image_tag(cover, "Cover Image", 2) return render_to_response( 'gcd/details/cover_marked.html', { 'issue': cover.issue, 'cover_tag': cover_tag, 'error_subject': '%s cover' % cover.issue, 'style': 'default', }, context_instance=RequestContext(request) ) else: return render_error(request, 'You are not allowed to mark covers for replacement.', redirect=False)
def delete_cover(request, id): cover = get_object_or_404(Cover, id=id) # check if there is a pending change for the cover try: revision = CoverRevision.objects.get(cover=cover, changeset__state__in=states.ACTIVE) return render_error(request, ('There currently is a <a href="%s">pending replacement</a> ' 'for this cover of %s.') % (urlresolvers.reverse('compare', kwargs={'id': revision.changeset.id}), esc(cover.issue)), redirect=False, is_safe=True) except: revision = None changeset = Changeset(indexer=request.user, state=states.PENDING, change_type=CTYPES['cover']) changeset.save() revision = CoverRevision(changeset=changeset, issue=cover.issue, cover=cover, deleted=True) revision.save() comments = request.POST['comments'] changeset.comments.create(commenter=request.user, text=comments, old_state=states.UNRESERVED, new_state=changeset.state) return HttpResponseRedirect(urlresolvers.reverse('edit_covers', kwargs={'issue_id': cover.issue.id}))
def update_profile(request, user_id=None): """ Helper method to perform the update if the main profile view detects a POST request. """ if request.user.id != int(user_id): return render_error(request, 'You may only edit your own profile.') errors = [] form = ProfileForm(request.POST) if not form.is_valid(): return render_to_response('gcd/accounts/profile.html', {'form': form}, context_instance=RequestContext(request)) set_password = False old = form.cleaned_data['old_password'] new = form.cleaned_data['new_password'] confirm = form.cleaned_data['confirm_new_password'] if (new or confirm) and not old: errors.append( u'You must supply your old password in order to change it.') elif old and (new or confirm): if not request.user.check_password(old): errors.append(u'Old password incorrect, please try again.') elif new != confirm: errors.append( u'New password and confirm new password do not match.') else: set_password = True if errors: return render_to_response('gcd/accounts/profile.html', { 'form': form, 'error_list': errors }, context_instance=RequestContext(request)) request.user.first_name = form.cleaned_data['first_name'] request.user.last_name = form.cleaned_data['last_name'] request.user.email = form.cleaned_data['email'] if set_password is True: request.user.set_password(new) request.user.save() indexer = request.user.indexer indexer.notify_on_approve = form.cleaned_data['notify_on_approve'] indexer.collapse_compare_view = form.cleaned_data['collapse_compare_view'] indexer.show_wiki_links = form.cleaned_data['show_wiki_links'] indexer.country = form.cleaned_data['country'] indexer.languages = form.cleaned_data['languages'] indexer.interests = form.cleaned_data['interests'] indexer.from_where = form.cleaned_data['from_where'] indexer.opt_in_email = form.cleaned_data['opt_in_email'] indexer.issue_detail = form.cleaned_data['issue_detail'] indexer.save() return HttpResponseRedirect( urlresolvers.reverse('view_profile', kwargs={'user_id': request.user.id}))
def process_response(self, request, response): if request.user.is_authenticated(): logout(request) return render_error(request, "Online editing is currently turned " "off, no user can login. We are working on the site. " "More information on the <a href='/'>main page</a>.", redirect=False, is_safe=True) return response
def logout(request): """ Handle logout. Prevent GET requests from having side effects (such as logging the user out). Don't leave the site on a user's error message after the user logs out. """ if request.method == 'POST': next_page = request.POST['next'] if re.match(urlresolvers.reverse('error'), next_page): next_page = '/' return standard_logout(request, next_page=next_page) elif request.user.is_authenticated(): return render_error(request, 'Please use the logout button to log out.') return render_error(request, 'Cannot logout because you are not logged in.')
def update_profile(request, user_id=None): """ Helper method to perform the update if the main profile view detects a POST request. """ if request.user.id != int(user_id): return render_error(request, 'You may only edit your own profile.') errors = [] form = ProfileForm(request.POST) if not form.is_valid(): return render_to_response('gcd/accounts/profile.html', { 'form': form }, context_instance=RequestContext(request)) set_password = False old = form.cleaned_data['old_password'] new = form.cleaned_data['new_password'] confirm = form.cleaned_data['confirm_new_password'] if (new or confirm) and not old: errors.append( u'You must supply your old password in order to change it.') elif old and (new or confirm): if not request.user.check_password(old): errors.append(u'Old password incorrect, please try again.') elif new != confirm: errors.append( u'New password and confirm new password do not match.') else: set_password = True if errors: return render_to_response('gcd/accounts/profile.html', { 'form': form, 'error_list': errors }, context_instance=RequestContext(request)) request.user.first_name = form.cleaned_data['first_name'] request.user.last_name = form.cleaned_data['last_name'] request.user.email = form.cleaned_data['email'] if set_password is True: request.user.set_password(new) request.user.save() indexer = request.user.indexer indexer.notify_on_approve = form.cleaned_data['notify_on_approve'] indexer.collapse_compare_view = form.cleaned_data['collapse_compare_view'] indexer.show_wiki_links = form.cleaned_data['show_wiki_links'] indexer.country = form.cleaned_data['country'] indexer.languages = form.cleaned_data['languages'] indexer.interests = form.cleaned_data['interests'] indexer.from_where = form.cleaned_data['from_where'] indexer.opt_in_email = form.cleaned_data['opt_in_email'] indexer.issue_detail = form.cleaned_data['issue_detail'] indexer.save() return HttpResponseRedirect( urlresolvers.reverse('view_profile', kwargs={'user_id': request.user.id}))
def unmentor(request, indexer_id): """ Releases a user from being mentored. POST only. This is NOT for "graduating" a user into not needing a mentor. It is for releasing the new user to find another mentor. """ indexer = get_object_or_404(Indexer, id=indexer_id) if indexer.mentor is None: return render_error(request, "This indexer does not have a mentor.") if request.user != indexer.mentor: return render_error(request, "You are not this indexer's mentor, so you may not un-mentor them.") if request.method == 'POST': indexer.mentor = None indexer.save() return HttpResponseRedirect(urlresolvers.reverse('mentoring')) return render_error(request, 'Please access this page through the proper form.')
def mentor_not_new(request, indexer_id): if not request.user.has_perm('gcd.can_mentor'): return render_error(request, 'You are not allowed to mentor new Indexers', redirect=False) indexer = get_object_or_404(Indexer, id=indexer_id) if indexer.mentor != request.user: return render_error(request, 'You are not allowed to change the state of this new Indexer', redirect=False) else: if request.method == 'POST': indexer.is_new = False indexer.max_reservations = settings.RESERVE_MAX_DEFAULT indexer.max_ongoing = settings.RESERVE_MAX_ONGOING_DEFAULT indexer.save() return HttpResponseRedirect(urlresolvers.reverse('mentoring'))
def login(request, template_name): """ Do some pre-checking before handing off to the standard login view. If anything goes wrong just let the standard login handle it. """ if request.user.is_authenticated(): return HttpResponseRedirect(urlresolvers.reverse('default_profile')) try: if request.method == "POST": user = User.objects.get(username=request.POST['username']) if user.indexer.registration_key is not None: if date.today() > (user.indexer.registration_expires + timedelta(1)): return render_error(request, ('The account with the email "%s" was never confirmed ' 'and has expired. You may <a href="' + \ urlresolvers.reverse('register') + \ '">re-register</a>. ') % esc(user.email), is_safe=True ) return render_error(request, ('The account with email "%s" has not yet been confirmed. ' 'You should receive an email that gives you a URL to visit ' 'to confirm your account. After you have visited that URL ' 'you will be able to log in and use your account. Please ' '<a href="mailto:%s">contact us</a> if you do not receive ' 'the email within a few hours.') % (esc(user.email), settings.EMAIL_CONTACT), is_safe=True) except Exception: pass if 'next' in request.POST: next = request.POST['next'] if re.match(r'/accounts/confirm/', next, flags=re.I): post = request.POST.copy() post['next'] = urlresolvers.reverse('welcome') request.POST = post if re.match(r'/gcd-error/', next, flags=re.I): post = request.POST.copy() post['next'] = urlresolvers.reverse('home') request.POST = post return standard_login(request, template_name=template_name)
def process_response(self, request, response): if request.user.is_authenticated(): logout(request) return render_error( request, "Online editing is currently turned " "off, no user can login. We are working on the site. " "More information on the <a href='/'>main page</a>.", redirect=False, is_safe=True) return response
def dummy(request, id=None, issue_id=None, model_name=None, image_type=None, image_id=None): return render_error(request, \ "Online editing and change history are currently turned off. " "We are working on the site. More information on the " "<a href='/'>main page</a>.", redirect=False, is_safe=True)
def handle_uploaded_image(request, display_obj, model_name, image_type, current_image=None): ''' process the uploaded file and generate ImageRevision ''' try: form = UploadImageForm(request.POST, request.FILES) except IOError: # sometimes uploads misbehave. connection dropped ? error_text = 'Something went wrong with the upload. ' + \ 'Please <a href="' + request.path + '">try again</a>.' return render_error(request, error_text, redirect=False, is_safe=True) if not form.is_valid(): return _display_image_upload_form(request, form, display_obj, model_name, image_type) # process form image = form.cleaned_data['image'] if current_image: from apps.oi.views import _is_reservable is_reservable = _is_reservable('image', current_image.id) if is_reservable == 0: return render_error(request, u'Cannot replace %s as it is already reserved.' % \ current_image.description()) # create OI records changeset = Changeset(indexer=request.user, state=states.OPEN, change_type=CTYPES['image']) changeset.save() revision = ImageRevision(changeset=changeset, content_type=ContentType.objects.get_for_model(display_obj), object_id=display_obj.id, type=ImageType.objects.get(name=image_type), marked=form.cleaned_data['marked']) if current_image: revision.image = current_image revision.is_replacement = True revision.save() revision.image_file.save(str(revision.id) + '.jpg', content=File(image)) revision.changeset.submit(form.cleaned_data['comments']) return HttpResponseRedirect(urlresolvers.reverse('editing'))
def _handle_import_error(request, changeset, error_text): response = render_error(request, '%s Back to the <a href="%s">editing page</a>.' % \ (error_text, urlresolvers.reverse('edit', kwargs={'id': changeset.id})), is_safe=True) # there might be a temporary file attached if hasattr(request, "tmpfile"): request.tmpfile.close() os.remove(request.tmpfile_name) return response, True
def upload_variant(request, issue_id): """ Handles uploading of variant covers """ issue = get_object_or_404(Issue, id=issue_id) if issue.variant_of: return render_error(request, 'Variants can only be uploaded to the base issue.') # check if there is a pending issue deletion if IssueRevision.objects.filter(issue=issue, deleted=True, changeset__state__in=states.ACTIVE): revision = IssueRevision.objects.get(issue=issue, changeset__state__in=states.ACTIVE) return render_error(request, ('%s is <a href="%s">pending deletion</a>. Covers ' 'cannot be added or modified.') % (esc(issue), urlresolvers.reverse('compare', kwargs={'id': revision.changeset.id})), redirect=False, is_safe=True) # current request is an upload if request.method == 'POST': return handle_uploaded_cover(request, None, issue, variant=True) # request is a GET for the form else: if 'oi_file_source' in request.session: vars = {'source' : request.session['oi_file_source'], 'remember_source' : True} else: vars = None form = UploadVariantScanForm(initial=vars) kwargs={'pending_variant_adds': Changeset.objects\ .filter(issuerevisions__variant_of=issue, #state__in=states.ACTIVE, state__in=[states.PENDING,states.REVIEWING], change_type__in=[CTYPES['issue_add'], CTYPES['variant_add']])} # display the form return _display_cover_upload_form(request, form, None, issue, variant=True, kwargs=kwargs)
def unmentor(request, indexer_id): """ Releases a user from being mentored. POST only. This is NOT for "graduating" a user into not needing a mentor. It is for releasing the new user to find another mentor. """ indexer = get_object_or_404(Indexer, id=indexer_id) if indexer.mentor is None: return render_error(request, "This indexer does not have a mentor.") if request.user != indexer.mentor: return render_error( request, "You are not this indexer's mentor, so you may not un-mentor them." ) if request.method == 'POST': indexer.mentor = None indexer.save() return HttpResponseRedirect(urlresolvers.reverse('mentoring')) return render_error(request, 'Please access this page through the proper form.')
def mentor(request, indexer_id): if not request.user.has_perm("gcd.can_mentor"): return render_error(request, "You are not allowed to mentor new Indexers", redirect=False) indexer = get_object_or_404(Indexer, id=indexer_id) if request.method == "POST": indexer.mentor = request.user indexer.save() return render_to_response( "gcd/accounts/mentor.html", {"indexer": indexer}, context_instance=RequestContext(request) )
def character_by_name(request, character_name, sort=ORDER_ALPHA): """Find stories based on characters. Since characters for whom a feature is named are often not also listed under character appearances, this search looks at both the feature and characters fields.""" if len(character_name) < 4: return render_error(request, 'A search for characters must use more than 3 letters.', redirect=False) q_obj = Q(characters__icontains=character_name) | \ Q(feature__icontains=character_name) return generic_by_name(request, character_name, q_obj, sort, credit="characters:" + character_name)
def mentor(request, indexer_id): if not request.user.has_perm('gcd.can_mentor'): return render_error(request, 'You are not allowed to mentor new Indexers', redirect=False) indexer = get_object_or_404(Indexer, id=indexer_id) if request.method == 'POST': indexer.mentor = request.user indexer.save() return render_to_response('gcd/accounts/mentor.html', {'indexer': indexer}, context_instance=RequestContext(request))
def vote(request): option = get_object_or_404(Option, id=request.POST['option']) if 'rank' in request.POST: rank = request.POST['rank'].strip() else: rank = None if option.topic.token is not None and \ request.POST['token'].strip() != option.topic.token: return render_error(request, 'You must supply an authorization token in order to vote on this topic.') vote = Vote(option=option, voter=request.user, rank=rank) vote.save() return HttpResponseRedirect(urlresolvers.reverse('ballot', kwargs={ 'id': option.topic.id }))
def mentor(request, indexer_id): if not request.user.has_perm('gcd.can_mentor'): return render_error(request, 'You are not allowed to mentor new Indexers', redirect=False) indexer = get_object_or_404(Indexer, id=indexer_id) if request.method == 'POST' and indexer.mentor is None: indexer.mentor = request.user indexer.save() # I kinda assume the HTTP_REFERER is always present, but just in case if request.META.has_key('HTTP_REFERER'): return HttpResponseRedirect(request.META['HTTP_REFERER']) return render_to_response('gcd/accounts/mentor.html', {'indexer': indexer}, context_instance=RequestContext(request))
def mentor(request, indexer_id): if not request.user.has_perm('gcd.can_mentor'): return render_error(request, 'You are not allowed to mentor new Indexers', redirect=False) indexer = get_object_or_404(Indexer, id=indexer_id) if request.method == 'POST' and indexer.mentor is None: indexer.mentor = request.user indexer.save() # I kinda assume the HTTP_REFERER is always present, but just in case if request.META.has_key('HTTP_REFERER'): return HttpResponseRedirect(request.META['HTTP_REFERER']) return render_to_response('gcd/accounts/mentor.html', { 'indexer' : indexer }, context_instance=RequestContext(request))
def profile(request, user_id=None, edit=False): """ View method to display (with this method) or edit (using the update_profile method) the user's profile data. """ if request.method == 'POST': return update_profile(request, user_id) if not request.user.is_authenticated(): return HttpResponseRedirect(urlresolvers.reverse('login')) if user_id is None: return HttpResponseRedirect( urlresolvers.reverse('view_profile', kwargs={'user_id': request.user.id})) else: profile_user = get_object_or_404(User, id=user_id) context = { 'profile_user': profile_user, 'settings': settings } if edit is True: if profile_user == request.user: form = ProfileForm(auto_id=True, initial={ 'email': profile_user.email, 'first_name': profile_user.first_name, 'last_name': profile_user.last_name, 'country': profile_user.indexer.country.id, 'languages': [ lang.id for lang in profile_user.indexer.languages.all() ], 'interests': profile_user.indexer.interests, 'from_where': profile_user.indexer.from_where, 'opt_in_email': profile_user.indexer.opt_in_email, 'issue_detail': profile_user.indexer.issue_detail, 'notify_on_approve': profile_user.indexer.notify_on_approve, 'collapse_compare_view': profile_user.indexer.collapse_compare_view, 'show_wiki_links': profile_user.indexer.show_wiki_links, }) context['form'] = form else: return render_error(request, "You may not edit other users' profiles") if profile_user == request.user: context['ranking'] = ranking(profile_user.indexer) return render_to_response('gcd/accounts/profile.html', context, context_instance=RequestContext(request))
def topic(request, id): topic = get_object_or_404(Topic, id=id) if not request.user.has_perm('gcd.can_vote'): return render_error( request, 'You do not have permission to vote on this topic.') # Note that if this was a secret ballot, this will be an empty # queryset. That is OK, the UI won't look at it in that case. # But this is why "voted" is not just a check for at least one vote here. votes = topic.options.filter(votes__voter=request.user) return render_to_response('voting/topic.html', { 'topic': topic, 'voted': topic.has_vote_from(request.user), 'votes': votes, 'closed': topic.deadline < datetime.now(), 'settings': settings, }, context_instance=RequestContext(request))
def profile(request, user_id=None, edit=False): if request.method == 'POST': return update_profile(request, user_id) if user_id is None: if request.user.is_authenticated(): return HttpResponseRedirect( urlresolvers.reverse('view_profile', kwargs={'user_id': request.user.id})) else: return HttpResponseRedirect(urlresolvers.reverse('login')) profile_user = request.user else: profile_user = get_object_or_404(User, id=user_id) context = {'profile_user': profile_user} if edit is True: if profile_user == request.user: form = ProfileForm( auto_id=True, initial={ 'email': profile_user.email, 'first_name': profile_user.first_name, 'last_name': profile_user.last_name, 'country': profile_user.indexer.country.id, 'languages': [lang.id for lang in profile_user.indexer.languages.all()], 'interests': profile_user.indexer.interests, }) context['form'] = form else: return render_error(request, "You may not edit other users' profiles") return render_to_response('gcd/accounts/profile.html', context, context_instance=RequestContext(request))
def topic(request, id): topic = get_object_or_404(Topic, id=id) voted = False votes = [] if not request.user.has_perm('gcd.can_vote'): return render_error( request, 'You do not have permission to vote on this topic.') votes = topic.options.filter(votes__voter=request.user) receipts = topic.receipts.filter(voter=request.user) voted = votes.count() > 0 or receipts.count() > 0 return render_to_response('voting/topic.html', { 'topic': topic, 'voted': voted, 'votes': votes, 'closed': topic.deadline < datetime.now(), 'settings': settings, }, context_instance=RequestContext(request))
def delete_cover(request, id): cover = get_object_or_404(Cover, id=id) # check if there is a pending change for the cover try: revision = CoverRevision.objects.get( cover=cover, changeset__state__in=states.ACTIVE) return render_error( request, ('There currently is a <a href="%s">pending replacement</a> ' 'for this cover of %s.') % (urlresolvers.reverse( 'compare', kwargs={'id': revision.changeset.id }), esc(cover.issue)), redirect=False, is_safe=True) except: revision = None changeset = Changeset(indexer=request.user, state=states.PENDING, change_type=CTYPES['cover']) changeset.save() revision = CoverRevision(changeset=changeset, issue=cover.issue, cover=cover, deleted=True) revision.save() comments = request.POST['comments'] changeset.comments.create(commenter=request.user, text=comments, old_state=states.UNRESERVED, new_state=changeset.state) return HttpResponseRedirect( urlresolvers.reverse('edit_covers', kwargs={'issue_id': cover.issue.id}))
def upload_cover(request, cover_id=None, issue_id=None): """ Handles uploading of covers be it - first upload - replacement upload - variant upload """ # this cannot actually happen if cover_id and issue_id: raise ValueError upload_template = 'oi/edit/upload_cover.html' style = 'default' # set cover, issue, covers, replace_cover, upload_type covers = [] replace_cover = None # if cover_id is present it is a replacement upload if cover_id: cover = get_object_or_404(Cover, id=cover_id) issue = cover.issue # check if there is a pending change for the cover if CoverRevision.objects.filter(cover=cover, changeset__state__in=states.ACTIVE): revision = CoverRevision.objects.get( cover=cover, changeset__state__in=states.ACTIVE) return render_error( request, ('There currently is a <a href="%s">pending replacement</a> ' 'for this cover of %s.') % (urlresolvers.reverse( 'compare', kwargs={'id': revision.changeset.id }), esc(cover.issue)), redirect=False, is_safe=True) upload_type = 'replacement' replace_cover = get_image_tag(cover, "cover to replace", ZOOM_MEDIUM) # no cover_id, therefore upload a cover to an issue (first or variant) else: issue = get_object_or_404(Issue, id=issue_id) cover = None if issue.has_covers(): covers = get_image_tags_per_issue(issue, "current covers", ZOOM_MEDIUM, as_list=True) upload_type = 'variant' else: upload_type = '' # generate tags for cover uploads for this issue currently in the queue active_covers_tags = [] active_covers = CoverRevision.objects.filter( issue=issue, changeset__state__in=states.ACTIVE, deleted=False).order_by('created') for active_cover in active_covers: active_covers_tags.append([ active_cover, get_preview_image_tag(active_cover, "pending cover", ZOOM_MEDIUM) ]) # current request is an upload if request.method == 'POST': try: form = UploadScanForm(request.POST, request.FILES) except IOError: # sometimes uploads misbehave. connection dropped ? error_text = 'Something went wrong with the upload. ' + \ 'Please <a href="' + request.path + '">try again</a>.' return render_error(request, error_text, redirect=False, is_safe=True) if not form.is_valid(): return render_to_response(upload_template, { 'form': form, 'cover': cover, 'issue': issue, 'style': style, 'replace_cover': replace_cover, 'current_covers': covers, 'upload_type': upload_type, 'table_width': UPLOAD_WIDTH }, context_instance=RequestContext(request)) # if scan is actually in the form handle it if 'scan' in request.FILES: # process form scan = request.FILES['scan'] file_source = request.POST['source'] marked = 'marked' in request.POST # create OI records changeset = Changeset(indexer=request.user, state=states.PENDING, change_type=CTYPES['cover']) changeset.save() if upload_type == 'replacement': revision = CoverRevision(changeset=changeset, issue=issue, cover=cover, file_source=file_source, marked=marked, is_replacement=True) else: revision = CoverRevision(changeset=changeset, issue=issue, file_source=file_source, marked=marked) revision.save() # put new uploaded covers into # media/<LOCAL_NEW_SCANS>/<monthname>_<year>/ # with name # <revision_id>_<date>_<time>.<ext> scan_name = str(revision.id) + os.path.splitext(scan.name)[1] upload_dir = settings.MEDIA_ROOT + LOCAL_NEW_SCANS + \ changeset.created.strftime('%B_%Y/').lower() destination_name = upload_dir + scan_name try: # essentially only needed at beginning of the month check_cover_dir(upload_dir) except IOError: changeset.delete() error_text = "Problem with file storage for uploaded " + \ "cover, please report an error." return render_error(request, error_text, redirect=False) # write uploaded file destination = open(destination_name, 'wb') for chunk in scan.chunks(): destination.write(chunk) destination.close() try: # generate different sizes we are using im = Image.open(destination.name) if im.size[0] >= 400: generate_sizes(revision, im) else: changeset.delete() os.remove(destination.name) info_text = "Image is too small, only " + str(im.size) + \ " in size." return render_to_response( upload_template, { 'form': form, 'info': info_text, 'cover': cover, 'current_covers': covers, 'replace_cover': replace_cover, 'upload_type': upload_type, 'table_width': UPLOAD_WIDTH, 'issue': issue }, context_instance=RequestContext(request)) except IOError: # just in case, django *should* have taken care of file type changeset.delete() os.remove(destination.name) return render_to_response(upload_template, { 'form': form, 'info' : 'Error: File \"' + scan.name + \ '" is not a valid picture.', 'cover' : cover, 'issue' : issue, 'current_covers' : covers, 'replace_cover' : replace_cover, 'upload_type' : upload_type, 'table_width': UPLOAD_WIDTH }, context_instance=RequestContext(request)) # all done, we can save the state changeset.comments.create(commenter=request.user, text=form.cleaned_data['comments'], old_state=states.UNRESERVED, new_state=changeset.state) if 'remember_source' in request.POST: request.session['oi_file_source'] = request.POST['source'] else: request.session.pop('oi_file_source', '') return HttpResponseRedirect( urlresolvers.reverse('upload_cover_complete', kwargs={'revision_id': revision.id})) # request is a GET for the form else: if 'oi_file_source' in request.session: vars = { 'source': request.session['oi_file_source'], 'remember_source': True } else: vars = None form = UploadScanForm(initial=vars) # display the form return render_to_response(upload_template, { 'form': form, 'cover': cover, 'issue': issue, 'current_covers': covers, 'replace_cover': replace_cover, 'active_covers': active_covers_tags, 'upload_type': upload_type, 'table_width': UPLOAD_WIDTH }, context_instance=RequestContext(request))