Exemple #1
0
    def handle(self, *args, **options):  # pylint: disable=too-many-locals
        """Does the job of the command"""
        translation.activate(django_settings.LANGUAGE_CODE)
        uid, file_name = self.get_params(options)

        try:
            user = User.objects.get(pk=uid)
        except User.DoesNotExist:  # pylint: disable=no-member
            raise CommandError('User with id {} does not exist'.format(uid))

        lang_data = dict()
        for profile in user.localized_askbot_profiles.all():
            lang = profile.language_code
            profile_url = user.get_absolute_url(language_code=lang)
            profile_data = {
                'about': profile.about,
                'profile_url': site_url(profile_url)
            }
            lang_data[lang] = profile_data

        user_profile = {
            'localized_profiles': lang_data,
            'date_of_birth': str(user.date_of_birth),
            'username': user.username,
            'profile_url': site_url(user.get_absolute_url()),
            'email': user.email
        }

        data = {'user_profile': user_profile}

        question_data = self.get_question_data(user)
        data['questions'] = list(question_data.values())

        answer_data = self.get_post_data(user, 'answer')
        data['answers'] = list(answer_data.values())

        comment_data = self.get_post_data(user, 'comment')
        data['comments'] = list(comment_data.values())

        upfiles = self.get_upfiles(data)

        temp_dir = tempfile.mkdtemp()
        self.backup_upfiles_and_avatar(upfiles, user, temp_dir)

        self.save_json_file(data, temp_dir)
        self.zip_tempdir(temp_dir, file_name)

        shutil.rmtree(temp_dir)
Exemple #2
0
def get_question_data(thread):
    """returns data dictionary for a given thread"""
    question_post = thread._question_post()  #pylint: disable=protected-access
    datum = {
        'added_at': get_epoch_str(thread.added_at),
        'id': question_post.id,
        'answer_count': thread.answer_count,
        'answer_ids': thread.get_answer_ids(),
        'accepted_answer_id': thread.accepted_answer_id,
        'view_count': thread.view_count,
        'score': thread.score,
        'last_activity_at': get_epoch_str(thread.last_activity_at),
        'title': thread.title,
        'summary': question_post.summary,
        'tags': thread.tagnames.strip().split(),
        'url': site_url(thread.get_absolute_url()),
    }
    if question_post.last_edited_at:
        datum['last_edited_at'] = get_epoch_str(question_post.last_edited_at)

    if question_post.last_edited_by:
        datum['last_edited_by'] = get_user_id_info(
            question_post.last_edited_by)

    if thread.closed:
        datum['closed'] = True
        datum['closed_by'] = get_user_id_info(thread.closed_by)
        datum['closed_at'] = get_epoch_str(thread.closed_at)
        datum['closed_reason'] = thread.get_close_reason_display()

    datum['author'] = get_user_id_info(question_post.author)
    datum['last_activity_by'] = get_user_id_info(thread.last_activity_by)
    return datum
Exemple #3
0
    def get_post_data(cls, user, post_type):
        """Returns a dictionary valued with with question data,
        keyed by question objects."""
        posts = user.posts.filter(post_type=post_type)

        # prune threadless posts and parentless
        have_threads = [post for post in posts if post.thread_id]
        if post_type == 'question':
            exportable = have_threads
        elif post_type == 'comment':
            exportable = [post for post in posts if post.parent_id]
        elif post_type == 'answer':
            exportable = posts

        # collect data per post:
        data = dict()
        for post in exportable:
            datum = {
                'text': post.text,
                'added_at': str(post.added_at),
                'last_edited_at': str(post.last_edited_at),
                'url': site_url(post.get_absolute_url())
            }
            data[post] = datum

        return data
Exemple #4
0
def akismet_check_spam(text, request):
    """Returns True if spam found, false if not,
    May raise exceptions if something is not right with
    the Akismet account/service/setup"""
    if not askbot_settings.USE_AKISMET:
        return False
    try:
        if askbot_settings.USE_AKISMET and askbot_settings.AKISMET_API_KEY == "":
            raise ImproperlyConfigured("You have not set AKISMET_API_KEY")
        data = {
            "user_ip": request.META.get("REMOTE_ADDR"),
            "user_agent": request.environ["HTTP_USER_AGENT"],
            "comment_author": smart_str(request.user.username),
        }
        if request.user.is_authenticated():
            data.update({"comment_author_email": request.user.email})

        api = Akismet(
            askbot_settings.AKISMET_API_KEY, smart_str(site_url(reverse("questions"))), "Askbot/%s" % get_version()
        )
        return api.comment_check(text, data, build_data=False)
    except APIKeyError:
        logging.critical("Akismet Key is missing")
    except AkismetError:
        logging.critical("Akismet error: Invalid Akismet key or Akismet account issue!")
    except Exception, e:
        logging.critical((u"Akismet error: %s" % unicode(e)).encode("utf-8"))
Exemple #5
0
    def start(self, callback_url = None):
        """starts the OAuth protocol communication and
        saves request token as :attr:`request_token`"""

        if callback_url is None:
            callback_url = self.callback_url
        
        client = oauth.Client(self.consumer)
        request_url = self.parameters['request_token_url']

        if callback_url:
            callback_url = site_url(callback_url)
            request_body = urllib.urlencode(dict(oauth_callback=callback_url))

            self.request_token = self.send_request(
                                            client = client,
                                            url = request_url,
                                            method = 'POST',
                                            body = request_body 
                                        )
        else:
            self.request_token = self.send_request(
                                            client,
                                            request_url,
                                            'GET'
                                        )
def akismet_check_spam(text, request):
    """Returns True if spam found, false if not,
    May raise exceptions if something is not right with
    the Akismet account/service/setup"""
    try:
        if askbot_settings.USE_AKISMET and askbot_settings.AKISMET_API_KEY == "":
            raise ImproperlyConfigured('You have not set AKISMET_API_KEY')
        data = {'user_ip': request.META.get('REMOTE_ADDR'),
                'user_agent': request.environ['HTTP_USER_AGENT'],
                'comment_author': smart_str(request.user.username)
                }
        if request.user.is_authenticated():
            data.update({'comment_author_email': request.user.email})

        api = Akismet(
            askbot_settings.AKISMET_API_KEY,
            smart_str(site_url(reverse('questions'))),
            "Askbot/%s" % get_version()
        )
        return api.comment_check(text, data, build_data=False)
    except APIKeyError:
        logging.critical('Akismet Key is missing')
    except AkismetError:
        logging.critical('Akismet error: Invalid Akismet key or Akismet account issue!')
    except Exception, e:
        logging.critical((u'Akismet error: %s' % unicode(e)).encode('utf-8'))
Exemple #7
0
def get_question_data(thread):
    """returns data dictionary for a given thread"""
    question_post = thread._question_post()
    datum = {
        'added_at': get_epoch_str(thread.added_at),
        'id': question_post.id,
        'answer_count': thread.answer_count,
        'answer_ids': thread.get_answer_ids(),
        'view_count': thread.view_count,
        'score': thread.score,
        'last_activity_at': get_epoch_str(thread.last_activity_at),
        'title': thread.title,
        'summary': question_post.summary,
        'tags': thread.tagnames.strip().split(),
        'url': site_url(thread.get_absolute_url()),
    }
    datum['author'] = {
        'id': thread._question_post().author.id,
        'username': thread._question_post().author.username
    }
    datum['last_activity_by'] = {
        'id': thread.last_activity_by.id,
        'username': thread.last_activity_by.username
    }
    return datum
Exemple #8
0
        def wrapper(request, *args, **kwargs):

            if askbot_settings.USE_AKISMET and askbot_settings.AKISMET_API_KEY == "":
                raise ImproperlyConfigured('You have not set AKISMET_API_KEY')

            if askbot_settings.USE_AKISMET and request.method == "POST":
                comment = smart_str(request.POST[field])
                data = {
                    'user_ip': request.META.get('REMOTE_ADDR'),
                    'user_agent': request.environ['HTTP_USER_AGENT'],
                    'comment_author': smart_str(request.user.username),
                }
                if request.user.is_authenticated():
                    data.update({'comment_author_email': request.user.email})

                from akismet import Akismet
                api = Akismet(askbot_settings.AKISMET_API_KEY,
                              smart_str(site_url(reverse('questions'))),
                              "Askbot/%s" % get_version())

                if api.comment_check(comment, data, build_data=False):
                    logging.debug('Spam detected in %s post at: %s',
                                  request.user.username,
                                  datetime.datetime.now())
                    spam_message = _('Spam was detected on your post, sorry '
                                     'for if this is a mistake')
                    if request.is_ajax():
                        return HttpResponseForbidden(
                            spam_message, mimetype="application/json")
                    else:
                        request.user.message_set.create(message=spam_message)
                        return HttpResponseRedirect(reverse('index'))

            return view_func(request, *args, **kwargs)
Exemple #9
0
        def wrapper(request, *args, **kwargs):

            if askbot_settings.USE_AKISMET and askbot_settings.AKISMET_API_KEY == "":
                raise ImproperlyConfigured('You have not set AKISMET_API_KEY')

            if askbot_settings.USE_AKISMET and request.method == "POST":
                comment = smart_str(request.POST[field])
                data = {'user_ip': request.META.get('REMOTE_ADDR'),
                        'user_agent': request.environ['HTTP_USER_AGENT'],
                        'comment_author': smart_str(request.user.username),
                        }
                if request.user.is_authenticated():
                    data.update({'comment_author_email': request.user.email})

                from akismet import Akismet
                api = Akismet(
                    askbot_settings.AKISMET_API_KEY,
                    smart_str(site_url(reverse('questions'))),
                    "Askbot/%s" % get_version()
                )

                if api.comment_check(comment, data, build_data=False):
                    logging.debug('Spam detected in %s post at: %s', request.user.username, timezone.now())
                    spam_message = _(
                        'Spam was detected on your post, sorry '
                        'for if this is a mistake'
                    )
                    if request.is_ajax():
                        return HttpResponseForbidden(spam_message, mimetype="application/json")
                    else:
                        # request.user.message_set.create(message=spam_message)
                        django_messages.info(request, spam_message)
                        return redirect('index')

            return view_func(request, *args, **kwargs)
def akismet_check_spam(text, request):
    """Returns True if spam found, false if not,
    May raise exceptions if something is not right with
    the Akismet account/service/setup"""
    if not askbot_settings.USE_AKISMET:
        return False
    try:
        if askbot_settings.USE_AKISMET and askbot_settings.AKISMET_API_KEY == "":
            raise ImproperlyConfigured('You have not set AKISMET_API_KEY')
        data = {'user_ip': request.META.get('REMOTE_ADDR'),
                'user_agent': request.environ['HTTP_USER_AGENT'],
                'comment_author': smart_str(request.user.username)
                }
        if request.user.is_authenticated():
            data.update({'comment_author_email': request.user.email})

        api = Akismet(
            askbot_settings.AKISMET_API_KEY,
            smart_str(site_url(reverse('questions'))),
            "Askbot/%s" % get_version()
        )
        return api.comment_check(text, data, build_data=False)
    except APIKeyError:
        logging.critical('Akismet Key is missing')
    except AkismetError:
        logging.critical('Akismet error: Invalid Akismet key or Akismet account issue!')
    except Exception as e:
        logging.critical((u'Akismet error: %s' % unicode(e)).encode('utf-8'))
    return False
Exemple #11
0
def get_question_data(thread):
    """returns data dictionary for a given thread"""
    question_post = thread._question_post()
    datum = {
        'added_at': get_epoch_str(thread.added_at),
        'id': question_post.id,
        'answer_count': thread.answer_count,
        'answer_ids': thread.get_answer_ids(),
        'accepted_answer_id': thread.accepted_answer_id,
        'view_count': thread.view_count,
        'score': thread.score,
        'last_activity_at': get_epoch_str(thread.last_activity_at),
        'title': thread.title,
        'summary': question_post.summary,
        'tags': thread.tagnames.strip().split(),
        'url': site_url(thread.get_absolute_url()),
    }
    datum['author'] = {
        'id': thread._question_post().author.id,
        'username': thread._question_post().author.username
    }
    datum['last_activity_by'] = {
        'id': thread.last_activity_by.id,
        'username': thread.last_activity_by.username
    }
    return datum
Exemple #12
0
def get_sso_login_url(request, success_url):
    """Returns the redirect url for the discourse SSO login"""

    # Generate a random nonce.
    nonce = generate_random_key()
    # Save it temporarily so that you can verify it with returned nonce value
    discourse_login_data = {
        'nonce': nonce,
        'timestamp': time.time(),
        'success_url': success_url
    }
    request.session['discourse_login'] = discourse_login_data
    # Create a new payload with nonce and return url
    # (where the Discourse will redirect user after verification).
    # Payload should look like: nonce=NONCE&return_sso_url=RETURN_URL
    return_url = site_url(reverse('user_complete_discourse_signin'))
    payload = 'nonce={}&return_sso_url={}'.format(nonce, return_url)
    # Base64 encode the above raw payload. -> BASE64_PAYLOAD
    base64_payload = base64.b64encode(payload)
    # URL encode the above BASE64_PAYLOAD.
    url_encoded_payload = urllib.quote(base64_payload)
    # Generate a HMAC-SHA256 signature from BASE64_PAYLOAD, lower case it -> HEX_SIGNATURE
    hex_signature = sign_payload(base64_payload)

    # Redirect the user to DISCOURSE_ROOT_URL/session/sso_provider?sso=URL_ENCODED_PAYLOAD&sig=HEX_SIGNATURE
    url_template = '{}/session/sso_provider?sso={}&sig={}'
    return url_template.format(askbot_settings.DISCOURSE_SITE_URL,
                               url_encoded_payload, hex_signature)
Exemple #13
0
def notify_admins_about_new_tags(tags=None, thread=None, user=None):
    thread_url = thread.get_absolute_url()
    return {
        'thread_url': html_utils.site_url(thread_url),
        'tags': tags,
        'user': user
    }
Exemple #14
0
    def start(self, callback_url = None):
        """starts the OAuth protocol communication and
        saves request token as :attr:`request_token`"""

        if callback_url is None:
            callback_url = self.callback_url
        
        client = oauth.Client(self.consumer)
        request_url = self.parameters['request_token_url']

        if callback_url:
            callback_url = site_url(callback_url)
            request_body = urllib.urlencode(dict(oauth_callback=callback_url))

            self.request_token = self.send_request(
                                            client = client,
                                            url = request_url,
                                            method = 'POST',
                                            body = request_body 
                                        )
        else:
            self.request_token = self.send_request(
                                            client,
                                            request_url,
                                            'GET'
                                        )
Exemple #15
0
def get_question_data(thread):
    """returns data dictionary for a given thread"""
    if thread.accepted_answer is not None:
        accepted = True
    else:
        accepted = False
    datum = {
        'added_at': thread.added_at.strftime('%s'),
        'id': thread._question_post().id,
        'answer_count': thread.answer_count,
        'view_count': thread.view_count,
        'score': thread.score,
        'last_activity_at': thread.last_activity_at.strftime('%s'),
        'title': thread.title,
        'tags': thread.tagnames.strip().split(),
        'url': site_url(thread.get_absolute_url()),
        'closed': thread.closed,
        'accepted': accepted,
    }
    datum['author'] = {
        'id': thread._question_post().author.id,
        'username': thread._question_post().author.username
    }
    datum['last_activity_by'] = {
        'id': thread.last_activity_by.id,
        'username': thread.last_activity_by.username
    }
    return datum
Exemple #16
0
 def process_context(self, context):
     url_name = context['handler_url_name']
     context.update({
         'site_name': askbot_settings.APP_SHORT_NAME,
         'recipient_user': None,  # needed for the Django template
         'validation_link': site_url(reverse(url_name)) + '?validation_code=' + context['key'],
     })
     return context
Exemple #17
0
 def process_context(self, context):
     context.update({
         'site_name': askbot_settings.APP_SHORT_NAME,
         'recipient_user': None,#needed for the Django template
         'validation_link': site_url(reverse('user_account_recover')) + \
                             '?validation_code=' + context['key']
     })
     return context
Exemple #18
0
    def process_context(self, context):
        to_user = context.get('to_user')
        from_user = context.get('from_user')
        post = context.get('post')
        update_activity = context.get('update_activity')
        update_type = self.get_update_type(update_activity)

        #unhandled update_type 'post_shared'
        #user_action = _('%(user)s shared a %(post_link)s.')

        origin_post = post.get_origin_post()
        post_url = site_url(post.get_absolute_url())

        can_reply = to_user.can_post_by_email()
        from askbot.models import get_reply_to_addresses
        reply_address, alt_reply_address = get_reply_to_addresses(
            to_user, post)
        alt_reply_subject = urllib.quote(
            ('Re: ' + post.thread.title).encode('utf-8'))

        return {
            'admin_email':
            askbot_settings.ADMIN_EMAIL,
            'recipient_user':
            to_user,
            'update_author_name':
            from_user.username,
            'receiving_user_name':
            to_user.username,
            'receiving_user_karma':
            to_user.reputation,
            'reply_by_email_karma_threshold':
            askbot_settings.MIN_REP_TO_POST_BY_EMAIL,
            'can_reply':
            can_reply,
            'update_type':
            update_type,
            'update_activity':
            update_activity,
            'post':
            post,
            'post_url':
            post_url,
            'origin_post':
            origin_post,
            'thread_title':
            origin_post.thread.title,
            'reply_address':
            reply_address,
            'alt_reply_address':
            alt_reply_address,
            'alt_reply_subject':
            alt_reply_subject,
            'is_multilingual':
            getattr(django_settings, 'ASKBOT_MULTILINGUAL', False),
            'reply_sep_tpl':
            const.SIMPLE_REPLY_SEPARATOR_TEMPLATE
        }
Exemple #19
0
def notify_admins_about_new_tags(
    tags = None, thread = None, user = None
):
    thread_url = thread.get_absolute_url()
    return {
        'thread_url': html_utils.site_url(thread_url),
        'tags': tags,
        'user': user
    }
Exemple #20
0
    def send_email_alerts(self, user):
        #does not change the database, only sends the email
        #todo: move this to template
        user.add_missing_askbot_subscriptions()
        #todo: q_list is a dictionary, not a list
        q_list = self.get_updated_questions_for_user(user)
        if len(q_list.keys()) == 0:
            return
        num_q = 0
        for question, meta_data in q_list.items():
            if meta_data['skip']:
                del q_list[question]
            else:
                num_q += 1
        if num_q > 0:
            threads = Thread.objects.filter(id__in=[qq.thread_id for qq in q_list.keys()])
            tag_summary = Thread.objects.get_tag_summary_from_threads(threads)

            question_count = len(q_list.keys())

            items_added = 0
            items_unreported = 0
            questions_data = list()
            for q, meta_data in q_list.items():
                act_list = []
                if meta_data['skip']:
                    continue
                if items_added >= askbot_settings.MAX_ALERTS_PER_EMAIL:
                    items_unreported = num_q - items_added #may be inaccurate actually, but it's ok
                    break
                else:
                    items_added += 1
                    if meta_data['new_q']:
                        act_list.append(_('new question'))
                    format_action_count('%(num)d rev', meta_data['q_rev'], act_list)
                    format_action_count('%(num)d ans', meta_data['new_ans'], act_list)
                    format_action_count('%(num)d ans rev', meta_data['ans_rev'], act_list)
                    questions_data.append({
                        'url': site_url(q.get_absolute_url()),
                        'info': ', '.join(act_list),
                        'title': q.thread.title
                    })

            activate_language(user.get_primary_language())
            email = BatchEmailAlert({
                'questions': questions_data,
                'question_count': question_count,
                'tag_summary': tag_summary,
                'user': user
            })

            if DEBUG_THIS_COMMAND == True:
                recipient_email = askbot_settings.ADMIN_EMAIL
            else:
                recipient_email = user.email

            email.send([recipient_email,])
Exemple #21
0
def PROCESS(parts=None,
            reply_address_object=None,
            subject_line=None,
            from_address=None,
            **kwargs):
    """handler to process the emailed message
    and make a post to askbot based on the contents of
    the email, including the text body and the file attachments"""
    #1) get actual email content
    #   todo: factor this out into the process_reply decorator
    reply_code = reply_address_object.address
    body_text, stored_files, signature = mail.process_parts(
        parts, reply_code, from_address)

    #2) process body text and email signature
    user = reply_address_object.user

    if signature != user.email_signature:
        user.email_signature = signature

    #3) validate email address and save user along with maybe new signature
    user.email_isvalid = True
    user.save()  #todo: actually, saving is not necessary, if nothing changed

    #here we might be in danger of chomping off some of the
    #message is body text ends with a legitimate text coinciding with
    #the user's email signature
    body_text = user.strip_email_signature(body_text)

    #4) actually make an edit in the forum
    robj = reply_address_object
    add_post_actions = ('post_comment', 'post_answer',
                        'auto_answer_or_comment')
    if robj.reply_action == 'replace_content':
        robj.edit_post(body_text, title=subject_line)
    elif robj.reply_action == 'append_content':
        robj.edit_post(body_text)  #in this case we don't touch the title
    elif robj.reply_action in add_post_actions:
        if robj.was_used:
            robj.edit_post(body_text, edit_response=True)
        else:
            robj.create_reply(body_text)
    elif robj.reply_action == 'validate_email':
        #todo: this is copy-paste - factor it out to askbot.mail.messages
        data = {
            'site_name': askbot_settings.APP_SHORT_NAME,
            'site_url': site_url(reverse('questions')),
            'ask_address': 'ask@' + askbot_settings.REPLY_BY_EMAIL_HOSTNAME
        }
        template = get_template('email/re_welcome_lamson_on.html')

        mail.send_mail(
            subject_line=_('Re: %s') % subject_line,
            body_text=template.render(Context(data)),  #todo: set lang
            recipient_list=[
                from_address,
            ])
    def handle(self, *args, **options): # pylint: disable=too-many-locals
        """Does the job of the command"""
        translation.activate(django_settings.LANGUAGE_CODE)
        uid, file_name = self.get_params(options)

        try:
            user = User.objects.get(pk=uid)
        except User.DoesNotExist: # pylint: disable=no-member
            raise CommandError('User with id {} does not exist'.format(uid))

        lang_data = dict()
        for profile in user.localized_askbot_profiles.all():
            lang = profile.language_code
            profile_url = user.get_absolute_url(language_code=lang)
            profile_data = {'about': profile.about,
                            'profile_url': site_url(profile_url)}
            lang_data[lang] = profile_data

        user_profile = {'localized_profiles': lang_data,
                        'date_of_birth': str(user.date_of_birth),
                        'username': user.username,
                        'profile_url': site_url(user.get_absolute_url()),
                        'email': user.email}

        data = {'user_profile': user_profile}

        question_data = self.get_question_data(user)
        data['questions'] = question_data.values()

        answer_data = self.get_post_data(user, 'answer')
        data['answers'] = answer_data.values()

        comment_data = self.get_post_data(user, 'comment')
        data['comments'] = comment_data.values()

        upfiles = self.get_upfiles(data)

        temp_dir = tempfile.mkdtemp()
        self.backup_upfiles_and_avatar(upfiles, user, temp_dir)

        self.save_json_file(data, temp_dir)
        self.zip_tempdir(temp_dir, file_name)

        shutil.rmtree(temp_dir)
    def handle_noargs(self, **options):
        if askbot_settings.ENABLE_EMAIL_ALERTS == False:
            return
        if askbot_settings.ENABLE_ACCEPT_ANSWER_REMINDERS == False:
            return
        #get questions without answers, excluding closed and deleted
        #order it by descending added_at date

        schedule = ReminderSchedule(
            askbot_settings.DAYS_BEFORE_SENDING_ACCEPT_ANSWER_REMINDER,
            askbot_settings.ACCEPT_ANSWER_REMINDER_FREQUENCY,
            askbot_settings.MAX_ACCEPT_ANSWER_REMINDERS)

        questions = models.Post.objects.get_questions().exclude(
            deleted=True).added_between(
                start=schedule.start_cutoff_date, end=schedule.end_cutoff_date
            ).filter(thread__answer_count__gt=0).filter(
                thread__accepted_answer__isnull=True  #answer_accepted = False
            ).order_by('-added_at')
        #for all users, excluding blocked
        #for each user, select a tag filtered subset
        #format the email reminder and send it
        for user in models.User.objects.exclude(status='b'):
            user_questions = questions.filter(author=user)

            final_question_list = user_questions.get_questions_needing_reminder(
                activity_type=const.TYPE_ACTIVITY_ACCEPT_ANSWER_REMINDER_SENT,
                user=user,
                recurrence_delay=schedule.recurrence_delay)
            #todo: rewrite using query set filter
            #may be a lot more efficient

            question_count = len(final_question_list)
            if question_count == 0:
                continue

            reminder_phrase = _('Please select the best responses to:')

            data = {
                'site_url': site_url(''),  #here we need only the domain name
                'questions': final_question_list,
                'reminder_phrase': reminder_phrase,
                'recipient_user': user
            }

            template = get_template('email/accept_answer_reminder.html')
            body_text = template.render(Context(data))  #todo: set lang

            subject_line = askbot_settings.WORDS_ACCEPT_BEST_ANSWERS_FOR_YOUR_QUESTIONS
            if DEBUG_THIS_COMMAND:
                print "User: %s<br>\nSubject:%s<br>\nText: %s<br>\n" % \
                    (user.email, subject_line, body_text)
            else:
                mail.send_mail(subject_line=subject_line,
                               body_text=body_text,
                               recipient_list=(user.email, ))
def PROCESS(
    parts = None,
    reply_address_object = None,
    subject_line = None,
    from_address = None,
    **kwargs
):
    """handler to process the emailed message
    and make a post to askbot based on the contents of
    the email, including the text body and the file attachments"""
    #1) get actual email content
    #   todo: factor this out into the process_reply decorator
    reply_code = reply_address_object.address
    body_text, stored_files, signature = mail.process_parts(parts, reply_code)

    #2) process body text and email signature
    user = reply_address_object.user

    if signature != user.email_signature:
        user.email_signature = signature

    #3) validate email address and save user along with maybe new signature
    user.email_isvalid = True
    user.save()#todo: actually, saving is not necessary, if nothing changed

    #here we might be in danger of chomping off some of the 
    #message is body text ends with a legitimate text coinciding with
    #the user's email signature
    body_text = user.strip_email_signature(body_text)

    #4) actually make an edit in the forum
    robj = reply_address_object
    add_post_actions = ('post_comment', 'post_answer', 'auto_answer_or_comment')
    if robj.reply_action == 'replace_content':
        robj.edit_post(body_text, title = subject_line)
    elif robj.reply_action == 'append_content':
        robj.edit_post(body_text)#in this case we don't touch the title
    elif robj.reply_action in add_post_actions:
        if robj.was_used:
            robj.edit_post(body_text, edit_response = True)
        else:
            robj.create_reply(body_text)
    elif robj.reply_action == 'validate_email':
        #todo: this is copy-paste - factor it out to askbot.mail.messages
        data = {
            'site_name': askbot_settings.APP_SHORT_NAME,
            'site_url': site_url(reverse('questions')),
            'ask_address': 'ask@' + askbot_settings.REPLY_BY_EMAIL_HOSTNAME
        }
        template = get_template('email/re_welcome_lamson_on.html')

        mail.send_mail(
            subject_line = _('Re: %s') % subject_line,
            body_text = template.render(Context(data)),#todo: set lang
            recipient_list = [from_address,]
        )
Exemple #25
0
 def create_topic_follow_action(thread, **kwargs):
     action = Action()
     action.text = "Follow the Topic : " + thread.title
     action.link = site_url(thread.get_absolute_url())
     if "user" in kwargs:
         action.user = kwargs["user"]
     if "invite" in kwargs:
         action.invite = kwargs["invite"]
     action.save()
     return action
Exemple #26
0
 def process_context(self, context):
     user = context['recipient_user']
     extra_data = {
         'ask_address': 'ask@' + askbot_settings.REPLY_BY_EMAIL_HOSTNAME,
         'can_post_by_email': user.can_post_by_email(),
         'site_name': askbot_settings.APP_SHORT_NAME,
         'site_url': site_url(reverse('questions')),
     }
     extra_data.update(context)
     return extra_data
Exemple #27
0
 def process_context(self, context):
     url_name = context["handler_url_name"]
     context.update(
         {
             "site_name": askbot_settings.APP_SHORT_NAME,
             "recipient_user": None,  # needed for the Django template
             "validation_link": site_url(reverse(url_name)) + "?validation_code=" + context["key"],
         }
     )
     return context
Exemple #28
0
 def process_context(self, context):
     user = context['recipient_user']
     extra_data = {
         'ask_address': 'ask@' + askbot_settings.REPLY_BY_EMAIL_HOSTNAME,
         'can_post_by_email': user.can_post_by_email(),
         'site_name': askbot_settings.APP_SHORT_NAME,
         'site_url': site_url(reverse('questions')),
     }
     extra_data.update(context)
     return extra_data
Exemple #29
0
def get_oauth2_starter_url(provider_name, csrf_token):
    """returns redirect url for the oauth2 protocol for a given provider"""
    from sanction.client import Client

    providers = get_enabled_login_providers()
    params = providers[provider_name]
    client_id = getattr(askbot_settings, provider_name.replace("-", "_").upper() + "_KEY")
    redirect_uri = site_url(reverse("user_complete_oauth2_signin"))
    client = Client(auth_endpoint=params["auth_endpoint"], client_id=client_id, redirect_uri=redirect_uri)
    return client.auth_uri(state=csrf_token, **params.get("extra_auth_params", {}))
Exemple #30
0
 def process_context(self, context):
     user = context["recipient_user"]
     extra_data = {
         "ask_address": "ask@" + askbot_settings.REPLY_BY_EMAIL_HOSTNAME,
         "can_post_by_email": user.can_post_by_email(),
         "site_name": askbot_settings.APP_SHORT_NAME,
         "site_url": site_url(reverse("questions")),
     }
     extra_data.update(context)
     return extra_data
Exemple #31
0
def get_oauth2_starter_url(provider_name, csrf_token):
    """returns redirect url for the oauth2 protocol for a given provider"""
    from requests_oauthlib.oauth2_session import OAuth2Session

    providers = get_enabled_login_providers()
    params = providers[provider_name]
    client_id = getattr(askbot_settings, format_setting_name(provider_name) + '_KEY')
    redirect_uri = site_url(reverse('user_complete_oauth2_signin'))
    session = OAuth2Session(client_id, redirect_uri=redirect_uri, state=csrf_token)

    url, csrf = session.authorization_url(params['auth_endpoint'],  **params.get('extra_auth_params', {}))
    return url.encode('utf-8')
Exemple #32
0
def get_oauth2_starter_url(provider_name, csrf_token):
    """returns redirect url for the oauth2 protocol for a given provider"""
    from sanction.client import Client

    providers = get_enabled_login_providers()
    params = providers[provider_name]
    client_id = getattr(askbot_settings, provider_name.upper() + '_KEY')
    redirect_uri = site_url(reverse('user_complete_oauth2_signin'))
    client = Client(auth_endpoint=params['auth_endpoint'],
                    client_id=client_id,
                    redirect_uri=redirect_uri)
    return client.auth_uri(state=csrf_token)
Exemple #33
0
 def test_api_v1_answer(self):
     user = self.create_user('user')
     question = self.post_question(user=user)
     answer = self.post_answer(user=user, question=question)
     response = self.client.get(reverse('api_v1_answer', kwargs={'answer_id': answer.id}))
     data = simplejson.loads(response.content)
     self.assertEqual(data['author']['id'], user.id)
     self.assertEqual(data['author']['username'], user.username)
     self.assertEqual(data['url'], site_url(answer.get_absolute_url()))
     self.assertEqual(data['added_at'], get_epoch_str(answer.added_at))
     self.assertEqual(data['score'], answer.score)
     self.assertEqual(data['id'], answer.id)
     self.assertEqual(data['summary'], answer.summary)
Exemple #34
0
def send_email_key(email, key, handler_url_name="user_account_recover"):
    """private function. sends email containing validation key
    to user's email address
    """
    subject = _("Recover your %(site)s account") % {"site": askbot_settings.APP_SHORT_NAME}

    data = {
        "site_name": askbot_settings.APP_SHORT_NAME,
        "validation_link": site_url(reverse(handler_url_name)) + "?validation_code=" + key,
    }
    template = get_template("authopenid/email_validation.html")
    message = template.render(data)  # todo: inject language preference
    send_mail(subject, message, django_settings.DEFAULT_FROM_EMAIL, [email])
Exemple #35
0
def get_user_data(user):
    """get common data about the user"""
    avatar_url = user.get_avatar_url()
    if not ('gravatar.com' in avatar_url):
        avatar_url = site_url(avatar_url)

    return {
        'id': user.id,
        'avatar': avatar_url,
        'username': user.username,
        'joined_at': get_epoch_str(user.date_joined),
        'last_seen_at': get_epoch_str(user.last_seen),
        'reputation': user.reputation,
    }
Exemple #36
0
def get_user_data(user):
    """get common data about the user"""
    avatar_url = user.get_avatar_url()
    if not ("gravatar.com" in avatar_url):
        avatar_url = site_url(avatar_url)

    return {
        "id": user.id,
        "avatar": avatar_url,
        "username": user.username,
        "joined_at": user.date_joined.strftime("%s"),
        "last_seen_at": user.last_seen.strftime("%s"),
        "reputation": user.reputation,
    }
Exemple #37
0
def get_oauth2_starter_url(provider_name, csrf_token):
    """returns redirect url for the oauth2 protocol for a given provider"""
    from sanction.client import Client

    providers = get_enabled_login_providers()
    params = providers[provider_name]
    client_id = getattr(askbot_settings, format_setting_name(provider_name) + '_KEY')
    redirect_uri = site_url(reverse('user_complete_oauth2_signin'))
    client = Client(
        auth_endpoint=params['auth_endpoint'],
        client_id=client_id,
        redirect_uri=redirect_uri
    )
    return client.auth_uri(state=csrf_token, **params.get('extra_auth_params', {}))
Exemple #38
0
def get_user_data(user):
    """get common data about the user"""
    avatar_url = user.get_avatar_url()
    if not ('gravatar.com' in avatar_url):
        avatar_url = site_url(avatar_url)

    return {
        'id': user.id,
        'avatar': avatar_url,
        'username': user.username,
        'joined_at': get_epoch_str(user.date_joined),
        'last_seen_at': get_epoch_str(user.last_seen),
        'reputation': user.reputation,
    }
def VALIDATE_EMAIL(
    parts = None,
    reply_address_object = None,
    from_address = None,
    **kwargs
):
    """process the validation email and save
    the email signature
    todo: go a step further and
    """
    reply_code = reply_address_object.address

    if DEBUG_EMAIL:
        msg = u'Received email validation from %s\n' % from_address
        sys.stderr.write(msg.encode('utf-8'))

    try:
        content, stored_files, signature = mail.process_parts(parts, reply_code)

        user = reply_address_object.user

        if signature != user.email_signature:
            user.email_signature = signature

        user.email_isvalid = True
        user.save()

        data = {
            'ask_address': 'ask@' + askbot_settings.REPLY_BY_EMAIL_HOSTNAME,
            'can_post_by_email': user.can_post_by_email(),
            'recipient_user': user,
            'site_name': askbot_settings.APP_SHORT_NAME,
            'site_url': site_url(reverse('questions')),
        }
        template = get_template('email/re_welcome_lamson_on.html')

        mail.send_mail(
            subject_line = _('Re: Welcome to %(site_name)s') % data,
            body_text = template.render(Context(data)),#todo: set lang
            recipient_list = [from_address,]
        )
    except ValueError:
        raise ValueError(
            _(
                'Please reply to the welcome email '
                'without editing it'
            )
        )
Exemple #40
0
def get_question_data(thread):
    """returns data dictionary for a given thread"""
    datum = {
        "added_at": thread.added_at.strftime("%s"),
        "id": thread._question_post().id,
        "answer_count": thread.answer_count,
        "view_count": thread.view_count,
        "score": thread.score,
        "last_activity_at": thread.last_activity_at.strftime("%s"),
        "title": thread.title,
        "tags": thread.tagnames.strip().split(),
        "url": site_url(thread.get_absolute_url()),
    }
    datum["author"] = {"id": thread._question_post().author.id, "username": thread._question_post().author.username}
    datum["last_activity_by"] = {"id": thread.last_activity_by.id, "username": thread.last_activity_by.username}
    return datum
Exemple #41
0
def VALIDATE_EMAIL(
    parts = None,
    reply_address_object = None,
    from_address = None,
    **kwargs
):
    """process the validation email and save
    the email signature
    todo: go a step further and
    """
    reply_code = reply_address_object.address

    if DEBUG_EMAIL:
        msg = u'Received email validation from %s\n' % from_address
        sys.stderr.write(msg.encode('utf-8'))

    try:
        content, stored_files, signature = mail.process_parts(parts, reply_code)

        user = reply_address_object.user

        if signature != user.email_signature:
            user.email_signature = signature

        user.email_isvalid = True
        user.save()

        data = {
            'site_name': askbot_settings.APP_SHORT_NAME,
            'site_url': site_url(reverse('questions')),
            'ask_address': 'ask@' + askbot_settings.REPLY_BY_EMAIL_HOSTNAME,
            'can_post_by_email': user.can_post_by_email()
        }
        template = get_template('email/re_welcome_lamson_on.html')

        mail.send_mail(
            subject_line = _('Re: Welcome to %(site_name)s') % data,
            body_text = template.render(Context(data)),#todo: set lang
            recipient_list = [from_address,]
        )
    except ValueError:
        raise ValueError(
            _(
                'Please reply to the welcome email '
                'without editing it'
            )
        )
Exemple #42
0
def complete_oauth2_signin(request):
    if "next_url" in request.session:
        next_url = request.session["next_url"]
        del request.session["next_url"]
    else:
        next_url = reverse("index")

    if "error" in request.GET:
        return HttpResponseRedirect(reverse("index"))

    csrf_token = request.GET.get("state", None)
    if csrf_token is None or csrf_token != request.session.pop("oauth2_csrf_token"):
        return HttpResponseBadRequest()

    providers = util.get_enabled_login_providers()
    provider_name = request.session.pop("provider_name")
    params = providers[provider_name]
    assert params["type"] == "oauth2"

    client_id = getattr(askbot_settings, provider_name.upper() + "_KEY")

    client_secret = getattr(askbot_settings, provider_name.upper() + "_SECRET")

    client = OAuth2Client(
        token_endpoint=params["token_endpoint"],
        resource_endpoint=params["resource_endpoint"],
        redirect_uri=site_url(reverse("user_complete_oauth2_signin")),
        client_id=client_id,
        client_secret=client_secret,
    )

    client.request_token(code=request.GET["code"], parser=params["response_parser"])

    # todo: possibly set additional parameters here
    user_id = params["get_user_id_function"](client)

    user = authenticate(oauth_user_id=user_id, provider_name=provider_name, method="oauth")

    logging.debug("finalizing oauth signin")

    request.session["email"] = ""  # todo: pull from profile
    request.session["username"] = ""  # todo: pull from profile

    return finalize_generic_signin(
        request=request, user=user, user_identifier=user_id, login_provider_name=provider_name, redirect_url=next_url
    )
Exemple #43
0
def get_oauth2_starter_url(provider_name, csrf_token):
    """returns redirect url for the oauth2 protocol for a given provider"""
    from sanction.client import Client

    providers = get_enabled_login_providers()
    params = providers[provider_name]
    client_id = getattr(askbot_settings, provider_name.upper() + '_KEY')
    redirect_uri = site_url(reverse('user_complete_oauth2_signin'))
    #qq = redirect_uri.split(':')
    #nurl = qq[0]+':'+qq[1]+qq[2][qq[2].find('/'):]
    #redirect_uri=nurl
    client = Client(
        auth_endpoint=params['auth_endpoint'],
        client_id=client_id,
        redirect_uri=redirect_uri
    )
    return client.auth_uri(state=csrf_token)
Exemple #44
0
def get_user_data(user_obj):
    """get common data about the user"""
    avatar_url = user_obj.get_avatar_url()
    if 'gravatar.com' not in avatar_url:
        avatar_url = site_url(avatar_url)

    return {
        'id': user_obj.id,
        'avatar': avatar_url,
        'username': user_obj.username,
        'joined_at': get_epoch_str(user_obj.date_joined),
        'last_seen_at': get_epoch_str(user_obj.last_seen),
        'reputation': user_obj.reputation,
        'gold': user_obj.gold,
        'silver': user_obj.silver,
        'bronze': user_obj.bronze,
    }
Exemple #45
0
    def start(self, callback_url=None):
        """starts the OAuth protocol communication and
        saves request token as :attr:`request_token`"""

        client = oauth.Client(self.consumer)
        request_url = self.parameters['request_token_url']

        params = dict()
        if self.parameters.get('callback_is_oob', False):
            params['oauth_callback'] = 'oob'  #callback_url
        else:
            params['oauth_callback'] = site_url(callback_url)

        self.request_token = self.send_request(client=client,
                                               url=request_url,
                                               method='POST',
                                               params=params)
Exemple #46
0
def get_answer_data(post):
    """returns data dictionary for a given answer post"""
    datum = {
        'added_at': get_epoch_str(post.added_at),
        'id': post.id,
        'score': post.score,
        'summary': post.summary,
        'url': site_url(post.get_absolute_url()),
    }
    datum['author'] = get_user_id_info(post.author)

    if post.last_edited_at:
        datum['last_edited_at'] = get_epoch_str(post.last_edited_at)

    if post.last_edited_by:
        datum['last_edited_by'] = get_user_id_info(post.last_edited_by)

    return datum
Exemple #47
0
def add_email_to_topic(request):
    data = json.loads(request.body)
    try:
        post = models.Post.objects.filter(
            post_type='question',
            id=data["threadId"]
        ).select_related('thread')[0]
    except IndexError:
        # Handle URL mapping - from old Q/A/C/ URLs to the new one
        try:
            post = models.Post.objects.filter(
                post_type='question',
                old_question_id=data["threadId"]
            ).select_related('thread')[0]
        except IndexError:
            raise Http404

    try:
        user = User.objects.get(email=data['email'])
    except User.DoesNotExist:
        user = None

    if user:
        action = Action.create_topic_follow_action(post.thread, user=user)
        from askbot.mail.messages import ActionEmail
        email = ActionEmail({
            'action_text': action.text,
            'user': user,
            "link": action.link
        })
        email.send([user.email, ])
        return HttpResponse()

    invite = Invite.create_invite(data['email'])
    action = Action.create_topic_follow_action(post.thread, invite=invite)

    from askbot.mail.messages import InviteUserEmail
    email = InviteUserEmail({
        'action_text': action.text,
        'user': user,
        "invite_url": site_url("/account/signup/?invite_code=" + invite.invite_code)
    })
    email.send([invite.email, ])
    return HttpResponse()
Exemple #48
0
    def start(self, callback_url=None):
        """starts the OAuth protocol communication and
        saves request token as :attr:`request_token`"""

        client = oauth.Client(self.consumer)
        request_url = self.parameters['request_token_url']

        params = dict()
        if self.parameters.get('callback_is_oob', False):
            params['oauth_callback'] = 'oob' #callback_url
        else:
            params['oauth_callback'] = site_url(callback_url)

        self.request_token = self.send_request(
                                        client=client,
                                        url=request_url,
                                        method='POST',
                                        params=params
                                    )
Exemple #49
0
def call_akismet(text, request=None, author=None, ip_addr=None, user_agent=None, command='check_spam'):
    """Calls akismet apy with a command.
    Supports commands 'check_spam', 'submit_spam' and 'submit_ham'
    """
    if not askbot_settings.USE_AKISMET:
        return False
    try:
        if askbot_settings.AKISMET_API_KEY.strip() == "":
            raise ImproperlyConfigured('You have not set AKISMET_API_KEY')

        data = {'comment_content': text}
        user = get_user(author, request)
        username = get_user_param(user, 'username')
        if username:
            data['comment_author'] = smart_str(username)

        email = get_user_param(user, 'email')
        if email:
            data['comment_author_email'] = email

        api = Akismet(key=askbot_settings.AKISMET_API_KEY,
                      blog_url=smart_str(site_url(reverse('questions'))))

        user_ip = ip_addr or request.META.get('REMOTE_ADDR')
        user_agent = user_agent or request.environ['HTTP_USER_AGENT']
        if command == 'check_spam':
            return api.comment_check(user_ip, user_agent, **data)
        elif command == 'submit_spam':
            return api.submit_spam(user_ip, user_agent, **data)
        elif command == 'submit_ham':
            return api.submit_ham(user_ip, user_agent, **data)
        else:
            raise RuntimeError('unknown akismet method: "{}"'.format(command))

        return api.comment_check(user_ip, user_agent, **data)
    except APIKeyError:
        logging.critical('Akismet Key is missing')
    except AkismetError:
        logging.critical('Akismet error: Invalid Akismet key or Akismet account issue!')
    except Exception as e:
        logging.critical((u'Akismet error: %s' % unicode(e)).encode('utf-8'))
    return False
    def test_command(self):
        # create user
        today = date.today()
        # create user & fill out profile
        user = User.objects.create(username='******', email='*****@*****.**')
        profile = UserProfile(auth_user_ptr=user, date_of_birth=today)
        profile.save()

        lang1 = 'en'
        lang2 = 'es'
        localized_profile1 = LocalizedUserProfile(auth_user=user,
                                                  language_code=lang1,
                                                  about='about me')
        localized_profile1.save()
        localized_profile2 = LocalizedUserProfile(auth_user=user,
                                                  language_code=lang2,
                                                  about='sobre mi')
        localized_profile2.save()

        # put three upfiles in place
        paths = list()
        for idx in range(1, 4):
            path = self.put_upfile('file{}.txt'.format(idx))
            paths.append(path)

        # post question with an image
        text_tpl = 'hello there ![image]({} "Image {}")'
        url = self.get_upfile_url_from_path(paths[0])
        question_text = text_tpl.format(url, 1)
        question = user.post_question(title='question',
                                      body_text=question_text,
                                      tags='one two')

        # post answer with an image
        url = self.get_upfile_url_from_path(paths[1])
        answer_text = text_tpl.format(url, 2)
        answer = user.post_answer(question, answer_text)

        # post comment with an image
        url = self.get_upfile_url_from_path(paths[2])
        comment_text = text_tpl.format(url, 3)
        comment = user.post_comment(answer, comment_text)

        # run extract data command into a temp dir
        askbot_dir = askbot.get_install_directory()
        test_dir = os.path.join(askbot_dir, 'tests', 'temp_export_user_data')

        if os.path.isdir(test_dir):
            shutil.rmtree(test_dir)
        os.makedirs(test_dir)

        backup_file = os.path.join(test_dir, 'backup.zip')
        management.call_command('askbot_export_user_data',
                                user_id=user.pk,
                                file_name=backup_file)
        # test: unzip the file
        zip_file = zipfile.ZipFile(backup_file, 'r')
        extract_dir = os.path.join(test_dir, 'extracted')
        zip_file.extractall(extract_dir)

        json_file = os.path.join(extract_dir, 'data.json')
        self.assertTrue(os.path.isfile(json_file))

        # test: load json
        with open(json_file) as f:
            json_data = json.loads(f.read())
        # test: validate question
        q_data = json_data['questions'][0]
        thread = question.thread
        self.assertEqual(q_data['title'], thread.title)
        self.assertEqual(q_data['tags'], thread.tagnames)
        self.assertEqual(q_data['text'], question.text)
        self.assertEqual(q_data['added_at'], str(question.added_at))
        self.assertEqual(q_data['last_edited_at'],
                         str(question.last_edited_at))
        question_url = site_url(question.get_absolute_url())
        self.assertEqual(q_data['url'], question_url)

        # test: validate answer, just check it's there
        self.assertEqual(len(json_data['answers']), 1)
        # test: validate comment
        self.assertEqual(len(json_data['comments']), 1)

        # test: validate user profile data
        user_data = json_data['user_profile']
        self.assertEqual(user_data['username'], user.username)
        lang_data = user_data['localized_profiles']

        profile_url_tpl = site_url('/{}/users/{}/bob/')
        self.assertEqual(lang_data[lang1]['about'], 'about me')
        lang1_url = profile_url_tpl.format('en', user.pk)
        self.assertEqual(lang_data[lang1]['profile_url'], lang1_url)
        self.assertEqual(lang_data[lang2]['about'], 'sobre mi')
        lang2_url = profile_url_tpl.format('es', user.pk)
        self.assertEqual(lang_data[lang2]['profile_url'], lang2_url)

        self.assertEqual(user_data['email'], user.email)
        self.assertEqual(user_data['date_of_birth'], str(today))

        # test: verify that uploaded files are there
        upfile_names = [os.path.basename(path) for path in paths]
        for name in upfile_names:
            extracted_path = os.path.join(extract_dir, 'upfiles', name)
            self.assertTrue(os.path.isfile(extracted_path))

        shutil.rmtree(test_dir)
Exemple #51
0
 def link(self):
     return site_url(reverse('questions'))
Exemple #52
0
 def item_link(self, item):
     """get full url to the item
     """
     return site_url(item.get_absolute_url())
Exemple #53
0
 def item_guid(self, item):
     """returns url without the slug
     because the slug can change
     """
     return site_url(item.get_absolute_url(no_slug=True))