Skip to content

Dev#94

Open
pparage wants to merge 23 commits intomasterfrom
dev
Open

Dev#94
pparage wants to merge 23 commits intomasterfrom
dev

Conversation

@pparage
Copy link
Copy Markdown

@pparage pparage commented Apr 16, 2026

What does it do?

This PR delivers the v0.18.0 release of MOSP, combining security hardening, two long-standing feature requests, a frontend modernization, and general UX polish.

Security fixes

  • Read SECRET_KEY and SECURITY_PASSWORD_SALT from environment variables instead of hardcoded values in config files (closes Recommendation to remove a default secret key #79)
  • Add ownership and organization membership checks on schema edit and delete routes (any authenticated user could previously modify schemas they did not own)
  • Replace HTTP GET delete endpoint with a proper two-step confirmation flow, preventing CSRF via crafted links
  • Harden schema permission decorator and add org_id server-side validation

New features

Frontend

  • Full Bootstrap 4 → Bootstrap 5 migration across all 45 templates (data-bs-* attributes, spacing utilities, removed bootstrap-select, replaced popper.js v1 with @popperjs/core v2)
  • CodeMirror 5 → CodeMirror 6 upgrade using an esbuild IIFE bundle
  • Replaced all inline style="color:red" form errors with Bootstrap text-danger utility classes
  • Added proper <label for="…"> elements to recovery, signup, and set-password forms
  • Fixed bSortableorderable in DataTables config (deprecated API)
  • Fixed onclick on <i> icon children instead of parent <a> links (confirm dialogs were non-functional)
  • Removed duplicate badge classes, deprecated align= HTML attributes, and spurious } in three {% extends %} tags
  • Empty-state messages when no objects, schemas, collections, or organizations exist
  • UX warning when a user has no organization membership (required to publish)

Other

  • Replace deprecated datetime.utcnow() with timezone-aware equivalent across all models
  • Replace print(e) debug statement with logger.error() in objectbp.py
  • Update Python and JS dependencies to address known CVEs
  • Fix postgresql:// scheme in production config sample (required by SQLAlchemy 2.x)

Questions

  • Does it require a DB change? Yes — one new column: Schema.forked_from_id (nullable FK). A migration is included.
  • Are you using it in production?

Release Type:

  • Major
  • Minor
  • Patch

pparage added 23 commits April 15, 2026 14:49
…er-side validation

- Use current_user.is_organization_member() instead of inline comprehension
- Add explicit comment on admin bypass rationale
- Clarify is_authenticated guard intent in docstring
- Add server-side org_id membership check in process_form create path
- Fix import order in schema.py (mosp.views after mosp.models)
- Add tests: 404, admin bypass, POST protection (6 tests total)
GET /schema/delete/<id> now shows a warning page with the schema name
and a count of objects that would be cascade-deleted; POST performs the
actual delete and redirects to the schemas list. Both routes are
protected by @login_required and @check_schema_edit_permission. A
SimpleForm is added to forms.py for CSRF protection on the confirmation
form. Tests cover owner GET (200), non-owner GET/POST (403), and
successful POST delete (302 + DB removal).
- Add forked_from_id self-referential FK to Schema model
- Alembic migration: c3f2a1b4e5d6
- POST /schema/fork/<id> route: copy schema into user's org, set provenance
- Fork modal in schema.html with org selector (Bootstrap 5)
- Provenance badge linking back to source schema
- Proper 403 error page (replaces redirect-to-login behavior)
- 3 new tests: fork creates copy, unauth redirects, wrong org rejects
Python (pip-audit):
- flask 3.0.2 → 3.1.3 (CVE-2026-27205)
- werkzeug 3.0.1 → 3.1.8 (CVE-2024-34069, CVE-2024-49766/67, CVE-2025-66221, CVE-2026-21860/27199)
- flask-cors 3.0.10 → 6.0.2 (PYSEC-2024-71, CVE-2024-1681/6844/6866/6839)
- requests 2.31.0 → 2.33.1 (CVE-2024-35195, CVE-2024-47081, CVE-2026-25645)
- certifi 2024.2.2 → 2026.2.25 (PYSEC-2024-230)
- idna 3.6 → 3.11 (PYSEC-2024-60)

JS (npm update — no vulnerabilities, minor bumps):
- @fortawesome/fontawesome-free 6.6.0 → 6.7.2
- @json-editor/json-editor 2.15.1 → 2.16.0
- bootstrap 5.3.3 → 5.3.8
- chart.js 4.4.3 → 4.5.1
- codemirror 6.0.1 → 6.0.2
- datatables.net-bs4 2.1.3 → 2.3.7
- papaparse 5.4.1 → 5.5.3
- docker-compose.yml: remove empty SECRET_KEY/SECURITY_PASSWORD_SALT placeholders
  that caused docker-compose up to crash; replace with comments only
- mosp/models/schema.py: wrap forked_from_id column and relationship definitions
  to respect 100-char line limit (flake8 E501)
- mosp/templates/errors/403.html: replace Bootstrap 3 'well' class with
  Bootstrap 5 'alert alert-danger'
- mosp/templates/schema.html: apply same org-membership guard to edit button
  as already applied to delete button (cosmetic hardening)
- tests/test_schema.py: add test verifying forged org_id is rejected on schema
  creation; correct assertion to 302 since WTForms choice validation fires first
- .gitignore: exclude instance/test.py and uv.lock
Replace datetime.utcnow() (deprecated in Python 3.12) with
datetime.now(timezone.utc).replace(tzinfo=None) across all models
and views. Replace print(e) debug calls in api/v2 with proper
logger.error() calls using exc_info=True.
Replace data-toggle/data-dismiss/data-target with data-bs-* equivalents
across all templates. Replace Bootstrap 4 .close buttons with Bootstrap
5 .btn-close. Downgrade codemirror from v6 (ES-module-only) to v5.65.x
which matches the lib/codemirror.js path used in edit_schema.html.
Build a self-hosted IIFE bundle (mosp/static/js/codemirror-bundle.js)
from codemirror@6 + @codemirror/lang-json using esbuild. The bundle is
rebuilt via `npm run build` or automatically on `npm install`.

Update edit_schema.html to use the CM6 EditorView API. Replace the
deprecated CodeMirror.fromTextArea() (v5) with EditorView + basicSetup
and JSON language support. The textarea value is synced back on submit.
Bootstrap 5 requires @popperjs/core v2. popper.js v1 does not expose
createPopper(), causing all dropdowns to fail with a TypeError.
Add data-bs-display="static" to navbar dropdown toggles to prevent
Popper from positioning menus outside the viewport. Rename
dropdown-menu-right to dropdown-menu-end (Bootstrap 5 rename).
In edit_schema, warn that the user must join/create an org before
creating a schema, with a link to the organizations list.

In admin edit_user, replace the broken bootstrap-select with a native
Bootstrap 5 form-select, and show a warning with a link to create
an org when no organizations exist yet.
Remove bootstrap-select (Bootstrap 4 only) entirely. Replace all
.selectpicker instances with .form-select across edit_object,
edit_collection, view_object, schema, admin/edit_organization templates.
Add Ctrl/Cmd hint on multi-selects. Remove unused bootstrap-select
CSS/JS from layout.html and uninstall the package.
Replace btn-default with btn-secondary/btn-primary. Consolidate all
event listeners inside DOMContentLoaded. Fix implicit global variable
(inputContent). Replace jQuery option manipulation with native
select.options.length = 0 and new Option(). Use insertAdjacentHTML
instead of innerHTML += for badge appending.
Global replacements:
- btn-default → btn-secondary
- text-right/left → text-end/start
- sr-only → visually-hidden
- float-right/left → float-end/start
- font-weight-* → fw-*
- badge-pill → rounded-pill, badge-primary → badge bg-primary
- form-row → row, form-group → mb-3
- text-justify removed (no BS5 equivalent)

Per-file structural fixes:
- about.html, index.html: jumbotron → p-5 bg-light rounded
- errors/404,500,503.html: .well → alert alert-warning/danger
- edit_user.html: navbar-form/input-group-prepend/append removed;
  restructured API key input-group for Bootstrap 5
- edit_json.html: toast header mr-auto → me-auto, close → btn-close
- layout.html: navbar ul mr-auto → me-auto
- Replace all inline style="color:red" form errors with Bootstrap text-danger divs
- Add proper <label for="..."> elements to account_recovery, signup, set_password forms
- Replace deprecated align= HTML attributes with Bootstrap float-start/text-center classes
- Fix bSortable -> orderable in DataTables config across 5 templates
- Remove spurious extra } from {% extends %} tags in help.html, terms.html, organization.html
- Fix onclick confirm() placed on icon children instead of parent anchor links
- Fix incorrect "Delete the object" title on collection delete button
- Fix label for= mismatch in edit_collection.html (description -> inputObject)
- Replace inline style="color:blue" icon with text-primary utility class
- Replace deprecated fa-remove icon with fa-trash in admin organizations
- Fix double badge class (badge badge bg-*) in user.html and schemas.html
- Standardize responsive table wrapper in view_diff.html
- Fix schema.html search input missing form-control class
- Add empty-state messages to all list/table views (no collections, objects, schemas, organizations)
@pparage pparage self-assigned this Apr 16, 2026
@pparage pparage added the enhancement Improvement of existing feature label Apr 16, 2026
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2febfcacec

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +24 to +29
op.create_foreign_key(
"fk_schema_forked_from_id",
"schema",
"schema",
["forked_from_id"],
["id"],
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Allow deleting schemas that have been forked

The new self-referential foreign key on schema.forked_from_id is created without an ondelete action, so PostgreSQL keeps the default NO ACTION behavior. After this migration, deleting an original schema that has at least one fork will raise an integrity error and make the new /schema/delete/<id> flow fail with a 500 at commit time. This blocks a core operation for any schema that has been forked.

Useful? React with 👍 / 👎.

Comment thread mosp/views/schema.py
Comment on lines +387 to +388
base_name = source.name + " (fork)"
name = base_name
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Bound fork names to the schema name column size

Fork names are generated by appending " (fork)" (and optionally a numeric suffix) to the source name, but Schema.name is limited to 100 characters. Forking any schema with a long valid name (e.g. 94+ chars) will produce an overlong value and trigger a DB error on db.session.commit(), returning a server error instead of creating the fork.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement Improvement of existing feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Recommendation to remove a default secret key Deletion of JSON schemas Copy a schema from an organization to an other

1 participant