Skip to content

Commit

Permalink
Merge pull request #665 from NBISweden/develop
Browse files Browse the repository at this point in the history
Merge  latest develop to production branch
  • Loading branch information
jhagberg authored Jun 29, 2023
2 parents 3c3ad59 + f4dbeb7 commit 64e1367
Show file tree
Hide file tree
Showing 12 changed files with 1,752 additions and 1,300 deletions.
2 changes: 1 addition & 1 deletion .docker/main
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ COPY --from=herdbook_frontend:latest --chown=node:node /home/node/node_modules/
RUN npm run build

FROM python:3.8-buster

ENV TZ='Europe/Stockholm'
RUN mkdir -p /code

RUN apt-get update && apt-get -y upgrade &&\
Expand Down
21 changes: 21 additions & 0 deletions app/herdbook.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,19 @@
KINSHIP_LIFETIME = 300


# Before_request
# function that will update users last_active field in the database
# this will be called before every request
@APP.before_request
def before_request():
"""
Callback that triggers before each request. This is used to update the users last active.
"""
# update last_active field in the database
if current_user.is_authenticated:
current_user.update_last_active()


@APP.after_request
def after_request(response):
"""
Expand Down Expand Up @@ -161,6 +174,14 @@ def get_user():
return jsonify(user.frontend_data() if user else None)


@APP.route("/api/active_users", methods=["GET"])
@login_required
def get_active_users():
minutes = request.args.get("minutes", default=15, type=int)
active_users = da.get_active_users(minutes, session.get("user_id", None))
return jsonify(active_users)


@APP.route("/api/manage/users")
def get_users():
"""
Expand Down
4 changes: 2 additions & 2 deletions app/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
APScheduler==3.10.0
boto3==1.26.79
botocore==1.29.138
cryptography==39.0.1
cryptography==41.0.0
endesive==2.0.9
Flask_Caching==2.0.2
flask_dance==6.2.0
Expand All @@ -14,7 +14,7 @@ pdfrw2==0.5.0
peewee==3.15.4
psycopg2-binary==2.9.5
PyMuPDF==1.21.1
pyOpenSSL==23.0.0
pyOpenSSL==23.2.0
qrcode==7.4.2
requests
setuptools==65.5.1 # not directly required, pinned by Snyk to avoid a vulnerability
Expand Down
28 changes: 25 additions & 3 deletions app/utils/data_access.py
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,31 @@ def get_users(user_uuid=None):
return None


def get_active_users(minutes, user_uuid=None):
"""
Returns a list of currently active users
"""
user = fetch_user_info(user_uuid)
time_ago = datetime.now() - timedelta(minutes=minutes)
if user is None:
return {"status": "error", "message": "Not logged in"}
if not (user.is_admin or user.is_manager):
return {"status": "error", "message": "Forbidden"}
try:
active_users = User.select().where(User.last_active >= time_ago)
except DoesNotExist:
return None
return [
{
"username": user.username,
"fullname": user.fullname,
"last_active": user.last_active,
}
for user in active_users
]


def get_user(user_id, user_uuid=None):
"""
Returns the user with id `user_id`, if the user identified by
Expand Down Expand Up @@ -849,7 +874,6 @@ def form_to_individual(form, user=None):
changed = False
if individual.id and not can_manage:
for admin_field in [field for field in admin_fields if field in form]:

if not form.get("issue_digital", False):
changed = (
f"{form[admin_field]}" != f"{getattr(individual, admin_field)}"
Expand Down Expand Up @@ -1052,7 +1076,6 @@ def add_individual(form, user_uuid):

def update_herdtracking_values(individual, new_herd, user_signature, tracking_date):
with DATABASE.atomic():

ht_history = (
HerdTracking.select()
.where(HerdTracking.individual == individual)
Expand Down Expand Up @@ -1572,7 +1595,6 @@ def get_breeding_event(breed_id, user_uuid):
return []

try:

with DATABASE.atomic():
breed = Breeding.select().where(Breeding.id == breed_id).get().as_dict()
herd = Herd.get(Herd.herd == breed["breeding_herd"])
Expand Down
39 changes: 36 additions & 3 deletions app/utils/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
)
from playhouse.migrate import PostgresqlMigrator, SqliteMigrator, migrate

CURRENT_SCHEMA_VERSION = 10
CURRENT_SCHEMA_VERSION = 11
DB_PROXY = Proxy()
DATABASE = None
DATABASE_MIGRATOR = None
Expand Down Expand Up @@ -855,6 +855,11 @@ class User(BaseModel, UserMixin):
uuid = UUIDField()
validated = BooleanField(default=False)
_privileges = TextField(column_name="privileges", default="[]")
last_active = DateTimeField(default=datetime.now)

def update_last_active(self):
self.last_active = datetime.now()
self.save()

@property
def privileges(self):
Expand Down Expand Up @@ -1370,7 +1375,6 @@ def migrate_1_to_2():
"""

with DATABASE.atomic():

cols = [x.name for x in DATABASE.get_columns("schemahistory")]

if "applied" not in cols:
Expand Down Expand Up @@ -1405,7 +1409,6 @@ def migrate_3_to_4():
"""

with DATABASE.atomic():

if (
"individual" not in DATABASE.get_tables()
or "color" not in DATABASE.get_tables()
Expand Down Expand Up @@ -1625,6 +1628,36 @@ def migrate_9_to_10():
).execute()


def migrate_10_to_11():
"""
Migrate between schema version 10 and 11.
"""
with DATABASE.atomic():
if "hbuser" not in DATABASE.get_tables():
# Can't run migration
SchemaHistory.insert( # pylint: disable=E1120
version=11,
comment="not yet bootstrapped, skipping",
applied=datetime.now(),
).execute()
return

cols = [x.name for x in DATABASE.get_columns("hbuser")]

if "last_active" not in cols:
# Go through hbuser and add last_active
migrate(
DATABASE_MIGRATOR.add_column(
"hbuser",
"last_active",
DateTimeField(default=datetime.now),
)
)
SchemaHistory.insert( # pylint: disable=E1120
version=11, comment="Add last_active to hbuser", applied=datetime.now()
).execute()


def check_migrations():
"""
Check if the database needs any migrations run and run those if that's the case.
Expand Down
Loading

0 comments on commit 64e1367

Please sign in to comment.