Commit Graph

132 Commits

Author SHA1 Message Date
Rômulo Penido
d4dbc354bc feat: return modified field on get component endpoint (#35508) 2024-09-25 14:32:35 -05:00
Jillian
5446877a86 Soft delete collections (#35496)
* refactor: use django signals to trigger LIBRARY_COLLECTION events

* refactor: use collection usage_key as search document id

This change standardises the search document "id" to be a meilisearch ID
generated from the usage key, for all types of indexed objects.

This is important for collections so we can locate the collection
document in the search index solely from the data provided by the
LIBRARY_COLLECTION_DELETED event (library_key + collection_key), even if
the collection has been deleted from the database.

* refactor: avoid fetching more data than we have to.

* get_library_collection_usage_key and
  searchable_doc_tags_for_collection do not need a Collection object;
  the usage key can be created from the library_key and collection_key.

* updated searchable_doc_for_collection to require the parts of the
  collection usage key + an optional collection. This allows us to
  identify the collection's search document from its usage key without
  requiring an existing Collection object (in case it's been deleted).
  Also removes the edge case for indexing Collections not associated
  with a ContentLibrary -- this won't ever really happen.

* feat: remove soft- and hard-deleted collections from search index

* feat: adds library_component_usage_key to content_libraries.api

* refactor: send CONTENT_OBJECT_ASSOCIATON_CHANGED on django model signals

so that added/removed collections are removed/re-added to component documents.

Special case: When a collection is soft-deleted/restored, we detect this
in the search index and update the collection's component documents
directly, without a CONTENT_OBJECT_ASSOCIATON_CHANGED signal.


* chore: bumps openedx-learning to 0.13.0
2024-09-25 13:29:18 -05:00
Kyle McCormick
f65403975a fix: don't wrap HTML data with newlines when serializing for LC (#35532)
When serializing to OLX, the Learning Core runtime wraps HTML content in
CDATA to avoid having to escape every individual `<`, `>`, and `&`. The
runtime also puts newlines around the content within the CDATA,
So, given HTML content `...`, we get `<![CDATA[\n...\n]]>`.

The problem is that every time you serialize an HTML block to OLX, it
adds another pair of newlines. These newlines aren't visible to the end
users, but they do make it so that importing and exporting content never
reached a stable, aka "canonical" form. It also makes unit testing
difficult, because the value of `html_block.data` becomes a moving
target.

We do not believe these newlines are necessary, so we have removed them
from the `CDATA` block, and added a unit test to ensure that HTML blocks
having a canonical serialization.

Closes: https://github.com/openedx/edx-platform/issues/35525
2024-09-25 14:32:25 +00:00
Chris Chávez
5927be7e0e feat: Add collection tags to index [FC-0062] (#35483)
* feat: Add collection tags to index

* feat: Add api functions to update tags in collections

* feat: Update tags on index when tag_object
2024-09-17 11:52:02 -05:00
Rômulo Penido
a94b5af403 feat: return publishing information on get component endpoint [FC-0062] (#35476)
* feat: return publishing information on get component endpoint

* feat: read data from component.versioning.draft

* test: update tests

* chore: update openedx-learning

---------

Co-authored-by: Jillian <jill@opencraft.com>
Co-authored-by: Chris Chávez <xnpiochv@gmail.com>
2024-09-16 14:03:08 -05:00
Jillian
c41fe89918 Store content object collections in search index [FC-0062] (#35469)
* feat: Add Library Collections REST endpoints

* test: Add tests for Collections REST APIs

* chore: Add missing __init__ files

* docs: Add warning about unstable REST APIs

* feat: emit CONTENT_OBJECT_ASSOCIATIONS_CHANGED
whenever a content object's tags or collections have changed,
and handle that event in content/search.

The deprecated CONTENT_OBJECT_TAGS_CHANGED event is still emitted when
tags change; to be removed after Sumac.

* docs: replaces CONTENT_OBJECT_TAGS_CHANGED with CONTENT_OBJECT_ASSOCIATIONS_CHANGED

* chore: updates openedx-events==9.14.0

* chore: updates openedx-learning==0.11.4

Co-authored-by: Yusuf Musleh <yusuf@opencraft.com>
Co-authored-by: Chris Chávez <xnpiochv@gmail.com>
Co-authored-by: Rômulo Penido <romulo@thinkdash.dev>
2024-09-13 08:20:54 -05:00
Yusuf Musleh
7665f13547 feat: Add Library Collections REST endpoints [FC-0062] (#35321)
* feat: Add Library Collections REST endpoints

* test: Add tests for Collections REST APIs

* chore: Add missing __init__ files

* feat: Add events emitting for Collections

* feat: Add REST endpoints to update Components in a Collections (temp) (#674)

* feat: add/remove components to/from a collection

* docs: Add warning about unstable REST APIs

* chore: updates openedx-events==9.14.0

* chore: updates openedx-learning==0.11.4

* fix: assert collection doc have unique id

---------

Co-authored-by: Jillian <jill@opencraft.com>
Co-authored-by: Chris Chávez <xnpiochv@gmail.com>
Co-authored-by: Rômulo Penido <romulo.penido@gmail.com>
2024-09-11 13:21:10 -05:00
Navin Karkera
e1495398e2 refactor: delete documents that were never published on discard 2024-08-19 17:01:25 +05:30
Navin Karkera
65258117d8 fix: delete discarded drafts from meilisearch index 2024-08-19 17:01:25 +05:30
Yusuf Musleh
11de2a4055 feat: REST API to allow pasting clipboard (staged) content into a library (#35199) 2024-08-15 09:58:06 -07:00
Chris Chávez
2788f2bc3b feat: New fields in library v2 details API view (#35091) 2024-08-01 11:50:13 -07:00
Jillian
20f7dbda7a fix: content search last_published date [FC-0059] (#35195)
* fix: use versioning.last_publish_log for components
* chore: bump openedx-learning to 0.10.1
2024-08-02 02:48:31 +09:30
Jillian
6b5d812d38 feat: adds sortable fields to studio content search index (#35103) 2024-07-25 18:18:49 +00:00
Yusuf Musleh
c625a8d387 [FC-0059] feat: Add order query param to lib v2 API (#35005)
* feat: Add `order` query param to lib v2 API

* test: Add tests for lib v2 `order` field
2024-07-03 00:21:00 +09:30
Chris Chávez
4fd60c4536 feat: Create content in library permission added to API response (#34934) 2024-06-24 12:15:57 -07:00
Yusuf Musleh
221e333154 feat: Use default pagination class for v2 library views (#34879)
This ensures `num_pages` is included in paginated response.
2024-06-11 11:15:25 -07:00
David Ormsbee
be03938377 refactor: update to use Learning Core's new public API
This also bumps our openedx-learning dependency to 0.10.0 (the first
version with the new openedx_learning.api package).
2024-05-21 16:05:56 -04:00
Kyle McCormick
15caa9746f refactor: Completely remove Blockstore (#34739)
Blockstore and all of its (experimental) functionality has been replaced with
openedx-learning, aka "Learning Core". This commit uninstalls the now-unused
openedx-blockstore package and removes all dangling references to it.

Note: This also removes the `copy_library_from_v1_to_v2` management command,
which has been broken ever since we switched from Blockstore to Learning Core.

Part of this DEPR: https://github.com/openedx/public-engineering/issues/238
2024-05-13 09:48:18 -04:00
Jillian
7ad225658f feat: don't use OLX for tags when copying/duplicating blocks (#34386) 2024-04-02 09:59:57 -07:00
David Ormsbee
86f1e5e8aa feat!: Switch v2 libraries to Learning Core data models (#34066)
This moves the Content Libraries V2 backend from Blockstore [1] over to
Learning Core [2] For high-level overview and rationale of this move, see
the Blockstore DEPR [3]. There are several follow-up tasks [4], most notably
adding support for static assets in libraries.

BREAKING CHANGE: Existing V2 libraries, backed by Blockstore, will stop
working. They will continue to be listed in Studio, but their content
will be unavailable. They need to be deleted (via Django admin) or manually
migrated to Learning Core. We do not expect production sites to be in
this situation, as the feature has never left "experimental" status.

[1] https://github.com/openedx-unsupported/blockstore
[2] https://github.com/openedx/openedx-learning/
[3] https://github.com/openedx/public-engineering/issues/238
[4] https://github.com/openedx/edx-platform/issues/34283
2024-02-22 16:38:05 +00:00
David Ormsbee
a9bd61d015 fix: make content_libraries ADR headers match doc guidelines
https://docs.openedx.org/en/latest/documentors/references/quick_reference_rst.html#headings
2024-02-01 16:15:42 -05:00
David Ormsbee
9d3625717c docs: ADR for course data independence from libraries
This is an ADR around the idea that course content should not need to
sync metadata from libraries during the import process or when copy and
pasting.
2024-02-01 16:15:42 -05:00
Kyle D. McCormick
ef0fc97a2d fix: in generate_block_key, get the usage key's block_id, not usage_id
UsageKeys don't have a usage_id field. This line would have crashed
if run.
2024-01-16 09:37:40 -05:00
Kyle D. McCormick
e8b60aef60 fix: move BlockKey and derived_key to avoid cyclical import
After we merged this PR: https://github.com/openedx/edx-platform/pull/33920
this error began popping up in logs:

    Unable to load XBlock 'staffgradedxblock'
    ....
    ImportError: cannot import name 'get_course_blocks' from
    partially initialized module 'lms.djangoapps.course_blocks.api'
    (most likely due to a circular import) ...

The root cause was the new imports of `derived_key` and `BlockKey` into
xmodule/library_content_block.py. Those new imports come from
xmodule/modulestore/store_utilities.py, which runs
`XBlock.load_classes()` at the module level, which fails because we are
still in the process of loading xmodule/library_content_block.

As a solution, we move both `derived_key` and `BlockKey` to
xmodule/util/keys.py. We could potentially move that file to opaque-keys
eventually, depending on how well we think that those concepts generalize.

Also:

* We rename the function from derived_key to derive_key, as
  functions should be verbs.
* We combine the first to parameters of derive_key (a source ContextKey
  and a source BlockKey) into a single parameter (a source UsageKey). In
  my opinion, this makes the function call easier to understand.
2024-01-16 09:37:40 -05:00
Yusuf Musleh
8d2ddd73ec feat: Add tags count for v2 library components (#33979) 2024-01-09 10:23:30 -08:00
connorhaugh
2eac2ef638 feat: keep learner state associated after libraries migration (#33920)
* fix: preserve learner state after v2 migration

Co-authored-by: Kyle McCormick <kyle@axim.org>

---------

Co-authored-by: Kyle McCormick <kyle@axim.org>
2023-12-18 15:14:28 -05:00
Braden MacDonald
5ab6238243 fix: handle paste of library content blocks correctly (#33926) 2023-12-18 09:48:46 -08:00
Kyle McCormick
140f85853d feat!: remove Content Libraries V2 index (#33888)
BREAKING CHANGE: Removes all code, tests, and settings related to
indexing of V2 (blockstore-backed) content libraries in elasticsearch.
This includes indexing of top-level library metadata as well as indexing
of library block metadata. Operators who enabled the experimental
Library Authoring MFE *and* the experimental ENABLE_CONTENT_LIBRARY_INDEX
feature may notice that sorting, filtering, and searching of V2
libraries and their blocks may now be slower and/or less powerful.
The ENABLE_CONTENT_LIBRARY_INDEX feature was already disabled by
default, so most/all operators (including edx.org) should not notice
any difference.

Removed settings include:

* FEATURES['ENABLE_CONTENT_LIBRARY_INDEX']
* ENABLE_ELASTICSEARCH_FOR_TESTS
* TEST_ELASTICSEARCH_USE_SSL
* TEST_ELASTICSEARCH_HOST
* TEST_ELASTICSEARCH_PORT

For rationale, see the updated "Status" section of:
./openedx/core/djangoapps/content_libraries/docs/decisions/0001-index-libraries-in-elasticsearch.rst
2023-12-07 14:57:31 -05:00
Kyle McCormick
27803f51c8 feat!: assume & remove BLOCKSTORE_USE_BLOCKSTORE_APP_API (#33765)
Originally, Blockstore was an independent micro-service, accessed via a REST API.
Then, we changed Blockstore so it could be installed as an in-process Django app.

To support both modes, there existed a blockstore_api wrapper library in edx-platform,
with toggles controlling whether the wrapper called out to the micro-service's REST API versus the
Django app's Python API. Now that the micro-service Blockstore implementation is deprecated,
though, this wrapper library and toggles are just unnecessary complexity.

As a first step towards cleanup, we:

* remove several toggles and settings (details below);
* remove the blocokstore_api wrapper methods which called the REST API and
  marshalled them back into Python objects; and
* remove all test cases which relied on the Blockstore micro-service (and were skippped in CI).

In the future, we will remove the content libraries indexer, 
clean up the remaining bits of blockstore_api, and flatten out all
the Blockstore-related test class hierarchies which are no longer nceessary.

BREAKING CHANGE:
* These Django settings are removed:
  * BLOCKSTORE_PUBLIC_URL_ROOT
  * BLOCKSTORE_API_URL
  * BLOCKSTORE_API_AUTH_TOKEN
  * BLOCKSTORE_USE_BLOCKSTORE_APP_API
* The blockstore.use_blockstore_app_api Waffle switch is removed.
* edx-platform will act as it did when the DJango setting BLOCKSTORE_USE_BLOCKSTORE_APP_API
  or the Waffle switch blockstore.use_blockstore_app_api were enabled. That is, any running Blockstore
  micro-service instance will be ignored, and the Blockstore package which is installed into edx-platform
  will be used instead.

Ref: https://github.com/openedx/blockstore/issues/296
2023-12-06 15:15:18 +00:00
Kyle McCormick
129940b562 fix: load children in a consistent manner when duplicating LC blocks (#33860)
After refactoring the library_content block to use asynchronous tasks
for syncing and duplicating children, we are seeing an error arise
during library_content duplication process on edx.org:

Traceback (most recent call last):
  File "/edx/app/edxapp/edx-platform/openedx/core/djangoapps/content_libraries/tasks.py", line 305, in duplicate_children
    _copy_overrides(store=store, user_id=user_id, source_block=source_block, dest_block=dest_block)
  File "/edx/app/edxapp/edx-platform/openedx/core/djangoapps/content_libraries/tasks.py", line 383, in _copy_overrides
    dest_block=dest_block.runtime.get_block(dest_child_key),
  File "/edx/app/edxapp/edx-platform/xmodule/x_module.py", line 1401, in get_block
    block = self.load_item(usage_id, for_parent=for_parent)
  File "/edx/app/edxapp/edx-platform/xmodule/modulestore/split_mongo/caching_descriptor_system.py", line 127, in _load_item
    block_data = self.get_module_data(block_key, course_key)
  File "/edx/app/edxapp/edx-platform/xmodule/modulestore/split_mongo/caching_descriptor_system.py", line 154, in get_module_data
    raise ItemNotFoundError(block_key)
xmodule.modulestore.exceptions.ItemNotFoundError: BlockKey(...)

We cannot reproduce the issue locally.
We are not entirely certain the cause of this, but we think it might
have do with caching. Specifically, the `store.get_item` and
`source_block.runtime.get_block` methods might use a different cache
than `dest_block.runtime.get_block`. It's possible that writes to
Mongo are sitting in one of those caches, causing reads from the
`dest_block.runtime`'s cache to fail to find dest_block's children.

We attempt to fix this by using the same "block getting" method
consistently. So instead of using a mix of `store.get_item`,
`source_block.runtime.get_block`, and `dest_block.runtime.get_block`,
we just use `store.get_item` everywhere.
2023-11-30 14:59:40 -05:00
connorhaugh
183e04d8b1 feat: add duplicate_children logging (#33829)
Add some logging to better capture the failures we've seen in duplication of library blocks.

Co-authored-by: Kyle McCormick <kyle@axim.org>
2023-11-29 12:56:24 -05:00
Kyle McCormick
e800ae7622 feat: provisionally support V2 libraries in LibraryContentBlock (randomized only) (#33263)
Refactors and reworks the LibraryContentBlock so that its
sync-from-library operations are asynchronous and work with
V2 content libraries. This also required us to make
library_content block duplication asynchronous, as that
involves syncing from the source library.

For the sake of clarity, this PR includes two major method renames:

* update_children(...) -> sync_from_library(...)
* refresh_library(...) -> sync_from_library(upgrade_to_latest=True, ...)

an an XBlock HTTP handler rename:

  /refresh_children -> /upgrade_and_sync

There are still a couple issues with import or duplication
of library_content blocks referencing V2 libraries other than
latest. These will be resolved in an upcoming PR.

Part of: https://openedx.atlassian.net/wiki/spaces/COMM/pages/3820617729/Spec+Memo+Content+Library+Authoring+Experience+V2
Follow-up work: https://github.com/openedx/edx-platform/issues/33640

Co-authored-by: Connor Haugh <chaugh@2u.com>
Co-authored-by: Eugene Dyudyunov <evgen.dyudyunov@raccoongang.com>
2023-11-20 15:58:10 +00:00
Pooja Kulkarni
9bf042b239 * feat: Enforce type hints for content_tagging app in edx-platform (#33484) 2023-10-16 12:25:59 -07:00
Kristin Aoki
f9c1af775c feat: change problem default display name (#33240) 2023-09-13 11:08:48 -04:00
connorhaugh
e788143564 test: remove flaky libraries asset test (#33195) 2023-09-07 17:20:20 +00:00
Rômulo Penido
c54070989b feat!: add new content authoring event signals 2023-07-25 16:45:39 +02:00
Ken Clary
d6f824db40 feat: basic get/post endpoint for v2 xblocks. TNL-10873 2023-07-20 16:03:32 -04:00
Braden MacDonald
57420ed613 feat: expand mypy static type checking (#32591)
* chore: typing + fixes for content_staging
* chore: typing + fixes for learning_sequences
* chore: typing + fixes for content_libraries
* chore: typing + fixes for new XBlock runtime
* feat: type hinting more code with mypy
2023-07-19 09:58:19 -07:00
connorhaugh
00b1ce28b9 feat: add library copy management command (#32598)
This PR introduces the "copy" management command, which copies v1 libraries into v2 libraries.
2023-07-10 15:45:18 -04:00
Jesper Hodge
a6c57811cd feat add xblock api endpoint (#32282)
* feat: add xblock endpoint for updating an xblock

fix: remove debugger

feat: make function call more generic

refactor: just use request.json for request data as before

refactor: extract method

fix: revert wrong method change

fix: refactor correct method

feat: use handle_xblock method so that we can do more than update xblocks

fix: usage_key_string defaults to None

add all CRUD operations

fix usage key parameter

refactor: create /views folder

refactor: move xblock view functions to xblock_services

fix: tests

fix: tests

refactor: move xblock API endpoint to contentstore

* docs: add explanatory comment to new xblock_service

* feat: add feature flag for enabling content editing api

* feat: raise 404 if studio content api is disabled

* tests: test xblock endpoint

* test: make all post tests work

* test: check that xblock_handler receives correct args

* refactor: create util mixin for course factories with staff

* refactor: extract course staff authorization tests

* refactor: extract tests to api view testcase class

* test: add get tests

* test: fix tests

* test: fix tests

* test: fix tests

* test: add all crud tests

* fix: refactor to fix tests

* fix: merge conflict

* fix: merge conflict

* fix: tests after merge

* fix: json request decorator

* fix: lint

* fix: lint

* fix: lint

* fix: lint

* fix: new test files

* fix: lint

* fix: lint and apply PR suggestions

* fix: lint

* fix: lint

* fix: lint

* fix: lint

* fix: lint

* fix: lint
2023-06-15 14:17:49 -04:00
Braden MacDonald
dd927c7fee chore: consolidate two different implementations for serializing XBlocks 2023-04-24 12:16:42 -07:00
Braden MacDonald
626f11f608 test: Import linter: optionally enforce usage of a package's public API (#31903)
* test: warn about dependencies from cms->openedx->lms and vice versa

* test: warn about importing from package's internal implementation code

* chore: Update some imports to use public APIs only

* chore: Update 'bookmarks' app to have stricter public API

* fix: we are sharing 'adapters' from olx_rest_api to content_staging
2023-04-20 11:34:51 -07:00
Tim McCormack
83f6e560b7 fix: Add code_owner decorator to remaining Celery tasks (#31762)
This will ensure that errors raised by these tasks will alert the right
team. `send_course_enrollment_email` is the one I set out to fix, but I
discovered a few others.

I located tasks that were missing decorators by running the following
search and visually inspecting the results, although semgrep might be able
to do better:

```
ack '^@.*task|^@set_code_owner_attribute' cms lms common openedx xmodule --ignore-dir=tests --python
```

Also, add more detailed explanation of why a couple of tasks can't use the
decorator. This should only be an issue on tasks inheriting from
UserTaskMixin, which in practice is just CourseExportTask and
CourseImportTask (and the apparently unused EnrollmentReadTask and
EnrollmentWriteTask), via UserTask.
2023-02-15 18:20:50 +00:00
Kyle McCormick
b5fd4cc55f fix: allow content libraries to be created through Django admin (#31719)
Previously, CMS Django admin would demand that at least one
LTIConfig be associated with the new library. This is not
necessary, but Django thought it was, because the `blank`
flag was not enabled on the ContentLibrary model's
`authored_lti_config` many-to-many field.

This should not affect the experimental blockstore-based
library authoring frontend, which already allows libraries
to be created without any authorized_lti_configs.

This will not affect the existing modulestore-based
library authoring frontend, since it doesn't even use
any of the models in question.

A migration is included with this commit, but it should NOT
change MySQL schema, since `blank` is a Django-level validation
flag.
2023-02-07 08:17:01 -05:00
Jillian
9f5c78e81e revert: temp: let XBlock API users optionally use LabXchange block types (#31315)
when fetching block metadata and rendering blocks while maintaining the
original usage IDs/OLX.

Reverts ef8f841ac2
2023-01-11 11:19:58 -08:00
Usama Sadiq
4734f9f16e fix: bump pylint version (#31084) 2022-10-27 12:19:09 +05:00
Sarina Canelake
4a2f231302 fix: fix github url strings (org edx -> openedx) 2022-09-15 14:52:28 -04:00
Jillian Vogel
5688ad0ba7 fix: call blockstore APIs in atomic transactions. [BD-14] (#30456)
* fix: call blockstore APIs in atomic transactions.

To ensure database integry when using the blockstore APIs, the Content
Library views which invoke blockstore API methods are wrapped in
database transactions.

* fix: assert create_library is called inside an atomic transaction block
2022-06-14 09:10:08 -07:00
Jillian Vogel
d0935d467c fix: fixes bug with HTML blocks in studio_view
Rendering asset URLs requires HTML blocks to be associated with a course key.
This change allows HTML blocks to be associated with libraries and still
render without error.
2022-04-21 09:39:59 +01:00
Jillian Vogel
732d8cb337 fix: use mako prefix lms. when XBlock runtime renders in Studio/authoring MFE
When the XBlock runtime is used in Studio/authoring mode, it needs to
use the template path prefix "lms." in order to locate the block
templates. (In LMS view, no prefix is required.)

Fixes bug introduced by https://github.com/openedx/edx-platform/pull/29354
and removes template workaround added by
https://github.com/openedx/edx-platform/pull/29517 (see Author Notes & Concerns)
2022-04-21 09:39:59 +01:00