Skip to content

Commit 56c0cff

Browse files
committed
Merge branch 'master' of https://github.com/PythonFreeCourse/lms into grades-mark
2 parents a315a0f + 8a41e38 commit 56c0cff

18 files changed

+526
-27
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,3 +135,4 @@ yarn-error.log*
135135
lms/lmsweb/config.py
136136
db.sqlite
137137
vim.session
138+
devops/rabbitmq.cookie

devops/build.sh

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@ SCRIPT_FILE_PATH=$(readlink -f "${0}")
44
SCRIPT_FOLDER=$(dirname "${SCRIPT_FILE_PATH}")
55
MAIN_FOLDER="${SCRIPT_FOLDER}/.."
66

7-
echo "Asking for sudo to chown the rabbitmq cookie:"
8-
sudo chown "$USER:$USER" "$SCRIPT_FOLDER/rabbitmq.cookie"
7+
echo "Using sudo to remove the old erlang cookie"
8+
ERLANG_COOKIE_FILE="${SCRIPT_FOLDER}/rabbitmq.cookie"
9+
sudo rm -f "$ERLANG_COOKIE_FILE"
910

1011
echo "Running build on folder ${MAIN_FOLDER}"
1112
( cd "${MAIN_FOLDER}" && docker build -t lms . )

devops/lms.yml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@ version: "3"
22

33
services:
44
db:
5-
image: postgres:13-alpine
5+
image: postgres:14-alpine
66
ports:
77
- 5432:5432
88
volumes:
99
- db-data-volume:/pg_data
1010
environment:
11-
- PGDATA=/pg_data/13/data
11+
- PGDATA=/pg_data/14/data
1212
- POSTGRES_DB=${DB_NAME:-db}
1313
- POSTGRES_USER=${DB_USERNAME:-postgres}
1414
- POSTGRES_PASSWORD=${DB_PASSWORD:-postgres}
@@ -97,6 +97,7 @@ services:
9797
volumes:
9898
- ../lms:/app_dir/lms
9999
- ../../notebooks-tests:/app_dir/notebooks-tests
100+
- repositories-data-volume:/repositories
100101
environment:
101102
- DB_NAME=${DB_NAME:-db}
102103
- DB_USER=${DB_USERNAME:-postgres}
@@ -109,6 +110,7 @@ services:
109110
- CELERY_CHECKS_PUBLIC_VHOST=lmstests-public
110111
- CELERY_RABBITMQ_HOST=rabbitmq
111112
- CELERY_RABBITMQ_PORT=5672
113+
- REPOSITORY_FOLDER=/repositories
112114
links:
113115
- db
114116
- rabbitmq
@@ -126,6 +128,7 @@ volumes:
126128
docker-engine-lib:
127129
db-data-volume:
128130
rabbit-data-volume:
131+
repositories-data-volume:
129132

130133

131134
networks:

devops/rabbitmq.cookie

Lines changed: 0 additions & 1 deletion
This file was deleted.

devops/start.sh

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,12 @@ else
77
echo "Using default dev variables"
88
fi
99

10-
1110
SCRIPT_FILE_PATH=$(readlink -f "${0}")
1211
SCRIPT_FOLDER=$(dirname "${SCRIPT_FILE_PATH}")
12+
ERLANG_COOKIE_FILE="${SCRIPT_FOLDER}/rabbitmq.cookie"
13+
14+
echo erlang_cookie=AAVyo5djdSMGIZXiwEQs3JeVaBx5l14z > "$ERLANG_COOKIE_FILE"
15+
chmod 600 "$ERLANG_COOKIE_FILE"
1316

1417
docker network create lms
1518

devops/upgrade_pg/upgrade.sh

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,20 @@
11
docker stop lms_db_1
22

33
# Put values here if you've configured them before
4-
# DB_NAME=lms
5-
# DB_USERNAME=lmsweb
6-
# DB_PASSWORD=
4+
CURRENT_VERSION=11
5+
NEW_VERSION=14
6+
DB_NAME=lms
7+
DB_USERNAME=lmsweb
8+
DB_PASSWORD=
9+
10+
echo "Remove these two lines to indicate you have filled the details"
11+
return 1
712

813
CURRENT_DATE=$(date +%d-%m-%Y_%H_%M_%S)
914
MOUNT_PATH=/pg_data
10-
PG_OLD_DATA=/pg_data/11/data
11-
PG_NEW_DATA=/pg_data/13/data
12-
BACKUP_FILENAME=v11.$CURRENT_DATE.sql
15+
PG_OLD_DATA=/pg_data/${CURRENT_VERSION}/data
16+
PG_NEW_DATA=/pg_data/${NEW_VERSION}/data
17+
BACKUP_FILENAME=v${CURRENT_VERSION}.${CURRENT_DATE}.sql
1318
BACKUP_PATH=$MOUNT_PATH/backup/$BACKUP_FILENAME
1419
BACKUP_DIR=$(dirname "$BACKUP_PATH")
1520
VOLUME_NAME=lms_db-data-volume
@@ -20,7 +25,7 @@ docker run --rm -v $VOLUME_NAME:$MOUNT_PATH \
2025
-e POSTGRES_DB="${DB_NAME:-db}" \
2126
-e POSTGRES_USER="${DB_USERNAME:-postgres}" \
2227
-e POSTGRES_PASSWORD="${DB_PASSWORD:-postgres}" \
23-
postgres:11-alpine \
28+
postgres:${CURRENT_VERSION}-alpine \
2429
/bin/bash -c "chown -R postgres:postgres $MOUNT_PATH \
2530
&& su - postgres /bin/bash -c \"/usr/local/bin/pg_ctl -D \\\"\$PGDATA\\\" start\" \
2631
&& mkdir -p \"$BACKUP_DIR\" \
@@ -33,7 +38,7 @@ docker run --rm -v $VOLUME_NAME:$MOUNT_PATH \
3338
-e POSTGRES_DB="${DB_NAME:-db}" \
3439
-e POSTGRES_USER="${DB_USERNAME:-postgres}" \
3540
-e POSTGRES_PASSWORD="${DB_PASSWORD:-postgres}" \
36-
postgres:13-alpine \
41+
postgres:$NEW_VERSION-alpine \
3742
/bin/bash -c "ls -la \"$BACKUP_DIR\" \
3843
&& mkdir -p \"\$PGDATA\" \
3944
&& chown -R postgres:postgres \"\$PGDATA\" \
@@ -43,3 +48,5 @@ docker run --rm -v $VOLUME_NAME:$MOUNT_PATH \
4348
&& su - postgres -c \"psql -f $BACKUP_PATH\" \
4449
&& printf \"\\\nhost all all all md5\\\n\" >> \"\$PGDATA/pg_hba.conf\" \
4550
"
51+
echo "Upgrade finished. Check for bad log messages. If none found, rerun:"
52+
echo "source ./build.sh && source ./start.sh && source ./bootstrap.sh"

lms/lmsdb/bootstrap.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,15 @@ def _add_exercise_course_id_and_number_columns_constraint() -> bool:
287287
db_config.database.commit()
288288

289289

290+
def _add_user_course_constaint() -> bool:
291+
migrator = db_config.get_migrator_instance()
292+
with db_config.database.transaction():
293+
migrate(
294+
migrator.add_index('usercourse', ('user_id', 'course_id'), True),
295+
)
296+
db_config.database.commit()
297+
298+
290299
def _last_status_view_migration() -> bool:
291300
Solution = models.Solution
292301
_migrate_column_in_table_if_needed(Solution, Solution.last_status_view)
@@ -320,6 +329,9 @@ def main():
320329
_last_course_viewed_migration()
321330
_uuid_migration()
322331

332+
if models.database.table_exists(models.UserCourse.__name__.lower()):
333+
_add_user_course_constaint()
334+
323335
models.database.create_tables(models.ALL_MODELS, safe=True)
324336

325337
if models.Role.select().count() == 0:

lms/lmsdb/models.py

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@
1616
BooleanField, Case, CharField, Check, DateTimeField, ForeignKeyField,
1717
IntegerField, JOIN, ManyToManyField, TextField, UUIDField, fn,
1818
)
19-
from playhouse.signals import Model, post_save, pre_save # type: ignore
19+
from playhouse.signals import ( # type: ignore
20+
Model, post_delete, post_save, pre_save,
21+
)
2022
from werkzeug.security import (
2123
check_password_hash, generate_password_hash,
2224
)
@@ -256,6 +258,11 @@ class UserCourse(BaseModel):
256258
course = ForeignKeyField(Course, backref='usercourses')
257259
date = DateTimeField(default=datetime.now)
258260

261+
class Meta:
262+
indexes = (
263+
(('user_id', 'course_id'), True),
264+
)
265+
259266
@classmethod
260267
def is_user_registered(cls, user_id: int, course_id: int) -> bool:
261268
return (
@@ -269,6 +276,24 @@ def is_user_registered(cls, user_id: int, course_id: int) -> bool:
269276
)
270277

271278

279+
@post_save(sender=UserCourse)
280+
def on_save_user_course(model_class, instance, created):
281+
"""Changes user's last course viewed."""
282+
if instance.user.last_course_viewed is None:
283+
instance.user.last_course_viewed = instance.course
284+
instance.user.save()
285+
286+
287+
@post_delete(sender=UserCourse)
288+
def on_delete_user_course(model_class, instance):
289+
"""Changes user's last course viewed."""
290+
if instance.user.last_course_viewed == instance.course:
291+
instance.user.last_course_viewed = (
292+
Course.fetch(instance.user).limit(1).scalar()
293+
)
294+
instance.user.save()
295+
296+
272297
class Notification(BaseModel):
273298
ID_FIELD_NAME = 'id'
274299
MAX_PER_USER = 10

lms/lmsweb/__init__.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import pathlib
22
import shutil
3+
import typing
34

45
from flask import Flask
56
from flask_babel import Babel # type: ignore
7+
from flask_httpauth import HTTPBasicAuth
68
from flask_limiter import Limiter # type: ignore
79
from flask_limiter.util import get_remote_address # type: ignore
810
from flask_mail import Mail # type: ignore
@@ -28,6 +30,8 @@
2830
static_folder=str(static_dir),
2931
)
3032

33+
http_basic_auth = HTTPBasicAuth()
34+
3135
limiter = Limiter(webapp, key_func=get_remote_address)
3236

3337

@@ -52,3 +56,18 @@
5256

5357
# gunicorn search for application
5458
application = webapp
59+
60+
61+
@http_basic_auth.get_password
62+
def get_password(username: str) -> typing.Optional[str]:
63+
user = models.User.get_or_none(models.User.username == username)
64+
return user.password if user else None
65+
66+
67+
@http_basic_auth.verify_password
68+
def verify_password(username: str, client_password: str):
69+
username_username = models.User.username == username
70+
login_user = models.User.get_or_none(username_username)
71+
if login_user is None or not login_user.is_password_valid(client_password):
72+
return False
73+
return login_user

lms/lmsweb/config.py.example

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,3 +67,5 @@ LIMITS_PER_HOUR = 50
6767

6868
# Change password settings
6969
MAX_INVALID_PASSWORD_TRIES = 5
70+
71+
REPOSITORY_FOLDER = os.getenv("REPOSITORY_FOLDER", os.path.abspath(os.path.join(os.curdir, "repositories")))

0 commit comments

Comments
 (0)