Muhammad Faraz Maqsood c5e56dfa2c fix: permission denied error for media directory
"""
discovery-1  | PermissionError: [Errno 13] Permission denied: '/openedx/discovery/course_discovery/media/media'
discovery-1  | 2024-06-25 13:35:29,038 ERROR 7 [django.request] /openedx/venv/lib/python3.8/site-packages/django/utils/log.py:241 - Internal Server Error: /admin/course_metadata/program/9/change/
discovery-1  | Traceback (most recent call last):
discovery-1  |   File "/openedx/venv/lib/python3.8/site-packages/django/core/handlers/exception.py", line 55, in inner
discovery-1  |     response = get_response(request)
discovery-1  |   File "/openedx/venv/lib/python3.8/site-packages/django/core/handlers/base.py", line 197, in _get_response
discovery-1  |     response = wrapped_callback(request, *callback_args, **callback_kwargs)
discovery-1  |   File "/openedx/venv/lib/python3.8/site-packages/django/contrib/admin/options.py", line 688, in wrapper
discovery-1  |     return self.admin_site.admin_view(view)(*args, **kwargs)
discovery-1  |   File "/openedx/venv/lib/python3.8/site-packages/django/utils/decorators.py", line 134, in _wrapper_view
discovery-1  |     response = view_func(request, *args, **kwargs)
discovery-1  |   File "/openedx/venv/lib/python3.8/site-packages/django/views/decorators/cache.py", line 62, in _wrapper_view_func
discovery-1  |     response = view_func(request, *args, **kwargs)
discovery-1  |   File "/openedx/venv/lib/python3.8/site-packages/django/contrib/admin/sites.py", line 242, in inner
discovery-1  |     return view(request, *args, **kwargs)
discovery-1  |   File "/openedx/venv/lib/python3.8/site-packages/django_object_actions/utils.py", line 57, in change_view
discovery-1  |     return super(BaseDjangoObjectActions, self).change_view(
discovery-1  |   File "/openedx/venv/lib/python3.8/site-packages/django/contrib/admin/options.py", line 1889, in change_view
discovery-1  |     return self.changeform_view(request, object_id, form_url, extra_context)
discovery-1  |   File "/openedx/venv/lib/python3.8/site-packages/django/utils/decorators.py", line 46, in _wrapper
discovery-1  |     return bound_method(*args, **kwargs)
discovery-1  |   File "/openedx/venv/lib/python3.8/site-packages/django/utils/decorators.py", line 134, in _wrapper_view
discovery-1  |     response = view_func(request, *args, **kwargs)
discovery-1  |   File "/openedx/venv/lib/python3.8/site-packages/django/contrib/admin/options.py", line 1747, in changeform_view
discovery-1  |     return self._changeform_view(request, object_id, form_url, extra_context)
discovery-1  |   File "/openedx/venv/lib/python3.8/site-packages/django/contrib/admin/options.py", line 1798, in _changeform_view
discovery-1  |     self.save_model(request, new_object, form, not add)
discovery-1  |   File "/openedx/discovery/./course_discovery/apps/course_metadata/admin.py", line 462, in save_model
discovery-1  |     super().save_model(request, obj, form, change)
discovery-1  |   File "/openedx/venv/lib/python3.8/site-packages/simple_history/admin.py", line 228, in save_model
discovery-1  |     super().save_model(request, obj, form, change)
discovery-1  |   File "/openedx/venv/lib/python3.8/site-packages/django/contrib/admin/options.py", line 1227, in save_model
discovery-1  |     obj.save()
discovery-1  |   File "/openedx/discovery/./course_discovery/apps/course_metadata/models.py", line 3613, in save
discovery-1  |     super().save(*args, **kwargs)
discovery-1  |   File "/openedx/discovery/./course_discovery/apps/course_metadata/models.py", line 102, in save
discovery-1  |     super().save(*args, **kwargs)
discovery-1  |   File "/openedx/venv/lib/python3.8/site-packages/django_extensions/db/models.py", line 22, in save
discovery-1  |     super().save(**kwargs)
discovery-1  |   File "/openedx/venv/lib/python3.8/site-packages/django/db/models/base.py", line 814, in save
discovery-1  |     self.save_base(
discovery-1  |   File "/openedx/venv/lib/python3.8/site-packages/model_utils/tracker.py", line 375, in inner
discovery-1  |     return original(instance, *args, **kwargs)
discovery-1  |   File "/openedx/venv/lib/python3.8/site-packages/django/db/models/base.py", line 877, in save_base
discovery-1  |     updated = self._save_table(
discovery-1  |   File "/openedx/venv/lib/python3.8/site-packages/django/db/models/base.py", line 981, in _save_table
discovery-1  |     values = [
discovery-1  |   File "/openedx/venv/lib/python3.8/site-packages/django/db/models/base.py", line 985, in <listcomp>
discovery-1  |     (getattr(self, f.attname) if raw else f.pre_save(self, False)),
discovery-1  |   File "/openedx/venv/lib/python3.8/site-packages/django/db/models/fields/files.py", line 317, in pre_save
discovery-1  |     file.save(file.name, file.file, save=False)
discovery-1  |   File "/openedx/venv/lib/python3.8/site-packages/stdimage/models.py", line 32, in save
discovery-1  |     super().save(name, content, save)
discovery-1  |   File "/openedx/venv/lib/python3.8/site-packages/django/db/models/fields/files.py", line 93, in save
discovery-1  |     self.name = self.storage.save(name, content, max_length=self.field.max_length)
discovery-1  |   File "/openedx/venv/lib/python3.8/site-packages/django/core/files/storage/base.py", line 38, in save
discovery-1  |     name = self._save(name, content)
discovery-1  |   File "/openedx/venv/lib/python3.8/site-packages/django/core/files/storage/filesystem.py", line 87, in _save
discovery-1  |     os.makedirs(directory, exist_ok=True)
discovery-1  |   File "/usr/lib/python3.8/os.py", line 213, in makedirs
discovery-1  |     makedirs(head, exist_ok=exist_ok)
discovery-1  |   File "/usr/lib/python3.8/os.py", line 213, in makedirs
discovery-1  |     makedirs(head, exist_ok=exist_ok)
discovery-1  |   File "/usr/lib/python3.8/os.py", line 223, in makedirs
discovery-1  |     mkdir(name, mode)
discovery-1  | PermissionError: [Errno 13] Permission denied: '/openedx/discovery/course_discovery/media/media'
"""
2024-07-01 19:41:37 +05:00
🌅
2019-07-11 13:44:16 +08:00
2024-06-20 01:51:37 +02:00
🌅
2019-07-11 13:44:16 +08:00
2023-11-24 08:39:38 +05:00
2019-07-11 16:32:59 +08:00
2023-05-17 10:24:21 +02:00
2024-06-04 12:30:44 +05:00
2024-06-07 22:19:39 +05:00

Course Discovery plugin for `Tutor <https://docs.tutor.edly.io>`_
=====================================================================

This is a plugin for `Tutor <https://docs.tutor.edly.io>`_ that integrates the `Course Discovery <https://github.com/edx/course-discovery/>`__ application in an Open edX platform. it is useful for integration with, for example, `Ecommerce <https://github.com/edx/ecommerce>`__ or an external course catalog.

Installation
------------

This plugin requires tutor>=3.6.0. If you have installed tutor from a pre-compiled binary, it already comes bundled with the discovery plugin. Otherwise::

    tutor plugins install discovery

Then, to enable this plugin, run::

    tutor plugins enable discovery

Restart and initialize your platform with::

    tutor local launch

Operations
----------

Creating a user
~~~~~~~~~~~~~~~

The discovery user interface will be available at http://discovery.local.edly.io for a local test instance, and at ``DISCOVERY_HOST`` (by default: http(s)://discovery.<your lms host>) in production. In order to run commands from the UI, a user must be created::

    tutor local run discovery ./manage.py createsuperuser

Then, you must login with this user at http://discovery.local.edly.io/admin.

Alternatively, you can login with oauth2 using a pre-existing user created on the LMS/CMS by accessing http(s)://discovery.<your lms host>/login. To do so, the proper domain names must exist and point to the production server.

Index configuration
~~~~~~~~~~~~~~~~~~~

Discovery uses separate indices for different models (the names are: course, course_run, person and program by default). And you can overwrite theses
names by configuring ``DISCOVERY_INDEX_OVERRIDES``::

    DISCOVERY_INDEX_OVERRIDES:
      course_discovery.apps.course_metadata.search_indexes.documents.course: your-course-index-name
      course_discovery.apps.course_metadata.search_indexes.documents.course_run: your-course-run-index-name
      course_discovery.apps.course_metadata.search_indexes.documents.person: your-person-index-name
      course_discovery.apps.course_metadata.search_indexes.documents.program: your-program-index-name

Re-indexing courses
~~~~~~~~~~~~~~~~~~~

::

    tutor local run discovery ./manage.py refresh_course_metadata --partner_code=openedx
    tutor local run discovery ./manage.py update_index --disable-change-limit

Caching programs
~~~~~~~~~~~~~~~~

In order to cache programs in the LMS, you will need to manually create a catalog integration. Make sure you use staff user for the below command. If ``lms_catalog_service_user`` is not a staff user, then make it a staff user in your LMS User model. This step should be performed just once::

    tutor local run lms ./manage.py lms create_catalog_integrations --enabled \
        --internal_api_url="" \
        --service_username=lms_catalog_service_user

Then run the below command, this command will cause errors every time as it tries to cache programs from all sites that are added to your LMS sites model::

    tutor local run lms ./manage.py lms cache_programs

If you don't want the errors, then make use of an extra argument to the command .i.e. ``--domain``. This argument will be equal to ``local.edly.io`` if you are running tutor local and ``local.edly.io:8000`` if you are running tutor dev::
    tutor local run lms ./manage.py lms cache_programs --domain="local.edly.io"
    or
    tutor dev run lms ./manage.py lms cache_programs --domain="local.edly.io:8000"

This last step should be performed every time you create new or make changes to existing programs.

Show Programs Tab
~~~~~~~~~~~~~~~~~

In order to show programs tab in the LMS dashboard, users will need to manually create an entry in ``Programs api config`` model in LMS Admin Panel. Go to http://local.edly.io/admin/programs/programsapiconfig/. Add ``Marketing path`` equal to ``/programs`` and enable it. Then Programs tab will be shown on the LMS where users can view their registered programs. It will show like as in below picture.

.. image:: https://github.com/overhangio/tutor-discovery/assets/122095701/e0224011-adc0-41e4-a104-af4cb0c24b82
    :alt: Programs Tab on LMS dashboard

In the above image, User can see explore programs button which is pointing to ``http://localhost:8080/programs`` by default. This link does not exist. So, users can change this link to their custom build marketing site url to show all programs there. This can be done by modifying ``Site Configurations`` model in LMS Admin Panel. Go to http://local.edly.io/admin/site_configuration/siteconfiguration/. Open respective LMS site configuration and add below dict in ``site values`` field like below image::

    "MKTG_URLS": {
        "ROOT": "https://custom-marketing-site-here.com"
    }

.. image:: https://github.com/overhangio/tutor-discovery/assets/122095701/2d588ea9-a830-40b6-9845-8fab56d7cb5a
    :alt: Add Custom Site for Explore Programs

Install extra requirements
~~~~~~~~~~~~~~~~~~~~~~~~~~

In order to install extra requirements, use DISCOVERY_EXTRA_PIP_REQUIREMENTS and re-build the docker image.::

  tutor config save \
    --set 'DISCOVERY_EXTRA_PIP_REQUIREMENTS=["git+https://github.com/myusername/myplugin"]'

Then, build the image, pointing to your fork if necessary::

  tutor images build discovery

Debugging
---------

To debug the course discovery service, you are encouraged to mount the course-discovery repo from the host in the development container:

    tutor dev start --mount /path/to/course-discovery/ discovery

You can then access the development server at http://discovery.local.edly.io:8381. Feel free to add breakpoints (``import pdb; pdb.set_trace()``) anywhere in your source code to debug your application.

Once a local repository is mounted in the image, you will have to install nodejs dependencies and collect static assets::

    tutor dev run discovery npm install --development
    tutor dev run discovery make static.dev

Troubleshooting
---------------

This Tutor plugin is maintained by Muhammad Faraz Maqsood from `Edly <https://edly.io/>`__. Community support is available from the official `Open edX forum <https://discuss.openedx.org>`__. Do you need help with this plugin? See the `troubleshooting <https://docs.tutor.edly.io/troubleshooting.html>`__ section from the Tutor documentation.


`Max retries exceeded with url`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

When running in production with HTTPS enabled, you may face this error during the `init` phase of `tutor local launch`:

```
requests.exceptions.ConnectionError: HTTPSConnectionPool(host='<LMS_HOST>', port=443): Max retries exceeded with url: /api/courses/v1/courses/?page=1&page_size=10&username=discovery
```

This error may be due to an incorrect DNS resolution of the LMS DNS record. With some cloud providers (for instance: [DigitalOcean](https://digitalocean.com/)) the `/etc/hosts` file on the host automatically contains the following entry::

    127.0.1.1 <LMS HOST>

This entry may be present if you named your server with the LMS hostname.

License
-------

This work is licensed under the terms of the `GNU Affero General Public License (AGPL) <https://github.com/overhangio/tutor/blob/master/LICENSE.txt>`_.
Description
Course Discovery plugin for Tutor
Readme 412 KiB
Languages
Python 67.2%
Dockerfile 24.2%
Makefile 8.6%