Exemple #1
0
 def add_like(self, user):
     like_activity = Activity.create_unless_exists(
         activity_type='asset_like',
         course_id=self.course_id,
         user_id=user.get_id(),
         object_type='asset',
         object_id=self.id,
         asset_id=self.id,
     )
     if like_activity:
         for asset_owner in self.users:
             Activity.create_unless_exists(
                 activity_type='get_asset_like',
                 course_id=self.course_id,
                 user_id=asset_owner.id,
                 object_type='asset',
                 object_id=self.id,
                 asset_id=self.id,
                 actor_id=user.get_id(),
                 reciprocal_id=like_activity.id,
             )
     self.likes = Activity.query.filter_by(
         asset_id=self.id, activity_type='asset_like').count()
     db.session.add(self)
     std_commit()
     return True
Exemple #2
0
 def create_link_submission_asset(self, course, user, category, assignment, submission, link_submission_tracker):
     try:
         existing_submission_asset = link_submission_tracker.get(submission.url, None)
         if existing_submission_asset:
             app.logger.debug(f'Adding new user to existing link asset: user {user.canvas_user_id}, asset {existing_submission_asset.id}.')
             existing_submission_asset.users.append(user)
             db.session.add(existing_submission_asset)
             std_commit()
         else:
             app.logger.info(
                 f'Will create link asset for submission: '
                 f'user {user.canvas_user_id}, submission {submission.id}, assignment {assignment.id}, {_format_course(course)}')
             link_submission_tracker[submission.url] = Asset.create(
                 asset_type='link',
                 canvas_assignment_id=assignment.id,
                 categories=[category],
                 course_id=course.id,
                 source=submission.url,
                 title=submission.url,
                 url=submission.url,
                 users=[user],
                 create_activity=False,
             )
     except Exception as e:
         app.logger.error(
             f'Failed to create link asset for an assignment submission: '
             f'user {user.canvas_user_id}, submission {submission.id}, assignment {assignment.id}, {_format_course(course)}')
         app.logger.exception(e)
Exemple #3
0
 def create(
     cls,
     activity_type,
     course_id,
     user_id,
     object_type,
     object_id=None,
     asset_id=None,
     actor_id=None,
     reciprocal_id=None,
     activity_metadata=None,
 ):
     activity = cls(
         activity_type=activity_type,
         course_id=course_id,
         user_id=user_id,
         object_type=object_type,
         object_id=object_id,
         asset_id=asset_id,
         actor_id=actor_id,
         reciprocal_id=reciprocal_id,
         activity_metadata=activity_metadata,
     )
     db.session.add(activity)
     std_commit()
     return activity
Exemple #4
0
 def increment_views(self, user):
     view_activity = Activity.create_unless_exists(
         activity_type='asset_view',
         course_id=self.course_id,
         user_id=user.id,
         object_type='asset',
         object_id=self.id,
         asset_id=self.id,
     )
     if view_activity:
         for asset_owner in self.users:
             Activity.create_unless_exists(
                 activity_type='get_asset_view',
                 course_id=self.course_id,
                 user_id=asset_owner.id,
                 object_type='asset',
                 object_id=self.id,
                 asset_id=self.id,
                 actor_id=user.id,
                 reciprocal_id=view_activity.id,
             )
     self.views = Activity.query.filter_by(
         asset_id=self.id, activity_type='asset_view').count()
     db.session.add(self)
     std_commit()
     return True
Exemple #5
0
    def poll_tab_configuration(self, db_course, api_course):
        tabs = api_course.get_tabs()
        course_updates = {}
        has_active_tools = False

        if db_course.asset_library_url:
            asset_library_tab = next((t for t in tabs if db_course.asset_library_url.endswith(t.html_url)), None)
            if not asset_library_tab or getattr(asset_library_tab, 'hidden', None):
                app.logger.info(f'No active tab found for Asset Library, will remove URL from db: {_format_course(db_course)}')
                course_updates['asset_library_url'] = None
            else:
                has_active_tools = True
        if db_course.engagement_index_url:
            engagement_index_tab = next((t for t in tabs if db_course.engagement_index_url.endswith(t.html_url)), None)
            if not engagement_index_tab or getattr(engagement_index_tab, 'hidden', None):
                app.logger.info(f'No active tab found for Engagement Index, will remove URL from db: {_format_course(db_course)}')
                course_updates['engagement_index_url'] = None
            else:
                has_active_tools = True

        if not has_active_tools:
            app.logger.info(f'No active tools found for course, will mark inactive: {_format_course(db_course)}')
            course_updates['active'] = False

        if course_updates:
            for key, value in course_updates.items():
                setattr(db_course, key, value)
            db.session.add(db_course)
            std_commit()

        return course_updates.get('active', True)
Exemple #6
0
    def run(self, canvas_api_domain, api_key):
        app.logger.info(f'New poller running for {canvas_api_domain}')
        api_url = f'https://{canvas_api_domain}'
        self.canvas = get_canvas(api_url, api_key)

        while True:
            course = db.session.query(Course) \
                .filter_by(canvas_api_domain=canvas_api_domain, active=True) \
                .order_by(nullsfirst(Course.last_polled.asc())) \
                .with_for_update() \
                .first()
            if not course:
                app.logger.info(f'No active courses found, poller exiting: {canvas_api_domain}')
                break
            app.logger.info(f"Will poll {_format_course(course)}, last polled {course.last_polled or 'never'}")
            course.last_polled = datetime.now()
            db.session.add(course)
            std_commit()

            try:
                self.poll_course(course)
            except Exception as e:
                app.logger.error(f'Failed to poll course {_format_course(course)}')
                app.logger.exception(e)
            sleep(5)
Exemple #7
0
def _create_assets(courses, users):
    course_id = courses[0].id

    def _create_category(visible):
        return Category.create(
            canvas_assignment_id=98765,
            canvas_assignment_name=
            f'Linger on your pale blue eyes (visible={visible})',
            course_id=course_id,
            title=f'Thought of you as my mountain top (visible={visible})',
            visible=visible,
        )

    category_visible = _create_category(True)
    category_hidden = _create_category(False)
    std_commit(allow_test_environment=True)

    assets = []
    for a in _test_assets:
        asset = Asset.create(
            asset_type=a['asset_type'],
            categories=[category_hidden, category_visible],
            course_id=course_id,
            description=None,
            title=a['title'],
            url=a['url'],
            users=[users[0]],
        )
        db.session.add(asset)
        assets.append(asset)
    std_commit(allow_test_environment=True)
    return assets
Exemple #8
0
 def handle_submission_activities(self, course, user, category, assignment, submission, activity_index):
     submission_metadata = {
         'submission_id': submission.id,
         'attempt': getattr(submission, 'attempt', None),
         'file_sync_enabled': category.visible,
     }
     activity_index[user.canvas_user_id] = activity_index.get(user.canvas_user_id, {})
     activity_index[user.canvas_user_id]['assignment_submit'] = activity_index[user.canvas_user_id].get('assignment_submit', {})
     existing_activity = activity_index[user.canvas_user_id]['assignment_submit'].get(assignment.id, None)
     if existing_activity:
         # If we've already seen this submission attempt and there's been no change in visibility settings,
         # skip submission processing.
         if (
             existing_activity.activity_metadata
             and existing_activity.activity_metadata.get('attempt', None) == submission_metadata['attempt']
             and existing_activity.activity_metadata.get('file_sync_enabled', None) == submission_metadata['file_sync_enabled']
         ):
             return False
         # Otherwise the existing activity needs updating and the submission should be processed.
         else:
             existing_activity.activity_metadata = submission_metadata
             db.session.add(existing_activity)
             std_commit()
             return True
     else:
         activity_index[user.canvas_user_id]['assignment_submit'][assignment.id] = Activity.create(
             activity_type='assignment_submit',
             course_id=course.id,
             user_id=user.id,
             object_type='canvas_submission',
             object_id=assignment.id,
             activity_metadata=submission_metadata,
         )
         return True
 def create(cls, canvas_api_domain, api_key):
     api_key = cls(
         canvas_api_domain=canvas_api_domain,
         api_key=api_key,
     )
     db.session.add(api_key)
     std_commit()
     return api_key
Exemple #10
0
def mock_asset(app, db_session):
    course = Course.create(
        canvas_api_domain='bcourses.berkeley.edu',
        canvas_course_id=randrange(1000000),
    )
    category_hidden = Category.create(
        canvas_assignment_name='Just look into her false colored eyes',
        course_id=course.id,
        title='What a clown (visible=False)',
        canvas_assignment_id=98765,
        visible=False,
    )
    category_visible = Category.create(
        canvas_assignment_name='Just look into her false colored eyes',
        course_id=course.id,
        title='What a clown (visible=True)',
        canvas_assignment_id=98765,
        visible=True,
    )
    course = Course.query.order_by(Course.name).all()[0]
    canvas_user_id = str(randint(1000000, 9999999))
    user = User.create(
        canvas_course_role='Student',
        canvas_course_sections=[],
        canvas_email=f'{canvas_user_id}@berkeley.edu',
        canvas_enrollment_state='active',
        canvas_full_name=f'Student {canvas_user_id}',
        canvas_user_id=canvas_user_id,
        course_id=course.id,
    )
    unique_token = datetime.now().isoformat()
    asset = Asset.create(
        asset_type='link',
        categories=[category_hidden, category_visible],
        course_id=course.id,
        description=None,
        download_url=
        f"s3://{app.config['AWS_S3_BUCKET_FOR_ASSETS']}/asset/{course.id}_{canvas_user_id}_{unique_token}.pdf",
        title=f'Mock Asset created at {unique_token}',
        url=f'https://en.wikipedia.org/wiki/{unique_token}',
        users=[user],
    )
    for test_comment in _get_mock_comments():
        comment = Comment.create(asset=asset,
                                 body=test_comment['body'],
                                 user_id=user.id)
        for reply in test_comment.get('replies', []):
            reply = Comment.create(
                asset=asset,
                body=reply['body'],
                parent_id=comment.id,
                user_id=user.id,
            )
    std_commit(allow_test_environment=True)
    yield asset
    db_session.delete(asset)
    std_commit(allow_test_environment=True)
Exemple #11
0
 def create(cls, activity_type, course_id, enabled=True, points=None):
     activity_type_instance = cls(
         activity_type=activity_type,
         course_id=course_id,
         enabled=enabled,
         points=points,
     )
     db.session.add(activity_type_instance)
     std_commit()
     return activity_type_instance
Exemple #12
0
 def delete(cls, comment_id):
     comment = cls.query.filter_by(id=comment_id).first()
     if comment:
         asset = comment.asset
         db.session.delete(comment)
         Activity.delete_by_object_id(object_type='comment',
                                      object_id=comment_id)
         std_commit(allow_test_environment=True)
         if asset:
             asset.refresh_comments_count()
Exemple #13
0
def _create_activity_types(courses):
    course = courses[0]
    for test_activity_type in _test_activity_types:
        ActivityType.create(
            course_id=course.id,
            activity_type=test_activity_type['type'],
            enabled=test_activity_type['enabled'],
            points=test_activity_type['points'],
        )
    std_commit(allow_test_environment=True)
 def test_update_comment_by_owner(self, client, fake_auth, mock_asset):
     """Comment author can update comment."""
     comment = Comment.query.first()
     fake_auth.login(comment.user_id)
     body = 'I, me, mine.'
     self._api_update_comment(client, body=body, comment_id=comment.id)
     std_commit(allow_test_environment=True)
     # Verify update
     comments = _api_get_comments(asset_id=comment.asset_id, client=client)
     updated_comment = next(c for c in comments if c['id'] == comment.id)
     assert updated_comment['body'] == body
Exemple #15
0
 def update(
     cls,
     category_id,
     title,
     visible,
 ):
     category = cls.find_by_id(category_id)
     category.title = title
     category.visible = visible
     db.session.add(category)
     std_commit()
     return category
Exemple #16
0
 def update(
     cls,
     asset_library_url,
     course_id,
     engagement_index_url,
 ):
     course = cls.find_by_id(course_id=course_id)
     course.asset_library_url = asset_library_url
     course.engagement_index_url = engagement_index_url
     db.session.add(course)
     std_commit()
     return course
Exemple #17
0
 def create(cls, asset, user_id, body, parent_id=None):
     comment = cls(
         asset_id=asset.id,
         user_id=user_id,
         body=body,
         parent_id=parent_id,
     )
     db.session.add(comment)
     std_commit(allow_test_environment=True)
     _create_activities_per_new_comment(asset=asset, comment=comment)
     asset.refresh_comments_count()
     return comment
Exemple #18
0
def _create_activities(assets, users):
    asset = assets[0]
    user = users[0]
    for test_activity in _test_activities:
        Activity.create(
            activity_type=test_activity['type'],
            course_id=asset.course_id,
            user_id=user.id,
            object_type=test_activity['object_type'],
            object_id=asset.id,
            asset_id=asset.id,
        )
    std_commit(allow_test_environment=True)
Exemple #19
0
 def update_preview(self, **kwargs):
     if kwargs.get('preview_status'):
         self.preview_status = kwargs['preview_status']
     if kwargs.get('thumbnail_url'):
         self.thumbnail_url = kwargs['thumbnail_url']
     if kwargs.get('image_url'):
         self.image_url = kwargs['image_url']
     if kwargs.get('pdf_url'):
         self.pdf_url = kwargs['pdf_url']
     if kwargs.get('metadata'):
         self.preview_metadata = kwargs['metadata']
     db.session.add(self)
     std_commit()
     return True
Exemple #20
0
 def update(
     cls,
     asset_id,
     title,
     categories=None,
     description=None,
 ):
     asset = Asset.find_by_id(asset_id)
     asset.title = title
     asset.description = description
     asset.categories = categories
     db.session.add(asset)
     std_commit()
     return asset
Exemple #21
0
    def create(
        cls,
        asset_type,
        course_id,
        title,
        users,
        canvas_assignment_id=None,
        categories=None,
        description=None,
        download_url=None,
        mime=None,
        source=None,
        url=None,
        visible=True,
        create_activity=True,
    ):
        asset = cls(
            asset_type=asset_type,
            canvas_assignment_id=canvas_assignment_id,
            categories=categories,
            course_id=course_id,
            description=description,
            download_url=download_url,
            mime=mime,
            source=source,
            title=title,
            url=url,
            users=users,
            visible=visible,
        )
        db.session.add(asset)
        std_commit()

        preview_url = download_url if asset_type == 'file' else url
        generate_previews(asset.id, preview_url)

        # Invisible assets generate no activities.
        if visible and create_activity is not False:
            for user in users:
                Activity.create(
                    activity_type='asset_add',
                    course_id=course_id,
                    user_id=user.id,
                    object_type='asset',
                    object_id=asset.id,
                    asset_id=asset.id,
                )

        return asset
 def _verify_delete_comment(self, asset, client):
     asset_feed = _api_get_asset(asset_id=asset.id, client=client)
     initial_comment_count = asset_feed['commentCount']
     assert initial_comment_count > 0
     comment = Comment.get_comments(asset_id=asset.id)[0]
     comment_id = comment['id']
     self._api_delete_comment(comment_id=comment_id, client=client)
     std_commit(allow_test_environment=True)
     comments = _api_get_comments(asset_id=asset.id, client=client)
     comment_ids = list(map(lambda c: c['id'], comments))
     assert comment_id not in comment_ids
     asset_feed = _api_get_asset(asset_id=asset.id, client=client)
     assert asset_feed['commentCount'] == initial_comment_count - 1
     activities = Activity.find_by_object_id(object_type='comment',
                                             object_id=comment_id)
     assert len(activities) == 0
Exemple #23
0
def _create_users(courses):
    course = courses[0]
    users = []
    for test_user in _test_users:
        user = User.create(
            canvas_course_role=test_user['canvas_course_role'],
            canvas_course_sections=[],
            canvas_email=test_user['canvas_email'],
            canvas_enrollment_state=test_user['canvas_enrollment_state'],
            canvas_full_name=test_user['canvas_full_name'],
            canvas_user_id=test_user['canvas_user_id'],
            course_id=course.id,
        )
        users.append(user)
    std_commit(allow_test_environment=True)
    return users
Exemple #24
0
 def create(
     cls,
     canvas_assignment_name,
     course_id,
     title,
     canvas_assignment_id=None,
     visible=True,
 ):
     category = cls(
         canvas_assignment_id=canvas_assignment_id,
         canvas_assignment_name=canvas_assignment_name,
         course_id=course_id,
         title=title,
         visible=visible,
     )
     db.session.add(category)
     std_commit()
     return category
Exemple #25
0
 def remove_like(self, user):
     db.session.query(Activity).filter_by(
         object_id=self.id,
         object_type='asset',
         activity_type='asset_like',
         user_id=user.get_id(),
     ).delete()
     db.session.query(Activity).filter_by(
         object_id=self.id,
         object_type='asset',
         activity_type='get_asset_like',
         actor_id=user.get_id(),
     ).delete()
     self.likes = Activity.query.filter_by(
         object_id=self.id, object_type='asset',
         activity_type='asset_like').count()
     db.session.add(self)
     std_commit()
     return True
Exemple #26
0
 def create(
     cls,
     canvas_api_domain,
     canvas_course_id,
     asset_library_url=None,
     engagement_index_url=None,
     name=None,
 ):
     course = cls(
         active=True,
         asset_library_url=asset_library_url,
         canvas_api_domain=canvas_api_domain,
         canvas_course_id=canvas_course_id,
         engagement_index_url=engagement_index_url,
         name=name,
     )
     db.session.add(course)
     std_commit()
     return course
Exemple #27
0
def _create_courses():
    for c in _test_canvas:
        canvas = Canvas(
            canvas_api_domain=c['canvas_api_domain'],
            api_key=c['api_key'],
            lti_key=c['lti_key'],
            lti_secret=c['lti_secret'],
            name=c['name'],
        )
        db.session.add(canvas)
    std_commit(allow_test_environment=True)

    courses = []
    for c in _test_courses:
        course = Course(
            active=c['active'],
            canvas_api_domain=c['canvas_api_domain'],
            canvas_course_id=c['canvas_course_id'],
        )
        db.session.add(course)
        courses.append(course)
    std_commit(allow_test_environment=True)
    return courses
Exemple #28
0
 def create_file_submission_assets(self, course, user, category, assignment, submission, file_submission_tracker):
     app.logger.info(
         f'Will create file assets for submission attachments: '
         f'user {user.canvas_user_id}, submission {submission.id}, assignment {assignment.id}, {_format_course(course)}')
     for attachment in getattr(submission, 'attachments', []):
         try:
             if attachment['size'] > 10485760:
                 app.logger.debug('Attachment too large, will not process.')
                 continue
             existing_submission_asset = file_submission_tracker.get(attachment['id'], None)
             if existing_submission_asset:
                 app.logger.debug(f'Adding new user to existing file asset: user {user.canvas_user_id}, asset {existing_submission_asset.id}.')
                 existing_submission_asset.users.append(user)
                 db.session.add(existing_submission_asset)
                 std_commit()
             else:
                 s3_attrs = Asset.upload_to_s3(
                     filename=attachment['filename'],
                     byte_stream=urlopen(attachment['url']).read(),
                     course_id=course.id,
                 )
                 file_submission_tracker[attachment['id']] = Asset.create(
                     asset_type='file',
                     canvas_assignment_id=assignment.id,
                     categories=[category],
                     course_id=course.id,
                     download_url=s3_attrs.get('download_url', None),
                     mime=s3_attrs.get('content_type', None),
                     title=attachment['filename'],
                     users=[user],
                     create_activity=False,
                 )
         except Exception as e:
             app.logger.error(
                 f'Failed to create file asset for an attachment: '
                 f'user {user.canvas_user_id}, submission {submission.id}, assignment {assignment.id}, {_format_course(course)}')
             app.logger.exception(e)
Exemple #29
0
 def create(
     cls,
     canvas_course_role,
     canvas_enrollment_state,
     canvas_full_name,
     canvas_user_id,
     course_id,
     canvas_course_sections=None,
     canvas_email=None,
     canvas_image=None,
 ):
     user = cls(
         canvas_course_role=canvas_course_role,
         canvas_course_sections=canvas_course_sections,
         canvas_email=canvas_email,
         canvas_enrollment_state=canvas_enrollment_state,
         canvas_full_name=canvas_full_name,
         canvas_image=canvas_image,
         canvas_user_id=canvas_user_id,
         course_id=course_id,
     )
     db.session.add(user)
     std_commit()
     return user
        def _create_user_at_lti_launch():
            _response = self._api_auth_lti_launch(
                client=client,
                custom_canvas_api_domain=canvas.canvas_api_domain,
                custom_canvas_course_id=canvas_course_id,
                custom_canvas_user_id=canvas_user_id,
                custom_external_tool_url=external_tool_url,
                lis_person_name_full=full_name,
                oauth_consumer_key=canvas.lti_key,
                roles='Student',
                tool_id=TOOL_ID_ASSET_LIBRARY,
            )
            std_commit(allow_test_environment=True)

            user = User.find_by_canvas_user_id(canvas_user_id)
            assert user
            assert user.canvas_full_name == full_name
            assert user.canvas_user_id == canvas_user_id

            course = user.course
            assert course.canvas_course_id == canvas_course_id
            assert course.engagement_index_url is None
            assert course.asset_library_url == external_tool_url
            return _response