예제 #1
0
def add_post(request):
    if request.method != 'POST':
        return HttpResponse(status=403)
    token = request.POST.get('token', None)
    title = request.POST.get('title', None)
    preview = request.POST.get('preview', None)
    body = request.POST.get('body', None)

    decode = jwt_helper.decode(token)
    try:
        user = User.objects.get(username=decode['email'])
    except:
        user = None
        return HttpResponse(status=403)

    if None in (token, title, body, preview):
        return HttpResponse(status=500)

    post = Post(title=title,
                preview=preview,
                body=body,
                business_id=20,
                user=user)
    post.save()
    try:
        post.save()
    except:
        pass

    res = {
        'msg': 'success',
    }
    return JsonResponse(res, safe=False)
예제 #2
0
    def test_list_dataset_reports(self):
        (other, teammate, contact, captain, super_admin, team, classroom,
         class_report_1, class_report_2,
         team_report) = self.create_dataset_reports()

        response = self.testapp.get(
            '/api/teams/{}/reports'.format(team.uid),
            headers=self.login_headers(contact),
        )
        reports = json.loads(response.body)

        # Should have correct path.
        expected_paths = {
            '/datasets/team/team_template/team.html',
            '/datasets/class2/class_template/bar.html',
            '/datasets/class1/class_template/foo.html',
        }
        self.assertEqual(
            set(urlparse(r['link']).path for r in reports),
            expected_paths,
        )

        # Jwt should match the path.
        for r in reports:
            url, token = r['link'].split('?token=')
            payload, error = jwt_helper.decode(token)
            self.assertIn('GET //neptune' + urlparse(url).path,
                          payload['allowed_endpoints'])
예제 #3
0
def check_status(request):
    status = False
    msg = ''
    e = ''
    u = ''
    if request.method != 'POST':
        return HttpResponse(status=403)
    token = request.POST.get('token', None)
    if not token:
        return HttpResponse(status=404)
    try:
        data = jwt_helper.decode(token)
    except:
        data = None
        msg = 'Error'

    if data:
        now = calendar.timegm(datetime.utcnow().utctimetuple())

        if now > data['expire']:
            msg = 'User expired'
        else:
            try:
                user = User.objects.get(username=data['email'])
                e = user.username
                u = user.first_name
                status = True
            except:
                msg = 'User does not exist'

    res = {'status': status, 'msg': msg, 'email': e, 'username': u}
    return JsonResponse(res, safe=False)
예제 #4
0
    def test_list_network_reports(self):
        network = Network.create(name="Foo Net", program_id="Program_foo")
        network.put()
        admin = User.create(email="*****@*****.**",
                            owned_networks=[network.uid])
        admin.put()

        template = 'network_tempate'
        filename = 'foo.html'

        report = Report.create(
            network_id=network.uid,
            filename=filename,
            dataset_id='Dataset_class1',
            template=template,
            content_type='text/html',
            preview=False,
        )
        report.put()

        response = self.testapp.get(
            '/api/networks/{}/reports'.format(network.uid),
            headers=self.login_headers(admin),
        )
        reports = json.loads(response.body)

        self.assertEqual(
            urlparse(reports[0]['link']).path,
            '/datasets/{}/{}/{}'.format(report.uid, template, filename),
        )

        url, token = reports[0]['link'].split('?token=')
        payload, error = jwt_helper.decode(token)
        self.assertIn('GET //neptune' + urlparse(url).path,
                      payload['allowed_endpoints'])
예제 #5
0
    def test_delete_issues_allowed_endpoints_jwt(self):
        """DELETE response has special jwt giving permission on Neptune."""
        user, team_dict = self.create()
        # Add some classrooms.
        c1 = Classroom.create(
            name='C1',
            team_id=team_dict['uid'],
            contact_id='User_contact',
            code='a a',
        )
        c2 = Classroom.create(
            name='C2',
            team_id=team_dict['uid'],
            contact_id='User_contact',
            code='b b',
        )
        Classroom.put_multi([c1, c2])

        response = self.testapp.delete(
            '/api/teams/{}'.format(team_dict['uid']),
            headers=self.login_headers(user),
        )

        jwt = response.headers['Authorization'][7:]  # drop "Bearer "
        payload, error = jwt_helper.decode(jwt)
        # Should include an endpoint for each classroom.
        self.assertEqual(
            set(payload['allowed_endpoints']),
            {
                'DELETE //neptune/api/codes/a-a',
                'DELETE //neptune/api/codes/b-b',
            },
        )
예제 #6
0
def add_post(request):
    if request.method != 'POST':
        return HttpResponse(status=403)
    token = request.POST.get('token', None)    
    title = request.POST.get('title', None)
    preview = request.POST.get('preview', None)
    body = request.POST.get('body', None)

    decode = jwt_helper.decode(token)
    try:
        user = User.objects.get(username=decode['email'])
    except:
        user = None
        return HttpResponse(status=403)

    if None in (token, title, body, preview):
        return HttpResponse(status=500)

    post = Post(
        title=title,
        preview=preview,
        body=body,
        business_id=20,
        user=user
    )
    post.save()
    try:
        post.save()
    except:
        pass

    res = {
        'msg': 'success',
    }
    return JsonResponse(res, safe=False)
예제 #7
0
    def test_delete_issues_allowed_endpoints_jwt(self):
        """DELETE response has special jwt giving permission on Neptune."""
        response = self.test_delete_allowed_by_contact()

        jwt = response.headers['Authorization'][7:]  # drop "Bearer "
        payload, error = jwt_helper.decode(jwt)
        self.assertEqual(
            payload['allowed_endpoints'],
            ['DELETE //neptune/api/codes/trout-viper'],
        )
예제 #8
0
    def jwt_allows_endpoint(self, endpoint_str=None):
        """Certain handlers are designed to be called from other platforms but
        require explicit permission from that platform to use.

        Returns boolean.
        """
        payload, error = jwt_helper.decode(self.get_jwt())
        if not payload or error:
            return False

        if endpoint_str is None:
            endpoint_str = self.get_endpoint_str()

        return endpoint_str in payload.get('allowed_endpoints', [])
예제 #9
0
    def get(self, parent_type, rel_id, filename):
        # Always require a jwt that specifies this path/report. This allows
        # shareable, expiring links.
        if not self.get_current_user().super_admin:
            params = self.get_params({'token': str})
            token = params.get('token', None)
            payload, error = jwt_helper.decode(token)
            if error == jwt_helper.EXPIRED:
                return self.http_forbidden("This link has expired.")
            elif not payload or error:
                return self.http_bad_request("Missing or invalid token.")

            allowed_endpoints = payload.get('allowed_endpoints', [])
            if self.get_endpoint_str() not in allowed_endpoints:
                return self.http_forbidden("Token does not allow endpoint.")

        if parent_type == 'organizations':
            parent_id = Organization.get_long_uid(rel_id),
        elif parent_type == 'teams':
            parent_id = Team.get_long_uid(rel_id),
        elif parent_type == 'classrooms':
            parent_id = Classroom.get_long_uid(rel_id),
        else:
            raise Exception("Unrecognized parent type: {}".format(parent_type))
        results = Report.get(parent_id=parent_id, filename=filename)

        if len(results) == 0:
            return self.http_not_found()
        report = results[0]

        # We intentionally don't check permissions or ownership any further
        # here, because reports are shared by link, and we already checked for
        # a jwt in the query string.

        self.response.headers.update({
            'Content-Disposition':
            'inline; filename={}'.format(report.filename),
            # Unicode not allowed in headers.
            'Content-Type':
            str(report.content_type),
        })
        try:
            with gcs.open(report.gcs_path, 'r') as gcs_file:
                self.response.write(gcs_file.read())
        except gcs.NotFoundError:
            logging.error("Couldn't find a gcs file for report {}".format(
                report.to_dict()))
            self.http_not_found()
예제 #10
0
def star_post(request):
    if request.method != 'POST':
        return HttpResponse(status=403)
    post_id = request.POST.get('post_id', None)
    token = request.POST.get('token', None)
    decode = jwt_helper.decode(token)
    user = User.objects.get(username=decode['email'])
    try:
        star = Star.objects.get(post_id=post_id, user=user)
        star.delete()
    except:
        star = Star(post_id=post_id, user=user)
        star.save()
    star_num = Star.objects.filter(post_id=post_id).count()
    res = {'star_num': star_num}
    return JsonResponse(res, safe=False)
예제 #11
0
def star_post(request):
    if request.method != 'POST':
        return HttpResponse(status=403)
    post_id = request.POST.get('post_id', None)
    token = request.POST.get('token', None)
    decode = jwt_helper.decode(token)
    user = User.objects.get(username=decode['email'])
    try:
        star = Star.objects.get(post_id=post_id, user=user)
        star.delete()
    except:
        star = Star(post_id=post_id, user=user)
        star.save()
    star_num = Star.objects.filter(post_id=post_id).count()
    res = {
        'star_num': star_num
    }
    return JsonResponse(res, safe=False)
예제 #12
0
def secret_add_post(request):
    if request.method != 'POST':
        return HttpResponse(status=403)
    token = request.POST.get('token', None)    
    business_id = request.POST.get('business_id', None)
    source = request.POST.get('source', None)
    title = request.POST.get('title', None)
    preview = request.POST.get('preview', None)
    body = request.POST.get('body', None)

    if None in (token, business_id, source, title, preview, body):
        return HttpResponse(status=500)

    decode = jwt_helper.decode(token)
    try:
        user = User.objects.get(username=decode['email'])
    except:
        user = None
        return HttpResponse(status=403)
    if user.id != 256:
        return HttpResponse(status=403)


    business = Business.objects.get(id=business_id)

    post = Post(
        title=title,
        preview=preview,
        body=body,
        source=source,
        business=business,
        is_approved=True,
    )
    post.save()
    try:
        post.save()
    except:
        pass

    res = {
        'msg': 'success',
    }
    return JsonResponse(res, safe=False)
예제 #13
0
def secret_add_post(request):
    if request.method != 'POST':
        return HttpResponse(status=403)
    token = request.POST.get('token', None)
    business_id = request.POST.get('business_id', None)
    source = request.POST.get('source', None)
    title = request.POST.get('title', None)
    preview = request.POST.get('preview', None)
    body = request.POST.get('body', None)

    if None in (token, business_id, source, title, preview, body):
        return HttpResponse(status=500)

    decode = jwt_helper.decode(token)
    try:
        user = User.objects.get(username=decode['email'])
    except:
        user = None
        return HttpResponse(status=403)
    if user.id != 256:
        return HttpResponse(status=403)

    business = Business.objects.get(id=business_id)

    post = Post(
        title=title,
        preview=preview,
        body=body,
        source=source,
        business=business,
        is_approved=True,
    )
    post.save()
    try:
        post.save()
    except:
        pass

    res = {
        'msg': 'success',
    }
    return JsonResponse(res, safe=False)
예제 #14
0
def check_status(request):
    status = False
    msg = ''
    e = ''
    u = ''
    if request.method != 'POST':
        return HttpResponse(status=403)
    token = request.POST.get('token', None)
    if not token:
        return HttpResponse(status=404)
    try:
        data = jwt_helper.decode(token)
    except:
        data = None
        msg = 'Error'

    if data:
        now = calendar.timegm(datetime.utcnow().utctimetuple())
        
        if now > data['expire']:
            msg = 'User expired'
        else:
            try:
                user = User.objects.get(username=data['email'])
                e = user.username
                u = user.first_name
                status = True
            except:
                msg = 'User does not exist'

    res = {
        'status': status,
        'msg': msg,
        'email': e,
        'username': u
    }
    return JsonResponse(res, safe=False)
예제 #15
0
    def test_get_owned(self):
        """You can get a team you own."""
        program = Program.create(
            name='Program Foo',
            label='TP1',
            preview_url='foo.com',
        )
        program.put()
        team = Team.create(name='foo', captain_id='User_cap',
                           program_id=program.uid)
        team.put()
        user = User.create(name='foo', email='*****@*****.**',
                           owned_teams=[team.uid])
        user.put()
        classroom = Classroom.create(name='foo', team_id=team.uid,
                                     contact_id=user.uid, code='trout viper')
        classroom.put()

        response = self.testapp.get(
            '/api/teams/{}'.format(team.uid),
            headers=self.login_headers(user),
        )
        response_dict = json.loads(response.body)
        self.assertEqual(response_dict['uid'], team.uid)

        # Should have allowed endpoints for all contained classrooms.
        jwt_payload, error = jwt_helper.decode(
            response.headers['Authorization'][7:])
        self.assertEqual(
            jwt_payload['allowed_endpoints'],
            [
                'GET //neptune/api/project_cohorts/trout-viper/participation',
                # This endpoint is available also b/c the user is the main
                # contact of this classroom.
                'GET //neptune/api/project_cohorts/trout-viper/completion'
            ],
        )
예제 #16
0
    def get_permissions(self, id, token):
        """Returns tuple like (dataset, http_error_method_name, error_msg)."""
        if token:
            # This URL has jwt authentication embedded in the query string so
            # that it is shareable. Ignore other permission rules as long as
            # the jwt is valid.
            payload, error = jwt_helper.decode(token)
            if not payload or error:
                return (None, 'http_unauthorized', error)

            allowed_endpoints = payload.get('allowed_endpoints', [])
            if self.get_endpoint_str() not in allowed_endpoints:
                return (None, 'http_forbidden', "Endpoint not allowed.")

            ds = Dataset.get_by_id(id)
            if not ds:
                return (None, 'http_not_found', None)

        else:
            # Without a token, do normal user-based authentication.
            user = self.get_current_user()
            if user.user_type == 'public':
                return (None, 'http_unauthorized', '')

            ds = Dataset.get_by_id(id)
            if not ds:
                return (None, 'http_not_found', None)

            if not ds.parent_id:
                if not user.super_admin:
                    return (None, 'http_forbidden',
                            "Only supers can get parentless datasets.")
            elif not owns(self.get_current_user(), ds.parent_id):
                return (None, 'http_forbidden', "Must own parent.")

        return (ds, None, None)
예제 #17
0
    def get_jwt_user(self, jwt_kwargs={}, token=None):
        """Is there a JWT that authenticates the user?

        Returns a tuple as (User or None, error str or None) where the error
        may be 'not found', 'used', or 'expired', just like
        AuthToken.checkTokenString. Error will only be not None if there is
        a JWT present, i.e. if the client isn't even trying to use JWT, the
        return value is (None, None).
        """
        token = token or self.get_jwt()
        payload, error = jwt_helper.decode(token, **jwt_kwargs)

        if not payload:
            # No valid token, so no user.
            return (None, error)

        if 'user_id' not in payload or 'email' not in payload:
            # No user in the token; this may only specify allowed_endpoints.
            return (None, jwt_helper.NO_USER)

        # Retrieve or create the users information.
        user = self.sync_user_with_token(payload)

        return (user, None)
예제 #18
0
    def test_put_issues_allowed_endpoints_jwt(self):
        """PUT response has special jwt giving permission on Neptune."""
        team_id = 'Team_foo'
        survey = Survey.create(team_id=team_id)
        survey.put()
        user = User.create(name='foo',
                           email='*****@*****.**',
                           owned_teams=[team_id])
        user.put()
        # Add some classrooms
        c1 = Classroom.create(name='C1',
                              team_id=team_id,
                              code='a a',
                              contact_id='User_contact')
        c2 = Classroom.create(name='C2',
                              team_id=team_id,
                              code='b b',
                              contact_id='User_contact')
        Classroom.put_multi([c1, c2])

        response = self.testapp.put_json(
            '/api/surveys/{}'.format(survey.uid),
            {'metrics': ['Metric_001', 'Metric_002']},
            headers=self.login_headers(user),
        )

        jwt = response.headers['Authorization'][7:]  # drop "Bearer "
        payload, error = jwt_helper.decode(jwt)
        # Should include an endpoint for each classroom.
        self.assertEqual(
            set(payload['allowed_endpoints']),
            {
                'PUT //neptune/api/codes/a-a',
                'PUT //neptune/api/codes/b-b',
            },
        )
예제 #19
0
    def get(self, user_id=None, team_id=None):
        complete = False

        # Determine authenticated user based on JWT token
        # @todo: can we apply jti or some other rule to make sure this URL isn't
        # inappropriately shareable?
        token = self.request.get('token', None)
        payload, error = jwt_helper.decode(token)
        if not payload or error:
            return self.http_forbidden()

        auth_user = User.get_by_id(payload['user_id'])

        user = User.get_by_id(user_id)
        team = Team.get_by_id(team_id)

        if not user or not team:
            return self.http_not_found()

        # The authenticated user can only retrieve their own certificate.
        # The authenticated user must own the team that they are requesting the
        #   certificate for.
        if not auth_user == user and not owns(auth_user, team):
            return self.http_forbidden()

        classrooms = Classroom.get(
            contact_id=user.uid,
            team_id=team_id,
        )

        cycles = Cycle.get(
            team_id=team_id,
            order='ordinal',
        )

        if len(classrooms) > 0 and len(cycles) > 0:
            cycle_participation = self.get_cycle_participation_pct(
                cycles,
                classrooms,
            )

            participation_complete = self.has_completed_three_cycles(
                cycle_participation)
        else:
            cycle_participation = [{
                'ordinal': c.ordinal,
                'pct': 0,
            } for c in cycles]
            participation_complete = False

        exit_survey_complete = self.has_completed_exit_survey(
            user,
            team_id,
        )

        if (exit_survey_complete and participation_complete):
            complete = True

        if (complete):
            # If a teacher has successfully completed participation for three
            # cycles, the certificate should not show any incomplete cycles
            # because they aren't relevant for the requirement of receiving the
            # completion certificate. See #1223.
            cycles_to_display = [
                c for c in cycle_participation if c['pct'] >= 80
            ][0:3]
        else:
            cycles_to_display = cycle_participation

        if util.is_localhost():
            neptune_protocol = 'http'
            neptune_domain = 'localhost:8080'
        else:
            neptune_protocol = 'https'
            neptune_domain = os.environ['NEPTUNE_DOMAIN']

        self.write(
            'completion.html',
            neptune_protocol=neptune_protocol,
            neptune_domain=neptune_domain,
            complete=complete,
            user_to_display=user,
            team=team,
            cycles_to_display=cycles_to_display,
            exit_survey_complete=exit_survey_complete,
        )