Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

0.16 into develop #12014

Merged
merged 87 commits into from
Mar 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
87 commits
Select commit Hold shift + click to select a range
4d442d6
Removes inconsistently applied and mostly no-op double click blocking.
rtibbles Jan 11, 2024
2ce9790
Delete coreAPI PageRoot component in favour of default component in k…
rtibbles Jan 12, 2024
f81afc9
Fix NO_FILE_BASED_LOGGING env var not working properly
KshitijThareja Jan 20, 2024
0641169
Fix condition check for env var
KshitijThareja Jan 20, 2024
717a931
Make code python2 compatible
KshitijThareja Jan 20, 2024
bb86130
Add condition check before calling render on response
KshitijThareja Jan 21, 2024
716eb84
Check if response.render is callable
KshitijThareja Jan 22, 2024
4655620
Merge pull request #7 from learningequality/release-v0.16.x
nick2432 Jan 23, 2024
e20025c
Avoid looking up the facility user twice if not needed.
rtibbles Jan 19, 2024
6aa9ef2
feat: update to vue-virtual-scroller 1.1.2
ThEditor Dec 22, 2023
d851068
feat: dynamic scroller
ThEditor Dec 22, 2023
36c83eb
fix: preloading offset pages
ThEditor Dec 22, 2023
4702ab5
chore: add theditor to authors
ThEditor Dec 22, 2023
7d8488e
revert: preloading offset pages
ThEditor Dec 23, 2023
740426b
chore: variable mode recyclable scroller
ThEditor Dec 29, 2023
5982d4a
fix: linting issues
ThEditor Jan 5, 2024
12490d2
chore: add recyclescroller credits
ThEditor Jan 5, 2024
b00e981
chore: dynamic height loading
ThEditor Jan 5, 2024
54490df
chore: scroll buffer & item height
ThEditor Jan 5, 2024
bdaf4c4
docs: modifications to recyclescroller
ThEditor Jan 5, 2024
2b0024b
refactor: lint fix
ThEditor Jan 5, 2024
fd46934
refactor: cleanup
ThEditor Jan 6, 2024
979391e
fix: mobile scrolling
ThEditor Jan 24, 2024
fa6100e
fix: extra space at pdf end
ThEditor Jan 24, 2024
fc3a453
Watch core for changes if KDS option is provided
thesujai Jan 25, 2024
3ac6614
refactor: lint fix
ThEditor Jan 25, 2024
3044120
Update env var condition
KshitijThareja Jan 25, 2024
1540ece
Add a check for response.content
KshitijThareja Jan 25, 2024
9b95098
refactor: more lint fixes
ThEditor Jan 26, 2024
705045a
Merge pull request #8 from learningequality/release-v0.16.x
nick2432 Jan 27, 2024
16cb765
Make .log function, .setLevel function work as expected
iskipu Jan 30, 2024
a6e7a24
Fixing-Lint
iskipu Jan 30, 2024
96fcdd1
change .log function to .info and remove .log function from Logging.js
iskipu Jan 30, 2024
128f865
using loglevel plugin to set the message prefix
iskipu Jan 31, 2024
f1807ac
make methodname uppercase
iskipu Feb 1, 2024
9ca7f44
[fix] responsive onboarding setup wizard
FidalMathew Feb 8, 2024
e5772da
add parentBreakpoint to LanguageSwitcherList
FidalMathew Feb 12, 2024
5ed8042
lint fix
FidalMathew Feb 12, 2024
0e2fe6b
lint fixes
FidalMathew Feb 12, 2024
08523f5
change margin to padding fix #11838
iskipu Feb 10, 2024
31aa24e
Trigger Build
iskipu Feb 16, 2024
753995d
Merge pull request #9 from learningequality/release-v0.16.x
nick2432 Feb 16, 2024
ef562e2
bump version number
marcellamaki Feb 21, 2024
33230a8
Merge pull request #11912 from marcellamaki/upgrade-kolibri-version
rtibbles Feb 21, 2024
1f5fa7c
Merge pull request #11853 from iskipu/screen_flicker
MisRob Feb 21, 2024
5cbec33
Merge branch 'learningequality:release-v0.16.x' into release-v0.16.x
nick2432 Feb 22, 2024
7b08d47
fix:import-duplicate-usernames
nick2432 Feb 22, 2024
9dbe675
Merge pull request #11762 from KshitijThareja/10506
bjester Feb 22, 2024
27fc14b
Try to use a different glob lib for now
bjester Feb 22, 2024
bfbcb3c
Fix glob access
bjester Feb 22, 2024
2d9d954
fix:import-duplicate-usernames
nick2432 Feb 23, 2024
83a6dab
Just use fast-glob which globby uses underneath
bjester Feb 23, 2024
401c1b6
Merge pull request #11758 from KshitijThareja/9161
rtibbles Feb 23, 2024
0f802b0
Properly handle case insensitive matches for existing usernames in bu…
nick2432 Feb 23, 2024
017af53
Refactor error handling in CustomDjangoCache to handle multiple error…
thesujai Feb 23, 2024
3a28d76
Merge pull request #11820 from iskipu/fix_logging_module
rtibbles Feb 23, 2024
d7086d1
Merge pull request #11913 from bjester/go-go-globby
rtibbles Feb 23, 2024
33790ad
Update packages versions for latest release.
rtibbles Feb 23, 2024
2c34515
Merge pull request #11919 from rtibbles/new_package
rtibbles Feb 24, 2024
11f8ead
Merge pull request #11785 from thesujai/devserver-with-kds
rtibbles Feb 24, 2024
ebda7c3
fix: os_user unnecessary password field
ThEditor Jan 29, 2024
4818901
fix:import-duplicate-usernames
nick2432 Feb 24, 2024
a49730d
fix:import-duplicate-usernames
nick2432 Feb 24, 2024
2de4f18
fix:import-duplicate-usernames
nick2432 Feb 24, 2024
c616eba
fix spinner misalignment and spinner flickering in download page
iskipu Feb 26, 2024
3b37b81
Merge pull request #11671 from ThEditor/scroller
AlexVelezLl Feb 26, 2024
18c297c
Merge pull request #11847 from FidalMathew/issue-7997
AlexVelezLl Feb 26, 2024
85e56d8
Merge pull request #11755 from rtibbles/exact_duplicate_usernames
marcellamaki Feb 27, 2024
c2d3ece
Merge pull request #11899 from nick2432/fix-import-duplicate-usernames
marcellamaki Feb 27, 2024
7a953e2
Merge pull request #11814 from ThEditor/osuserpass
marcellamaki Feb 27, 2024
18448e7
Update Mac tests to run on Python 3.10
rtibbles Jan 19, 2024
dcce356
Merge pull request #11753 from learningequality/rtibbles-patch-1
marcellamaki Feb 27, 2024
51a7503
Merge pull request #11730 from rtibbles/rooting_out_pages
marcellamaki Feb 27, 2024
91f0b3e
Merge pull request #11719 from rtibbles/double_click_blocking
marcellamaki Feb 27, 2024
b3e7aa3
Install KDS 3.0.1
MisRob Feb 29, 2024
650359a
Pin vue and vue-template-compiler to ensure correct version is used i…
rtibbles Feb 29, 2024
a19234a
Merge pull request #11930 from rtibbles/pin_vue_and_templates
bjester Mar 1, 2024
f1f71f2
fix syntax
iskipu Mar 1, 2024
33e4c76
Merge pull request #11929 from MisRob/upgrade-kds
rtibbles Mar 1, 2024
4cf7b76
fix syntax again :)
iskipu Mar 2, 2024
f63cb78
Merge pull request #11921 from iskipu/spinner_misalign
LianaHarris360 Mar 4, 2024
c888bd8
Use FacilityUser instead of AUTH_USER_MODEL in migrations
Mar 13, 2024
3fa705c
Do further cleanup to remove unneeded swappable dependencies in migra…
rtibbles Feb 28, 2024
4959560
Merge pull request #11984 from jredrejo/do_not_use_AUTH_USER_MODEL
jredrejo Mar 13, 2024
b7e52c8
add IsAuthenticated permission class in api/content/contentrequest
thesujai Mar 15, 2024
8ca3654
Merge pull request #11995 from thesujai/IsAuthenticated-permission
rtibbles Mar 17, 2024
66d0f6d
Merge branch 'release-v0.16.x' into develop
rtibbles Mar 21, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/tox.yml
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ jobs:
strategy:
max-parallel: 5
matrix:
python-version: [3.6]
python-version: ['3.10']

steps:
- uses: actions/checkout@v4
Expand Down
1 change: 1 addition & 0 deletions AUTHORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,3 +103,4 @@ If you have contributed to Kolibri, feel free to add your name and Github accoun
| Alex Vélez | AlexVelezLl |
| Mazen Oweiss | moweiss |
| Eshaan Aggarwal | EshaanAgg |
| Nikhil Sharma | ThEditor |
2 changes: 1 addition & 1 deletion kolibri/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,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__ = "[email protected]"
Expand Down
2 changes: 0 additions & 2 deletions kolibri/core/assets/src/core-app/apiSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,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';
Expand Down Expand Up @@ -203,7 +202,6 @@ export default {
PrivacyLinkAndModal,
LearnOnlyDeviceNotice,
SuggestedTime,
PageRoot,
MasteryModel,
NotificationsRoot,
KolibriLoadingSnippet,
Expand Down
7 changes: 6 additions & 1 deletion kolibri/core/assets/src/kolibri_app.js
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
18 changes: 13 additions & 5 deletions kolibri/core/assets/src/logging.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,31 @@

import loglevel from 'loglevel';

const console = global.console;

class Logger {
constructor(loggerName) {
this.loggerName = loggerName;
this.logger = loglevel.getLogger(loggerName);
this.setMessagePrefix();
Object.keys(loglevel.levels).forEach(methodName => {
const name = methodName.toLowerCase();
const logFunction = this.logger[name];
if (logFunction) {
this[name] = logFunction.bind(console, this.messagePrefix(name));
this[name] = param => {
return this.logger[name](param);
};
}
});
}

messagePrefix(type) {
return `[${type.toUpperCase()}: ${this.loggerName}]`;
setMessagePrefix() {
var originalFactory = this.logger.methodFactory;
this.logger.methodFactory = function(methodName, logLevel, loggerName) {
var rawMethod = originalFactory(methodName, logLevel, loggerName);
return function(message) {
rawMethod(`[${methodName.toUpperCase()}: ${loggerName}] ` + message);
};
};
this.logger.setLevel(this.logger.getLevel());
}

setLevel(level, persist) {
Expand Down
16 changes: 0 additions & 16 deletions kolibri/core/assets/src/state/modules/core/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
1 change: 0 additions & 1 deletion kolibri/core/assets/src/state/modules/core/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ export default {
state() {
return {
error: '',
blockDoubleClicks: false,
loading: true,
pageSessionId: 0,
totalProgress: null,
Expand Down
3 changes: 0 additions & 3 deletions kolibri/core/assets/src/state/modules/core/mutations.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
},
Expand Down
18 changes: 0 additions & 18 deletions kolibri/core/assets/src/views/PageRoot.vue

This file was deleted.

4 changes: 3 additions & 1 deletion kolibri/core/assets/src/views/SyncStatusDisplay.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<template>

<span>
<span :style="{ display: 'flex', alignItems: 'center' }">
<KCircularLoader
v-if="syncInProgress"
:size="20"
Expand Down Expand Up @@ -135,6 +135,7 @@
.inline-loader {
display: inline-block;
margin-right: 8px;
margin-left: 0;
vertical-align: bottom;
}

Expand All @@ -146,6 +147,7 @@
.small {
display: inline-block;
margin-top: 0;
margin-bottom: 0;
font-size: 11px;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,12 @@
windowBreakpoint,
};
},
props: {
parentBreakpoint: {
type: Number,
default: -1,
},
},
data() {
return {
showLanguageModal: false,
Expand All @@ -75,8 +81,14 @@
return availableLanguages[currentLanguage];
},
numVisibleLanguageBtns() {
// At windowBreakpoint = 0, only the "More languages" button will show
return Math.min(4, this.windowBreakpoint);
// At visibleBtns = 0, only the "More languages" button will show
let visibleBtns = 4;
if (this.parentBreakpoint < 0) {
visibleBtns = this.windowBreakpoint;
} else {
visibleBtns = this.parentBreakpoint;
}
return Math.min(4, visibleBtns);
},
numSelectableLanguages() {
return this.selectableLanguages.length;
Expand Down
37 changes: 19 additions & 18 deletions kolibri/core/auth/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -897,7 +897,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
Expand All @@ -917,24 +933,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
Expand Down
35 changes: 31 additions & 4 deletions kolibri/core/auth/management/commands/bulkimportusers.py
Original file line number Diff line number Diff line change
Expand Up @@ -269,8 +269,20 @@ 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
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 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()}
if lowercase_username in lowercase_users:
return None # Duplicate username

return username

Expand Down Expand Up @@ -533,7 +545,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 = []
Expand Down Expand Up @@ -563,7 +575,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 = {
Expand All @@ -578,6 +590,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"],
Expand Down
31 changes: 28 additions & 3 deletions kolibri/core/auth/test/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -1240,9 +1240,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):
Expand Down
Loading
Loading