From 4d442d67c5de3f0762ebca108fa3b3827d7e4e50 Mon Sep 17 00:00:00 2001 From: Richard Tibbles Date: Thu, 11 Jan 2024 15:04:04 -0800 Subject: [PATCH 01/61] Removes inconsistently applied and mostly no-op double click blocking. --- .../assets/src/state/modules/core/actions.js | 16 ---------------- .../core/assets/src/state/modules/core/index.js | 1 - .../assets/src/state/modules/core/mutations.js | 3 --- kolibri/plugins/learn/assets/src/app.js | 1 - .../learn/assets/src/views/TopicsContentPage.vue | 12 ------------ .../assets/src/views/UserAuthLayout.vue | 12 ------------ 6 files changed, 45 deletions(-) diff --git a/kolibri/core/assets/src/state/modules/core/actions.js b/kolibri/core/assets/src/state/modules/core/actions.js index a9bad1fcab8..3eaf813ae48 100644 --- a/kolibri/core/assets/src/state/modules/core/actions.js +++ b/kolibri/core/assets/src/state/modules/core/actions.js @@ -92,22 +92,6 @@ export function handleApiError(store, { error, reloadOnReconnect = false } = {}) throw error; } -/** - * Used to prevent inadvertent actions if a user double-clicks to navigate - * - * Something of a hack. A better strategy would be to create a new - * `setLoading` action which handles both `state.core.loading` and - * `state.core.blockDoubleClicks` with a single function. - */ -export function blockDoubleClicks(store) { - if (!store.state.blockDoubleClicks) { - store.commit('CORE_BLOCK_CLICKS', true); - setTimeout(() => { - store.commit('CORE_BLOCK_CLICKS', false); - }, 500); - } -} - export function setSession(store, { session, clientNow }) { const serverTime = session.server_time; if (clientNow) { diff --git a/kolibri/core/assets/src/state/modules/core/index.js b/kolibri/core/assets/src/state/modules/core/index.js index 59076b4ed2c..f0e72c83ce4 100644 --- a/kolibri/core/assets/src/state/modules/core/index.js +++ b/kolibri/core/assets/src/state/modules/core/index.js @@ -10,7 +10,6 @@ export default { state() { return { error: '', - blockDoubleClicks: false, loading: true, pageSessionId: 0, totalProgress: null, diff --git a/kolibri/core/assets/src/state/modules/core/mutations.js b/kolibri/core/assets/src/state/modules/core/mutations.js index ffeeb04c656..a02d3203729 100644 --- a/kolibri/core/assets/src/state/modules/core/mutations.js +++ b/kolibri/core/assets/src/state/modules/core/mutations.js @@ -15,9 +15,6 @@ export default { CORE_SET_ERROR(state, error) { state.error = error; }, - CORE_BLOCK_CLICKS(state, blocked) { - state.blockDoubleClicks = blocked; - }, SET_TOTAL_PROGRESS(state, progress) { state.totalProgress = progress; }, diff --git a/kolibri/plugins/learn/assets/src/app.js b/kolibri/plugins/learn/assets/src/app.js index 4f114111176..0634d4314ae 100644 --- a/kolibri/plugins/learn/assets/src/app.js +++ b/kolibri/plugins/learn/assets/src/app.js @@ -43,7 +43,6 @@ class LearnModule extends KolibriApp { // after every navigation, block double-clicks router.afterEach((toRoute, fromRoute) => { - this.store.dispatch('blockDoubleClicks'); this.store.dispatch('resetModuleState', { toRoute, fromRoute }); }); super.ready(); diff --git a/kolibri/plugins/learn/assets/src/views/TopicsContentPage.vue b/kolibri/plugins/learn/assets/src/views/TopicsContentPage.vue index e80c144d962..4ba94fd466e 100644 --- a/kolibri/plugins/learn/assets/src/views/TopicsContentPage.vue +++ b/kolibri/plugins/learn/assets/src/views/TopicsContentPage.vue @@ -5,8 +5,6 @@ class="main-wrapper" > -
- state.core.error, - blockDoubleClicks: state => state.core.blockDoubleClicks, }), isCoachContent() { return this.content && this.content.coach_content ? 1 : 0; @@ -735,15 +732,6 @@ outline-style: none !important; } - .click-mask { - position: fixed; - top: 0; - left: 0; - z-index: 24; - width: 100%; - height: 100%; - } - .loader { position: fixed; right: 0; diff --git a/kolibri/plugins/user_auth/assets/src/views/UserAuthLayout.vue b/kolibri/plugins/user_auth/assets/src/views/UserAuthLayout.vue index fbdb18373cc..bac2199e5e0 100644 --- a/kolibri/plugins/user_auth/assets/src/views/UserAuthLayout.vue +++ b/kolibri/plugins/user_auth/assets/src/views/UserAuthLayout.vue @@ -6,8 +6,6 @@ :style="mainWrapperStyles" > -
-
state.core.error, loading: state => state.core.loading, - blockDoubleClicks: state => state.core.blockDoubleClicks, }), isAuthorized() { return !( @@ -168,15 +165,6 @@ overflow-x: auto; } - .click-mask { - position: fixed; - top: 0; - left: 0; - z-index: 24; - width: 100%; - height: 100%; - } - .debug { font-family: monospace; font-size: large; From 2ce9790b121d1568630f795e27842cb7bdcebbd8 Mon Sep 17 00:00:00 2001 From: Richard Tibbles Date: Fri, 12 Jan 2024 14:19:09 -0800 Subject: [PATCH 02/61] Delete coreAPI PageRoot component in favour of default component in kolibri_app. --- kolibri/core/assets/src/core-app/apiSpec.js | 2 -- kolibri/core/assets/src/kolibri_app.js | 7 ++++++- kolibri/core/assets/src/views/PageRoot.vue | 18 ------------------ kolibri/plugins/coach/assets/src/app.js | 4 ---- .../learn/assets/src/my_downloads/app.js | 4 ---- kolibri/plugins/policies/assets/src/app.js | 4 ---- kolibri/plugins/user_profile/assets/src/app.js | 4 ---- 7 files changed, 6 insertions(+), 37 deletions(-) delete mode 100644 kolibri/core/assets/src/views/PageRoot.vue diff --git a/kolibri/core/assets/src/core-app/apiSpec.js b/kolibri/core/assets/src/core-app/apiSpec.js index 8d64a667011..d17dad1d196 100644 --- a/kolibri/core/assets/src/core-app/apiSpec.js +++ b/kolibri/core/assets/src/core-app/apiSpec.js @@ -102,7 +102,6 @@ import LearnOnlyDeviceNotice from '../views/LearnOnlyDeviceNotice'; import themeConfig from '../styles/themeConfig'; import sortLanguages from '../utils/sortLanguages'; import * as sync from '../views/sync/syncComponentSet'; -import PageRoot from '../views/PageRoot'; import NotificationsRoot from '../views/NotificationsRoot'; import useMinimumKolibriVersion from '../composables/useMinimumKolibriVersion'; import useUserSyncStatus from '../composables/useUserSyncStatus'; @@ -211,7 +210,6 @@ export default { PrivacyLinkAndModal, LearnOnlyDeviceNotice, SuggestedTime, - PageRoot, MasteryModel, NotificationsRoot, KolibriLoadingSnippet, diff --git a/kolibri/core/assets/src/kolibri_app.js b/kolibri/core/assets/src/kolibri_app.js index b06390bc80f..44f60b9bd9f 100644 --- a/kolibri/core/assets/src/kolibri_app.js +++ b/kolibri/core/assets/src/kolibri_app.js @@ -27,7 +27,12 @@ export default class KolibriApp extends KolibriModule { * @return {Object} A component definition for the root component of this single page app. */ get RootVue() { - return {}; + // By default return the component that just renders router-view, + // which will render the component for the current route. + return { + functional: true, + render: createElement => createElement('router-view'), + }; } /* * @return {Store} A convenience getter to return the vuex store. diff --git a/kolibri/core/assets/src/views/PageRoot.vue b/kolibri/core/assets/src/views/PageRoot.vue deleted file mode 100644 index 7b89f941696..00000000000 --- a/kolibri/core/assets/src/views/PageRoot.vue +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - diff --git a/kolibri/plugins/coach/assets/src/app.js b/kolibri/plugins/coach/assets/src/app.js index 7123caaa065..38feed9487a 100644 --- a/kolibri/plugins/coach/assets/src/app.js +++ b/kolibri/plugins/coach/assets/src/app.js @@ -3,7 +3,6 @@ import useUser from 'kolibri.coreVue.composables.useUser'; import redirectBrowser from 'kolibri.utils.redirectBrowser'; import { setChannelInfo } from 'kolibri.coreVue.vuex.actions'; import router from 'kolibri.coreVue.router'; -import PageRoot from 'kolibri.coreVue.components.PageRoot'; import KolibriApp from 'kolibri_app'; import routes from './routes'; import pluginModule from './modules/pluginModule'; @@ -15,9 +14,6 @@ class CoachToolsModule extends KolibriApp { get routes() { return routes; } - get RootVue() { - return PageRoot; - } get pluginModule() { return pluginModule; } diff --git a/kolibri/plugins/learn/assets/src/my_downloads/app.js b/kolibri/plugins/learn/assets/src/my_downloads/app.js index 49bae640f25..41d208ccf30 100644 --- a/kolibri/plugins/learn/assets/src/my_downloads/app.js +++ b/kolibri/plugins/learn/assets/src/my_downloads/app.js @@ -1,4 +1,3 @@ -import PageRoot from 'kolibri.coreVue.components.PageRoot'; import KolibriApp from 'kolibri_app'; import routes from './routes'; import pluginModule from './modules/pluginModule'; @@ -7,9 +6,6 @@ class MyDownloadsModule extends KolibriApp { get routes() { return routes; } - get RootVue() { - return PageRoot; - } get pluginModule() { return pluginModule; } diff --git a/kolibri/plugins/policies/assets/src/app.js b/kolibri/plugins/policies/assets/src/app.js index b48824c7f2d..08912ebb379 100644 --- a/kolibri/plugins/policies/assets/src/app.js +++ b/kolibri/plugins/policies/assets/src/app.js @@ -1,4 +1,3 @@ -import PageRoot from 'kolibri.coreVue.components.PageRoot'; import routes from './routes'; import pluginModule from './modules/pluginModule'; import KolibriApp from 'kolibri_app'; @@ -7,9 +6,6 @@ class PoliciesModule extends KolibriApp { get routes() { return routes; } - get RootVue() { - return PageRoot; - } get pluginModule() { return pluginModule; } diff --git a/kolibri/plugins/user_profile/assets/src/app.js b/kolibri/plugins/user_profile/assets/src/app.js index 0fce9ef7fbf..522dd1aa590 100644 --- a/kolibri/plugins/user_profile/assets/src/app.js +++ b/kolibri/plugins/user_profile/assets/src/app.js @@ -1,5 +1,4 @@ import router from 'kolibri.coreVue.router'; -import PageRoot from 'kolibri.coreVue.components.PageRoot'; import routes from './routes'; import pluginModule from './modules/pluginModule'; import KolibriApp from 'kolibri_app'; @@ -8,9 +7,6 @@ class UserProfileModule extends KolibriApp { get routes() { return routes; } - get RootVue() { - return PageRoot; - } get pluginModule() { return pluginModule; } From f81afc9b46bb068c13183f03336b651585c64f84 Mon Sep 17 00:00:00 2001 From: KshitijThareja Date: Sat, 20 Jan 2024 17:14:41 +0530 Subject: [PATCH 03/61] Fix NO_FILE_BASED_LOGGING env var not working properly --- kolibri/utils/conf.py | 4 +++- kolibri/utils/logger.py | 44 +++++++++++++++++++++++------------------ 2 files changed, 28 insertions(+), 20 deletions(-) diff --git a/kolibri/utils/conf.py b/kolibri/utils/conf.py index 9b1ef053624..2bba63c96b9 100644 --- a/kolibri/utils/conf.py +++ b/kolibri/utils/conf.py @@ -29,6 +29,7 @@ #: Absolute path of the main user data directory. #: Will be created automatically if it doesn't exist. KOLIBRI_HOME = os.path.abspath(os.path.expanduser(os.environ["KOLIBRI_HOME"])) +NO_FILE_BASED_LOGGING = os.environ.get("KOLIBRI_NO_FILE_BASED_LOGGING", False) # Creating KOLIBRI_HOME atm. has to happen here as for instance utils.cli is not # called through py.test. This file is the first basic entry point of @@ -44,7 +45,8 @@ # Create a folder named logs inside KOLIBRI_HOME to store all the log files. LOG_ROOT = os.path.join(KOLIBRI_HOME, "logs") if not os.path.exists(LOG_ROOT): - os.mkdir(LOG_ROOT) + if not (NO_FILE_BASED_LOGGING.lower() == "true"): + os.mkdir(LOG_ROOT) def __initialize_options(): diff --git a/kolibri/utils/logger.py b/kolibri/utils/logger.py index fcfa1688a52..c4be57b9ef2 100644 --- a/kolibri/utils/logger.py +++ b/kolibri/utils/logger.py @@ -197,7 +197,7 @@ def get_default_logging_config(LOG_ROOT, debug=False, debug_database=False): DEFAULT_HANDLERS = ( ["console", "console-error"] - if NO_FILE_BASED_LOGGING + if (NO_FILE_BASED_LOGGING.lower() == "true") else ["file", "console", "console-error", "file_debug"] ) @@ -237,24 +237,30 @@ def get_default_logging_config(LOG_ROOT, debug=False, debug_database=False): "formatter": "color", "stream": "ext://sys.stdout", }, - "file": { - "level": "INFO", - "filters": [], - "class": "kolibri.utils.logger.KolibriTimedRotatingFileHandler", - "filename": os.path.join(LOG_ROOT, "kolibri.txt"), - "formatter": "simple_date", - "when": "midnight", - "backupCount": 30, - "encoding": "utf-8", - }, - "file_debug": { - "level": "DEBUG", - "filters": ["require_debug_true"], - "class": "logging.FileHandler", - "filename": os.path.join(LOG_ROOT, "debug.txt"), - "formatter": "simple_date", - "encoding": "utf-8", - }, + **( + { + "file": { + "level": "INFO", + "filters": [], + "class": "kolibri.utils.logger.KolibriTimedRotatingFileHandler", + "filename": os.path.join(LOG_ROOT, "kolibri.txt"), + "formatter": "simple_date", + "when": "midnight", + "backupCount": 30, + "encoding": "utf-8", + }, + "file_debug": { + "level": "DEBUG", + "filters": ["require_debug_true"], + "class": "logging.FileHandler", + "filename": os.path.join(LOG_ROOT, "debug.txt"), + "formatter": "simple_date", + "encoding": "utf-8", + }, + } + if not (NO_FILE_BASED_LOGGING.lower() == "true") + else {} + ), }, "loggers": { "": { From 06411698e8212ba768fd7684da308143a8de45fa Mon Sep 17 00:00:00 2001 From: KshitijThareja Date: Sat, 20 Jan 2024 18:05:36 +0530 Subject: [PATCH 04/61] Fix condition check for env var --- kolibri/utils/conf.py | 2 +- kolibri/utils/logger.py | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/kolibri/utils/conf.py b/kolibri/utils/conf.py index 2bba63c96b9..782d1d7e26a 100644 --- a/kolibri/utils/conf.py +++ b/kolibri/utils/conf.py @@ -45,7 +45,7 @@ # Create a folder named logs inside KOLIBRI_HOME to store all the log files. LOG_ROOT = os.path.join(KOLIBRI_HOME, "logs") if not os.path.exists(LOG_ROOT): - if not (NO_FILE_BASED_LOGGING.lower() == "true"): + if not (NO_FILE_BASED_LOGGING and str(NO_FILE_BASED_LOGGING).lower() == "true"): os.mkdir(LOG_ROOT) diff --git a/kolibri/utils/logger.py b/kolibri/utils/logger.py index c4be57b9ef2..ee6a4b84406 100644 --- a/kolibri/utils/logger.py +++ b/kolibri/utils/logger.py @@ -197,7 +197,7 @@ def get_default_logging_config(LOG_ROOT, debug=False, debug_database=False): DEFAULT_HANDLERS = ( ["console", "console-error"] - if (NO_FILE_BASED_LOGGING.lower() == "true") + if (NO_FILE_BASED_LOGGING and str(NO_FILE_BASED_LOGGING).lower() == "true") else ["file", "console", "console-error", "file_debug"] ) @@ -258,7 +258,10 @@ def get_default_logging_config(LOG_ROOT, debug=False, debug_database=False): "encoding": "utf-8", }, } - if not (NO_FILE_BASED_LOGGING.lower() == "true") + if not ( + NO_FILE_BASED_LOGGING + and str(NO_FILE_BASED_LOGGING).lower() == "true" + ) else {} ), }, From 717a9310fb8ef7f272bd4b17a700ea5cbe06cd47 Mon Sep 17 00:00:00 2001 From: KshitijThareja Date: Sat, 20 Jan 2024 18:26:05 +0530 Subject: [PATCH 05/61] Make code python2 compatible --- kolibri/utils/logger.py | 80 ++++++++++++++++++++--------------------- 1 file changed, 38 insertions(+), 42 deletions(-) diff --git a/kolibri/utils/logger.py b/kolibri/utils/logger.py index ee6a4b84406..6ad9d4c5768 100644 --- a/kolibri/utils/logger.py +++ b/kolibri/utils/logger.py @@ -205,6 +205,43 @@ def get_default_logging_config(LOG_ROOT, debug=False, debug_database=False): DEFAULT_LEVEL = "INFO" if not debug else "DEBUG" DATABASE_LEVEL = "INFO" if not debug_database else "DEBUG" + handlers = { + "console-error": { + "level": "ERROR", + "class": "kolibri.utils.logger.EncodingStreamHandler", + "formatter": "color", + "stream": "ext://sys.stderr", + }, + "console": { + "level": DEFAULT_LEVEL, + "filters": ["no_exceptions"], + "class": "kolibri.utils.logger.EncodingStreamHandler", + "formatter": "color", + "stream": "ext://sys.stdout", + }, + } + + if not (NO_FILE_BASED_LOGGING and str(NO_FILE_BASED_LOGGING).lower() == "true"): + handlers["file"] = { + "level": "INFO", + "filters": [], + "class": "kolibri.utils.logger.KolibriTimedRotatingFileHandler", + "filename": os.path.join(LOG_ROOT, "kolibri.txt"), + "formatter": "simple_date", + "when": "midnight", + "backupCount": 30, + "encoding": "utf-8", + } + + handlers["file_debug"] = { + "level": "DEBUG", + "filters": ["require_debug_true"], + "class": "logging.FileHandler", + "filename": os.path.join(LOG_ROOT, "debug.txt"), + "formatter": "simple_date", + "encoding": "utf-8", + } + return { "version": 1, "disable_existing_loggers": False, @@ -223,48 +260,7 @@ def get_default_logging_config(LOG_ROOT, debug=False, debug_database=False): "log_colors": LOG_COLORS, }, }, - "handlers": { - "console-error": { - "level": "ERROR", - "class": "kolibri.utils.logger.EncodingStreamHandler", - "formatter": "color", - "stream": "ext://sys.stderr", - }, - "console": { - "level": DEFAULT_LEVEL, - "filters": ["no_exceptions"], - "class": "kolibri.utils.logger.EncodingStreamHandler", - "formatter": "color", - "stream": "ext://sys.stdout", - }, - **( - { - "file": { - "level": "INFO", - "filters": [], - "class": "kolibri.utils.logger.KolibriTimedRotatingFileHandler", - "filename": os.path.join(LOG_ROOT, "kolibri.txt"), - "formatter": "simple_date", - "when": "midnight", - "backupCount": 30, - "encoding": "utf-8", - }, - "file_debug": { - "level": "DEBUG", - "filters": ["require_debug_true"], - "class": "logging.FileHandler", - "filename": os.path.join(LOG_ROOT, "debug.txt"), - "formatter": "simple_date", - "encoding": "utf-8", - }, - } - if not ( - NO_FILE_BASED_LOGGING - and str(NO_FILE_BASED_LOGGING).lower() == "true" - ) - else {} - ), - }, + "handlers": handlers, "loggers": { "": { "handlers": DEFAULT_HANDLERS, From bb86130e5546ec76ac04870a81173b2f8e4c2f85 Mon Sep 17 00:00:00 2001 From: KshitijThareja Date: Sun, 21 Jan 2024 11:04:40 +0530 Subject: [PATCH 06/61] Add condition check before calling render on response --- kolibri/core/decorators.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kolibri/core/decorators.py b/kolibri/core/decorators.py index 833fc443efa..e5e0885ffca 100644 --- a/kolibri/core/decorators.py +++ b/kolibri/core/decorators.py @@ -339,7 +339,8 @@ def cache_no_user_data(view_func): _response = local() def render_and_cache(response, cache_key): - response.render() + if hasattr(response, "render"): + response.render() etag = hashlib.md5( kolibri_version.encode("utf-8") + str(response.content).encode("utf-8") ).hexdigest() From 716eb8400ade5fa54af3f89db158053b9d52d066 Mon Sep 17 00:00:00 2001 From: KshitijThareja Date: Mon, 22 Jan 2024 15:32:44 +0530 Subject: [PATCH 07/61] Check if response.render is callable --- kolibri/core/decorators.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kolibri/core/decorators.py b/kolibri/core/decorators.py index e5e0885ffca..8bd6aed8973 100644 --- a/kolibri/core/decorators.py +++ b/kolibri/core/decorators.py @@ -339,7 +339,7 @@ def cache_no_user_data(view_func): _response = local() def render_and_cache(response, cache_key): - if hasattr(response, "render"): + if hasattr(response, "render") and callable(response.render): response.render() etag = hashlib.md5( kolibri_version.encode("utf-8") + str(response.content).encode("utf-8") From e20025c4d54682287bfa801a899b0695d8b25cba Mon Sep 17 00:00:00 2001 From: Richard Tibbles Date: Fri, 19 Jan 2024 13:44:59 -0800 Subject: [PATCH 08/61] Avoid looking up the facility user twice if not needed. Ensure we don't error when exact username duplicates exist in a facility. --- kolibri/core/auth/api.py | 37 +++++++++++++++--------------- kolibri/core/auth/test/test_api.py | 31 ++++++++++++++++++++++--- 2 files changed, 47 insertions(+), 21 deletions(-) diff --git a/kolibri/core/auth/api.py b/kolibri/core/auth/api.py index c7ed80ea00d..8e96b784791 100644 --- a/kolibri/core/auth/api.py +++ b/kolibri/core/auth/api.py @@ -878,7 +878,23 @@ def create(self, request): status=status.HTTP_401_UNAUTHORIZED, ) - # Find the FacilityUser we're looking for use later on + user = None + if interface.enabled and valid_app_key_on_request(request): + # If we are in app context, then try to get the automatically created OS User + # if it matches the username, without needing a password. + user = self._check_os_user(request, username) + if user is None: + # Otherwise attempt full authentication + user = authenticate( + username=username, password=password, facility=facility_id + ) + if user is not None and user.is_active: + # Correct password, and the user is marked "active" + login(request, user) + # Success! + return self.get_session_response(request) + # Otherwise, try to give a helpful error message + # Find the FacilityUser we're looking for try: unauthenticated_user = FacilityUser.objects.get( username__iexact=username, facility=facility_id @@ -898,24 +914,9 @@ def create(self, request): ) except FacilityUser.MultipleObjectsReturned: # Handle case of multiple matching usernames - unauthenticated_user = FacilityUser.objects.get( + unauthenticated_user = FacilityUser.objects.filter( username__exact=username, facility=facility_id - ) - user = None - if interface.enabled and valid_app_key_on_request(request): - # If we are in app context, then try to get the automatically created OS User - # if it matches the username, without needing a password. - user = self._check_os_user(request, username) - if user is None: - # Otherwise attempt full authentication - user = authenticate( - username=username, password=password, facility=facility_id - ) - if user is not None and user.is_active: - # Correct password, and the user is marked "active" - login(request, user) - # Success! - return self.get_session_response(request) + ).first() if unauthenticated_user.password == NOT_SPECIFIED: # Here - we have a Learner whose password is "NOT_SPECIFIED" because they were created # while the "Require learners to log in with password" setting was disabled - but now diff --git a/kolibri/core/auth/test/test_api.py b/kolibri/core/auth/test/test_api.py index 2b191e99a6a..e0d11baad23 100644 --- a/kolibri/core/auth/test/test_api.py +++ b/kolibri/core/auth/test/test_api.py @@ -1180,9 +1180,34 @@ def test_case_insensitive_matching_usernames(self): # Assert the expected behavior for the second user self.assertEqual(response_user2.status_code, 200) - # Cleanup: Delete the created users - self.user1.delete() - self.user2.delete() + def test_case_sensitive_matching_usernames(self): + FacilityUserFactory.create(username="shared_username", facility=self.facility) + + response_user2 = self.client.post( + reverse("kolibri:core:session-list"), + data={ + "username": "shared_username", + "password": DUMMY_PASSWORD, + "facility": self.facility.id, + }, + format="json", + ) + + # Assert the expected behavior for the second user + self.assertEqual(response_user2.status_code, 200) + + # Test no error when authentication fails + response_user3 = self.client.post( + reverse("kolibri:core:session-list"), + data={ + "username": "shared_username", + "password": "wrong_password", + "facility": self.facility.id, + }, + format="json", + ) + + self.assertEqual(response_user3.status_code, 401) class SignUpBase(object): From 6aa9ef24f08ca3f3eac377be7d5c3e5a5d55c667 Mon Sep 17 00:00:00 2001 From: theditor Date: Fri, 22 Dec 2023 18:56:38 +0530 Subject: [PATCH 09/61] feat: update to vue-virtual-scroller 1.1.2 --- .../assets/src/views/PdfRendererIndex.vue | 13 +++++++------ kolibri/plugins/pdf_viewer/package.json | 2 +- yarn.lock | 16 ++++++++-------- 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/kolibri/plugins/pdf_viewer/assets/src/views/PdfRendererIndex.vue b/kolibri/plugins/pdf_viewer/assets/src/views/PdfRendererIndex.vue index 6583a97df5b..39f2bf90678 100644 --- a/kolibri/plugins/pdf_viewer/assets/src/views/PdfRendererIndex.vue +++ b/kolibri/plugins/pdf_viewer/assets/src/views/PdfRendererIndex.vue @@ -84,17 +84,18 @@ :layout8="{ span: showSideBar ? 6 : 8 }" :layout12="{ span: showSideBar ? 9 : 12 }" > - - @@ -123,7 +124,7 @@ import throttle from 'lodash/throttle'; import debounce from 'lodash/debounce'; import logger from 'kolibri.lib.logging'; - import { RecycleList } from 'vue-virtual-scroller'; + import { RecycleScroller } from 'vue-virtual-scroller'; import 'vue-virtual-scroller/dist/vue-virtual-scroller.css'; // polyfill necessary for recycle list import 'intersection-observer'; @@ -146,7 +147,7 @@ components: { SideBar, PdfPage, - RecycleList, + RecycleScroller, CoreFullscreen, }, mixins: [responsiveWindowMixin, commonCoreStrings], diff --git a/kolibri/plugins/pdf_viewer/package.json b/kolibri/plugins/pdf_viewer/package.json index 822ada18cb8..2dcfa45540f 100644 --- a/kolibri/plugins/pdf_viewer/package.json +++ b/kolibri/plugins/pdf_viewer/package.json @@ -6,7 +6,7 @@ "dependencies": { "intersection-observer": "0.12.2", "pdfjs-dist": "^2.16.105", - "vue-virtual-scroller": "0.12.0", + "vue-virtual-scroller": "1.1.2", "web-streams-polyfill": "^3.2.1" } } diff --git a/yarn.lock b/yarn.lock index ffdbe66d37c..581785cde4f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11598,12 +11598,12 @@ vue-meta@^2.4.0: dependencies: deepmerge "^4.2.2" -vue-observe-visibility@^0.4.1: +vue-observe-visibility@^0.4.4: version "0.4.6" resolved "https://registry.yarnpkg.com/vue-observe-visibility/-/vue-observe-visibility-0.4.6.tgz#878cb8ebcf3078e40807af29774e97105ebd519e" integrity sha512-xo0CEVdkjSjhJoDdLSvoZoQrw/H2BlzB5jrCBKGZNXN2zdZgMuZ9BKrxXDjNP2AxlcCoKc8OahI3F3r3JGLv2Q== -vue-resize@^0.4.4: +vue-resize@^0.4.5: version "0.4.5" resolved "https://registry.yarnpkg.com/vue-resize/-/vue-resize-0.4.5.tgz#4777a23042e3c05620d9cbda01c0b3cc5e32dcea" integrity sha512-bhP7MlgJQ8TIkZJXAfDf78uJO+mEI3CaLABLjv0WNzr4CcGRGPIAItyWYnP6LsPA4Oq0WE+suidNs6dgpO4RHg== @@ -11634,14 +11634,14 @@ vue-template-es2015-compiler@^1.6.0, vue-template-es2015-compiler@^1.9.0: resolved "https://registry.yarnpkg.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz#1ee3bc9a16ecbf5118be334bb15f9c46f82f5825" integrity sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw== -vue-virtual-scroller@0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/vue-virtual-scroller/-/vue-virtual-scroller-0.12.0.tgz#42f8fd7b299cd4d4fd1f5e14676792c229b890e2" - integrity sha512-01hKN99psA9Hq6zJajQc8H63sgqjpytHC8IyO+WKm6JzdVi8LeJQQqMrz5iUAFW6ZDGk+hvxaAqqcnJv+X8vYg== +vue-virtual-scroller@1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vue-virtual-scroller/-/vue-virtual-scroller-1.1.2.tgz#b8a6362f177abf3f2149ce1eac18013c71fe353b" + integrity sha512-SkUyc7QHCJFB5h1Fya7LxVizlVzOZZuFVipBGHYoTK8dwLs08bIz/tclvRApYhksaJIm/nn51inzO2UjpGJPMQ== dependencies: scrollparent "^2.0.1" - vue-observe-visibility "^0.4.1" - vue-resize "^0.4.4" + vue-observe-visibility "^0.4.4" + vue-resize "^0.4.5" vue2-teleport@^1.0.1: version "1.0.1" From d851068575a20aa29d4d2c34918f45f746931a29 Mon Sep 17 00:00:00 2001 From: theditor Date: Fri, 22 Dec 2023 20:48:42 +0530 Subject: [PATCH 10/61] feat: dynamic scroller --- .../assets/src/views/PdfRendererIndex.vue | 53 +++++++++++-------- 1 file changed, 31 insertions(+), 22 deletions(-) diff --git a/kolibri/plugins/pdf_viewer/assets/src/views/PdfRendererIndex.vue b/kolibri/plugins/pdf_viewer/assets/src/views/PdfRendererIndex.vue index 39f2bf90678..53ecc6d60c0 100644 --- a/kolibri/plugins/pdf_viewer/assets/src/views/PdfRendererIndex.vue +++ b/kolibri/plugins/pdf_viewer/assets/src/views/PdfRendererIndex.vue @@ -84,31 +84,39 @@ :layout8="{ span: showSideBar ? 6 : 8 }" :layout12="{ span: showSideBar ? 9 : 12 }" > - - @@ -124,7 +132,7 @@ import throttle from 'lodash/throttle'; import debounce from 'lodash/debounce'; import logger from 'kolibri.lib.logging'; - import { RecycleScroller } from 'vue-virtual-scroller'; + import { DynamicScroller, DynamicScrollerItem } from 'vue-virtual-scroller'; import 'vue-virtual-scroller/dist/vue-virtual-scroller.css'; // polyfill necessary for recycle list import 'intersection-observer'; @@ -145,11 +153,12 @@ export default { name: 'PdfRendererIndex', components: { - SideBar, - PdfPage, - RecycleScroller, - CoreFullscreen, - }, + SideBar, + PdfPage, + DynamicScroller, + CoreFullscreen, + DynamicScrollerItem +}, mixins: [responsiveWindowMixin, commonCoreStrings], data: () => ({ progress: null, From 36c83eb8518b1a2860d0bd2c0b4d2d9bc2bc4d56 Mon Sep 17 00:00:00 2001 From: theditor Date: Fri, 22 Dec 2023 21:09:05 +0530 Subject: [PATCH 11/61] fix: preloading offset pages --- kolibri/plugins/pdf_viewer/assets/src/views/PdfRendererIndex.vue | 1 + 1 file changed, 1 insertion(+) diff --git a/kolibri/plugins/pdf_viewer/assets/src/views/PdfRendererIndex.vue b/kolibri/plugins/pdf_viewer/assets/src/views/PdfRendererIndex.vue index 53ecc6d60c0..02fdb0977fb 100644 --- a/kolibri/plugins/pdf_viewer/assets/src/views/PdfRendererIndex.vue +++ b/kolibri/plugins/pdf_viewer/assets/src/views/PdfRendererIndex.vue @@ -90,6 +90,7 @@ :items="pdfPages" :minItemSize="itemHeight" :emitUpdate="true" + :buffer="1.5 * itemHeight" class="pdf-container scroller-height" keyField="index" @update="handleUpdate" From 4702ab57ae23cf4e3b5b52bd99c6eadc2109daab Mon Sep 17 00:00:00 2001 From: theditor Date: Fri, 22 Dec 2023 23:25:49 +0530 Subject: [PATCH 12/61] chore: add theditor to authors --- AUTHORS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS.md b/AUTHORS.md index b7383333720..fd43e7e59a6 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -99,3 +99,4 @@ If you have contributed to Kolibri, feel free to add your name and Github accoun | Kris Katkus | katkuskris | | Garvit Singhal | GarvitSinghal47 | | Mazen Oweiss | moweiss | +| Nikhil Sharma | ThEditor | \ No newline at end of file From 7d8488ee834bac61f6ecf356731bdf0b7c94f5e2 Mon Sep 17 00:00:00 2001 From: theditor Date: Sat, 23 Dec 2023 14:29:47 +0530 Subject: [PATCH 13/61] revert: preloading offset pages --- kolibri/plugins/pdf_viewer/assets/src/views/PdfRendererIndex.vue | 1 - 1 file changed, 1 deletion(-) diff --git a/kolibri/plugins/pdf_viewer/assets/src/views/PdfRendererIndex.vue b/kolibri/plugins/pdf_viewer/assets/src/views/PdfRendererIndex.vue index 02fdb0977fb..53ecc6d60c0 100644 --- a/kolibri/plugins/pdf_viewer/assets/src/views/PdfRendererIndex.vue +++ b/kolibri/plugins/pdf_viewer/assets/src/views/PdfRendererIndex.vue @@ -90,7 +90,6 @@ :items="pdfPages" :minItemSize="itemHeight" :emitUpdate="true" - :buffer="1.5 * itemHeight" class="pdf-container scroller-height" keyField="index" @update="handleUpdate" From 740426b3c31c65f8c39ae58e2a5a77d08316a3ab Mon Sep 17 00:00:00 2001 From: theditor Date: Sat, 30 Dec 2023 02:00:23 +0530 Subject: [PATCH 14/61] chore: variable mode recyclable scroller --- .../assets/src/views/PdfRendererIndex.vue | 58 +- .../assets/src/views/RecyclableScroller.vue | 839 ++++++++++++++++++ yarn.lock | 6 +- 3 files changed, 869 insertions(+), 34 deletions(-) create mode 100644 kolibri/plugins/pdf_viewer/assets/src/views/RecyclableScroller.vue diff --git a/kolibri/plugins/pdf_viewer/assets/src/views/PdfRendererIndex.vue b/kolibri/plugins/pdf_viewer/assets/src/views/PdfRendererIndex.vue index 53ecc6d60c0..b325d29deeb 100644 --- a/kolibri/plugins/pdf_viewer/assets/src/views/PdfRendererIndex.vue +++ b/kolibri/plugins/pdf_viewer/assets/src/views/PdfRendererIndex.vue @@ -84,39 +84,29 @@ :layout8="{ span: showSideBar ? 6 : 8 }" :layout12="{ span: showSideBar ? 9 : 12 }" > - - + @@ -132,8 +122,6 @@ import throttle from 'lodash/throttle'; import debounce from 'lodash/debounce'; import logger from 'kolibri.lib.logging'; - import { DynamicScroller, DynamicScrollerItem } from 'vue-virtual-scroller'; - import 'vue-virtual-scroller/dist/vue-virtual-scroller.css'; // polyfill necessary for recycle list import 'intersection-observer'; import commonCoreStrings from 'kolibri.coreVue.mixins.commonCoreStrings'; @@ -141,6 +129,7 @@ import CoreFullscreen from 'kolibri.coreVue.components.CoreFullscreen'; import '../utils/domPolyfills'; import { EventBus } from '../utils/event_utils'; + import RecyclableScroller from './RecyclableScroller'; import PdfPage from './PdfPage'; import SideBar from './SideBar'; @@ -155,9 +144,10 @@ components: { SideBar, PdfPage, - DynamicScroller, CoreFullscreen, - DynamicScrollerItem + RecyclableScroller, + // DynamicScroller, + // DynamicScrollerItem }, mixins: [responsiveWindowMixin, commonCoreStrings], data: () => ({ @@ -195,9 +185,9 @@ documentLoading() { return this.progress < 1; }, - itemHeight() { - return this.firstPageHeight * this.scale + MARGIN; - }, + // itemHeight() { + // return this.firstPageHeight * this.scale + MARGIN; + // }, savedLocation() { if (this.extraFields && this.extraFields.contentState) { return this.extraFields.contentState.savedLocation; @@ -299,15 +289,21 @@ }; this.eventBus = new EventBus(); this.prepComponentData = loadingPdf.promise - .then(pdfDocument => { + .then(async pdfDocument => { // Get initial info from the loaded pdf document this.pdfDocument = pdfDocument; this.totalPages = this.pdfDocument.numPages; // init pdfPages array for (let i = 0; i < this.totalPages; i++) { + const pageSize = await this.pdfDocument.getPage(i + 1).then(page => { + return page.getViewport({ scale: 1 }).height; + }); this.pdfPages.push({ page: null, resolved: false, + size: () => { + return pageSize * this.scale + MARGIN; + }, index: i, }); } diff --git a/kolibri/plugins/pdf_viewer/assets/src/views/RecyclableScroller.vue b/kolibri/plugins/pdf_viewer/assets/src/views/RecyclableScroller.vue new file mode 100644 index 00000000000..14503b74474 --- /dev/null +++ b/kolibri/plugins/pdf_viewer/assets/src/views/RecyclableScroller.vue @@ -0,0 +1,839 @@ + + + + + \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 581785cde4f..854d2b878d8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10042,9 +10042,9 @@ screenfull@^5.2.0: integrity sha512-9BakfsO2aUQN2K9Fdbj87RJIEZ82Q9IGim7FqM5OsebfoFC6ZHXgDq/KvniuLTPdeM8wY2o6Dj3WQ7KeQCj3cA== scrollparent@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/scrollparent/-/scrollparent-2.0.1.tgz#715d5b9cc57760fb22bdccc3befb5bfe06b1a317" - integrity sha1-cV1bnMV3YPsivczDvvtb/gaxoxc= + version "2.1.0" + resolved "https://registry.yarnpkg.com/scrollparent/-/scrollparent-2.1.0.tgz#6cae915c953835886a6ba0d77fdc2bb1ed09076d" + integrity sha512-bnnvJL28/Rtz/kz2+4wpBjHzWoEzXhVg/TE8BeVGJHUqE8THNIRnDxDWMktwM+qahvlRdvlLdsQfYe+cuqfZeA== scss-parser@^1.0.6: version "1.0.6" From 5982d4a8634b6392ad57483a0488066a8ad3176a Mon Sep 17 00:00:00 2001 From: theditor Date: Fri, 5 Jan 2024 11:54:55 +0530 Subject: [PATCH 15/61] fix: linting issues --- AUTHORS.md | 2 +- .../assets/src/views/PdfRendererIndex.vue | 14 +- .../assets/src/views/RecyclableScroller.vue | 850 +++++++++--------- 3 files changed, 449 insertions(+), 417 deletions(-) diff --git a/AUTHORS.md b/AUTHORS.md index fd43e7e59a6..82e5b95ac22 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -99,4 +99,4 @@ If you have contributed to Kolibri, feel free to add your name and Github accoun | Kris Katkus | katkuskris | | Garvit Singhal | GarvitSinghal47 | | Mazen Oweiss | moweiss | -| Nikhil Sharma | ThEditor | \ No newline at end of file +| Nikhil Sharma | ThEditor | diff --git a/kolibri/plugins/pdf_viewer/assets/src/views/PdfRendererIndex.vue b/kolibri/plugins/pdf_viewer/assets/src/views/PdfRendererIndex.vue index b325d29deeb..811ee9e5b0c 100644 --- a/kolibri/plugins/pdf_viewer/assets/src/views/PdfRendererIndex.vue +++ b/kolibri/plugins/pdf_viewer/assets/src/views/PdfRendererIndex.vue @@ -142,13 +142,13 @@ export default { name: 'PdfRendererIndex', components: { - SideBar, - PdfPage, - CoreFullscreen, - RecyclableScroller, - // DynamicScroller, - // DynamicScrollerItem -}, + SideBar, + PdfPage, + CoreFullscreen, + RecyclableScroller, + // DynamicScroller, + // DynamicScrollerItem + }, mixins: [responsiveWindowMixin, commonCoreStrings], data: () => ({ progress: null, diff --git a/kolibri/plugins/pdf_viewer/assets/src/views/RecyclableScroller.vue b/kolibri/plugins/pdf_viewer/assets/src/views/RecyclableScroller.vue index 14503b74474..bcdce2c792c 100644 --- a/kolibri/plugins/pdf_viewer/assets/src/views/RecyclableScroller.vue +++ b/kolibri/plugins/pdf_viewer/assets/src/views/RecyclableScroller.vue @@ -1,4 +1,5 @@ - + + - - \ No newline at end of file + \ No newline at end of file From 12490d24673f703b646291c60a554ba4dc57ad7d Mon Sep 17 00:00:00 2001 From: theditor Date: Fri, 5 Jan 2024 12:20:53 +0530 Subject: [PATCH 16/61] chore: add recyclescroller credits --- .../pdf_viewer/assets/src/views/RecyclableScroller.vue | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/kolibri/plugins/pdf_viewer/assets/src/views/RecyclableScroller.vue b/kolibri/plugins/pdf_viewer/assets/src/views/RecyclableScroller.vue index bcdce2c792c..db517532be2 100644 --- a/kolibri/plugins/pdf_viewer/assets/src/views/RecyclableScroller.vue +++ b/kolibri/plugins/pdf_viewer/assets/src/views/RecyclableScroller.vue @@ -1,3 +1,10 @@ + + + @@ -20,12 +21,41 @@ components: { OnboardingStepBase, LanguageSwitcherList, - }, + }, + data() { + return { + parentBreakpoint: 4 + } + }, + mounted() { + this.updateWidth(); + window.addEventListener('resize', this.updateWidth); + }, + beforeDestroy() { + window.removeEventListener('resize', this.updateWidth); + }, inject: ['wizardService'], methods: { handleSubmit() { this.wizardService.send('CONTINUE'); }, + updateWidth() { + const element = this.$refs.container.$el + const width = element.offsetWidth + let num = 4; + if (width < 440) { + num = 0; + } else if(width < 520) { + num = 1; + } else if(width < 600) { + num = 2; + } else if (width < 660) { + num = 3; + } else { + num = 4; + } + this.parentBreakpoint = num; + }, }, $trs: { languageFormHeader: { From 5ed8042456e4580e3674ff1807ff7bfdf22369f6 Mon Sep 17 00:00:00 2001 From: Fidal Mathew <84982038+FidalMathew@users.noreply.github.com> Date: Mon, 12 Feb 2024 05:01:14 +0000 Subject: [PATCH 36/61] lint fix --- .../onboarding-forms/DefaultLanguageForm.vue | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/kolibri/plugins/setup_wizard/assets/src/views/onboarding-forms/DefaultLanguageForm.vue b/kolibri/plugins/setup_wizard/assets/src/views/onboarding-forms/DefaultLanguageForm.vue index 802b1de7c84..fb0fd4a0e8a 100644 --- a/kolibri/plugins/setup_wizard/assets/src/views/onboarding-forms/DefaultLanguageForm.vue +++ b/kolibri/plugins/setup_wizard/assets/src/views/onboarding-forms/DefaultLanguageForm.vue @@ -43,17 +43,18 @@ const element = this.$refs.container.$el const width = element.offsetWidth let num = 4; - if (width < 440) { - num = 0; - } else if(width < 520) { - num = 1; - } else if(width < 600) { - num = 2; - } else if (width < 660) { - num = 3; - } else { - num = 4; - } + + if (width < 440) { + num = 0; + } else if(width < 520) { + num = 1; + } else if(width < 600) { + num = 2; + } else if (width < 660) { + num = 3; + } else { + num = 4; + } this.parentBreakpoint = num; }, }, From 0e2fe6b83f960e7436f39e16012354b174469d89 Mon Sep 17 00:00:00 2001 From: Fidal Mathew <84982038+FidalMathew@users.noreply.github.com> Date: Mon, 12 Feb 2024 05:25:57 +0000 Subject: [PATCH 37/61] lint fixes --- .../LanguageSwitcherList.vue | 18 +++++----- .../assets/src/views/OnboardingStepBase.vue | 1 + .../onboarding-forms/DefaultLanguageForm.vue | 35 ++++++++++--------- 3 files changed, 28 insertions(+), 26 deletions(-) diff --git a/kolibri/core/assets/src/views/language-switcher/LanguageSwitcherList.vue b/kolibri/core/assets/src/views/language-switcher/LanguageSwitcherList.vue index 6f115fe4a84..13f059d6e31 100644 --- a/kolibri/core/assets/src/views/language-switcher/LanguageSwitcherList.vue +++ b/kolibri/core/assets/src/views/language-switcher/LanguageSwitcherList.vue @@ -55,12 +55,13 @@ components: { LanguageSwitcherModal, }, - mixins: [responsiveWindowMixin, languageSwitcherMixin], + mixins: [responsiveWindowMixin, languageSwitcherMixin], props: { - parentBreakpoint: { - type: Number + parentBreakpoint: { + type: Number, + default: -1, + }, }, - }, data() { return { showLanguageModal: false, @@ -76,11 +77,10 @@ numVisibleLanguageBtns() { // At visibleBtns = 0, only the "More languages" button will show let visibleBtns = 4; - if (this.parentBreakpoint === undefined) { - visibleBtns = this.windowBreakpoint - } - else { - visibleBtns=this.parentBreakpoint + if (this.parentBreakpoint < 0) { + visibleBtns = this.windowBreakpoint; + } else { + visibleBtns = this.parentBreakpoint; } return Math.min(4, visibleBtns); }, diff --git a/kolibri/plugins/setup_wizard/assets/src/views/OnboardingStepBase.vue b/kolibri/plugins/setup_wizard/assets/src/views/OnboardingStepBase.vue index 5e012a834da..4acc6a9f816 100644 --- a/kolibri/plugins/setup_wizard/assets/src/views/OnboardingStepBase.vue +++ b/kolibri/plugins/setup_wizard/assets/src/views/OnboardingStepBase.vue @@ -278,6 +278,7 @@ max-width: $page-container-max-width; padding-bottom: 5em; margin: 5em auto 0; + &.windowIsSmall { width: 100vw; height: 100vh; diff --git a/kolibri/plugins/setup_wizard/assets/src/views/onboarding-forms/DefaultLanguageForm.vue b/kolibri/plugins/setup_wizard/assets/src/views/onboarding-forms/DefaultLanguageForm.vue index fb0fd4a0e8a..24cda2f506a 100644 --- a/kolibri/plugins/setup_wizard/assets/src/views/onboarding-forms/DefaultLanguageForm.vue +++ b/kolibri/plugins/setup_wizard/assets/src/views/onboarding-forms/DefaultLanguageForm.vue @@ -1,11 +1,12 @@ @@ -21,42 +22,42 @@ components: { OnboardingStepBase, LanguageSwitcherList, - }, + }, data() { return { - parentBreakpoint: 4 - } - }, + parentBreakpoint: 4, + }; + }, mounted() { - this.updateWidth(); - window.addEventListener('resize', this.updateWidth); - }, + this.updateWidth(); + window.addEventListener('resize', this.updateWidth); + }, beforeDestroy() { - window.removeEventListener('resize', this.updateWidth); - }, + window.removeEventListener('resize', this.updateWidth); + }, inject: ['wizardService'], methods: { handleSubmit() { this.wizardService.send('CONTINUE'); }, updateWidth() { - const element = this.$refs.container.$el - const width = element.offsetWidth + const element = this.$refs.container.$el; + const width = element.offsetWidth; let num = 4; if (width < 440) { num = 0; - } else if(width < 520) { + } else if (width < 520) { num = 1; - } else if(width < 600) { + } else if (width < 600) { num = 2; } else if (width < 660) { num = 3; } else { num = 4; } - this.parentBreakpoint = num; - }, + this.parentBreakpoint = num; + }, }, $trs: { languageFormHeader: { From 08523f5419e23ec8a7fff224eb2054b895334fc2 Mon Sep 17 00:00:00 2001 From: iskipu Date: Sat, 10 Feb 2024 17:03:59 +0530 Subject: [PATCH 38/61] change margin to padding fix #11838 --- .../learn/assets/src/views/LibraryPage/index.vue | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/kolibri/plugins/learn/assets/src/views/LibraryPage/index.vue b/kolibri/plugins/learn/assets/src/views/LibraryPage/index.vue index 0ba50dae0b4..73708e1a14b 100644 --- a/kolibri/plugins/learn/assets/src/views/LibraryPage/index.vue +++ b/kolibri/plugins/learn/assets/src/views/LibraryPage/index.vue @@ -458,11 +458,11 @@ } }, gridOffset() { - const marginTop = + const paddingTop = !this.windowIsLarge && (this.isLocalLibraryEmpty || this.deviceId) ? '140px' : '110px'; return this.isRtl - ? { marginRight: `${this.sidePanelWidth + 24}px`, marginTop } - : { marginLeft: `${this.sidePanelWidth + 24}px`, marginTop }; + ? { paddingRight: `${this.sidePanelWidth + 24}px`, paddingTop } + : { paddingLeft: `${this.sidePanelWidth + 24}px`, paddingTop }; }, sidePanelWidth() { if ( @@ -605,9 +605,9 @@ } .main-grid { - margin-top: 110px; - margin-right: 24px; - margin-bottom: 96px; + padding-top: 110px; + padding-right: 24px; + padding-bottom: 96px; } .channels-label { From 31aa24e43b6d6434b431471a114bca2bdfd912f2 Mon Sep 17 00:00:00 2001 From: iskipu Date: Fri, 16 Feb 2024 09:45:15 +0530 Subject: [PATCH 39/61] Trigger Build From ef562e2c5256a931683605bb614c09d1da6f88af Mon Sep 17 00:00:00 2001 From: Marcella Maki Date: Wed, 21 Feb 2024 10:48:33 -0500 Subject: [PATCH 40/61] bump version number --- kolibri/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kolibri/__init__.py b/kolibri/__init__.py index ba10d90a778..321ead98555 100755 --- a/kolibri/__init__.py +++ b/kolibri/__init__.py @@ -15,7 +15,7 @@ #: This may not be the exact version as it's subject to modification with #: get_version() - use ``kolibri.__version__`` for the exact version string. -VERSION = (0, 16, 0) +VERSION = (0, 16, 1) __author__ = "Learning Equality" __email__ = "info@learningequality.org" From 7b08d47158888d131c6fb16181a4d23f147ce963 Mon Sep 17 00:00:00 2001 From: nick2432 Date: Thu, 22 Feb 2024 15:27:17 +0530 Subject: [PATCH 41/61] fix:import-duplicate-usernames --- kolibri/core/auth/management/commands/bulkimportusers.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/kolibri/core/auth/management/commands/bulkimportusers.py b/kolibri/core/auth/management/commands/bulkimportusers.py index 4a39845373a..400ef4b85e7 100644 --- a/kolibri/core/auth/management/commands/bulkimportusers.py +++ b/kolibri/core/auth/management/commands/bulkimportusers.py @@ -270,8 +270,13 @@ def add_check(self, header_name, check, message): def get_username(self, row): username = row.get(self.header_translation["USERNAME"]) - if username in self.users.keys(): - return None + lowercase_username = username.lower() + + # Convert existing keys in self.users to lowercase + lowercase_users = {key.lower(): value for key, value in self.users.items()} + + if lowercase_username in lowercase_users: + return None # Duplicate username return username From 27fc14b97be50f133344485849e6e22520fc169b Mon Sep 17 00:00:00 2001 From: Blaine Jester Date: Thu, 22 Feb 2024 14:22:03 -0800 Subject: [PATCH 42/61] Try to use a different glob lib for now --- packages/kolibri-tools/lib/cli.js | 4 +- packages/kolibri-tools/lib/glob.js | 17 +++ .../kolibri-tools/lib/i18n/SyncContext.js | 2 +- packages/kolibri-tools/lib/i18n/astUtils.js | 2 +- packages/kolibri-tools/lib/i18n/utils.js | 2 +- packages/kolibri-tools/package.json | 4 +- yarn.lock | 128 +----------------- 7 files changed, 28 insertions(+), 131 deletions(-) create mode 100644 packages/kolibri-tools/lib/glob.js diff --git a/packages/kolibri-tools/lib/cli.js b/packages/kolibri-tools/lib/cli.js index e87ffbb7b3c..d0d2eab466d 100755 --- a/packages/kolibri-tools/lib/cli.js +++ b/packages/kolibri-tools/lib/cli.js @@ -356,7 +356,7 @@ program const Minimatch = require('minimatch').Minimatch; patternCheck = new Minimatch(options.pattern, {}); } - const glob = require('glob'); + const glob = require('./glob'); const { logging, lint, noChange } = require('./lint'); const chokidar = require('chokidar'); const watchMode = options.monitor; @@ -447,7 +447,7 @@ program if (!files.length) { program.command('compress').help(); } else { - const glob = require('glob'); + const glob = require('./glob'); const compressFile = require('./compress'); Promise.all( files.map(file => { diff --git a/packages/kolibri-tools/lib/glob.js b/packages/kolibri-tools/lib/glob.js new file mode 100644 index 00000000000..44a9a368e05 --- /dev/null +++ b/packages/kolibri-tools/lib/glob.js @@ -0,0 +1,17 @@ +const globbySync = require('globby').sync; + +/** + * Small wrapper around glob dependency to make it easier to switch to a different library + */ +module.exports = { + /** + * Synchronously search for files that match a glob pattern + * @param {string} globPath + * @param {object} options + * @param {string[]} options.ignore + * @returns {string[]} + */ + sync(globPath, { ignore = [] } = {}) { + return globbySync(globPath, { ignore }); + }, +}; diff --git a/packages/kolibri-tools/lib/i18n/SyncContext.js b/packages/kolibri-tools/lib/i18n/SyncContext.js index 527b571534d..87014e84e9d 100644 --- a/packages/kolibri-tools/lib/i18n/SyncContext.js +++ b/packages/kolibri-tools/lib/i18n/SyncContext.js @@ -1,10 +1,10 @@ // Import packages const fs = require('fs'); const path = require('path'); -const glob = require('glob'); const traverse = require('ast-traverse'); const get = require('lodash/get'); const vueCompiler = require('vue-template-compiler'); +const glob = require('../glob'); const logging = require('../logging'); const { insertContent } = require('../vueTools'); const { diff --git a/packages/kolibri-tools/lib/i18n/astUtils.js b/packages/kolibri-tools/lib/i18n/astUtils.js index 8bf305d3f69..2fdb2cdcdcd 100644 --- a/packages/kolibri-tools/lib/i18n/astUtils.js +++ b/packages/kolibri-tools/lib/i18n/astUtils.js @@ -8,7 +8,7 @@ const get = require('lodash/get'); const isPlainObject = require('lodash/isPlainObject'); const isString = require('lodash/isString'); const isArray = require('lodash/isArray'); -const { glob } = require('glob'); +const { glob } = require('../glob'); const logging = require('../logging'); const { resolve } = require('../alias_import_resolver'); const { CONTEXT_LINE } = require('./constants'); diff --git a/packages/kolibri-tools/lib/i18n/utils.js b/packages/kolibri-tools/lib/i18n/utils.js index f82ef57b3ce..912aea9c7e4 100644 --- a/packages/kolibri-tools/lib/i18n/utils.js +++ b/packages/kolibri-tools/lib/i18n/utils.js @@ -1,10 +1,10 @@ const fs = require('fs'); const path = require('path'); -const glob = require('glob'); const intersection = require('lodash/intersection'); const { parse } = require('csv-parse/sync'); const { lint } = require('kolibri-tools/lib/lint'); const { addAliases, resetAliases } = require('kolibri-tools/lib/alias_import_resolver'); +const glob = require('../glob'); const logging = require('../logging'); /* diff --git a/packages/kolibri-tools/package.json b/packages/kolibri-tools/package.json index 185c72bf4b6..3c7d7a618df 100644 --- a/packages/kolibri-tools/package.json +++ b/packages/kolibri-tools/package.json @@ -48,7 +48,7 @@ "espree": "9.6.1", "esquery": "^1.5.0", "express": "^4.18.2", - "glob": "^10.3.10", + "globby": "^11.1.0", "htmlhint": "^1.1.4", "ini": "^4.1.1", "jest": "^29.7.0", @@ -101,4 +101,4 @@ "devDependencies": { "rewire": "^6.0.0" } -} \ No newline at end of file +} diff --git a/yarn.lock b/yarn.lock index ffdbe66d37c..8c7e3f0a872 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1108,18 +1108,6 @@ resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== -"@isaacs/cliui@^8.0.2": - version "8.0.2" - resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550" - integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA== - dependencies: - string-width "^5.1.2" - string-width-cjs "npm:string-width@^4.2.0" - strip-ansi "^7.0.1" - strip-ansi-cjs "npm:strip-ansi@^6.0.1" - wrap-ansi "^8.1.0" - wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" - "@istanbuljs/load-nyc-config@^1.0.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" @@ -1436,11 +1424,6 @@ mkdirp "^1.0.4" rimraf "^3.0.2" -"@pkgjs/parseargs@^0.11.0": - version "0.11.0" - resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" - integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== - "@shopify/draggable@^1.0.0-beta.8": version "1.0.0-beta.8" resolved "https://registry.yarnpkg.com/@shopify/draggable/-/draggable-1.0.0-beta.8.tgz#2eb3c2f72298ce3e53fe16f34ab124cc495cd4fc" @@ -2260,11 +2243,6 @@ ansi-regex@^5.0.1: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== -ansi-regex@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a" - integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA== - ansi-styles@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" @@ -2290,11 +2268,6 @@ ansi-styles@^5.0.0: resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== -ansi-styles@^6.1.0: - version "6.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" - integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== - anymatch@^3.0.3, anymatch@~3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" @@ -4087,7 +4060,7 @@ cross-spawn@^6.0.5: shebang-command "^1.2.0" which "^1.2.9" -cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: +cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== @@ -4695,11 +4668,6 @@ draft-js@^0.10.1: immutable "~3.7.4" object-assign "^4.1.0" -eastasianwidth@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" - integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== - editorconfig@^0.15.3: version "0.15.3" resolved "https://registry.yarnpkg.com/editorconfig/-/editorconfig-0.15.3.tgz#bef84c4e75fb8dcb0ce5cee8efd51c15999befc5" @@ -4740,11 +4708,6 @@ emoji-regex@^8.0.0: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== -emoji-regex@^9.2.2: - version "9.2.2" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" - integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== - emojis-list@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" @@ -5675,14 +5638,6 @@ foreachasync@^3.0.0: resolved "https://registry.yarnpkg.com/foreachasync/-/foreachasync-3.0.0.tgz#5502987dc8714be3392097f32e0071c9dee07cf6" integrity sha1-VQKYfchxS+M5IJfzLgBxyd7gfPY= -foreground-child@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.1.1.tgz#1d173e776d75d2772fed08efe4a0de1ea1b12d0d" - integrity sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg== - dependencies: - cross-spawn "^7.0.0" - signal-exit "^4.0.1" - form-data@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" @@ -5896,17 +5851,6 @@ glob-to-regexp@^0.4.1: resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== -glob@^10.3.10: - version "10.3.10" - resolved "https://registry.yarnpkg.com/glob/-/glob-10.3.10.tgz#0351ebb809fd187fe421ab96af83d3a70715df4b" - integrity sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g== - dependencies: - foreground-child "^3.1.0" - jackspeak "^2.3.5" - minimatch "^9.0.1" - minipass "^5.0.0 || ^6.0.2 || ^7.0.0" - path-scurry "^1.10.1" - glob@^7.0.0, glob@^7.0.3, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@^7.2.0: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" @@ -7017,15 +6961,6 @@ istanbul-reports@^3.1.3: html-escaper "^2.0.0" istanbul-lib-report "^3.0.0" -jackspeak@^2.3.5: - version "2.3.5" - resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-2.3.5.tgz#443f237f9eeeb0d7c6ec34835ef5289bb4acb068" - integrity sha512-Ratx+B8WeXLAtRJn26hrhY8S1+Jz6pxPMrkrdkgb/NstTNiqMhX0/oFVu5wX+g5n6JlEu2LPsDJmY8nRP4+alw== - dependencies: - "@isaacs/cliui" "^8.0.2" - optionalDependencies: - "@pkgjs/parseargs" "^0.11.0" - jest-changed-files@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-29.7.0.tgz#1c06d07e77c78e1585d020424dedc10d6e17ac3a" @@ -7862,11 +7797,6 @@ lru-cache@^7.7.1: resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-7.14.1.tgz#8da8d2f5f59827edb388e63e459ac23d6d408fea" integrity sha512-ysxwsnTKdAx96aTRdhDOCQfDgbHnt8SK0KY8SEjO0wHinhWOFTESbjVCMPbU1uGXg/ch4lifqx0wfjOawU2+WA== -"lru-cache@^9.1.1 || ^10.0.0": - version "10.0.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.0.0.tgz#b9e2a6a72a129d81ab317202d93c7691df727e61" - integrity sha512-svTf/fzsKHffP42sujkO/Rjs37BCIsQVRCeNYIm9WN8rgT7ffoUnRtZCqU+6BqcSBdv8gwJeTz8knJpgACeQMw== - m3u8-parser@4.8.0: version "4.8.0" resolved "https://registry.yarnpkg.com/m3u8-parser/-/m3u8-parser-4.8.0.tgz#4a2d591fdf6f2579d12a327081198df8af83083d" @@ -8128,13 +8058,6 @@ minimatch@^5.0.1: dependencies: brace-expansion "^2.0.1" -minimatch@^9.0.1: - version "9.0.1" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.1.tgz#8a555f541cf976c622daf078bb28f29fb927c253" - integrity sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w== - dependencies: - brace-expansion "^2.0.1" - minimatch@~3.0.2: version "3.0.8" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.8.tgz#5e6a59bd11e2ab0de1cfb843eb2d82e546c321c1" @@ -8220,11 +8143,6 @@ minipass@^4.0.0: dependencies: yallist "^4.0.0" -"minipass@^5.0.0 || ^6.0.2 || ^7.0.0": - version "7.0.1" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.0.1.tgz#dff63464407cd8b83d7f008c0f116fa8c9b77ebf" - integrity sha512-NQ8MCKimInjVlaIqx51RKJJB7mINVkLTJbsZKmto4UAAOC/CWXES8PGaOgoBZyqoUsUA/U3DToGK7GJkkHbjJw== - minizlib@^2.0.0, minizlib@^2.1.1, minizlib@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931" @@ -8846,14 +8764,6 @@ path-parse@^1.0.7: resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== -path-scurry@^1.10.1: - version "1.10.1" - resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.10.1.tgz#9ba6bf5aa8500fe9fd67df4f0d9483b2b0bfc698" - integrity sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ== - dependencies: - lru-cache "^9.1.1 || ^10.0.0" - minipass "^5.0.0 || ^6.0.2 || ^7.0.0" - path-to-regexp@0.1.7: version "0.1.7" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" @@ -10254,11 +10164,6 @@ signal-exit@^3.0.7: resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== -signal-exit@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.0.1.tgz#96a61033896120ec9335d96851d902cc98f0ba2a" - integrity sha512-uUWsN4aOxJAS8KOuf3QMyFtgm1pkb6I+KRZbRF/ghdf5T7sM+B1lLLzPDxswUjkmHyxQAVzEgG35E3NzDM9GVw== - simple-markdown@^0.2.1: version "0.2.2" resolved "https://registry.yarnpkg.com/simple-markdown/-/simple-markdown-0.2.2.tgz#bede9c89274b441ee98c4869e5b27f23c9959b88" @@ -10554,7 +10459,7 @@ string-replace-loader@^3.1.0: loader-utils "^2.0.0" schema-utils "^3.0.0" -"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -10580,15 +10485,6 @@ string-width@^3.0.0: is-fullwidth-code-point "^2.0.0" strip-ansi "^5.1.0" -string-width@^5.0.1, string-width@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" - integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== - dependencies: - eastasianwidth "^0.2.0" - emoji-regex "^9.2.2" - strip-ansi "^7.0.1" - string.prototype.trim@^1.2.8: version "1.2.8" resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz#f9ac6f8af4bd55ddfa8895e6aea92a96395393bd" @@ -10630,7 +10526,7 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@6.0.1, strip-ansi@^6.0.0, strip-ansi@^6.0.1: +strip-ansi@6.0.1, strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -10658,13 +10554,6 @@ strip-ansi@^5.1.0, strip-ansi@^5.2.0: dependencies: ansi-regex "^4.1.0" -strip-ansi@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.0.1.tgz#61740a08ce36b61e50e65653f07060d000975fb2" - integrity sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw== - dependencies: - ansi-regex "^6.0.1" - strip-bom@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" @@ -11959,7 +11848,7 @@ word-wrap@^1.2.3, word-wrap@~1.2.3: resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.4.tgz#cb4b50ec9aca570abd1f52f33cd45b6c61739a9f" integrity sha512-2V81OA4ugVo5pRo46hAoD2ivUJx8jXmWXfUkY4KFNw0hEptvN0QfH3K4nHiwzGeKl5rFKedV48QVoqYavy4YpA== -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: +wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -11968,15 +11857,6 @@ word-wrap@^1.2.3, word-wrap@~1.2.3: string-width "^4.1.0" strip-ansi "^6.0.0" -wrap-ansi@^8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" - integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== - dependencies: - ansi-styles "^6.1.0" - string-width "^5.0.1" - strip-ansi "^7.0.1" - wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" From bfbcb3c01846d6f44b6a9310a747e94d64ca8e61 Mon Sep 17 00:00:00 2001 From: Blaine Jester Date: Thu, 22 Feb 2024 14:53:25 -0800 Subject: [PATCH 43/61] Fix glob access --- packages/kolibri-tools/lib/i18n/astUtils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/kolibri-tools/lib/i18n/astUtils.js b/packages/kolibri-tools/lib/i18n/astUtils.js index 2fdb2cdcdcd..4e60be61289 100644 --- a/packages/kolibri-tools/lib/i18n/astUtils.js +++ b/packages/kolibri-tools/lib/i18n/astUtils.js @@ -8,7 +8,7 @@ const get = require('lodash/get'); const isPlainObject = require('lodash/isPlainObject'); const isString = require('lodash/isString'); const isArray = require('lodash/isArray'); -const { glob } = require('../glob'); +const glob = require('../glob'); const logging = require('../logging'); const { resolve } = require('../alias_import_resolver'); const { CONTEXT_LINE } = require('./constants'); From 2d9d9542d99dd7836fbb0bd8a9648c6c8979dafb Mon Sep 17 00:00:00 2001 From: nick2432 Date: Fri, 23 Feb 2024 17:30:49 +0530 Subject: [PATCH 44/61] fix:import-duplicate-usernames --- kolibri/core/auth/management/commands/bulkimportusers.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/kolibri/core/auth/management/commands/bulkimportusers.py b/kolibri/core/auth/management/commands/bulkimportusers.py index 400ef4b85e7..1d9de74164c 100644 --- a/kolibri/core/auth/management/commands/bulkimportusers.py +++ b/kolibri/core/auth/management/commands/bulkimportusers.py @@ -272,9 +272,13 @@ def get_username(self, row): username = row.get(self.header_translation["USERNAME"]) lowercase_username = username.lower() + # Check if a user with the provided username exists (case-insensitive) + existing_user = FacilityUser.objects.filter(username__iexact=lowercase_username).first() + # Convert existing keys in self.users to lowercase + if existing_user: + return None # Duplicate username # Convert existing keys in self.users to lowercase lowercase_users = {key.lower(): value for key, value in self.users.items()} - if lowercase_username in lowercase_users: return None # Duplicate username From 83a6dab64298ba77bf3e9c9d4c7f2be5629628f2 Mon Sep 17 00:00:00 2001 From: Blaine Jester Date: Fri, 23 Feb 2024 09:56:21 -0800 Subject: [PATCH 45/61] Just use fast-glob which globby uses underneath --- packages/kolibri-tools/lib/glob.js | 30 +++++++++++++++++++++++------ packages/kolibri-tools/package.json | 2 +- yarn.lock | 11 +++++++++++ 3 files changed, 36 insertions(+), 7 deletions(-) diff --git a/packages/kolibri-tools/lib/glob.js b/packages/kolibri-tools/lib/glob.js index 44a9a368e05..671527aa656 100644 --- a/packages/kolibri-tools/lib/glob.js +++ b/packages/kolibri-tools/lib/glob.js @@ -1,4 +1,14 @@ -const globbySync = require('globby').sync; +const fastGlob = require('fast-glob'); + +const defaultOptions = { + ignore: [], + expandDirectories: true, + braceExpansion: true, + dot: false, + extglob: true, + globstar: true, + caseSensitiveMatch: true, +}; /** * Small wrapper around glob dependency to make it easier to switch to a different library @@ -6,12 +16,20 @@ const globbySync = require('globby').sync; module.exports = { /** * Synchronously search for files that match a glob pattern - * @param {string} globPath - * @param {object} options - * @param {string[]} options.ignore + * @param {string|string[]} globPaths + * @param {object} options - see fast-glob options * @returns {string[]} */ - sync(globPath, { ignore = [] } = {}) { - return globbySync(globPath, { ignore }); + sync(globPaths, options = {}) { + if (Array.isArray(globPaths)) { + globPaths = [...new Set(globPaths)]; + } else { + globPaths = [globPaths]; + } + + return fastGlob.sync(globPaths, { + ...defaultOptions, + ...options, + }); }, }; diff --git a/packages/kolibri-tools/package.json b/packages/kolibri-tools/package.json index 3c7d7a618df..991d51836bc 100644 --- a/packages/kolibri-tools/package.json +++ b/packages/kolibri-tools/package.json @@ -48,7 +48,7 @@ "espree": "9.6.1", "esquery": "^1.5.0", "express": "^4.18.2", - "globby": "^11.1.0", + "fast-glob": "^3.3.2", "htmlhint": "^1.1.4", "ini": "^4.1.1", "jest": "^29.7.0", diff --git a/yarn.lock b/yarn.lock index 8c7e3f0a872..47a623ede14 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5427,6 +5427,17 @@ fast-glob@^3.2.11, fast-glob@^3.2.9: merge2 "^1.3.0" micromatch "^4.0.4" +fast-glob@^3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129" + integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.4" + fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" From 0f802b0d22bd33177f09209f95ee1c947b402eea Mon Sep 17 00:00:00 2001 From: Nikhil anand <77477551+nick2432@users.noreply.github.com> Date: Sat, 24 Feb 2024 01:35:40 +0530 Subject: [PATCH 46/61] Properly handle case insensitive matches for existing usernames in bulkimport (#11779) --- .../management/commands/bulkimportusers.py | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/kolibri/core/auth/management/commands/bulkimportusers.py b/kolibri/core/auth/management/commands/bulkimportusers.py index 4a39845373a..7e945d54dca 100644 --- a/kolibri/core/auth/management/commands/bulkimportusers.py +++ b/kolibri/core/auth/management/commands/bulkimportusers.py @@ -534,7 +534,7 @@ def compare_fields(self, user_obj, values): setattr(user_obj, field, values[field]) return changed - def build_users_objects(self, users): + def build_users_objects(self, users): # noqa C901 new_users = [] update_users = [] keeping_users = [] @@ -564,7 +564,7 @@ def build_users_objects(self, users): if user_obj.username != user: # check for duplicated username in the facility existing_user = FacilityUser.objects.get( - username=user, facility=self.default_facility + username__iexact=user, facility=self.default_facility ) if existing_user: error = { @@ -579,6 +579,21 @@ def build_users_objects(self, users): if self.compare_fields(user_obj, values): update_users.append(user_obj) else: + # If UUID is not specified, check for a username clash + if values["uuid"] == "": + existing_user = FacilityUser.objects.filter( + username__iexact=user, facility=self.default_facility + ).first() + if existing_user: + error = { + "row": users[user]["position"], + "username": user, + "message": MESSAGES[DUPLICATED_USERNAME], + "field": "USERNAME", + "value": user, + } + per_line_errors.append(error) + continue if values["uuid"] != "": error = { "row": users[user]["position"], From 017af53b8054c721c99cf4b250baf2f0aaebd4cd Mon Sep 17 00:00:00 2001 From: Sujai Kumar Gupta Date: Sat, 24 Feb 2024 01:38:11 +0530 Subject: [PATCH 47/61] Refactor error handling in CustomDjangoCache to handle multiple error types (#11808) --- .../deployment/default/custom_django_cache.py | 191 ++++++++++-------- 1 file changed, 109 insertions(+), 82 deletions(-) diff --git a/kolibri/deployment/default/custom_django_cache.py b/kolibri/deployment/default/custom_django_cache.py index ee7dc661c43..a81d95392fd 100644 --- a/kolibri/deployment/default/custom_django_cache.py +++ b/kolibri/deployment/default/custom_django_cache.py @@ -13,6 +13,30 @@ class CustomDjangoCache(DjangoCache): https://github.com/grantjenks/python-diskcache/blob/v4.1.0/diskcache/djangocache.py """ + ERRORS_TO_HANDLE = (sqlite3.OperationalError, AssertionError) + + def try_execute(self, method_name, error_return_value, *args, **kwargs): + """ + Safely executes a method with error handling. + :param method_name --> (str): name of method to execute + :param error_return_value --> (any): value to return if error occur + :param *args: positional arguments for method + :param *kwargs: keyword arguments for method + :return: The return value of the executed method if successful, + otherwise returns error_return_value + """ + try: + method = getattr(super(CustomDjangoCache, self), method_name) + if method is None: + raise ValueError( + "{method_name} is not a valid method".format( + method_name=method_name + ) + ) + return method(*args, **kwargs) + except self.ERRORS_TO_HANDLE: + return error_return_value + def add( self, key, @@ -23,12 +47,17 @@ def add( tag=None, retry=True, ): - try: - return super(CustomDjangoCache, self).add( - key, value, timeout, version, read, tag, retry - ) - except sqlite3.OperationalError: - return False + return self.try_execute( + "add", + False, + key=key, + value=value, + timeout=timeout, + version=version, + read=read, + tag=tag, + retry=retry, + ) def has_key(self, key, version=None): """Returns True if the key is in the cache and has not expired. @@ -38,12 +67,7 @@ def has_key(self, key, version=None): :return: True if key is found """ - try: - return super(CustomDjangoCache, self).has_key( # noqa: W601 - key, version=version - ) - except sqlite3.OperationalError: - return False + return self.try_execute("has_key", False, key=key, version=version) def get( self, @@ -55,12 +79,17 @@ def get( tag=False, retry=False, ): - try: - return super(CustomDjangoCache, self).get( - key, default, version, read, expire_time, tag, retry - ) - except sqlite3.OperationalError: - return None + return self.try_execute( + "get", + None, + key=key, + default=default, + version=version, + read=read, + expire_time=expire_time, + tag=tag, + retry=retry, + ) def set( self, @@ -72,95 +101,93 @@ def set( tag=None, retry=True, ): - try: - return super(CustomDjangoCache, self).set( - key, value, timeout, version, read, tag, retry - ) - except sqlite3.OperationalError: - return False + return self.try_execute( + "set", + False, + key=key, + value=value, + timeout=timeout, + version=version, + read=read, + tag=tag, + retry=retry, + ) def touch(self, key, timeout=DEFAULT_TIMEOUT, version=None, retry=True): - try: - return super(CustomDjangoCache, self).touch(key, timeout, version, retry) - except sqlite3.OperationalError: - return False + return self.try_execute( + "touch", + False, + key=key, + timeout=timeout, + version=version, + retry=retry, + ) def pop( self, key, default=None, version=None, expire_time=False, tag=False, retry=True ): - try: - return super(CustomDjangoCache, self).pop( - key, default, version, expire_time, tag, retry - ) - except sqlite3.OperationalError: - return None + return self.try_execute( + "pop", + None, + key=key, + default=default, + version=version, + expire_time=expire_time, + tag=tag, + retry=retry, + ) def delete(self, key, version=None, retry=True): - try: - super(CustomDjangoCache, self).delete(key, version, retry) - except sqlite3.OperationalError: - pass + self.try_execute( + "delete", + None, + key=key, + version=version, + retry=retry, + ) def incr(self, key, delta=1, version=None, default=None, retry=True): - try: - return super(CustomDjangoCache, self).incr( - key, delta, version, default, retry - ) - except sqlite3.OperationalError: - return None + return self.try_execute( + "incr", + None, + key=key, + delta=delta, + version=version, + default=default, + retry=retry, + ) def decr(self, key, delta=1, version=None, default=None, retry=True): - try: - return super(CustomDjangoCache, self).decr( - key, delta, version, default, retry - ) - except sqlite3.OperationalError: - return None + return self.try_execute( + "decr", + None, + key=key, + delta=delta, + version=version, + default=default, + retry=retry, + ) def expire(self, retry=False): - try: - return super(CustomDjangoCache, self).expire(retry) - except sqlite3.OperationalError: - return 0 + return self.try_execute("expire", 0, retry=retry) def stats(self, enable=True, reset=False): - try: - return super(CustomDjangoCache, self).stats(enable, reset) - except sqlite3.OperationalError: - return 0, 0 + return self.try_execute("stats", (0, 0), enable=enable, reset=reset) def create_tag_index(self): - try: - super(CustomDjangoCache, self).create_tag_index() - except sqlite3.OperationalError: - pass + return self.try_execute("create_tag_index", None) def drop_tag_index(self): - try: - super(CustomDjangoCache, self).drop_tag_index() - except sqlite3.OperationalError: - pass + return self.try_execute("drop_tag_index", None) def evict(self, tag): - try: - return super(CustomDjangoCache, self).evict(tag) - except sqlite3.OperationalError: - return 0 + return self.try_execute("evict", 0, tag=tag) def cull(self): - try: - return super(CustomDjangoCache, self).cull() - except sqlite3.OperationalError: - return 0 + return self.try_execute("cull", 0) def clear(self): - try: - return super(CustomDjangoCache, self).clear() - except sqlite3.OperationalError: - return 0 + return self.try_execute("clear", 0) def close(self, **kwargs): - try: - super(CustomDjangoCache, self).close(**kwargs) - except sqlite3.OperationalError: - pass + return self.try_execute("close", None, **kwargs) From 33790ad664b5ef795f31c6f95438ad0c2f9d2c25 Mon Sep 17 00:00:00 2001 From: Richard Tibbles Date: Fri, 23 Feb 2024 14:22:12 -0800 Subject: [PATCH 48/61] Update packages versions for latest release. --- packages/browserslist-config-kolibri/package.json | 2 +- packages/eslint-plugin-kolibri/package.json | 2 +- packages/kolibri-core-for-export/package.json | 2 +- packages/kolibri-tools/package.json | 8 ++++---- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/browserslist-config-kolibri/package.json b/packages/browserslist-config-kolibri/package.json index 284b10b055e..e757b4b9a4c 100644 --- a/packages/browserslist-config-kolibri/package.json +++ b/packages/browserslist-config-kolibri/package.json @@ -1,6 +1,6 @@ { "name": "browserslist-config-kolibri", - "version": "0.16.0-dev.7", + "version": "0.16.1-dev.0", "description": "Browsers list configuration for Kolibri", "main": "index.js", "repository": "github.com/learningequality/kolibri", diff --git a/packages/eslint-plugin-kolibri/package.json b/packages/eslint-plugin-kolibri/package.json index 97bd968e825..3397153f409 100644 --- a/packages/eslint-plugin-kolibri/package.json +++ b/packages/eslint-plugin-kolibri/package.json @@ -1,6 +1,6 @@ { "name": "eslint-plugin-kolibri", - "version": "0.16.0-dev.7", + "version": "0.16.1-dev.0", "description": "Custom rules.", "author": "Learning Equality", "main": "lib/index.js", diff --git a/packages/kolibri-core-for-export/package.json b/packages/kolibri-core-for-export/package.json index ea9efbce850..38330827095 100644 --- a/packages/kolibri-core-for-export/package.json +++ b/packages/kolibri-core-for-export/package.json @@ -1,6 +1,6 @@ { "name": "kolibri", - "version": "0.16.0-dev.7", + "version": "0.16.1-dev.0", "description": "The Kolibri core API", "repository": "github.com/learningequality/kolibri", "author": "Learning Equality", diff --git a/packages/kolibri-tools/package.json b/packages/kolibri-tools/package.json index 991d51836bc..cf60a50eebe 100644 --- a/packages/kolibri-tools/package.json +++ b/packages/kolibri-tools/package.json @@ -1,6 +1,6 @@ { "name": "kolibri-tools", - "version": "0.16.0-dev.7", + "version": "0.16.1-dev.0", "description": "Tools for building Kolibri frontend plugins", "main": "lib/cli.js", "repository": "github.com/learningequality/kolibri", @@ -25,7 +25,7 @@ "babel-core": "7.0.0-bridge.0", "babel-jest": "^29.7.0", "babel-loader": "^9.1.3", - "browserslist-config-kolibri": "0.16.0-dev.7", + "browserslist-config-kolibri": "0.16.1-dev.0", "chalk": "4.1.2", "check-node-version": "^4.2.1", "chokidar": "^3.5.3", @@ -43,7 +43,7 @@ "eslint-config-vue": "^2.0.2", "eslint-plugin-import": "^2.29.1", "eslint-plugin-jest": "^23.3.0", - "eslint-plugin-kolibri": "0.16.0-dev.7", + "eslint-plugin-kolibri": "0.16.1-dev.0", "eslint-plugin-vue": "^7.3.0", "espree": "9.6.1", "esquery": "^1.5.0", @@ -101,4 +101,4 @@ "devDependencies": { "rewire": "^6.0.0" } -} +} \ No newline at end of file From ebda7c348a88cf5488f4cb5f0a73a6aa69d2c006 Mon Sep 17 00:00:00 2001 From: theditor Date: Mon, 29 Jan 2024 13:53:21 +0530 Subject: [PATCH 49/61] fix: os_user unnecessary password field --- kolibri/plugins/user_auth/assets/src/views/SignInPage/index.vue | 1 + 1 file changed, 1 insertion(+) diff --git a/kolibri/plugins/user_auth/assets/src/views/SignInPage/index.vue b/kolibri/plugins/user_auth/assets/src/views/SignInPage/index.vue index 0c3d19daf03..6c04e1511f5 100644 --- a/kolibri/plugins/user_auth/assets/src/views/SignInPage/index.vue +++ b/kolibri/plugins/user_auth/assets/src/views/SignInPage/index.vue @@ -339,6 +339,7 @@ // and forth this.usernameBlurred = false; this.passwordBlurred = false; + this.usernameSubmittedWithoutPassword = false; this.loginError = null; }, // Sets the selected list user and/or logs them in From 4818901e1b8cf68753193f3ab1103fec3ace0ad0 Mon Sep 17 00:00:00 2001 From: nick2432 Date: Sat, 24 Feb 2024 17:56:12 +0530 Subject: [PATCH 50/61] fix:import-duplicate-usernames --- kolibri/core/auth/management/commands/bulkimportusers.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kolibri/core/auth/management/commands/bulkimportusers.py b/kolibri/core/auth/management/commands/bulkimportusers.py index 1d9de74164c..80cbb40e809 100644 --- a/kolibri/core/auth/management/commands/bulkimportusers.py +++ b/kolibri/core/auth/management/commands/bulkimportusers.py @@ -270,12 +270,13 @@ def add_check(self, header_name, check, message): def get_username(self, row): username = row.get(self.header_translation["USERNAME"]) + uuid = row.get(self.header_translation["UUID"]) lowercase_username = username.lower() # Check if a user with the provided username exists (case-insensitive) existing_user = FacilityUser.objects.filter(username__iexact=lowercase_username).first() # Convert existing keys in self.users to lowercase - if existing_user: + if existing_user and uuid == "": return None # Duplicate username # Convert existing keys in self.users to lowercase lowercase_users = {key.lower(): value for key, value in self.users.items()} From a49730d52abdcd580d42cd47cf3fb204113909a7 Mon Sep 17 00:00:00 2001 From: nick2432 Date: Sat, 24 Feb 2024 21:39:37 +0530 Subject: [PATCH 51/61] fix:import-duplicate-usernames --- kolibri/core/auth/test/test_bulk_import.py | 91 ++++++++++++++++++++++ 1 file changed, 91 insertions(+) diff --git a/kolibri/core/auth/test/test_bulk_import.py b/kolibri/core/auth/test/test_bulk_import.py index e985b3c314a..3c9a35baca6 100644 --- a/kolibri/core/auth/test/test_bulk_import.py +++ b/kolibri/core/auth/test/test_bulk_import.py @@ -252,6 +252,97 @@ def test_password_is_required(self): assert "'value': '*'" in result[1] assert "new_coach" in result[1] assert "'row': 2" in result[1] + def test_case_insensitive_usernames(self): + _, first_filepath = tempfile.mkstemp(suffix=".csv") + rows = [ + [ + None, + "peter", + "password1", + None, + "LEARNER", + None, + "2001", + "FEMALE", + "new_class", + None, + ], + [ + None, + "PETER", + "password2", + None, + "FACILITY_COACH", + None, + "1969", + "MALE", + None, + "new_class", + ], + ] + self.create_csv(first_filepath, rows) + call_command("bulkimportusers", first_filepath, facility=self.facility.id) + + # Retrieve the user(s) + users = FacilityUser.objects.filter(username__iexact="peter") + + # Ensure that only one user is created, and it has the latest password + assert users.count() == 1 + + def test_username_already_exists(self): + _, first_filepath = tempfile.mkstemp(suffix=".csv") + rows = [ + [ + None, + "peter", # Adding the first user with the username "peter" + "passwd1", + None, + "LEARNER", + None, + "2001", + "FEMALE", + "new_class", + None, + ], + ] + self.create_csv(first_filepath, rows) + + call_command("bulkimportusers", first_filepath, facility=self.facility.id) + + # Get the initial count of users with the username "peter" + initial_peter_count = FacilityUser.objects.filter(username="peter").count() + peter1 = FacilityUser.objects.get(username="peter") + passwd1 = peter1.password + # Check that the count of users with the username "peter" is one + assert initial_peter_count == 1 + + # Attempt to add another user with the same username "peter" + _, second_filepath = tempfile.mkstemp(suffix=".csv") + rows = [ + [ + None, + "peter", # Attempting to add another user with the same username "peter" + "another_password", + None, + "LEARNER", + None, + "2001", + "FEMALE", + "new_class", + None, + ], + ] + self.create_csv(second_filepath, rows) + + # Check that the command raises an IntegrityError when trying to add a user with an existing username + call_command("bulkimportusers", second_filepath, facility=self.facility.id) + + # Check that the count of users with the username "peter" is still one + assert FacilityUser.objects.filter(username="peter").count() == 1 + peter2 = FacilityUser.objects.get(username="peter") + passwd2 = peter2.password + # Check that the password of the existing user remains unchanged + assert passwd2 == passwd1 def test_asterisk_in_password(self): _, first_filepath = tempfile.mkstemp(suffix=".csv") From 2de4f18685a925b8e4cb239a17114667a57d00bf Mon Sep 17 00:00:00 2001 From: nick2432 Date: Sat, 24 Feb 2024 21:52:50 +0530 Subject: [PATCH 52/61] fix:import-duplicate-usernames --- kolibri/core/auth/management/commands/bulkimportusers.py | 4 +++- kolibri/core/auth/test/test_bulk_import.py | 5 +++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/kolibri/core/auth/management/commands/bulkimportusers.py b/kolibri/core/auth/management/commands/bulkimportusers.py index 80cbb40e809..1b77ee9d36a 100644 --- a/kolibri/core/auth/management/commands/bulkimportusers.py +++ b/kolibri/core/auth/management/commands/bulkimportusers.py @@ -274,7 +274,9 @@ def get_username(self, row): lowercase_username = username.lower() # Check if a user with the provided username exists (case-insensitive) - existing_user = FacilityUser.objects.filter(username__iexact=lowercase_username).first() + existing_user = FacilityUser.objects.filter( + username__iexact=lowercase_username + ).first() # Convert existing keys in self.users to lowercase if existing_user and uuid == "": return None # Duplicate username diff --git a/kolibri/core/auth/test/test_bulk_import.py b/kolibri/core/auth/test/test_bulk_import.py index 3c9a35baca6..a1cd530a7ce 100644 --- a/kolibri/core/auth/test/test_bulk_import.py +++ b/kolibri/core/auth/test/test_bulk_import.py @@ -252,6 +252,7 @@ def test_password_is_required(self): assert "'value': '*'" in result[1] assert "new_coach" in result[1] assert "'row': 2" in result[1] + def test_case_insensitive_usernames(self): _, first_filepath = tempfile.mkstemp(suffix=".csv") rows = [ @@ -282,10 +283,10 @@ def test_case_insensitive_usernames(self): ] self.create_csv(first_filepath, rows) call_command("bulkimportusers", first_filepath, facility=self.facility.id) - + # Retrieve the user(s) users = FacilityUser.objects.filter(username__iexact="peter") - + # Ensure that only one user is created, and it has the latest password assert users.count() == 1 From c616eba4937a347e85f41b24157c7785e6cd5aec Mon Sep 17 00:00:00 2001 From: iskipu Date: Mon, 26 Feb 2024 15:04:01 +0530 Subject: [PATCH 53/61] fix spinner misalignment and spinner flickering in download page --- .../assets/src/views/SyncStatusDisplay.vue | 4 ++- .../views/DownloadsList/index.vue | 30 +++++++++++++------ 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/kolibri/core/assets/src/views/SyncStatusDisplay.vue b/kolibri/core/assets/src/views/SyncStatusDisplay.vue index 31aa08fa843..364817fcf9e 100644 --- a/kolibri/core/assets/src/views/SyncStatusDisplay.vue +++ b/kolibri/core/assets/src/views/SyncStatusDisplay.vue @@ -1,6 +1,6 @@ diff --git a/kolibri/plugins/media_player/assets/src/views/MediaPlayerLanguages/LanguagesMenuItem.vue b/kolibri/plugins/media_player/assets/src/views/MediaPlayerLanguages/LanguagesMenuItem.vue index 8fb004c063b..cc690e9d9ac 100644 --- a/kolibri/plugins/media_player/assets/src/views/MediaPlayerLanguages/LanguagesMenuItem.vue +++ b/kolibri/plugins/media_player/assets/src/views/MediaPlayerLanguages/LanguagesMenuItem.vue @@ -5,7 +5,7 @@ ref="kRadioButton" name="languages-menu-item" :label="label" - :value="1" + :buttonValue="1" :currentValue="selected ? 1 : 0" @change="setLanguage(value)" @keydown.enter="setLanguage(value), $emit('hide')" diff --git a/kolibri/plugins/setup_wizard/assets/src/views/JoinOrNewLOD.vue b/kolibri/plugins/setup_wizard/assets/src/views/JoinOrNewLOD.vue index fadc0901869..662f37647ab 100644 --- a/kolibri/plugins/setup_wizard/assets/src/views/JoinOrNewLOD.vue +++ b/kolibri/plugins/setup_wizard/assets/src/views/JoinOrNewLOD.vue @@ -8,13 +8,13 @@

{{ getCommonSyncString('changeLater') }} diff --git a/kolibri/plugins/setup_wizard/assets/src/views/onboarding-forms/FacilityPermissionsForm.vue b/kolibri/plugins/setup_wizard/assets/src/views/onboarding-forms/FacilityPermissionsForm.vue index 3f2b79e693a..0ee1ea17e1e 100644 --- a/kolibri/plugins/setup_wizard/assets/src/views/onboarding-forms/FacilityPermissionsForm.vue +++ b/kolibri/plugins/setup_wizard/assets/src/views/onboarding-forms/FacilityPermissionsForm.vue @@ -11,7 +11,7 @@ ref="first-button" v-model="selected" class="permission-preset-radio-button" - :value="Presets.NONFORMAL" + :buttonValue="Presets.NONFORMAL" :label="$tr('nonFormalLabel')" :description="$tr('nonFormalDescription')" /> @@ -24,7 +24,7 @@ diff --git a/kolibri/plugins/setup_wizard/assets/src/views/onboarding-forms/FullOrLearnOnlyDeviceForm.vue b/kolibri/plugins/setup_wizard/assets/src/views/onboarding-forms/FullOrLearnOnlyDeviceForm.vue index e99f13dd900..31817e72a7c 100644 --- a/kolibri/plugins/setup_wizard/assets/src/views/onboarding-forms/FullOrLearnOnlyDeviceForm.vue +++ b/kolibri/plugins/setup_wizard/assets/src/views/onboarding-forms/FullOrLearnOnlyDeviceForm.vue @@ -7,13 +7,13 @@ diff --git a/kolibri/plugins/setup_wizard/assets/src/views/onboarding-forms/GettingStartedForm.vue b/kolibri/plugins/setup_wizard/assets/src/views/onboarding-forms/GettingStartedForm.vue index 6be5af6762f..00ca54a7568 100644 --- a/kolibri/plugins/setup_wizard/assets/src/views/onboarding-forms/GettingStartedForm.vue +++ b/kolibri/plugins/setup_wizard/assets/src/views/onboarding-forms/GettingStartedForm.vue @@ -6,13 +6,13 @@ > diff --git a/kolibri/plugins/setup_wizard/assets/src/views/onboarding-forms/GuestAccessForm.vue b/kolibri/plugins/setup_wizard/assets/src/views/onboarding-forms/GuestAccessForm.vue index 8a21c6b4d3d..81f8e949653 100644 --- a/kolibri/plugins/setup_wizard/assets/src/views/onboarding-forms/GuestAccessForm.vue +++ b/kolibri/plugins/setup_wizard/assets/src/views/onboarding-forms/GuestAccessForm.vue @@ -14,13 +14,13 @@ ref="yesRadio" v-model="setting" :label="$tr('yesOptionLabel')" - :value="true" + :buttonValue="true" />

{{ $tr('changeLater') }} diff --git a/kolibri/plugins/setup_wizard/assets/src/views/onboarding-forms/HowAreYouUsingKolibri.vue b/kolibri/plugins/setup_wizard/assets/src/views/onboarding-forms/HowAreYouUsingKolibri.vue index 30a432d786a..5ed028f17d3 100644 --- a/kolibri/plugins/setup_wizard/assets/src/views/onboarding-forms/HowAreYouUsingKolibri.vue +++ b/kolibri/plugins/setup_wizard/assets/src/views/onboarding-forms/HowAreYouUsingKolibri.vue @@ -9,13 +9,13 @@ diff --git a/kolibri/plugins/setup_wizard/assets/src/views/onboarding-forms/RequirePasswordForLearnersForm.vue b/kolibri/plugins/setup_wizard/assets/src/views/onboarding-forms/RequirePasswordForLearnersForm.vue index 1645bbcaae7..690f8cc08a0 100644 --- a/kolibri/plugins/setup_wizard/assets/src/views/onboarding-forms/RequirePasswordForLearnersForm.vue +++ b/kolibri/plugins/setup_wizard/assets/src/views/onboarding-forms/RequirePasswordForLearnersForm.vue @@ -13,14 +13,14 @@ v-model="setting" class="radio-button" :label="$tr('yesOptionLabel')" - :value="true" + :buttonValue="true" />

{{ getCommonSyncString('changeLater') }} diff --git a/kolibri/plugins/setup_wizard/assets/src/views/onboarding-forms/SetUpLearningFacilityForm.vue b/kolibri/plugins/setup_wizard/assets/src/views/onboarding-forms/SetUpLearningFacilityForm.vue index f4a4095ead1..d8c59ef38af 100644 --- a/kolibri/plugins/setup_wizard/assets/src/views/onboarding-forms/SetUpLearningFacilityForm.vue +++ b/kolibri/plugins/setup_wizard/assets/src/views/onboarding-forms/SetUpLearningFacilityForm.vue @@ -8,13 +8,13 @@ diff --git a/kolibri/plugins/user_profile/assets/src/views/ChangeFacility/SelectFacility.vue b/kolibri/plugins/user_profile/assets/src/views/ChangeFacility/SelectFacility.vue index 658616f774d..d3ae9478646 100644 --- a/kolibri/plugins/user_profile/assets/src/views/ChangeFacility/SelectFacility.vue +++ b/kolibri/plugins/user_profile/assets/src/views/ChangeFacility/SelectFacility.vue @@ -23,7 +23,7 @@ diff --git a/packages/kolibri-common/components/MeteredConnectionNotificationModal.vue b/packages/kolibri-common/components/MeteredConnectionNotificationModal.vue index 30edec9fc27..3943f77a039 100644 --- a/packages/kolibri-common/components/MeteredConnectionNotificationModal.vue +++ b/packages/kolibri-common/components/MeteredConnectionNotificationModal.vue @@ -13,14 +13,14 @@ diff --git a/packages/kolibri-core-for-export/package.json b/packages/kolibri-core-for-export/package.json index 38330827095..f5349131469 100644 --- a/packages/kolibri-core-for-export/package.json +++ b/packages/kolibri-core-for-export/package.json @@ -24,7 +24,7 @@ "js-cookie": "^3.0.5", "knuth-shuffle-seeded": "^1.0.6", "kolibri-constants": "0.2.0", - "kolibri-design-system": "https://github.com/learningequality/kolibri-design-system#v2.0.0", + "kolibri-design-system": "3.0.1", "lockr": "0.8.5", "lodash": "^4.17.21", "loglevel": "^1.8.1", diff --git a/yarn.lock b/yarn.lock index 946479d0694..73e472612f2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4293,7 +4293,7 @@ data-urls@^3.0.2: whatwg-mimetype "^3.0.0" whatwg-url "^11.0.0" -date-fns@^1.28.2: +date-fns@^1.28.2, date-fns@^1.30.1: version "1.30.1" resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.30.1.tgz#2e71bf0b119153dbb4cc4e88d9ea5acfb50dc05c" integrity sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw== @@ -7583,13 +7583,16 @@ kolibri-constants@0.2.0: resolved "https://registry.yarnpkg.com/kolibri-constants/-/kolibri-constants-0.2.0.tgz#47c9d773894e23251ba5ac4db420822e45603142" integrity sha512-WYDMGDzB9gNxRbpX1O2cGe1HrJvLvSZGwMuAv6dqrxJgPf7iO+Hi40/1CXjHM7nk5CRt+hn5bqnMzCBmj1omPA== -"kolibri-design-system@https://github.com/learningequality/kolibri-design-system#v2.0.0": - version "1.3.0" - resolved "https://github.com/learningequality/kolibri-design-system#13e539592fd87508cd32f60e4ad22c1ec320559b" +kolibri-design-system@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/kolibri-design-system/-/kolibri-design-system-3.0.1.tgz#ba6368c78ffab1d6195b828b1aacc4f11b9a67c3" + integrity sha512-/O+KuYTGiv5z9VTlm8bIWZwanMdearGmIP162EqaVn2tIbo/hY42lsuAbGSTZPi5CITm+LJ9r99ogImDRH8z2w== dependencies: + "@vue/composition-api" "^1.7.2" aphrodite "https://github.com/learningequality/aphrodite/" autosize "^3.0.21" css-element-queries "^1.2.0" + date-fns "^1.30.1" frame-throttle "^3.0.0" fuzzysearch "^1.0.3" keen-ui "^1.3.0" @@ -7598,6 +7601,7 @@ kolibri-constants@0.2.0: purecss "^0.6.2" tippy.js "^4.2.1" vue-intl "^3.1.0" + xstate "^4.38.3" launch-editor-middleware@^2.6.1: version "2.6.1" From 650359a2ea901e85777b7cee40b7f5a64755735f Mon Sep 17 00:00:00 2001 From: Richard Tibbles Date: Thu, 29 Feb 2024 13:48:27 -0800 Subject: [PATCH 56/61] Pin vue and vue-template-compiler to ensure correct version is used in kolibri-tools. --- kolibri/core/package.json | 2 +- packages/browserslist-config-kolibri/package.json | 2 +- packages/eslint-plugin-kolibri/package.json | 2 +- packages/kolibri-core-for-export/package.json | 4 ++-- packages/kolibri-tools/package.json | 8 ++++---- yarn.lock | 4 ++-- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/kolibri/core/package.json b/kolibri/core/package.json index 5fac3833773..32faafea6cc 100644 --- a/kolibri/core/package.json +++ b/kolibri/core/package.json @@ -31,7 +31,7 @@ "shave": "^5.0.3", "tinycolor2": "^1.6.0", "ua-parser-js": "^1.0.37", - "vue": "^2.6.14", + "vue": "2.6.14", "vue-intl": "3.1.0", "vue-meta": "^2.4.0", "vue-router": "^3.6.5", diff --git a/packages/browserslist-config-kolibri/package.json b/packages/browserslist-config-kolibri/package.json index e757b4b9a4c..cdeeac98985 100644 --- a/packages/browserslist-config-kolibri/package.json +++ b/packages/browserslist-config-kolibri/package.json @@ -1,6 +1,6 @@ { "name": "browserslist-config-kolibri", - "version": "0.16.1-dev.0", + "version": "0.16.1-dev.1", "description": "Browsers list configuration for Kolibri", "main": "index.js", "repository": "github.com/learningequality/kolibri", diff --git a/packages/eslint-plugin-kolibri/package.json b/packages/eslint-plugin-kolibri/package.json index 3397153f409..66a53df2367 100644 --- a/packages/eslint-plugin-kolibri/package.json +++ b/packages/eslint-plugin-kolibri/package.json @@ -1,6 +1,6 @@ { "name": "eslint-plugin-kolibri", - "version": "0.16.1-dev.0", + "version": "0.16.1-dev.1", "description": "Custom rules.", "author": "Learning Equality", "main": "lib/index.js", diff --git a/packages/kolibri-core-for-export/package.json b/packages/kolibri-core-for-export/package.json index 38330827095..d30c6c9bc02 100644 --- a/packages/kolibri-core-for-export/package.json +++ b/packages/kolibri-core-for-export/package.json @@ -1,6 +1,6 @@ { "name": "kolibri", - "version": "0.16.1-dev.0", + "version": "0.16.1-dev.1", "description": "The Kolibri core API", "repository": "github.com/learningequality/kolibri", "author": "Learning Equality", @@ -34,7 +34,7 @@ "shave": "^5.0.3", "tinycolor2": "^1.6.0", "ua-parser-js": "^1.0.37", - "vue": "^2.6.14", + "vue": "2.6.14", "vue-intl": "3.1.0", "vue-meta": "^2.4.0", "vue-router": "^3.6.5", diff --git a/packages/kolibri-tools/package.json b/packages/kolibri-tools/package.json index cf60a50eebe..60d9fff36f5 100644 --- a/packages/kolibri-tools/package.json +++ b/packages/kolibri-tools/package.json @@ -1,6 +1,6 @@ { "name": "kolibri-tools", - "version": "0.16.1-dev.0", + "version": "0.16.1-dev.1", "description": "Tools for building Kolibri frontend plugins", "main": "lib/cli.js", "repository": "github.com/learningequality/kolibri", @@ -25,7 +25,7 @@ "babel-core": "7.0.0-bridge.0", "babel-jest": "^29.7.0", "babel-loader": "^9.1.3", - "browserslist-config-kolibri": "0.16.1-dev.0", + "browserslist-config-kolibri": "0.16.1-dev.1", "chalk": "4.1.2", "check-node-version": "^4.2.1", "chokidar": "^3.5.3", @@ -43,7 +43,7 @@ "eslint-config-vue": "^2.0.2", "eslint-plugin-import": "^2.29.1", "eslint-plugin-jest": "^23.3.0", - "eslint-plugin-kolibri": "0.16.1-dev.0", + "eslint-plugin-kolibri": "0.16.1-dev.1", "eslint-plugin-vue": "^7.3.0", "espree": "9.6.1", "esquery": "^1.5.0", @@ -88,7 +88,7 @@ "vue-jest": "^3.0.0", "vue-loader": "^15.11.1", "vue-style-loader": "^4.1.3", - "vue-template-compiler": "^2.6.11", + "vue-template-compiler": "2.6.14", "webpack": "^5.89.0", "webpack-cli": "^5.1.4", "webpack-dev-server": "^4.15.1", diff --git a/yarn.lock b/yarn.lock index 946479d0694..67a8f04970d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11521,7 +11521,7 @@ vue-style-loader@^4.1.0, vue-style-loader@^4.1.3: hash-sum "^1.0.2" loader-utils "^1.0.2" -vue-template-compiler@^2.6.11: +vue-template-compiler@2.6.14: version "2.6.14" resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.6.14.tgz#a2f0e7d985670d42c9c9ee0d044fed7690f4f763" integrity sha512-ODQS1SyMbjKoO1JBJZojSw6FE4qnh9rIpUZn2EUT86FKizx9uH5z6uXiIrm4/Nb/gwxTi/o17ZDEGWAXHvtC7g== @@ -11548,7 +11548,7 @@ vue2-teleport@^1.0.1: resolved "https://registry.yarnpkg.com/vue2-teleport/-/vue2-teleport-1.0.1.tgz#1b7f9f69c1223f522cf6cd81c39b8d6019e1cf66" integrity sha512-hbY/Q0x8qXGFxo6h4KU4YYesUcN+uUjliqqC0PoNSgpcbS2QRb3qXi+7XMTgLYs0a8i7o1H6Mu43UV4Vbgkhgw== -vue@^2.6.14: +vue@2.6.14, vue@^2.6.14: version "2.6.14" resolved "https://registry.yarnpkg.com/vue/-/vue-2.6.14.tgz#e51aa5250250d569a3fbad3a8a5a687d6036e235" integrity sha512-x2284lgYvjOMj3Za7kqzRcUSxBboHqtgRE2zlos1qWaOye5yUmHn42LB1250NJBLRwEcdrB0JRwyPTEPhfQjiQ== From f1f71f2307ac4300c930ccd816fcb81f73728729 Mon Sep 17 00:00:00 2001 From: iskipu Date: Fri, 1 Mar 2024 22:39:13 +0530 Subject: [PATCH 57/61] fix syntax --- .../learn/assets/src/my_downloads/views/DownloadsList/index.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kolibri/plugins/learn/assets/src/my_downloads/views/DownloadsList/index.vue b/kolibri/plugins/learn/assets/src/my_downloads/views/DownloadsList/index.vue index ddb1c7a77e9..ea4d20306a6 100644 --- a/kolibri/plugins/learn/assets/src/my_downloads/views/DownloadsList/index.vue +++ b/kolibri/plugins/learn/assets/src/my_downloads/views/DownloadsList/index.vue @@ -66,7 +66,7 @@

From 4cf7b76e1f7f99b59f37069869c5ff27ae121c6d Mon Sep 17 00:00:00 2001 From: iskipu Date: Sat, 2 Mar 2024 10:15:09 +0530 Subject: [PATCH 58/61] fix syntax again :) --- .../learn/assets/src/my_downloads/views/DownloadsList/index.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kolibri/plugins/learn/assets/src/my_downloads/views/DownloadsList/index.vue b/kolibri/plugins/learn/assets/src/my_downloads/views/DownloadsList/index.vue index ea4d20306a6..f9ce865a4d5 100644 --- a/kolibri/plugins/learn/assets/src/my_downloads/views/DownloadsList/index.vue +++ b/kolibri/plugins/learn/assets/src/my_downloads/views/DownloadsList/index.vue @@ -89,7 +89,7 @@
From c888bd836fa998863fee704d095532ad51119f53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Redrejo?= Date: Wed, 13 Mar 2024 17:17:52 +0100 Subject: [PATCH 59/61] Use FacilityUser instead of AUTH_USER_MODEL in migrations --- kolibri/core/device/migrations/0016_osuser.py | 2 +- .../core/device/migrations/0018_add_learner_device_status.py | 4 ++-- kolibri/core/discovery/migrations/0007_device_pinning.py | 4 ++-- .../core/discovery/migrations/0013_recreate_pinned_device.py | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/kolibri/core/device/migrations/0016_osuser.py b/kolibri/core/device/migrations/0016_osuser.py index 851f25e6744..f9fab0ff710 100644 --- a/kolibri/core/device/migrations/0016_osuser.py +++ b/kolibri/core/device/migrations/0016_osuser.py @@ -26,7 +26,7 @@ class Migration(migrations.Migration): primary_key=True, related_name="os_user", serialize=False, - to=settings.AUTH_USER_MODEL, + to="kolibriauth.FacilityUser", ), ), ("os_username", models.CharField(db_index=True, max_length=64)), diff --git a/kolibri/core/device/migrations/0018_add_learner_device_status.py b/kolibri/core/device/migrations/0018_add_learner_device_status.py index 837e0787eb7..11807b725d5 100644 --- a/kolibri/core/device/migrations/0018_add_learner_device_status.py +++ b/kolibri/core/device/migrations/0018_add_learner_device_status.py @@ -13,7 +13,7 @@ class Migration(migrations.Migration): dependencies = [ ("kolibriauth", "0020_facilitydataset_extra_fields"), - migrations.swappable_dependency(settings.AUTH_USER_MODEL), + migrations.swappable_dependency("kolibriauth.FacilityUser"), ("device", "0017_extra_settings"), ] @@ -58,7 +58,7 @@ class Migration(migrations.Migration): models.OneToOneField( on_delete=django.db.models.deletion.CASCADE, related_name="learner_device_status", - to=settings.AUTH_USER_MODEL, + to="kolibriauth.FacilityUser", ), ), ], diff --git a/kolibri/core/discovery/migrations/0007_device_pinning.py b/kolibri/core/discovery/migrations/0007_device_pinning.py index 64c1f2c2bd5..865b203bc2b 100644 --- a/kolibri/core/discovery/migrations/0007_device_pinning.py +++ b/kolibri/core/discovery/migrations/0007_device_pinning.py @@ -14,7 +14,7 @@ class Migration(migrations.Migration): dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), + migrations.swappable_dependency("kolibriauth.FacilityUser"), ("discovery", "0006_networklocation_min_content_schema_version"), ] @@ -41,7 +41,7 @@ class Migration(migrations.Migration): "user", models.ForeignKey( on_delete=django.db.models.deletion.CASCADE, - to=settings.AUTH_USER_MODEL, + to="kolibriauth.FacilityUser", ), ), ], diff --git a/kolibri/core/discovery/migrations/0013_recreate_pinned_device.py b/kolibri/core/discovery/migrations/0013_recreate_pinned_device.py index 2bcef951091..e64dfc7465b 100644 --- a/kolibri/core/discovery/migrations/0013_recreate_pinned_device.py +++ b/kolibri/core/discovery/migrations/0013_recreate_pinned_device.py @@ -13,7 +13,7 @@ class Migration(migrations.Migration): dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), + migrations.swappable_dependency("kolibriauth.FacilityUser"), ("discovery", "0012_remove_pinned_device"), ] @@ -41,7 +41,7 @@ class Migration(migrations.Migration): "user", models.ForeignKey( on_delete=django.db.models.deletion.CASCADE, - to=settings.AUTH_USER_MODEL, + to="kolibriauth.FacilityUser", ), ), ], From 3fa705caadebbab9682d85f0a79d8cd710d62f4d Mon Sep 17 00:00:00 2001 From: Richard Tibbles Date: Wed, 28 Feb 2024 15:44:22 -0800 Subject: [PATCH 60/61] Do further cleanup to remove unneeded swappable dependencies in migrations. --- kolibri/core/bookmarks/migrations/0001_initial.py | 1 - kolibri/core/device/migrations/0012_syncqueue.py | 2 +- kolibri/core/device/migrations/0013_usersyncstatus.py | 2 +- .../core/device/migrations/0018_add_learner_device_status.py | 1 - kolibri/core/discovery/migrations/0007_device_pinning.py | 2 +- .../core/discovery/migrations/0013_recreate_pinned_device.py | 2 +- kolibri/core/exams/migrations/0005_individualsyncableexam.py | 1 - .../core/lessons/migrations/0003_individualsyncablelesson.py | 1 - 8 files changed, 4 insertions(+), 8 deletions(-) diff --git a/kolibri/core/bookmarks/migrations/0001_initial.py b/kolibri/core/bookmarks/migrations/0001_initial.py index bf6e4201618..161e23f2067 100644 --- a/kolibri/core/bookmarks/migrations/0001_initial.py +++ b/kolibri/core/bookmarks/migrations/0001_initial.py @@ -15,7 +15,6 @@ class Migration(migrations.Migration): dependencies = [ ("kolibriauth", "0019_collection_no_mptt"), - migrations.swappable_dependency("kolibriauth.FacilityUser"), ] operations = [ diff --git a/kolibri/core/device/migrations/0012_syncqueue.py b/kolibri/core/device/migrations/0012_syncqueue.py index f8db062edfc..0762711f3d9 100644 --- a/kolibri/core/device/migrations/0012_syncqueue.py +++ b/kolibri/core/device/migrations/0012_syncqueue.py @@ -15,7 +15,7 @@ class Migration(migrations.Migration): dependencies = [ - migrations.swappable_dependency("kolibriauth.FacilityUser"), + ("kolibriauth", "0001_initial"), ("device", "0011_devicesettings_subset_of_users_device"), ] diff --git a/kolibri/core/device/migrations/0013_usersyncstatus.py b/kolibri/core/device/migrations/0013_usersyncstatus.py index 40dcd9c2b29..bf9ba804ee7 100644 --- a/kolibri/core/device/migrations/0013_usersyncstatus.py +++ b/kolibri/core/device/migrations/0013_usersyncstatus.py @@ -12,7 +12,7 @@ class Migration(migrations.Migration): dependencies = [ ("morango", "0016_store_deserialization_error"), - migrations.swappable_dependency("kolibriauth.FacilityUser"), + ("kolibriauth", "0001_initial"), ("device", "0012_syncqueue"), ] diff --git a/kolibri/core/device/migrations/0018_add_learner_device_status.py b/kolibri/core/device/migrations/0018_add_learner_device_status.py index 11807b725d5..efa11b74d9f 100644 --- a/kolibri/core/device/migrations/0018_add_learner_device_status.py +++ b/kolibri/core/device/migrations/0018_add_learner_device_status.py @@ -13,7 +13,6 @@ class Migration(migrations.Migration): dependencies = [ ("kolibriauth", "0020_facilitydataset_extra_fields"), - migrations.swappable_dependency("kolibriauth.FacilityUser"), ("device", "0017_extra_settings"), ] diff --git a/kolibri/core/discovery/migrations/0007_device_pinning.py b/kolibri/core/discovery/migrations/0007_device_pinning.py index 865b203bc2b..019730c56d0 100644 --- a/kolibri/core/discovery/migrations/0007_device_pinning.py +++ b/kolibri/core/discovery/migrations/0007_device_pinning.py @@ -14,7 +14,7 @@ class Migration(migrations.Migration): dependencies = [ - migrations.swappable_dependency("kolibriauth.FacilityUser"), + ("kolibriauth", "0001_initial"), ("discovery", "0006_networklocation_min_content_schema_version"), ] diff --git a/kolibri/core/discovery/migrations/0013_recreate_pinned_device.py b/kolibri/core/discovery/migrations/0013_recreate_pinned_device.py index e64dfc7465b..c4d87cf0b4a 100644 --- a/kolibri/core/discovery/migrations/0013_recreate_pinned_device.py +++ b/kolibri/core/discovery/migrations/0013_recreate_pinned_device.py @@ -13,7 +13,7 @@ class Migration(migrations.Migration): dependencies = [ - migrations.swappable_dependency("kolibriauth.FacilityUser"), + ("kolibriauth", "0001_initial"), ("discovery", "0012_remove_pinned_device"), ] diff --git a/kolibri/core/exams/migrations/0005_individualsyncableexam.py b/kolibri/core/exams/migrations/0005_individualsyncableexam.py index 8c0c3b2d57d..aba9b9b7a14 100644 --- a/kolibri/core/exams/migrations/0005_individualsyncableexam.py +++ b/kolibri/core/exams/migrations/0005_individualsyncableexam.py @@ -15,7 +15,6 @@ class Migration(migrations.Migration): dependencies = [ ("kolibriauth", "0019_collection_no_mptt"), - migrations.swappable_dependency("kolibriauth.FacilityUser"), ("exams", "0004_exam_add_dates_opened_created_and_archived"), ] diff --git a/kolibri/core/lessons/migrations/0003_individualsyncablelesson.py b/kolibri/core/lessons/migrations/0003_individualsyncablelesson.py index 8816d38b7a4..1b5deea5fd1 100644 --- a/kolibri/core/lessons/migrations/0003_individualsyncablelesson.py +++ b/kolibri/core/lessons/migrations/0003_individualsyncablelesson.py @@ -15,7 +15,6 @@ class Migration(migrations.Migration): dependencies = [ ("kolibriauth", "0019_collection_no_mptt"), - migrations.swappable_dependency("kolibriauth.FacilityUser"), ("lessons", "0002_auto_20180221_1115"), ] From b7e52c884469f1080a0324c73ef29279b63d0855 Mon Sep 17 00:00:00 2001 From: Sujai Kumar Gupta Date: Sat, 16 Mar 2024 02:31:14 +0530 Subject: [PATCH 61/61] add IsAuthenticated permission class in api/content/contentrequest --- kolibri/core/content/api.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kolibri/core/content/api.py b/kolibri/core/content/api.py index 54f6e6f2e0a..7c08e8f6538 100644 --- a/kolibri/core/content/api.py +++ b/kolibri/core/content/api.py @@ -40,6 +40,7 @@ from rest_framework import viewsets from rest_framework.decorators import action from rest_framework.generics import get_object_or_404 +from rest_framework.permissions import IsAuthenticated from rest_framework.response import Response from kolibri.core.api import BaseValuesViewset @@ -1392,6 +1393,7 @@ class ContentRequestViewset(ReadOnlyValuesViewset, CreateModelMixin): filter_backends = (DjangoFilterBackend,) filter_class = ContentRequestFilter pagination_class = OptionalPageNumberPagination + permission_classes = [IsAuthenticated] values = ( "id",