예제 #1
0
파일: views.py 프로젝트: sunxivincent/web
def helper_handle_access_token(request, access_token):
    # https://gist.github.com/owocki/614a18fbfec7a5ed87c97d37de70b110
    # interest API via token
    github_user_data = get_github_user_data(access_token)
    request.session['handle'] = github_user_data['login']
    profile = Profile.objects.filter(handle__iexact=request.session['handle']).first()
    request.session['profile_id'] = profile.pk
예제 #2
0
def remove_interest(request, bounty_id):
    """Unclaim work from the Bounty.

    Can only be called by someone who has started work

    :request method: POST

    post_id (int): ID of the Bounty.

    Returns:
        dict: The success key with a boolean value and accompanying error.

    """
    profile_id = request.user.profile.pk if request.user.is_authenticated and hasattr(request.user, 'profile') else None

    access_token = request.GET.get('token')
    if access_token:
        helper_handle_access_token(request, access_token)
        github_user_data = get_github_user_data(access_token)
        profile = Profile.objects.filter(handle=github_user_data['login']).first()
        profile_id = profile.pk

    if not profile_id:
        return JsonResponse(
            {'error': _('You must be authenticated via github to use this feature!')},
            status=401)

    try:
        bounty = Bounty.objects.get(pk=bounty_id)
    except Bounty.DoesNotExist:
        return JsonResponse({'errors': ['Bounty doesn\'t exist!']},
                            status=401)

    try:
        interest = Interest.objects.get(profile_id=profile_id, bounty=bounty)
        record_user_action(request.user, 'stop_work', interest)
        bounty.interested.remove(interest)
        interest.delete()
        maybe_market_to_slack(bounty, 'stop_work')
        maybe_market_to_user_slack(bounty, 'stop_work')
        maybe_market_to_twitter(bounty, 'stop_work')
    except Interest.DoesNotExist:
        return JsonResponse({
            'errors': [_('You haven\'t expressed interest on this bounty.')],
            'success': False},
            status=401)
    except Interest.MultipleObjectsReturned:
        interest_ids = bounty.interested \
            .filter(
                profile_id=profile_id,
                bounty=bounty
            ).values_list('id', flat=True) \
            .order_by('-created')

        bounty.interested.remove(*interest_ids)
        Interest.objects.filter(pk__in=list(interest_ids)).delete()

    return JsonResponse({'success': True})
예제 #3
0
    def test_get_github_user_data_failure(self):
        """Test the github utility get_github_user_data method."""
        headers = dict({'Authorization': f'token {self.user_oauth_token}'}, **JSON_HEADER)
        data = {'login': '******'}
        responses.add(responses.GET, 'https://api.github.com/user',
                      json=data, headers=headers, status=404)
        result = get_github_user_data(self.user_oauth_token)

        assert result == {}
예제 #4
0
    def test_get_github_user_data_failure(self):
        """Test the github utility get_github_user_data method."""
        headers = dict({'Authorization': f'token {self.user_oauth_token}'}, **JSON_HEADER)
        data = {'login': '******'}
        responses.add(responses.GET, 'https://api.github.com/user',
                      json=data, headers=headers, status=404)
        result = get_github_user_data(self.user_oauth_token)

        assert result == {}
예제 #5
0
def github_callback(request):
    """Handle the Github authentication callback."""
    # Get request parameters to handle authentication and the redirect.
    code = request.GET.get('code', None)
    redirect_uri = request.GET.get('redirect_uri')

    if not code or not redirect_uri:
        raise Http404

    # Get OAuth token and github user data.
    access_token = get_github_user_token(code)
    github_user_data = get_github_user_data(access_token)
    handle = github_user_data.get('login')
    ip_address = '24.210.224.38' if settings.DEBUG else get_real_ip(request)
    geolocation_data = {}

    if ip_address:
        geolocation_data = get_location_from_ip(ip_address)

    if handle:
        # Create or update the Profile with the github user data.
        user_profile, _ = Profile.objects.update_or_create(
            handle=handle,
            defaults={
                'data': github_user_data or {},
                'email': get_github_primary_email(access_token),
                'github_access_token': access_token
            })

        # Update the user's session with handle and email info.
        session_data = {
            'handle': user_profile.handle,
            'email': user_profile.email,
            'access_token': user_profile.github_access_token,
            'profile_id': user_profile.pk,
            'name': user_profile.data.get('name', None),
            'access_token_last_validated': timezone.now().isoformat(),
        }
        for k, v in session_data.items():
            request.session[k] = v

        # record a useraction for this
        UserAction.objects.create(profile=user_profile,
                                  action='Login',
                                  metadata={},
                                  ip_address=ip_address,
                                  location_data=geolocation_data)

    response = redirect(redirect_uri)
    response.set_cookie('last_github_auth_mutation', int(time.time()))
    return response
예제 #6
0
def github_callback(request):
    """Handle the Github authentication callback."""
    # Get request parameters to handle authentication and the redirect.
    code = request.GET.get('code', None)
    redirect_uri = request.GET.get('redirect_uri')

    if not code or not redirect_uri:
        raise Http404

    # Get OAuth token and github user data.
    access_token = get_github_user_token(code)
    github_user_data = get_github_user_data(access_token)
    handle = github_user_data.get('login')
    github_repos = get_github_repos(access_token)

    if handle:
        # Create or update the Profile with the github user data.
        # user_profile, _ = Profile.objects.update_or_create(
        #     handle=handle,
        #     defaults={
        #         'data': github_user_data or {},
        #         'email': get_github_primary_email(access_token),
        #         'github_access_token': access_token
        #     })

        # Update the user's session with handle and email info.
        session_data = {
            'handle': handle,
            'user_repos': github_repos,
            'email': get_github_primary_email(access_token),
            'access_token': access_token,
            'name': github_user_data.get('name', None),
            'access_token_last_validated': timezone.now().isoformat(),
        }
        for k, v in session_data.items():
            request.session[k] = v

        # # record a useraction for this
        # UserAction.objects.create(
        #     profile=user_profile,
        #     action='Login',
        #     metadata={},
        #     )


    response = redirect(redirect_uri)
    response.set_cookie('last_github_auth_mutation', int(time.time()))
    return response
예제 #7
0
def github_callback(request):
    """Handle the Github authentication callback."""
    # Get request parameters to handle authentication and the redirect.
    code = request.GET.get('code', None)
    redirect_uri = request.GET.get('redirect_uri')

    if not code or not redirect_uri:
        raise Http404

    # Get OAuth token and github user data.
    access_token = get_github_user_token(code)
    github_user_data = get_github_user_data(access_token)
    handle = github_user_data.get('login')
    github_repos = get_github_repos(access_token)

    if handle:
        # Create or update the Profile with the github user data.
        # user_profile, _ = Profile.objects.update_or_create(
        #     handle=handle,
        #     defaults={
        #         'data': github_user_data or {},
        #         'email': get_github_primary_email(access_token),
        #         'github_access_token': access_token
        #     })

        # Update the user's session with handle and email info.
        session_data = {
            'handle': handle,
            'user_repos': github_repos,
            'email': get_github_primary_email(access_token),
            'access_token': access_token,
            'name': github_user_data.get('name', None),
            'access_token_last_validated': timezone.now().isoformat(),
        }
        for k, v in session_data.items():
            request.session[k] = v

        # # record a useraction for this
        # UserAction.objects.create(
        #     profile=user_profile,
        #     action='Login',
        #     metadata={},
        #     )

    response = redirect(redirect_uri)
    response.set_cookie('last_github_auth_mutation', int(time.time()))
    return response
예제 #8
0
def github_callback(request):
    """Handle the Github authentication callback."""
    # Get request parameters to handle authentication and the redirect.
    code = request.GET.get('code', None)
    redirect_uri = request.GET.get('redirect_uri')

    if not code or not redirect_uri:
        raise Http404

    # Get OAuth token and github user data.
    access_token = get_github_user_token(code)
    github_user_data = get_github_user_data(access_token)
    handle = github_user_data.get('login')

    if handle:
        # Create or update the Profile with the github user data.
        user_profile, _ = Profile.objects.update_or_create(
            handle=handle,
            defaults={
                'data': github_user_data or {},
                'email': get_github_primary_email(access_token),
                'github_access_token': access_token
            })

        # Update the user's session with handle and email info.
        session_data = {
            'handle': user_profile.handle,
            'email': user_profile.email,
            'access_token': user_profile.github_access_token,
            'profile_id': user_profile.pk,
            'access_token_last_validated': timezone.now().isoformat(),
        }
        for k, v in session_data.items():
            request.session[k] = v

    response = redirect(redirect_uri)
    response.set_cookie('last_github_auth_mutation', int(time.time()))
    return response
예제 #9
0
def new_interest(request, bounty_id):
    """Claim Work for a Bounty.

    :request method: POST

    Args:
        bounty_id (int): ID of the Bounty.

    Returns:
        dict: The success key with a boolean value and accompanying error.

    """
    profile_id = request.user.profile.pk if request.user.is_authenticated and hasattr(
        request.user, 'profile') else None

    access_token = request.GET.get('token')
    if access_token:
        helper_handle_access_token(request, access_token)
        github_user_data = get_github_user_data(access_token)
        profile = Profile.objects.prefetch_related('bounty_set') \
            .filter(handle=github_user_data['login']).first()
        profile_id = profile.pk
    else:
        profile = request.user.profile if profile_id else None

    if not profile_id:
        return JsonResponse(
            {
                'error':
                _('You must be authenticated via github to use this feature!')
            },
            status=401)

    try:
        bounty = Bounty.objects.get(pk=bounty_id)
    except Bounty.DoesNotExist:
        raise Http404

    num_issues = profile.max_num_issues_start_work
    active_bounties = Bounty.objects.current().filter(
        idx_status__in=['open', 'started'])
    num_active = Interest.objects.filter(profile_id=profile_id,
                                         bounty__in=active_bounties).count()
    is_working_on_too_much_stuff = num_active >= num_issues
    if is_working_on_too_much_stuff:
        return JsonResponse(
            {
                'error':
                _(f'You may only work on max of {num_issues} issues at once.'),
                'success':
                False
            },
            status=401)

    if profile.has_been_removed_by_staff():
        return JsonResponse(
            {
                'error':
                _('Because a staff member has had to remove you from a bounty in the past, you are unable to start more work at this time. Please contact support.'
                  ),
                'success':
                False
            },
            status=401)

    try:
        Interest.objects.get(profile_id=profile_id, bounty=bounty)
        return JsonResponse(
            {
                'error':
                _('You have already expressed interest in this bounty!'),
                'success': False
            },
            status=401)
    except Interest.DoesNotExist:
        issue_message = request.POST.get("issue_message")
        interest = create_new_interest_helper(bounty, request.user,
                                              issue_message)

    except Interest.MultipleObjectsReturned:
        bounty_ids = bounty.interested \
            .filter(profile_id=profile_id) \
            .values_list('id', flat=True) \
            .order_by('-created')[1:]

        Interest.objects.filter(pk__in=list(bounty_ids)).delete()

        return JsonResponse(
            {
                'error':
                _('You have already expressed interest in this bounty!'),
                'success': False
            },
            status=401)

    return JsonResponse({
        'success': True,
        'profile': ProfileSerializer(interest.profile).data
    })
예제 #10
0
def save(request):
    status = 422
    message = 'Please use a POST'
    body = {}
    try:
        body = json.loads(request.body)
    except Exception:
        status = 400
        message = 'Bad Request'

    if body.get('bounty_id', False):
        access_token = body.get('token') if body.get(
            'token') else request.GET.get('token')
        github_username = body.get('github_username')
        try:
            github_user_data = get_github_user_data(access_token)
        except Exception:
            github_user_data = {}
        access_token_invalid = not access_token or github_user_data.get(
            'login') != github_username
        if access_token_invalid:
            status = 405
            message = f'Not authorized or invalid github token for github user {github_username}'
        else:
            # handle a POST
            bounty_id = body.get('bounty_id')
            email_address = body.get('email_address')
            direction = body.get('direction')

            # do validation
            validation_failed = False

            # email
            try:
                validate_email(email_address)
            except ValidationError:
                validation_failed = 'email'

            # bounty
            if not Bounty.objects.filter(pk=bounty_id).exists():
                validation_failed = 'bounty does not exist'

            # direction
            if direction not in ['+', '-']:
                validation_failed = 'direction must be either + or -'

            # github_username
            if not github_username:
                validation_failed = 'no github_username'

            # handle validation failures
            if validation_failed:
                status = 422
                message = f'Validation failed: {validation_failed}'
            else:
                bounty = Bounty.objects.get(pk=bounty_id)
                # save obj
                Match.objects.create(
                    bounty=bounty,
                    email=email_address,
                    direction=direction,
                    github_username=github_username,
                )

                try:
                    if direction == '+':
                        profiles = Profile.objects.filter(
                            handle=github_username)
                        profile = profiles.first() if profiles.exists(
                        ) else None
                        interest = Interest.objects.create(
                            profile_id=profile.pk)
                        bounty.interested.add(interest)
                        # TODO -- user create_new_interest_helper
                except Exception as e:
                    print(f'could not get profile {e}')
                    logging.exception(e)

                # send match email
                if direction == '+':
                    to_emails = [email_address, bounty.bounty_owner_email]
                    new_match(to_emails, bounty, github_username)

                # response
                status = 200
                message = 'Success'
    response = {
        'status': status,
        'message': message,
    }
    return JsonResponse(response, status=status)