diff --git a/.github/workflows/qc_checks.yaml b/.github/workflows/qc_checks.yaml index 2bca01f939..1d12994d9e 100644 --- a/.github/workflows/qc_checks.yaml +++ b/.github/workflows/qc_checks.yaml @@ -705,7 +705,7 @@ jobs: env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Upload SARIF file - uses: github/codeql-action/upload-sarif@3599b3baa15b485a2e49ef411a7a4bb2452e7f93 # pin@v3 + uses: github/codeql-action/upload-sarif@64d10c13136e1c5bce3e5fbde8d4906eeaafc885 # pin@v3 with: sarif_file: results.sarif category: zizmor diff --git a/.github/workflows/scorecard.yaml b/.github/workflows/scorecard.yaml index 865ff219f7..5fbc41b747 100644 --- a/.github/workflows/scorecard.yaml +++ b/.github/workflows/scorecard.yaml @@ -37,7 +37,7 @@ jobs: persist-credentials: false - name: "Run analysis" - uses: ossf/scorecard-action@05b42c624433fc40578a4040d5cf5e36ddca8cde # v2.4.2 + uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3 with: results_file: results.sarif results_format: sarif @@ -67,6 +67,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@3599b3baa15b485a2e49ef411a7a4bb2452e7f93 # v3.30.5 + uses: github/codeql-action/upload-sarif@64d10c13136e1c5bce3e5fbde8d4906eeaafc885 # v3.30.6 with: sarif_file: results.sarif diff --git a/.github/workflows/stale.yaml b/.github/workflows/stale.yaml index 923111e407..131ed2d94a 100644 --- a/.github/workflows/stale.yaml +++ b/.github/workflows/stale.yaml @@ -16,7 +16,7 @@ jobs: pull-requests: write steps: - - uses: actions/stale@3a9db7e6a41a89f618792c92c0e97cc736e1b13f # pin@v10.0.0 + - uses: actions/stale@5f858e3efba33a5ca4407a664cc011ad407f2008 # pin@v10.1.0 with: repo-token: ${{ secrets.GITHUB_TOKEN }} stale-issue-message: "This issue seems stale. Please react to show this is still important." diff --git a/contrib/packager.io/functions.sh b/contrib/packager.io/functions.sh index eede301be1..d59a88e4ef 100755 --- a/contrib/packager.io/functions.sh +++ b/contrib/packager.io/functions.sh @@ -166,6 +166,18 @@ function detect_envs() { export INVENTREE_DB_PASSWORD=$(jq -r '.[].database.PASSWORD' <<< ${INVENTREE_CONF_DATA}) export INVENTREE_DB_HOST=$(jq -r '.[].database.HOST' <<< ${INVENTREE_CONF_DATA}) export INVENTREE_DB_PORT=$(jq -r '.[].database.PORT' <<< ${INVENTREE_CONF_DATA}) + + # Parse site URL if not already set + if [ -z "${INVENTREE_SITE_URL}" ]; then + # Try to read out the app config + if [ -n "$(inventree config:get INVENTREE_SITE_URL)" ]; then + echo "# POI03| Getting site URL from app config" + export INVENTREE_SITE_URL=$(inventree config:get INVENTREE_SITE_URL) + else + echo "# POI03| Getting site URL from config file" + export INVENTREE_SITE_URL=$(jq -r '.[].site_url' <<< ${INVENTREE_CONF_DATA}) + fi + fi else echo "# POI03| No config file found: ${INVENTREE_CONFIG_FILE}, using envs or defaults" @@ -190,6 +202,8 @@ function detect_envs() { export INVENTREE_DB_HOST=${INVENTREE_DB_HOST:-samplehost} export INVENTREE_DB_PORT=${INVENTREE_DB_PORT:-123456} + export INVENTREE_SITE_URL=${INVENTREE_SITE_URL} + export SETUP_CONF_LOADED=true fi @@ -209,6 +223,7 @@ function detect_envs() { fi echo "# POI03| INVENTREE_DB_HOST=${INVENTREE_DB_HOST}" echo "# POI03| INVENTREE_DB_PORT=${INVENTREE_DB_PORT}" + echo "# POI03| INVENTREE_SITE_URL=${INVENTREE_SITE_URL}" } function create_initscripts() { @@ -313,7 +328,7 @@ function update_or_install() { # Run update as app user echo "# POI12| Updating InvenTree" sudo -u ${APP_USER} --preserve-env=$SETUP_ENVS bash -c "cd ${APP_HOME} && pip install wheel" - sudo -u ${APP_USER} --preserve-env=$SETUP_ENVS bash -c "cd ${APP_HOME} && invoke update | sed -e 's/^/# POI12| u | /;'" + sudo -u ${APP_USER} --preserve-env=$SETUP_ENVS bash -c "cd ${APP_HOME} && set -e && invoke update | sed -e 's/^/# POI12| u | /;'" # Make sure permissions are correct again echo "# POI12| Set permissions for data dir and media: ${DATA_DIR}" @@ -373,10 +388,15 @@ function set_site() { # Check if INVENTREE_SITE_URL in inventree config if [ -z "$(inventree config:get INVENTREE_SITE_URL)" ]; then - echo "# POI14| Setting up InvenTree site URL" - inventree config:set INVENTREE_SITE_URL=http://${INVENTREE_IP} + # Prefer current INVENTREE_SITE_URL if set + if [ -n "${INVENTREE_SITE_URL}" ]; then + inventree config:set INVENTREE_SITE_URL=${INVENTREE_SITE_URL} + else + echo "# POI14| Setting up InvenTree site URL" + inventree config:set INVENTREE_SITE_URL=http://${INVENTREE_IP} + fi else - echo "# POI14| Site URL already set - skipping" + echo "# POI14| Site URL already set to '$INVENTREE_SITE_URL' - skipping" fi } @@ -385,11 +405,16 @@ function final_message() { echo -e "####################################################################################" echo -e "This InvenTree install uses nginx, the settings for the webserver can be found in" echo -e "${SETUP_NGINX_FILE}" - echo -e "Try opening InvenTree with either\nhttp://localhost/ or http://${INVENTREE_IP}/\n" - echo -e "Admin user data:" - echo -e " Email: ${INVENTREE_ADMIN_EMAIL}" - echo -e " Username: ${INVENTREE_ADMIN_USER}" - echo -e " Password: ${INVENTREE_ADMIN_PASSWORD}" + echo -e "Try opening InvenTree with any of \n${INVENTREE_SITE_URL} , http://localhost/ or http://${INVENTREE_IP}/ \n" + # Print admin user data only if set + if ["${INVENTREE_ADMIN_USER}" ]; then + echo -e "Admin user data:" + echo -e " Email: ${INVENTREE_ADMIN_EMAIL}" + echo -e " Username: ${INVENTREE_ADMIN_USER}" + echo -e " Password: ${INVENTREE_ADMIN_PASSWORD}" + else + echo -e "No admin set during this operation - depending on the deployment method a admin user might have been created with an initial password saved in `${SETUP_ADMIN_PASSWORD_FILE}`" + fi echo -e "####################################################################################" } diff --git a/contrib/packager.io/postinstall.sh b/contrib/packager.io/postinstall.sh index 4e5734fb5a..3d96188392 100755 --- a/contrib/packager.io/postinstall.sh +++ b/contrib/packager.io/postinstall.sh @@ -14,7 +14,7 @@ echo "# POI01| Importing functions" echo "# POI01| Functions imported" # Envs that should be passed to setup commands -export SETUP_ENVS=PATH,APP_HOME,INVENTREE_MEDIA_ROOT,INVENTREE_STATIC_ROOT,INVENTREE_BACKUP_DIR,INVENTREE_SITE_URL,INVENTREE_PLUGINS_ENABLED,INVENTREE_PLUGIN_FILE,INVENTREE_CONFIG_FILE,INVENTREE_SECRET_KEY_FILE,INVENTREE_DB_ENGINE,INVENTREE_DB_NAME,INVENTREE_DB_USER,INVENTREE_DB_PASSWORD,INVENTREE_DB_HOST,INVENTREE_DB_PORT,INVENTREE_ADMIN_USER,INVENTREE_ADMIN_EMAIL,INVENTREE_ADMIN_PASSWORD,SETUP_NGINX_FILE,SETUP_ADMIN_PASSWORD_FILE,SETUP_NO_CALLS,SETUP_DEBUG,SETUP_EXTRA_PIP,SETUP_PYTHON,SETUP_ADMIN_NOCREATION +export SETUP_ENVS=PATH,APP_HOME,INVENTREE_MEDIA_ROOT,INVENTREE_STATIC_ROOT,INVENTREE_BACKUP_DIR,INVENTREE_PLUGINS_ENABLED,INVENTREE_PLUGIN_FILE,INVENTREE_CONFIG_FILE,INVENTREE_SECRET_KEY_FILE,INVENTREE_DB_ENGINE,INVENTREE_DB_NAME,INVENTREE_DB_USER,INVENTREE_DB_PASSWORD,INVENTREE_DB_HOST,INVENTREE_DB_PORT,INVENTREE_ADMIN_USER,INVENTREE_ADMIN_EMAIL,INVENTREE_ADMIN_PASSWORD,INVENTREE_SITE_URL,SETUP_NGINX_FILE,SETUP_ADMIN_PASSWORD_FILE,SETUP_NO_CALLS,SETUP_DEBUG,SETUP_EXTRA_PIP,SETUP_PYTHON,SETUP_ADMIN_NOCREATION # Get the envs detect_local_env diff --git a/contrib/packager.io/preinstall.sh b/contrib/packager.io/preinstall.sh index f15fb49e06..9ae899fdb9 100755 --- a/contrib/packager.io/preinstall.sh +++ b/contrib/packager.io/preinstall.sh @@ -6,7 +6,7 @@ echo "# PRI01| Running preinstall script - start - $(date)" PATH=${APP_HOME}/env/bin:${APP_HOME}/:/sbin:/bin:/usr/sbin:/usr/bin: # Envs that should be passed to setup commands -export SETUP_ENVS=PATH,APP_HOME,INVENTREE_MEDIA_ROOT,INVENTREE_STATIC_ROOT,INVENTREE_BACKUP_DIR,INVENTREE_PLUGINS_ENABLED,INVENTREE_PLUGIN_FILE,INVENTREE_CONFIG_FILE,INVENTREE_SECRET_KEY_FILE,INVENTREE_DB_ENGINE,INVENTREE_DB_NAME,INVENTREE_DB_USER,INVENTREE_DB_PASSWORD,INVENTREE_DB_HOST,INVENTREE_DB_PORT,INVENTREE_ADMIN_USER,INVENTREE_ADMIN_EMAIL,INVENTREE_ADMIN_PASSWORD,SETUP_NGINX_FILE,SETUP_ADMIN_PASSWORD_FILE,SETUP_NO_CALLS,SETUP_DEBUG,SETUP_EXTRA_PIP,SETUP_PYTHON +export SETUP_ENVS=PATH,APP_HOME,INVENTREE_MEDIA_ROOT,INVENTREE_STATIC_ROOT,INVENTREE_BACKUP_DIR,INVENTREE_PLUGINS_ENABLED,INVENTREE_PLUGIN_FILE,INVENTREE_CONFIG_FILE,INVENTREE_SECRET_KEY_FILE,INVENTREE_DB_ENGINE,INVENTREE_DB_NAME,INVENTREE_DB_USER,INVENTREE_DB_PASSWORD,INVENTREE_DB_HOST,INVENTREE_DB_PORT,INVENTREE_ADMIN_USER,INVENTREE_ADMIN_EMAIL,INVENTREE_ADMIN_PASSWORD,INVENTREE_SITE_URL,SETUP_NGINX_FILE,SETUP_ADMIN_PASSWORD_FILE,SETUP_NO_CALLS,SETUP_DEBUG,SETUP_EXTRA_PIP,SETUP_PYTHON if test -f "${APP_HOME}/env/bin/pip"; then # Check if clear-generated is available diff --git a/docs/docs/manufacturing/bom.md b/docs/docs/manufacturing/bom.md index aa74434c6e..72f0aef389 100644 --- a/docs/docs/manufacturing/bom.md +++ b/docs/docs/manufacturing/bom.md @@ -88,11 +88,17 @@ Note that inherited BOM Line Items only flow "downwards" in the variant inherita ## BOM Creation -BOMs can be created manually, by adjusting individual line items, or by upload an existing BOM file. +BOMs can be created manually, by adjusting individual line items, or by uploading (importing) an existing BOM file. + +### Importing a BOM + +BOM data can be imported from an existing file (such as CSV or Excel) from the *BOM* panel for a particular part/assembly. This process is a special case of the more general [data import process](../settings/import.md). + +At the top of the *BOM* panel, click on the {{ icon("file-arrow-left", color="green", title="Import BOM Data") }} icon to open the import dialog. ### Add BOM Item -To manually add a BOM item, navigate to the part/assembly detail page then click on the "BOM" tab. On top of the tab view, click on the {{ icon("edit", color="blue", title="Edit") }} icon then, after the page reloads, click on the {{ icon("plus-circle") }} icon. +To manually add a BOM item, navigate to the part/assembly detail page then click on the *BOM* panel tab. On top of the *BOM* view, click on the {{ icon("edit", color="blue", title="Edit") }} icon then, after the page reloads, click on the {{ icon("plus-circle") }} icon. The `Create BOM Item` form will be displayed: diff --git a/docs/docs/settings/error_codes.md b/docs/docs/settings/error_codes.md index 0b422441d0..47253c4777 100644 --- a/docs/docs/settings/error_codes.md +++ b/docs/docs/settings/error_codes.md @@ -9,9 +9,12 @@ Errors - These are critical errors which should be addressed as soon as possible #### INVE-E1 **No frontend included - Backend/web** -Only stable / production releases of InvenTree include the frontend panel. This is both a measure of resource-saving and attack surface reduction. If you want to use the frontend panel, you can either:″ +Only stable / production releases of InvenTree include the frontend panel. This is both a measure of resource-saving and attack surface reduction. + +If you want to use the frontend panel, you can either: + - use a docker image that is version-tagged or the stable version -- use a package version that is from the stable or version stream +- use a package version that is from the stable or version stream - if you are and it is not working, run `sudo inventree run cli update` to re-run the upgrade - install node and yarn on the server to build the frontend with the [invoke](../start/invoke.md) task `int.frontend-build` Raise an issue if none of these options work. diff --git a/docs/docs/start/config.md b/docs/docs/start/config.md index c151bf6a32..87660787ef 100644 --- a/docs/docs/start/config.md +++ b/docs/docs/start/config.md @@ -83,7 +83,7 @@ Date and time values are stored in the database in UTC format, and are converted By default, the InvenTree server will not automatically apply database migrations. When the InvenTree installation is updated (*or a plugin is installed which requires database migrations*), database migrations must be applied manually by the system administrator. -With "auto update" enabled, the InvenTree server will automatically apply database migrations as required. To enable automatic database updates, set `INVENTREE_AUTO_UPDATE` to `True`. +With "auto update" enabled, the InvenTree server will automatically apply database migrations as required when plugins are changed. To enable automatic database updates, set `INVENTREE_AUTO_UPDATE` to `True`. However, this setting is not sufficient when updating your InvenTree installation - you must still ensure that you follow the required steps for updating InvenTree as per your installation method. ## Debugging and Logging Options diff --git a/src/backend/InvenTree/InvenTree/sentry.py b/src/backend/InvenTree/InvenTree/sentry.py index 714b5292c9..5307220ee9 100644 --- a/src/backend/InvenTree/InvenTree/sentry.py +++ b/src/backend/InvenTree/InvenTree/sentry.py @@ -23,7 +23,7 @@ def default_sentry_dsn(): return 'https://3928ccdba1d34895abde28031fd00100@o378676.ingest.sentry.io/6494600' -def sentry_ignore_errors(): +def sentry_ignore_errors(): # pragma: no cover """Return a list of error types to ignore. These error types will *not* be reported to sentry.io. @@ -40,7 +40,7 @@ def sentry_ignore_errors(): ] -def init_sentry(dsn, sample_rate, tags): +def init_sentry(dsn, sample_rate, tags): # pragma: no cover """Initialize sentry.io error reporting.""" logger.info('Initializing sentry.io integration') @@ -66,7 +66,7 @@ def init_sentry(dsn, sample_rate, tags): sentry_sdk.set_tag('git_date', InvenTree.version.inventreeCommitDate()) -def report_exception(exc, scope: Optional[dict] = None): +def report_exception(exc, scope: Optional[dict] = None): # pragma: no cover """Report an exception to sentry.io.""" assert settings.TESTING == False, ( 'report_exception should not be called in testing mode' diff --git a/src/backend/InvenTree/InvenTree/settings.py b/src/backend/InvenTree/InvenTree/settings.py index b06286562c..965fbc05de 100644 --- a/src/backend/InvenTree/InvenTree/settings.py +++ b/src/backend/InvenTree/InvenTree/settings.py @@ -170,7 +170,7 @@ structlog.configure( cache_logger_on_first_use=True, ) # Optionally add database-level logging -if get_setting('INVENTREE_DB_LOGGING', 'db_logging', False): +if get_setting('INVENTREE_DB_LOGGING', 'db_logging', False): # pragma: no cover LOGGING['loggers'] = {'django.db.backends': {'level': LOG_LEVEL or 'DEBUG'}} # Get a logger instance for this setup file @@ -369,7 +369,7 @@ MIDDLEWARE = CONFIG.get( # In DEBUG mode, add support for django-querycount # Ref: https://github.com/bradmontgomery/django-querycount -if DEBUG and get_boolean_setting( +if DEBUG and get_boolean_setting( # pragma: no cover 'INVENTREE_DEBUG_QUERYCOUNT', 'debug_querycount', False ): MIDDLEWARE.append('querycount.middleware.QueryCountMiddleware') @@ -405,7 +405,7 @@ AUTHENTICATION_BACKENDS = ( # LDAP support LDAP_AUTH = get_boolean_setting('INVENTREE_LDAP_ENABLED', 'ldap.enabled', False) -if LDAP_AUTH: +if LDAP_AUTH: # pragma: no cover import django_auth_ldap.config # type: ignore[unresolved-import] import ldap # type: ignore[unresolved-import] @@ -943,7 +943,7 @@ Q_CLUSTER = { } # Configure django-q sentry integration -if SENTRY_ENABLED and SENTRY_DSN: +if SENTRY_ENABLED and SENTRY_DSN: # pragma: no cover Q_CLUSTER['error_reporter'] = {'sentry': {'dsn': SENTRY_DSN}} if GLOBAL_CACHE_ENABLED: # pragma: no cover @@ -1296,14 +1296,14 @@ FRONTEND_SETTINGS = config.get_frontend_settings(debug=DEBUG) FRONTEND_URL_BASE = FRONTEND_SETTINGS['base_url'] # region auth -for app in SOCIAL_BACKENDS: +for app in SOCIAL_BACKENDS: # pragma: no cover # Ensure that the app starts with 'allauth.socialaccount.providers' social_prefix = 'allauth.socialaccount.providers.' - if not app.startswith(social_prefix): # pragma: no cover + if not app.startswith(social_prefix): app = social_prefix + app - INSTALLED_APPS.append(app) # pragma: no cover + INSTALLED_APPS.append(app) SOCIALACCOUNT_PROVIDERS = get_setting( 'INVENTREE_SOCIAL_PROVIDERS', 'social_providers', None, typecast=dict @@ -1331,7 +1331,7 @@ login_attempts = get_setting('INVENTREE_LOGIN_ATTEMPTS', 'login_attempts', 5) try: login_attempts = int(login_attempts) login_attempts = f'{login_attempts}/m,{login_attempts}/m' -except ValueError: +except ValueError: # pragma: no cover pass ACCOUNT_RATE_LIMITS = {'login_failed': login_attempts} @@ -1493,7 +1493,7 @@ FLAGS = { # Get custom flags from environment/yaml CUSTOM_FLAGS = get_setting('INVENTREE_FLAGS', 'flags', None, typecast=dict) -if CUSTOM_FLAGS: +if CUSTOM_FLAGS: # pragma: no cover if not isinstance(CUSTOM_FLAGS, dict): logger.error('Invalid custom flags, must be valid dict: %s', str(CUSTOM_FLAGS)) else: @@ -1552,5 +1552,5 @@ OAUTH2_CHECK_EXCLUDED = [ # This setting mutes schema checks for these rule/met '/api/webhook/{endpoint}/:post', ] -if SITE_URL and not TESTING: +if SITE_URL and not TESTING: # pragma: no cover SPECTACULAR_SETTINGS['SERVERS'] = [{'url': SITE_URL}] diff --git a/src/backend/InvenTree/plugin/builtin/integration/core_notifications.py b/src/backend/InvenTree/plugin/builtin/integration/core_notifications.py index f55fe46a79..3634c2b3e0 100644 --- a/src/backend/InvenTree/plugin/builtin/integration/core_notifications.py +++ b/src/backend/InvenTree/plugin/builtin/integration/core_notifications.py @@ -38,6 +38,10 @@ class InvenTreeUINotifications(NotificationMixin, InvenTreePlugin): if not users: return False + # Ensure that there is always target object - see https://github.com/inventree/InvenTree/issues/10435 + if not target: + target = self.plugin_config() + # Bulk create notification messages for all provided users for user in users: entries.append( diff --git a/src/backend/InvenTree/web/templates/web/index.html b/src/backend/InvenTree/web/templates/web/index.html index 879f7daf2a..26ed53e62c 100644 --- a/src/backend/InvenTree/web/templates/web/index.html +++ b/src/backend/InvenTree/web/templates/web/index.html @@ -13,7 +13,7 @@ -
+
If you see this text there might be an Issue with your update - see INVE-E1 in the docs for help
{% spa_settings %}
{% if bundle == "NOT_FOUND" %}