Skip to content

[18.0] dms_field: multiple issues in the embedded folder-template mechanism (crash on new records, cross-model directory mixing, template persisting live directories, and silent invisibility with no access groups) #494

Description

@valero1120

Module

dms, dms_field

Describe the bug

While implementing a custom module that embeds dms_directory_ids on a generic model (project.project) via the standard dms.field.mixin pattern (same approach as the existing hr_dms_field/sale_dms_field submodules), we found four distinct issues in the dms_list widget and the "Embedded DMS Template" mechanism. Filing them together since they all surfaced while testing the same feature end-to-end, but each has an independent root cause.


Bug 1 — New/unsaved record with an embedded dms_list field crashes (OwlError)

Steps to reproduce (pure dms + dms_field, no custom module needed):

  1. Documents > Configuration > Storages > New.
  2. The form crashes immediately with an uncaught OwlError:

Root cause: in dms_list_controller.esm.js, processProps() does:

storage_domain = [["id", "in", this.model.root.records.map((record) => record.resId)]];

this.model.root.records only exists on a list datapoint. On a single, unsaved record form, this.model.root is a Record datapoint with no .records property → undefined.map() throws.

The same unguarded pattern exists in the dms.field.template branch (this.model.root.data.dms_directory_ids.records.map(...)), which can equally throw if that field isn't loaded yet.

Expected behavior: opening/creating a new record with an embedded dms_list field should render an empty state, not crash.


Bug 2 — Autocompute domain doesn't filter by res_model, mixing directories across unrelated models

Steps to reproduce:

  1. Create a dms.field.template for a generic model (e.g. project.project).
  2. Ensure a project.project record ends up sharing the same numeric id as an existing dms.field.template record (easy to hit on a small/demo DB — e.g. both id=2).
  3. Open that project's form, go to the embedded dms_list field.
  4. The widget shows the template's own root directory (named after the template) instead of the project's own directory.

Root cause: in buildDMSDomain(), when autocompute_directory is true (used for any generic model via the mixin), the domain only filters by res_id:

result = Domain.and([result, new Domain([["res_id", "=", this.model.root.resId]])]);

No res_model term is added. Since dms.directory.res_id is a plain Integer (paired with res_model for a polymorphic reference, not a Many2one), two records of different models sharing the same numeric id get mixed together.

Expected behavior: the autocompute domain should also filter by res_model (the real model of the record being viewed).


Bug 3 — Defining a Template's folder structure creates real, live dms.directory records instead of a pure template definition

Steps to reproduce:

  1. Documents > Configuration > Embedded DMS Templates > New, set Storage + Model, save.
  2. In the "Documents" tab, use the add-directory toolbar action to define the hierarchy (e.g. "Legal", "Technical", "Financial").

Each directory defined here is persisted as a real, standalone dms.directory row (res_model = 'dms.field.template', res_id = <template id> for the root; no res_model/res_id at all for its children — see _prepare_child_directory_vals()). As a result these show up as ordinary, "live" folders throughout the rest of Documents (General Folders menu, the Files sidebar category tree, etc.), which is confusing since they're meant to be a template blueprint, not folders anyone should browse/use directly.

We attempted a view-level mitigation (overriding the domain of action_dms_directory/action_dms_file and the directory_id searchpanel field to exclude root_directory_id.res_model = 'dms.field.template'). This works for the main "Folders" window action, but not for the hierarchical <searchpanel> category tree used in the Files view — that tree is built via a separate mechanism that ignores the field's domain attribute, so template-owned folders still show up there even with 0 files inside. We could not find a safe, view-only way to hide them from every entry point without risking hiding the same directories from the Template's own editing screen (which legitimately needs to see them).

Expected behavior: the template's folder hierarchy should be stored as lightweight template configuration, not as real dms.directory records that leak into every general-purpose folder browser in the system.


Bug 4 — A directory (or its owning Template) with no Access Group ends up invisible to every user, including admins, with zero errors or warnings

Steps to reproduce:

  1. Create an Embedded DMS Template, leave "Groups" empty, save.
  2. Click the add-root-directory action.
  3. The directory is created successfully in the database (confirmed via direct SQL — correct res_id/res_model/storage_id), but it never appears anywhere in the UI — not in the template's own embedded view, not in Folders/Files, not even after a hard page reload — for any user, including a database administrator.

Root cause: dms.security.mixin._get_access_groups_query() grants access to a directory exclusively through membership in a dms.access.group linked to it (dms_directory_complete_groups_rel). With zero groups linked, that subquery is always empty, so the resulting access domain matches nothing for anyone. There is no "no groups = open to everyone" fallback, and no validation preventing you from creating/using a template without any group — the record is created silently and just never shows up anywhere, with no error message pointing at the actual cause.

Note: this specific risk is limited to the Template's own root directory. Directories created for the records that use the template (e.g. an actual project.project) are safe by comparison, since _prepare_directory_vals() always adds an auto-generated per-record group via _get_autogenerated_group() — but the Template's own directory-creation branch (res_model == "dms.field.template") does not have this safety net.

Expected behavior: either (a) creating a directory/template with no Access Group should be blocked with a clear validation error, or (b) directories with no group should fall back to some sane default visibility, so this doesn't fail completely silently.

Affected versions

18.0 (branch 18.0, tested 2026-07)

Additional context

We worked around Bugs 1 and 2 locally with a patch()-based JS override (no core files modified) adding defensive guards before every .map() call in processProps(), and an explicit res_model term in buildDMSDomain(). For Bug 4, we added group_ids = fields.Many2many(required=True) as a field-level override on dms.field.template, which is simple and doesn't touch the widget's save cycle. Bug 3 we left unresolved beyond a partial, view-only cosmetic mitigation, since a proper fix would require changes to how template structures are stored. Happy to share the patches or open a PR if useful.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions