Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
86e89fe
Add a shared `lazy_init_backend` helper for use in reworking of backe…
jonasbardino Jul 22, 2026
fa34854
Begin refactoring a couple of shared Xgi unit test helpers into wsgisup.
jonasbardino Jul 22, 2026
4367a0c
Implement lazy init of `environ` and `initialize_main_variables` call…
jonasbardino Jul 22, 2026
4564746
Reworked cat.py and datatransfer.py backend unit tests to use the new…
jonasbardino Jul 22, 2026
9f92b49
Continue with docs.py and add matching basic unit tests.
jonasbardino Jul 22, 2026
72d3abd
Continue with resedit.py and add matching basic unit tests.
jonasbardino Jul 22, 2026
f1544cc
Adjust `lazy_init_backend` to take and optional `init_kwargs` dict an…
jonasbardino Jul 22, 2026
6269477
Adjust lazy init to include same title settings as initialize_main_va…
jonasbardino Jul 22, 2026
62bab32
Continue with fileman.py and add matching basic unit tests.
jonasbardino Jul 22, 2026
88e5433
Continue with vgridworkflows.py and add matching basic unit tests.
jonasbardino Jul 22, 2026
7f8cb3b
Actually add the unit tests for vgridworkflows.
jonasbardino Jul 22, 2026
07aefda
Add additional tests for docs.py with a few disabled until we fix cor…
jonasbardino Jul 22, 2026
778c3b0
Continue with reqoid.py backend and add matching basic unit tests.
jonasbardino Jul 22, 2026
a2a867f
Remove indavertently added workaround in last commit.
jonasbardino Jul 22, 2026
e11b8fe
Add missing reqoid unit tests intended for previous commit.
jonasbardino Jul 22, 2026
fef2cf0
Continue with home.py and add matching basic unit tests.
jonasbardino Jul 23, 2026
121010b
Minor non-functional polish.
jonasbardino Jul 23, 2026
d279143
Continue with vgridman.py and add matching basic unit tests.
jonasbardino Jul 23, 2026
1268ce4
Continue with freezedb.py and add matching basic unit tests.
jonasbardino Jul 23, 2026
e597be4
Continue with jupyter.py and add matching basic unit tests.
jonasbardino Jul 23, 2026
bf87349
Update tests to really use test configuration and expect error if req…
jonasbardino Jul 23, 2026
b380c82
Simplify and use the same backend_main call format with specific test
jonasbardino Jul 23, 2026
f939001
Extend reqoid with test for disabled oid site signup.
jonasbardino Jul 23, 2026
53ed400
Continue with reqcert.py and add matching basic unit tests.
jonasbardino Jul 23, 2026
325ca18
Adjustments to fit reality after applying fixes from other PRs.
jonasbardino Jul 23, 2026
cc4f11c
Move title style and script helper dicts from `output` to `init` modu…
jonasbardino Jul 22, 2026
f054925
Enable the unit tests that the previous commit fixed.
jonasbardino Jul 22, 2026
7abfcf0
Also duplicate base_menu init from initialize_main_variables in lazy …
jonasbardino Jul 23, 2026
8f2971b
Re-enable a few more tests that work as-is now.
jonasbardino Jul 23, 2026
4497e46
Re-enablethe remining tests that work as-is now.
jonasbardino Jul 23, 2026
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
20 changes: 11 additions & 9 deletions mig/shared/functional.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# --- BEGIN_HEADER ---
#
# functional - functionality backend helpers
# Copyright (C) 2003-2023 The MiG Project lead by Brian Vinter
# Copyright (C) 2003-2026 The MiG Project by the Science HPC Center at UCPH
#
# This file is part of MiG.
#
Expand All @@ -20,7 +20,8 @@
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
# USA.
#
# -- END_HEADER ---
#
Expand All @@ -33,21 +34,21 @@

from past.builtins import basestring
import os
import time

# REJECT_UNSET is not used directly but exposed to functionality

from mig.shared.accountstate import check_account_status, \
check_update_account_expire
from mig.shared.base import requested_backend, force_native_str, get_site_base_url

Check warning on line 40 in mig/shared/functional.py

View workflow job for this annotation

GitHub Actions / Style check python and annotate

line too long (82 > 80 characters)
from mig.shared.defaults import csrf_field, auth_openid_ext_db
from mig.shared.findtype import is_user
from mig.shared.httpsclient import extract_client_cert, extract_client_openid, \
from mig.shared.httpsclient import extract_client_openid, \
extract_base_url
from mig.shared.init import find_entry, make_title_entry, make_header_entry
from mig.shared.safeinput import validated_input, REJECT_UNSET
from mig.shared.useradm import expire_oid_sessions

# REJECT_UNSET is not used directly but exposed to functionality
__exports = [REJECT_UNSET]


def warn_on_rejects(rejects, output_objects):
"""Helper to fill in output_objects in case of rejects"""
Expand Down Expand Up @@ -89,6 +90,7 @@
output_objects,
allow_rejects,
prefilter_map=None,
environ=None,
typecheck_overrides={}
):
"""A wrapper used by most back end functionality.
Expand Down Expand Up @@ -145,7 +147,7 @@
if client_id is missing.
The optional typecheck_overrides dictionary is passed directly to the base
validate_input and can be used to loosen input validation. Please refer to
the validate_input doc.

Check warning on line 150 in mig/shared/functional.py

View workflow job for this annotation

GitHub Actions / Style check python and annotate

trailing whitespace
"""

logger = configuration.logger
Expand All @@ -154,7 +156,6 @@
creds_error = ''
pending_expire, account_expire = True, 0
account_accessible, account_status = True, 'active'
user_dict = None
if not client_id:
creds_error = "Invalid or missing user credentials"
elif not is_user(client_id, configuration):
Expand All @@ -176,7 +177,7 @@
# Expired users can still log out or use their login to access the
# (unprivileged) account request pages to renew their account with
# auto-fill of fields.
if creds_error and not requested_backend(environ) in \
if creds_error and requested_backend(environ) not in \
['logout', 'autologout', 'reqoid', 'reqcert', 'extcert']:
# Simple init to get page preamble even where initialize_main_variables
# was called with most things disabled because no or limited direct
Expand Down Expand Up @@ -211,14 +212,14 @@
if not client_id:
output_objects.append(
{'object_type': 'text', 'text': '''Apparently you do not
already have access to %s, but you can sign up:''' % configuration.short_title

Check warning on line 215 in mig/shared/functional.py

View workflow job for this annotation

GitHub Actions / Style check python and annotate

line too long (82 > 80 characters)
})
output_objects.append({'object_type': 'link', 'text':
'%s sign up page' %
configuration.short_title,
'destination': signup_url + signup_query})

Check warning on line 220 in mig/shared/functional.py

View workflow job for this annotation

GitHub Actions / Style check python and annotate

line too long (81 > 80 characters)
output_objects.append(
{'object_type': 'text', 'text': '''If you already signed up and

Check warning on line 222 in mig/shared/functional.py

View workflow job for this annotation

GitHub Actions / Style check python and annotate

line too long (83 > 80 characters)
received a user certificate you probably just need to import it in your
browser.'''})
else:
Expand Down Expand Up @@ -253,7 +254,7 @@
if oid_db and identity:
logger.info("openid expire user %s in %s" % (identity,
oid_db))
(success, _) = expire_oid_sessions(configuration, oid_db,

Check warning on line 257 in mig/shared/functional.py

View workflow job for this annotation

GitHub Actions / Style check python and annotate

line too long (81 > 80 characters)
identity)
if oid_db == auth_openid_ext_db and \
'extoid' in configuration.site_signup_methods:
Expand All @@ -263,8 +264,8 @@
% (client_id, base_url))
elif base_url in (configuration.migserver_https_ext_oidc_url,
configuration.migserver_https_mig_oidc_url):
# No obvious logout/expire session cookie here prior to signup

Check warning on line 267 in mig/shared/functional.py

View workflow job for this annotation

GitHub Actions / Style check python and annotate

line too long (82 > 80 characters)
logger.warning("possibly missing logout for client_id %s on %s" %

Check warning on line 268 in mig/shared/functional.py

View workflow job for this annotation

GitHub Actions / Style check python and annotate

line too long (85 > 80 characters)
(client_id, base_url))
if base_url == configuration.migserver_https_ext_oidc_url \
and 'extoidc' in configuration.site_signup_methods:
Expand All @@ -282,7 +283,8 @@

(status, retval) = validate_input(user_arguments_dict, defaults,
output_objects, allow_rejects,
filter_values,
prefilter_map=filter_values,
environ=environ,
typecheck_overrides=typecheck_overrides)

return (status, retval)
37 changes: 9 additions & 28 deletions mig/shared/functionality/cat.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# --- BEGIN_HEADER ---
#
# cat - show lines of one or more files
# Copyright (C) 2003-2024 The MiG Project lead by Brian Vinter
# Copyright (C) 2003-2026 The MiG Project by the Science HPC Center at UCPH
#
# This file is part of MiG.
#
Expand All @@ -20,7 +20,8 @@
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
# USA.
#
# -- END_HEADER ---
#
Expand All @@ -41,8 +42,8 @@
write_file_lines
from mig.shared.functional import validate_input_and_cert, REJECT_UNSET
from mig.shared.handlers import safe_handler, get_csrf_limit
from mig.shared.init import initialize_main_variables, find_entry, \
make_start_entry, start_error, start_download
from mig.shared.init import find_entry, lazy_init_backend, start_download, \
start_error
from mig.shared.parseflags import verbose, binary
from mig.shared.userio import GDPIOLogError, gdp_iolog
from mig.shared.safeinput import valid_path_pattern
Expand Down Expand Up @@ -90,32 +91,12 @@
return ['file_output', defaults]


def main(client_id, user_arguments_dict, environ=None):
def main(client_id, user_arguments_dict, environ=None, init_main_res=None,
init_kwargs=None):
"""Main function wrapper used by front end"""

if environ is None:
environ = os.environ

(configuration, logger, output_objects, op_name) = \
initialize_main_variables(client_id)

return _main(configuration, logger, environ, op_name=op_name,
output_objects=output_objects, client_id=client_id,
user_arguments_dict=user_arguments_dict)


def _main(configuration, logger, environ, op_name='', output_objects=None, client_id=None,
user_arguments_dict=None):
"""Actual main function to generate contents for the front end"""

assert environ is not None, "required arg: environ"

if logger is None:
logger = configuration.logger

# Create new output_objects list with start entry if None was supplied
if output_objects is None:
output_objects = [make_start_entry()]
(configuration, logger, output_objects, op_name, environ) = \
lazy_init_backend(client_id, environ, init_main_res, init_kwargs)

client_dir = client_id_dir(client_id)
defaults = signature()[1]
Expand Down
46 changes: 12 additions & 34 deletions mig/shared/functionality/datatransfer.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# --- BEGIN_HEADER ---
#
# datatransfer - import and export data in the backgroud
# Copyright (C) 2003-2023 The MiG Project lead by Brian Vinter
# Copyright (C) 2003-2026 The MiG Project by the Science HPC Center at UCPH
#
# This file is part of MiG.
#
Expand All @@ -20,7 +20,8 @@
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
# USA.
#
# -- END_HEADER ---
#
Expand All @@ -34,13 +35,13 @@
import time

from mig.shared import returnvalues
from mig.shared.base import client_id_dir, mask_creds, hexlify, requested_backend
from mig.shared.base import client_id_dir, mask_creds, hexlify
from mig.shared.defaults import default_pager_entries, csrf_field, protocol_aliases

Check warning on line 39 in mig/shared/functionality/datatransfer.py

View workflow job for this annotation

GitHub Actions / Style check python and annotate

line too long (83 > 80 characters)
from mig.shared.fileio import read_tail_lines
from mig.shared.functional import validate_input_and_cert
from mig.shared.handlers import safe_handler, get_csrf_limit, make_csrf_token
from mig.shared.htmlgen import man_base_js, man_base_html, html_post_helper
from mig.shared.init import initialize_main_variables, find_entry, make_title_entry, make_start_entry
from mig.shared.init import find_entry, lazy_init_backend
from mig.shared.parseflags import quiet
from mig.shared.pwcrypto import make_digest, make_encrypt
from mig.shared.transferfunctions import build_transferitem_object, \
Expand All @@ -56,8 +57,8 @@
get_actions = ['show', 'fillimport', 'fillexport']
transfer_actions = ['import', 'export', 'deltransfer', 'redotransfer']
# TODO: add these internal data shuffling targets on a separate tab without
#address and creds
#shuffling_actions = ['move', 'copy', 'unpack', 'pack', 'remove']
# address and creds
# shuffling_actions = ['move', 'copy', 'unpack', 'pack', 'remove']
shuffling_actions = []
key_actions = ['generatekey', 'delkey']
post_actions = transfer_actions + shuffling_actions + key_actions
Expand Down Expand Up @@ -88,35 +89,12 @@
return ['text', defaults]


def main(client_id, user_arguments_dict, environ=None):
def main(client_id, user_arguments_dict, environ=None, init_main_res=None,
init_kwargs=None):
"""Main function wrapper used by front end"""

if environ is None:
environ = os.environ

(configuration, logger, output_objects, op_name) = \
initialize_main_variables(client_id)

return _main(configuration, logger, environ, op_name=op_name,
output_objects=output_objects, client_id=client_id,
user_arguments_dict=user_arguments_dict)


def _main(configuration, logger, environ, op_name='', output_objects=None, client_id=None,
user_arguments_dict=None):
"""Actual main function to generate contents for the front end"""

assert environ is not None, "required arg: environ"

if logger is None:
logger = configuration.logger

# Create new output_objects list with start entry if None was supplied
if output_objects is None:
output_objects = [make_start_entry()]
if not op_name:
op_name = requested_backend()
output_objects.append(make_title_entry('%s' % op_name))
(configuration, logger, output_objects, op_name, environ) = \
lazy_init_backend(client_id, environ, init_main_res, init_kwargs)

defaults = signature()[1]
(validate_status, accepted) = validate_input_and_cert(
Expand Down Expand Up @@ -182,7 +160,7 @@
var fields = 0;
var max_fields = 20;
var src_input = "<label for=\'transfer_src\'>Source path(s)</label>";
src_input += "<input id=\'src_FIELD\' type=text size=60 name=transfer_src value=\'PATH\' title=\'relative source path: local for exports and remote for imports\' />";

Check warning on line 163 in mig/shared/functionality/datatransfer.py

View workflow job for this annotation

GitHub Actions / Style check python and annotate

line too long (170 > 80 characters)
src_input += "<input id=\'src_file_FIELD\' type=radio onclick=\'setSrcDir(FIELD, false);\' checked />Source file";
src_input += "<input id=\'src_dir_FIELD\' type=radio onclick=\'setSrcDir(FIELD, true);\' />Source directory (recursive)";
src_input += "<br />";
Expand Down Expand Up @@ -836,7 +814,7 @@
try:
password_encrypted = make_encrypt(configuration, password)
password_digest = ''
except:
except Exception:
password_encrypted = ''
password_digest = make_digest(
'datatransfer', client_id, password,
Expand Down
15 changes: 9 additions & 6 deletions mig/shared/functionality/docs.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
Expand Down Expand Up @@ -40,8 +40,9 @@
from mig.shared import mrslkeywords
from mig.shared import resconfkeywords
from mig.shared import returnvalues
from mig.shared.defaults import keyword_auto
from mig.shared.functional import validate_input
from mig.shared.init import initialize_main_variables
from mig.shared.init import lazy_init_backend
from mig.shared.output import get_valid_outputformats


Expand Down Expand Up @@ -606,18 +607,20 @@
'text': 'sshfs client (GNU v2.0)'})


def main(client_id, user_arguments_dict):
"""Main function used by front end"""
def main(client_id, user_arguments_dict, environ=None, init_main_res=None,
init_kwargs={'op_menu': keyword_auto}):
"""Main function wrapper used by front end"""

(configuration, logger, output_objects, op_name, environ) = \
lazy_init_backend(client_id, environ, init_main_res, init_kwargs)

(configuration, logger, output_objects, op_name) = \
initialize_main_variables(client_id, op_header=False,
op_menu=client_id)
defaults = signature()[1]
(validate_status, accepted) = validate_input(
user_arguments_dict,
defaults,
output_objects,
allow_rejects=False,
environ=environ,
)
if not validate_status:
return (accepted, returnvalues.CLIENT_ERROR)
Expand Down
25 changes: 13 additions & 12 deletions mig/shared/functionality/fileman.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# --- BEGIN_HEADER ---
#
# fileman - File manager UI for browsing and manipulating files and folders
# Copyright (C) 2003-2025 The MiG Project by the Science HPC Center at UCPH
# Copyright (C) 2003-2026 The MiG Project by the Science HPC Center at UCPH
#
# This file is part of MiG.
#
Expand All @@ -20,7 +20,8 @@
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
# USA.
#
# -- END_HEADER ---
#
Expand All @@ -31,10 +32,8 @@

from __future__ import absolute_import

import sys

from mig.shared import returnvalues
from mig.shared.base import client_id_dir
from mig.shared.defaults import trash_linkname, csrf_backends, csrf_field, \
default_max_chunks
from mig.shared.freezefunctions import import_freeze_form
Expand All @@ -44,7 +43,7 @@
from mig.shared.gdp.all import get_project_from_client_id
from mig.shared.handlers import get_csrf_limit, make_csrf_token
from mig.shared.htmlgen import themed_styles, legacy_user_interface
from mig.shared.init import initialize_main_variables, find_entry, extract_menu
from mig.shared.init import extract_menu, find_entry, lazy_init_backend
from mig.shared.pwcrypto import sorted_hash_algos, default_algo
from mig.shared.sharelinks import create_share_link_form, import_share_link_form

Expand Down Expand Up @@ -463,7 +462,7 @@
('%s' % (configuration.site_enable_transfers and legacy_buttons)).lower(),
'enable_gdp':
('%s' % configuration.site_enable_gdp).lower(),
'max_stream_size': 64*1024*1024
'max_stream_size': 64 * 1024 * 1024
}

js_import = '''
Expand Down Expand Up @@ -590,7 +589,7 @@
/* jquery-ui-1.7.x option format */
$.ui.dialog.defaults.bgiframe = true;
}
''' % fill_entries
''' # no use for fill_entries here
js_ready = '''
/* wrap in try/catch for debugging - disabled in prodution */
/*
Expand Down Expand Up @@ -661,12 +660,13 @@
return ['', defaults]


def main(client_id, user_arguments_dict):
"""Main function used by front end"""
def main(client_id, user_arguments_dict, environ=None, init_main_res=None,
init_kwargs={'op_header': False}):
"""Main function wrapper used by front end"""

(configuration, logger, output_objects, op_name, environ) = \
lazy_init_backend(client_id, environ, init_main_res, init_kwargs)

(configuration, logger, output_objects, op_name) = \
initialize_main_variables(client_id, op_header=False)
client_dir = client_id_dir(client_id)
defaults = signature()[1]
(validate_status, accepted) = validate_input_and_cert(
user_arguments_dict,
Expand All @@ -675,6 +675,7 @@
client_id,
configuration,
allow_rejects=False,
environ=environ,
# NOTE: path cannot use wildcards here
typecheck_overrides={},
)
Expand Down
Loading
Loading