mirror of
https://github.com/mattermost/mattermost.git
synced 2026-09-01 15:00:08 +08:00
017a7102f8
* Add rank property field type and migrate classification field to use it Introduces a new 'rank' property field type that behaves identically to 'select' across validation, access-control masking, options handling, and rendering. The classification markings admin panel now creates its template, system, and channel fields as 'rank' instead of 'select', with a paired DB migration to flip any existing classification rows. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * Enforce rank validation on ranked property field options For PropertyFieldTypeRank fields, every option must carry a non-negative, unique rank. Adds the Rank field to CustomProfileAttributesSelectOption and strips stray Rank values from options on non-rank field types so they cannot drift into persisted attrs. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * Materialize rank options in AttributeView and signal field updates to access control Extend the AttributeView materialized view so rank-typed property values are exposed as {"name", "rank"} objects, enabling downstream ABAC SQL and CEL machinery to compare a user's rank against a named option without baking rank integers into policy expressions. Add OnPropertyFieldOptionsChanged on the access control service interface and call it after every property field update so the service can drop any per-field metadata it caches (such as the rank-by-name map) and invalidate compiled-policy cache entries that reference the field. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Show rank-and-lower options/values for shared_only rank fields shared_only masking on a rank field previously required an exact option match, the same as select/multiselect. For rank fields the intended semantics are clearance-style: a caller sees every option and every target value at or below their own rank. filterSharedOnlyFieldOptions and filterSharedOnlyValue now branch rank fields to filterSharedOnlyRankFieldOptions / filterSharedOnlyRankValue, which compare against the caller's rank instead of intersecting option IDs. Select, multiselect, and scalar (text/date/user) masking are unchanged. A caller with no value of their own has no rank and sees nothing; the source plugin still sees everything. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * Render rank property field type like select in webapp Treat the new 'rank' custom profile attribute type as a single-select everywhere it is editable, and make it fully usable from the system console: - user_settings/general: render rank fields as a single-select dropdown (resolving option IDs to names) instead of a free-text input. - system_user_detail: resolve rank option names and render the value input as a native single-select. - user_properties_type_menu: add a selectable "Rank" field type (reusing the Select icon) so existing rank fields display correctly and admins can create new rank fields from the UI. - en.json: add the "Rank" type label string. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * Make rank cache invalidation cluster-aware and cover field deletion OnPropertyFieldOptionsChanged previously dropped the access control service's per-field rank cache only on the node handling the property field update, so peer nodes kept serving stale name->rank maps until restart. It was also wired into the update path only, leaving deleted rank fields cached indefinitely. Call OnPropertyFieldOptionsChanged from DeletePropertyField so a removed rank field's cached options are dropped too. The access control service now broadcasts the invalidation cluster-wide (see companion enterprise change). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * Backfill option ranks when migrating classification fields to rank The select->rank conversion previously only flipped the field type. On upgrades the existing classification options carry no rank (master's select option struct has no rank field, so the UI-sent rank was dropped on save), which left an invalid rank field: the matview projected null ranks, shared_only masking hid every value, and the validation hook rejected any later edit. Backfill a rank onto each option from its 1-based array position. The classification UI keeps levels in severity order and rewrites the full options array on every save, so position is the authoritative ordering; 1-based matches both the UI's `opt.rank ?? (i+1)` fallback and the presets' ranks, so a configured preset is still recognized after upgrade. The flip and backfill share one migration (one transaction), so the field is never observable in the invalid (rank, null-rank) state, and the down migration strips the rank key to restore the prior select shape. Only the three known classification fields with a non-empty options array are touched; the updates match at most three rows and add no meaningful lock footprint. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * Add System Console UI for ranked property fields Implements the admin UI for the ranked property field type across three System Console surfaces: - User Attributes: the "Ranked" attribute type, numbered value chips in ascending rank order, a per-chip popover (rename / change rank / remove), and an "Edit ranking" modal with drag-reorder, arrow steppers, numeric rank inputs, auto-assigned next rank, and inline duplicate rejection. - Membership Policy editor: ranked comparison operators (is exactly, is not, is at least, is greater than, is at most, is less than) shown for ranked attributes in place of the standard set, with CEL build/parse and default-operator wiring. - User detail: a ranked-value picker rendering options highest-rank-first with numbered badges and a checkmark on the assigned value. Adds Playwright e2e coverage for all three surfaces (plus page-object helpers) and webapp unit tests for the operator wiring and rank utilities. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * Fix enterprise CI: regenerate access-control mocks and add rank i18n key The enterprise CI lane fails on two pre-existing backend gaps on this branch: - go vet (check-style): OnPropertyFieldOptionsChanged was added to PolicyAdministrationPointInterface but the generated einterfaces mocks were never regenerated, so AccessControlServiceInterface / PolicyAdministrationPointInterface mocks no longer satisfy the interface (access_control_test.go, access_control_masking_test.go). Add the missing method to both mocks. - Check i18n: enterprise access_control/administration.go references the app.pap.rehydrate_rank.app_error key, which was never added to server/i18n/en.json. Add it so `make i18n-extract` produces a clean diff. Verified: both affected test packages compile, `make i18n-extract` yields no diff, and `make i18n-check` passes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * Retrigger enterprise CI Pick up enterprise fix 15914c11 (require.NoError in rank cel_utils tests) in the combined Enterprise CI/tests lane, which pins the enterprise SHA at mattermost-side dispatch time. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * Retrigger enterprise CI Pick up enterprise fix 48db14db (golangci-lint findings in rank access-control code) in the combined Enterprise CI/tests lane. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * Clamp shared_only rank values to the caller's rank instead of hiding For a shared_only rank field, filterSharedOnlyRankValue previously hid a target's value entirely when the target outranked the caller, returning nil. That answered "is the target at or below me?" but not the question the field exists for: "what can we talk about, and at what level?" A higher-ranked target simply disappeared. Now the value is clamped to the highest rank the caller shares with the target — the target's own value when it is at or below the caller's rank, otherwise the option at the caller's own rank. The caller always learns their shared ceiling and never sees a rank above their own. Ranks are unique per field, so the clamp target is unambiguous. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * Renumber rank migrations to 194-197 (after property_groups 193) 000193_add_property_groups_schema_version was already on master, so our rank migrations should follow it: 194-197. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Fix e2e classification helper field names after rename migration Migration 000196 renamed channel_classification → classification and system_classification → classification. Update the e2e helpers to create and clean up fields with the new canonical names so the frontend (which looks for 'classification') can find them. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Remove unused i18n key and fix e2e prettier formatting app.pap.save_policy.advanced_expression_blocked was added to en.json but never used as an AppError key in Go code — remove it so i18n-check passes. Also fix prettier formatting in ranked_operators.spec.ts. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Fix 000194 down migration: drop AttributeView before enum rebuild TestUpAndDownMigrations/Should_be_reversible_for_postgres failed because the down migration rebuilds the property_field_type enum (Postgres can't drop an enum value in place), which requires ALTER COLUMN on PropertyFields.Type. The AttributeView materialized view reads that column, so Postgres rejects the alter: "cannot alter type of a column used by a view or rule". The up path is unaffected because it uses ADD VALUE (no column rewrite); only the down rebuild trips the dependency. Mirror the canonical drop-view / alter-column / recreate-view pattern: drop AttributeView, rebuild the enum, then recreate the no-rank view (the same definition 000197's down restores, which 000177's down later replaces). Verified end-to-end against PostgreSQL 16: full up-then-down sequence now passes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * Add unit tests for rank validation and field-change signalling Fills two gaps flagged by PR test analysis: - access_control_attribute_validation_test.go: rank option validation (valid ranks persist; missing/negative/duplicate rank rejected; zero rank allowed; non-rank fields strip stray rank values). - property_field_test.go: UpdatePropertyFields/DeletePropertyField signal the access control service via OnPropertyFieldOptionsChanged for each affected field, and stay nil-safe when no AC service exists. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * Add api4 tests for rank-field permission branching Fills the API gap flagged by PR test analysis: rank fields participate in the isOptionsOnly permission branch alongside select/multiselect. - properties_test.go: an options-only PATCH on a rank field uses the narrower manage-options permission (member succeeds), while a structural PATCH (name change) requires the full edit-field permission (member forbidden, admin succeeds). - custom_profile_attributes_test.go: an options-only PATCH on a rank CPA field routes through the options path and round-trips ranks. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * Add mmctl unit tests for rank attribute resolution Fills the mmctl gap flagged by PR test analysis. Both resolution directions for rank-typed attributes were untested: - user_attributes_test.go (TestResolveDisplayValue): a stored rank option ID resolves to its option name for display; unknown IDs and option-less fields fall back to the raw value. - user_attributes_value_test.go (TestResolveOptionNamesToIDs): setting a rank value by option name resolves to the option ID; already-an-ID and unknown names pass through. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * Refine ranked attribute editing UI Edit ranking modal: - Derive ranks from row position so reordering or removing a value always keeps them contiguous (1..N) with no gaps or duplicates - Drop the arrow steppers in favor of drag-only reordering; render the drag clone through a body portal so it isn't offset by the modal dialog transform - Show values as read-only chips (lowest-first) with Lowest/Highest labels - "Add value" toggles into an inline row (fake handle + borderless field); Enter commits the value instead of closing the modal - Title shows the field name plus "Ranked attribute" Inline rank values: - Rank badge fills the left of the chip; add an inline remove (X) that reuses react-select's CrossIcon so it matches select fields Also give the rank attribute type its own SortAscendingIcon and trim a couple of stale comments. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * Fix SCSS property order lint errors Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Fix e2e rank modal tests to match drag-and-drop UX The ranked schema modal uses position-based ranks (drag to reorder) — there are no editable numeric rank inputs per row and no per-row name inputs. The two failing tests were written against an earlier design that had those inputs: - "rejects a duplicate rank inline" expected .ranked-schema-modal__rank-input and .ranked-schema-modal__error (neither exists). Replaced with a test that covers the actual duplicate-label guard on the add-value inline input. - "adds a value via the Edit ranking modal" expected .ranked-schema-modal__name-input (doesn't exist) and that save is disabled while the add input is open (it isn't — save is disabled only when rows is empty). Updated to use the real add-value flow: click "Add value", fill .ranked-schema-modal__add-input, blur to commit. Also removes the three broken page-object helpers (rankedModalRankInputs, rankedModalError, rankedModalNameInputs) whose CSS selectors never existed. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Enforce positive ranks and backfill them on select-to-rank conversion Rank values must be positive integers (>= 1), matching the webapp's isValidRank helper and rankForIndex which both require rank >= 1. The server was accepting rank = 0 (rank < 0 check), allowing invalid data that would cause filtering bugs: a caller with a rank-0 option would see nothing in a shared-only field since no option would satisfy rank <= 0. Change the guard to rank <= 0 and update the error message and tests accordingly. When converting a field from select/multiselect to rank via the type dropdown, the existing options had no ranks. The server's option validation then rejected the save (or the UI showed stale local state appearing valid). Auto-assign contiguous 1-based ranks in array order at the point of type change so the conversion is immediately valid and the user does not need to open the rank-ordering modal just to commit. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Show an inline error when a ranked option is renamed to a duplicate Renaming a ranked option to a name already used by another option was silently ignored: the draft reverted with no feedback, leaving the user unsure why their edit didn't stick. The add-value flow already warns on duplicates; the rename path now matches it. The chip popover surfaces "Values must be unique." beneath the label input while the typed name collides, and the rename stays blocked so a duplicate is never committed. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * Scroll the ranked schema list so the modal footer stays in view A ranked attribute with many values (e.g. 30) grew the edit modal taller than the viewport, pushing the Save/Cancel footer off the bottom of the screen where it couldn't be reached. Cap the value list at 50vh and scroll it internally, keeping the header and footer anchored. The list is the droppable's own scroll container, so react-beautiful-dnd auto-scrolls it while a row is being dragged, and a small right padding keeps the scrollbar clear of the remove buttons. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * Add a shared allow-list for option-bearing property field types The "is this a select/multiselect/rank field?" check was open-coded as a three-way type-negation chain in the model, both PSAv2 patch handlers, and the access-control shared-options filter. Each copy had to be kept in sync by hand as field types were added. Introduce an optionFieldTypes allow-list in the model with a PropertyFieldType.SupportsOptions() helper (mirroring the webapp's supportsOptions) and route every call site through it, so adding a future option-bearing type is a one-line change. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * Guard the rank options filter before its store lookup filterSharedOnlyRankFieldOptions built the option-rank map and ran the caller-rank store lookup before checking whether the field had a usable options array at all. A field with no options (or a malformed attrs blob) has nothing to filter, yet still paid for a database query. Move the cheap nil/shape guards to the top so an optionless field returns immediately, and reuse the extracted options slice in the filter loop instead of pulling it out of attrs a second time. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * Memoize the ranked attribute editors' event handlers The rank schema modal and the inline rank-values cell recreated every handler (drag-end, move, remove, confirm, rename, add) on each render. These are passed down to the modal footer, the drag-and-drop context, and per-chip popovers, so the fresh identities defeated memoization downstream. Wrap them in useCallback with explicit dependencies. No behavior change. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * Add tests for the classification select-to-rank migration The 000195 conversion is non-trivial: it flips specific (Name, ObjectType) fields in the access_control group from select to rank, then backfills a 1-based rank onto each option from its array position, guarding against empty or absent options arrays. Cover the behavior end to end against a real Postgres schema: the type flip with position-derived ranks in order, the empty- and absent-options guards (type flips without fabricating options), the name/object-type/group mismatches that must stay select, and the down round-trip that strips the ranks and reverts the type. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * Gate the rank property field type behind a feature flag Add a PropertyFieldRank feature flag (off by default) that gates the "rank" custom profile attribute type. The enforcement is a single app-layer gate, rankPropertyFieldGate, shared by both CreatePropertyField (blocks creating a rank field) and UpdatePropertyFields (blocks converting an existing field to rank). When the flag is off it returns app.property_field.rank_disabled.app_error. The admin console CPA type menu hides the rank option unless the flag is on, read via useGetFeatureFlagValue. Existing app/api4 tests that exercise rank fields now enable the flag in their setup so they continue to pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * Scope the rank feature-flag gate to user-object fields The PropertyFieldRank gate rejected any rank-typed field create/update when the flag was off. But classification markings now uses the rank type internally (template/system/channel object types) and ships GA behind the separate ClassificationMarkings flag, which is on by default while PropertyFieldRank is off by default. The migration also converts existing classification fields to rank unconditionally. Together this broke the classification admin panel in the default configuration: both creating new classification fields and editing existing (migrated) ones returned app.property_field.rank_disabled.app_error. Scope the gate to ObjectType == user, which is the only origin of the user-facing rank CPA type (createCPAField forces ObjectType=user). Rank fields on other object types are exempt, so classification keeps working regardless of the flag while the user-facing CPA rank type stays gated. Add regression cases proving a non-user (classification-style) rank field is creatable and convertible-to with the flag off, and enable PropertyFieldRank in the e2e default config so the user-facing rank specs pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * Update webapp/channels/src/components/admin_console/system_properties/rank_badge.scss Co-authored-by: abhijit-singh <abhijitsingh0702@gmail.com> * Enable the rank feature flag in the e2e CI server env The new rank e2e tests failed in playwright-full because the CI docker server gets feature flags from MM_FEATUREFLAGS_* env vars (config patches don't stick without a SplitKey), and PropertyFieldRank was only set in the local default_config.ts. Add the matching env var so the flag is on in CI. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * Fix stale migration-number references in classification rank down migrations The 000195 and 000196 down migrations carried comment references to their development-era numbers (000191/000192). Correct them to the current numbering (000195 reverses itself; 000196's down restores distinct names before 000195's down matches on them). Addresses review feedback from @mgdelacroix. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * Use PropertyFieldType.SupportsOptions() for option-field type checks Replace the repeated `Select || Multiselect || Rank` comparisons with the existing SupportsOptions() helper across the access-control masking, validation, and option-filtering paths, and in mmctl value resolution. Behavior is unchanged (SupportsOptions covers exactly those three types). Addresses review feedback from @mgdelacroix. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * webapp: use supportsOptions() helper for option-field type checks Replace the repeated `type === 'select' || 'multiselect' || 'rank'` checks with the existing supportsOptions() helper from @mattermost/types/properties, matching the server-side SupportsOptions() usage. Addresses review feedback from @mgdelacroix. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * Include rank in extractOptionIDsFromValue error message The function handles select, multiselect and rank, but the error message only listed select and multiselect. Addresses review feedback from @mgdelacroix. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * Validate option rank in CustomProfileAttributesSelectOption.IsValid When an option carries a rank, enforce that it is a positive integer at the model layer, mirroring the field-level option validation. Rank stays optional so select/multiselect options (which carry none) remain valid. Addresses review feedback from @mgdelacroix. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * Invalidate access-control cache before broadcasting field update In UpdatePropertyFields, move the OnPropertyFieldOptionsChanged notification above the websocket broadcast so a client reacting to the update event never re-reads stale cached field metadata. This matches the ordering already used in DeletePropertyField. Addresses review feedback from @mgdelacroix. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * Assert stored options in options-only patch permission tests The select/multiselect/rank options-only update tests only checked that the request succeeded; also assert the returned field's options (id, name, and rank for the rank case) so the tests actually verify the change was persisted. Addresses review feedback from @mgdelacroix. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * Add FeatureFlagPropertyFieldRank to webapp ClientConfig type The server-side PropertyFieldRank feature flag and user_properties_type_menu.test.tsx reference FeatureFlagPropertyFieldRank, but it was never added to the webapp ClientConfig FeatureFlags type, leaving tsc -b red. Add the missing field. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * Tighten the ranked option popover spacing Drop MUI's default 8px MuiList top/bottom padding on the per-option popover and reduce the label input's bottom padding to 4px, so the popover reads tighter without jamming the label input against the top edge. Addresses design feedback from @abhijit-singh. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * Add header and footer dividers to the Edit ranking modal Enable GenericModal's bodyDivider and footerDivider so the ranked schema modal shows a divider under the header and above the Save/Cancel footer, which also delineates the scroll area when the value list is long. Addresses design feedback from @abhijit-singh. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * Match ranked 'Add values…' affordance to select/multiselect The ranked values cell now mirrors the select/multiselect CreatableSelect cell for consistency across field types: - Tab commits a pending value (keeping focus in the input for the next one) when it's non-empty and not a duplicate, matching the select cell; a blank/duplicate input lets Tab move focus away normally. - The empty-state placeholder uses the shared 'Add values… (required)' text and matches react-select's placeholder color (full-opacity neutral50) and 10px content inset, so size, color, and left alignment line up with the select cell. - The placeholder is hidden once values exist, mirroring react-select. - The chips well gets the same hover/focus background tint and text cursor as the select control. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * Auto-size the ranked 'Add values…' input like react-select The bare <input> scrolled its overflow in a fixed-width box, while the select/multiselect cell grows its input and wraps to a new row as you type. Replicate react-select's sizer technique: wrap the input in an inline-grid whose hidden ::after mirrors the live text (content: attr(data-value), white-space: pre, font: inherit) and sizes the grid column the input fills. The input now grows with its content and, as a flex child of the values well, wraps to a new row when it no longer fits. Both the input and the sizer use 'font: inherit' (matching react-select) so the measured and rendered text line up and the font matches the select cell. Since the auto-sized input no longer spans the whole cell, a mousedown handler on the well forwards focus to the input, mirroring react-select's clickable control. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * Fix consistent-type-imports lint errors in Playwright e2e specs Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Enable PropertyFieldRank feature flag in rank e2e test setup The Rank type option in the attribute type menu is gated behind the PropertyFieldRank feature flag. initSetup resets config, so the flag must be explicitly re-enabled before the test exercises the UI selector. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Remove broken feature-flag patchConfig from rank e2e setup setupTest called patchConfig({FeatureFlags: {PropertyFieldRank: 'true'}}) with the string 'true'. PropertyFieldRank is a Go bool, so the server's patchConfig handler (which does json.Decode(&cfg) into *model.Config before any filtering) failed to unmarshal the string into a bool and returned 400 "Invalid or missing config in request body." This hard-failed setupTest and all four specs (CI run 27387310039: 4/4 failed at spec line 36). The call was both broken and unnecessary: - Without a SplitKey the config store marks FeatureFlags read-only (PlatformService.SetupFeatureFlags -> SetReadOnlyFF(!splitConfigured)), so no patchConfig can toggle a flag. The flag is enabled at the server level: the MM_FEATUREFLAGS_PROPERTYFIELDRANK env var in CI (added to e2e-tests/.ci/server.generate.sh) and the server config locally. - With the env var in place, all four specs passed at commit 8fca57bf3b; the later commit that added this line is what regressed them. Remove the call and document where the flag actually comes from. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * Locate ranked add-value input by class, not placeholder The "creates a ranked attribute" spec timed out at addRankValuesToLast waiting for getByPlaceholder('Add value…') on the inline add-value input. Commit3c12f30008("Match ranked 'Add values…' affordance to select/multiselect") changed that input in two ways the page object never caught up with: - the placeholder text became 'Add values… (required)' (plural, suffixed), so 'Add value…' no longer matches; and - the placeholder now renders only in the empty state (placeholder={showPlaceholder ? ... : undefined}), so it disappears after the first value is added — a placeholder lookup can never add 3 values. Locate the input by its stable class .user-property-rank-values__add-input instead, which is present regardless of options count or placeholder text. This is the real failure the reverted patchConfig change had misdiagnosed as a feature-flag issue. The spec passed at8fca57bf3bbecause that predates3c12f30008(placeholder was then 'Add value…' and always shown). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * Empty commit to retrigger CI after enterprise branch update Co-authored-by: Maria A Nunez <maria.nunez@mattermost.com> * Fix migration test after renumbering 000194 to 000198 During conflict resolution, migration 000194_add_type_id_index_to_access_control_policies was renumbered to 000198 to maintain sequential ordering after the new rank migrations. This commit updates the corresponding test file to match: - Renamed migration_000194_test.go to migration_000198_test.go - Updated test function name from TestMigration000194 to TestMigration000198 - Updated migration file references to point to 000198 instead of 000194 Co-authored-by: Maria A Nunez <maria.nunez@mattermost.com> * Renumber migrations: restore 000194 from master, move rank migrations to 000196-000199 The 000194_add_type_id_index_to_access_control_policies migration came from master and should keep its original number. Our rank migrations have been renumbered: - 000194 -> 000196: add_rank_to_property_field_type - 000195 -> 000197: convert_classification_fields_to_rank - 000196 -> 000198: rename_classification_linked_fields - 000197 -> 000199: add_rank_to_attribute_view This leaves 000195 available for the threadmemberships_cleanup_v2 migration from master. Co-authored-by: Maria A Nunez <maria.nunez@mattermost.com> * Rename migration test files to match renumbered migrations After renumbering rank migrations from 000194-000197 to 000196-000199, the test file migration_000195_test.go (which tests the classification->rank conversion) needed to be renamed to migration_000197_test.go to match the new migration number. Updated the test function name and migration file references accordingly. Co-authored-by: Maria A Nunez <maria.nunez@mattermost.com> * Filter policy field autocomplete to user-type fields only Add ObjectType: user filter to GetAccessControlFieldsAutocomplete so the attribute picker in the Membership Policies editor no longer surfaces template, system, and channel classification-marking fields as ghost entries alongside real user CPAs. MM-69366 Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> Co-authored-by: abhijit-singh <abhijitsingh0702@gmail.com> Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Maria A Nunez <maria.nunez@mattermost.com> Co-authored-by: Mattermost Build <build@mattermost.com>
621 lines
19 KiB
Go
621 lines
19 KiB
Go
// Code generated by mockery v2.53.4. DO NOT EDIT.
|
|
|
|
// Regenerate this file using `make einterfaces-mocks`.
|
|
|
|
package mocks
|
|
|
|
import (
|
|
model "github.com/mattermost/mattermost/server/public/model"
|
|
request "github.com/mattermost/mattermost/server/public/shared/request"
|
|
mock "github.com/stretchr/testify/mock"
|
|
)
|
|
|
|
// AccessControlServiceInterface is an autogenerated mock type for the AccessControlServiceInterface type
|
|
type AccessControlServiceInterface struct {
|
|
mock.Mock
|
|
}
|
|
|
|
// AccessEvaluation provides a mock function with given fields: rctx, accessRequest
|
|
func (_m *AccessControlServiceInterface) AccessEvaluation(rctx request.CTX, accessRequest model.AccessRequest) (model.AccessDecision, *model.AppError) {
|
|
ret := _m.Called(rctx, accessRequest)
|
|
|
|
if len(ret) == 0 {
|
|
panic("no return value specified for AccessEvaluation")
|
|
}
|
|
|
|
var r0 model.AccessDecision
|
|
var r1 *model.AppError
|
|
if rf, ok := ret.Get(0).(func(request.CTX, model.AccessRequest) (model.AccessDecision, *model.AppError)); ok {
|
|
return rf(rctx, accessRequest)
|
|
}
|
|
if rf, ok := ret.Get(0).(func(request.CTX, model.AccessRequest) model.AccessDecision); ok {
|
|
r0 = rf(rctx, accessRequest)
|
|
} else {
|
|
r0 = ret.Get(0).(model.AccessDecision)
|
|
}
|
|
|
|
if rf, ok := ret.Get(1).(func(request.CTX, model.AccessRequest) *model.AppError); ok {
|
|
r1 = rf(rctx, accessRequest)
|
|
} else {
|
|
if ret.Get(1) != nil {
|
|
r1 = ret.Get(1).(*model.AppError)
|
|
}
|
|
}
|
|
|
|
return r0, r1
|
|
}
|
|
|
|
// CheckExpression provides a mock function with given fields: rctx, expression
|
|
func (_m *AccessControlServiceInterface) CheckExpression(rctx request.CTX, expression string) ([]model.CELExpressionError, *model.AppError) {
|
|
ret := _m.Called(rctx, expression)
|
|
|
|
if len(ret) == 0 {
|
|
panic("no return value specified for CheckExpression")
|
|
}
|
|
|
|
var r0 []model.CELExpressionError
|
|
var r1 *model.AppError
|
|
if rf, ok := ret.Get(0).(func(request.CTX, string) ([]model.CELExpressionError, *model.AppError)); ok {
|
|
return rf(rctx, expression)
|
|
}
|
|
if rf, ok := ret.Get(0).(func(request.CTX, string) []model.CELExpressionError); ok {
|
|
r0 = rf(rctx, expression)
|
|
} else {
|
|
if ret.Get(0) != nil {
|
|
r0 = ret.Get(0).([]model.CELExpressionError)
|
|
}
|
|
}
|
|
|
|
if rf, ok := ret.Get(1).(func(request.CTX, string) *model.AppError); ok {
|
|
r1 = rf(rctx, expression)
|
|
} else {
|
|
if ret.Get(1) != nil {
|
|
r1 = ret.Get(1).(*model.AppError)
|
|
}
|
|
}
|
|
|
|
return r0, r1
|
|
}
|
|
|
|
// DeletePolicy provides a mock function with given fields: rctx, id
|
|
func (_m *AccessControlServiceInterface) DeletePolicy(rctx request.CTX, id string) *model.AppError {
|
|
ret := _m.Called(rctx, id)
|
|
|
|
if len(ret) == 0 {
|
|
panic("no return value specified for DeletePolicy")
|
|
}
|
|
|
|
var r0 *model.AppError
|
|
if rf, ok := ret.Get(0).(func(request.CTX, string) *model.AppError); ok {
|
|
r0 = rf(rctx, id)
|
|
} else {
|
|
if ret.Get(0) != nil {
|
|
r0 = ret.Get(0).(*model.AppError)
|
|
}
|
|
}
|
|
|
|
return r0
|
|
}
|
|
|
|
// ExpressionToVisualAST provides a mock function with given fields: rctx, expression
|
|
func (_m *AccessControlServiceInterface) ExpressionToVisualAST(rctx request.CTX, expression string) (*model.VisualExpression, *model.AppError) {
|
|
ret := _m.Called(rctx, expression)
|
|
|
|
if len(ret) == 0 {
|
|
panic("no return value specified for ExpressionToVisualAST")
|
|
}
|
|
|
|
var r0 *model.VisualExpression
|
|
var r1 *model.AppError
|
|
if rf, ok := ret.Get(0).(func(request.CTX, string) (*model.VisualExpression, *model.AppError)); ok {
|
|
return rf(rctx, expression)
|
|
}
|
|
if rf, ok := ret.Get(0).(func(request.CTX, string) *model.VisualExpression); ok {
|
|
r0 = rf(rctx, expression)
|
|
} else {
|
|
if ret.Get(0) != nil {
|
|
r0 = ret.Get(0).(*model.VisualExpression)
|
|
}
|
|
}
|
|
|
|
if rf, ok := ret.Get(1).(func(request.CTX, string) *model.AppError); ok {
|
|
r1 = rf(rctx, expression)
|
|
} else {
|
|
if ret.Get(1) != nil {
|
|
r1 = ret.Get(1).(*model.AppError)
|
|
}
|
|
}
|
|
|
|
return r0, r1
|
|
}
|
|
|
|
// GetChannelMembersToRemove provides a mock function with given fields: rctx, channelID
|
|
func (_m *AccessControlServiceInterface) GetChannelMembersToRemove(rctx request.CTX, channelID string) ([]*model.ChannelMember, *model.AppError) {
|
|
ret := _m.Called(rctx, channelID)
|
|
|
|
if len(ret) == 0 {
|
|
panic("no return value specified for GetChannelMembersToRemove")
|
|
}
|
|
|
|
var r0 []*model.ChannelMember
|
|
var r1 *model.AppError
|
|
if rf, ok := ret.Get(0).(func(request.CTX, string) ([]*model.ChannelMember, *model.AppError)); ok {
|
|
return rf(rctx, channelID)
|
|
}
|
|
if rf, ok := ret.Get(0).(func(request.CTX, string) []*model.ChannelMember); ok {
|
|
r0 = rf(rctx, channelID)
|
|
} else {
|
|
if ret.Get(0) != nil {
|
|
r0 = ret.Get(0).([]*model.ChannelMember)
|
|
}
|
|
}
|
|
|
|
if rf, ok := ret.Get(1).(func(request.CTX, string) *model.AppError); ok {
|
|
r1 = rf(rctx, channelID)
|
|
} else {
|
|
if ret.Get(1) != nil {
|
|
r1 = ret.Get(1).(*model.AppError)
|
|
}
|
|
}
|
|
|
|
return r0, r1
|
|
}
|
|
|
|
// GetPoliciesForFieldIDs provides a mock function with given fields: rctx, fieldIDs
|
|
func (_m *AccessControlServiceInterface) GetPoliciesForFieldIDs(rctx request.CTX, fieldIDs []string) ([]*model.AccessControlPolicy, *model.AppError) {
|
|
ret := _m.Called(rctx, fieldIDs)
|
|
|
|
if len(ret) == 0 {
|
|
panic("no return value specified for GetPoliciesForFieldIDs")
|
|
}
|
|
|
|
var r0 []*model.AccessControlPolicy
|
|
var r1 *model.AppError
|
|
if rf, ok := ret.Get(0).(func(request.CTX, []string) ([]*model.AccessControlPolicy, *model.AppError)); ok {
|
|
return rf(rctx, fieldIDs)
|
|
}
|
|
if rf, ok := ret.Get(0).(func(request.CTX, []string) []*model.AccessControlPolicy); ok {
|
|
r0 = rf(rctx, fieldIDs)
|
|
} else {
|
|
if ret.Get(0) != nil {
|
|
r0 = ret.Get(0).([]*model.AccessControlPolicy)
|
|
}
|
|
}
|
|
|
|
if rf, ok := ret.Get(1).(func(request.CTX, []string) *model.AppError); ok {
|
|
r1 = rf(rctx, fieldIDs)
|
|
} else {
|
|
if ret.Get(1) != nil {
|
|
r1 = ret.Get(1).(*model.AppError)
|
|
}
|
|
}
|
|
|
|
return r0, r1
|
|
}
|
|
|
|
// GetPolicy provides a mock function with given fields: rctx, id
|
|
func (_m *AccessControlServiceInterface) GetPolicy(rctx request.CTX, id string) (*model.AccessControlPolicy, *model.AppError) {
|
|
ret := _m.Called(rctx, id)
|
|
|
|
if len(ret) == 0 {
|
|
panic("no return value specified for GetPolicy")
|
|
}
|
|
|
|
var r0 *model.AccessControlPolicy
|
|
var r1 *model.AppError
|
|
if rf, ok := ret.Get(0).(func(request.CTX, string) (*model.AccessControlPolicy, *model.AppError)); ok {
|
|
return rf(rctx, id)
|
|
}
|
|
if rf, ok := ret.Get(0).(func(request.CTX, string) *model.AccessControlPolicy); ok {
|
|
r0 = rf(rctx, id)
|
|
} else {
|
|
if ret.Get(0) != nil {
|
|
r0 = ret.Get(0).(*model.AccessControlPolicy)
|
|
}
|
|
}
|
|
|
|
if rf, ok := ret.Get(1).(func(request.CTX, string) *model.AppError); ok {
|
|
r1 = rf(rctx, id)
|
|
} else {
|
|
if ret.Get(1) != nil {
|
|
r1 = ret.Get(1).(*model.AppError)
|
|
}
|
|
}
|
|
|
|
return r0, r1
|
|
}
|
|
|
|
// GetPolicyRuleAttributes provides a mock function with given fields: rctx, policyID, action
|
|
func (_m *AccessControlServiceInterface) GetPolicyRuleAttributes(rctx request.CTX, policyID string, action string) (map[string][]string, *model.AppError) {
|
|
ret := _m.Called(rctx, policyID, action)
|
|
|
|
if len(ret) == 0 {
|
|
panic("no return value specified for GetPolicyRuleAttributes")
|
|
}
|
|
|
|
var r0 map[string][]string
|
|
var r1 *model.AppError
|
|
if rf, ok := ret.Get(0).(func(request.CTX, string, string) (map[string][]string, *model.AppError)); ok {
|
|
return rf(rctx, policyID, action)
|
|
}
|
|
if rf, ok := ret.Get(0).(func(request.CTX, string, string) map[string][]string); ok {
|
|
r0 = rf(rctx, policyID, action)
|
|
} else {
|
|
if ret.Get(0) != nil {
|
|
r0 = ret.Get(0).(map[string][]string)
|
|
}
|
|
}
|
|
|
|
if rf, ok := ret.Get(1).(func(request.CTX, string, string) *model.AppError); ok {
|
|
r1 = rf(rctx, policyID, action)
|
|
} else {
|
|
if ret.Get(1) != nil {
|
|
r1 = ret.Get(1).(*model.AppError)
|
|
}
|
|
}
|
|
|
|
return r0, r1
|
|
}
|
|
|
|
// GetTeamMembersToRemove provides a mock function with given fields: rctx, teamID
|
|
func (_m *AccessControlServiceInterface) GetTeamMembersToRemove(rctx request.CTX, teamID string) ([]*model.TeamMember, *model.AppError) {
|
|
ret := _m.Called(rctx, teamID)
|
|
|
|
if len(ret) == 0 {
|
|
panic("no return value specified for GetTeamMembersToRemove")
|
|
}
|
|
|
|
var r0 []*model.TeamMember
|
|
var r1 *model.AppError
|
|
if rf, ok := ret.Get(0).(func(request.CTX, string) ([]*model.TeamMember, *model.AppError)); ok {
|
|
return rf(rctx, teamID)
|
|
}
|
|
if rf, ok := ret.Get(0).(func(request.CTX, string) []*model.TeamMember); ok {
|
|
r0 = rf(rctx, teamID)
|
|
} else {
|
|
if ret.Get(0) != nil {
|
|
r0 = ret.Get(0).([]*model.TeamMember)
|
|
}
|
|
}
|
|
|
|
if rf, ok := ret.Get(1).(func(request.CTX, string) *model.AppError); ok {
|
|
r1 = rf(rctx, teamID)
|
|
} else {
|
|
if ret.Get(1) != nil {
|
|
r1 = ret.Get(1).(*model.AppError)
|
|
}
|
|
}
|
|
|
|
return r0, r1
|
|
}
|
|
|
|
// HasMaskedValuesForCaller provides a mock function with given fields: rctx, expression, resolver
|
|
func (_m *AccessControlServiceInterface) HasMaskedValuesForCaller(rctx request.CTX, expression string, resolver model.MaskingFieldResolver) (bool, *model.AppError) {
|
|
ret := _m.Called(rctx, expression, resolver)
|
|
|
|
if len(ret) == 0 {
|
|
panic("no return value specified for HasMaskedValuesForCaller")
|
|
}
|
|
|
|
var r0 bool
|
|
var r1 *model.AppError
|
|
if rf, ok := ret.Get(0).(func(request.CTX, string, model.MaskingFieldResolver) (bool, *model.AppError)); ok {
|
|
return rf(rctx, expression, resolver)
|
|
}
|
|
if rf, ok := ret.Get(0).(func(request.CTX, string, model.MaskingFieldResolver) bool); ok {
|
|
r0 = rf(rctx, expression, resolver)
|
|
} else {
|
|
r0 = ret.Get(0).(bool)
|
|
}
|
|
|
|
if rf, ok := ret.Get(1).(func(request.CTX, string, model.MaskingFieldResolver) *model.AppError); ok {
|
|
r1 = rf(rctx, expression, resolver)
|
|
} else {
|
|
if ret.Get(1) != nil {
|
|
r1 = ret.Get(1).(*model.AppError)
|
|
}
|
|
}
|
|
|
|
return r0, r1
|
|
}
|
|
|
|
// Init provides a mock function with given fields: rctx
|
|
func (_m *AccessControlServiceInterface) Init(rctx request.CTX) *model.AppError {
|
|
ret := _m.Called(rctx)
|
|
|
|
if len(ret) == 0 {
|
|
panic("no return value specified for Init")
|
|
}
|
|
|
|
var r0 *model.AppError
|
|
if rf, ok := ret.Get(0).(func(request.CTX) *model.AppError); ok {
|
|
r0 = rf(rctx)
|
|
} else {
|
|
if ret.Get(0) != nil {
|
|
r0 = ret.Get(0).(*model.AppError)
|
|
}
|
|
}
|
|
|
|
return r0
|
|
}
|
|
|
|
// MaskExpressionForCaller provides a mock function with given fields: rctx, expression, resolver
|
|
func (_m *AccessControlServiceInterface) MaskExpressionForCaller(rctx request.CTX, expression string, resolver model.MaskingFieldResolver) (string, bool, *model.AppError) {
|
|
ret := _m.Called(rctx, expression, resolver)
|
|
|
|
if len(ret) == 0 {
|
|
panic("no return value specified for MaskExpressionForCaller")
|
|
}
|
|
|
|
var r0 string
|
|
var r1 bool
|
|
var r2 *model.AppError
|
|
if rf, ok := ret.Get(0).(func(request.CTX, string, model.MaskingFieldResolver) (string, bool, *model.AppError)); ok {
|
|
return rf(rctx, expression, resolver)
|
|
}
|
|
if rf, ok := ret.Get(0).(func(request.CTX, string, model.MaskingFieldResolver) string); ok {
|
|
r0 = rf(rctx, expression, resolver)
|
|
} else {
|
|
r0 = ret.Get(0).(string)
|
|
}
|
|
|
|
if rf, ok := ret.Get(1).(func(request.CTX, string, model.MaskingFieldResolver) bool); ok {
|
|
r1 = rf(rctx, expression, resolver)
|
|
} else {
|
|
r1 = ret.Get(1).(bool)
|
|
}
|
|
|
|
if rf, ok := ret.Get(2).(func(request.CTX, string, model.MaskingFieldResolver) *model.AppError); ok {
|
|
r2 = rf(rctx, expression, resolver)
|
|
} else {
|
|
if ret.Get(2) != nil {
|
|
r2 = ret.Get(2).(*model.AppError)
|
|
}
|
|
}
|
|
|
|
return r0, r1, r2
|
|
}
|
|
|
|
// MergeExpressionWithMaskedValuesCanonical provides a mock function with given fields: rctx, submittedExpr, storedExpr, resolver
|
|
func (_m *AccessControlServiceInterface) MergeExpressionWithMaskedValuesCanonical(rctx request.CTX, submittedExpr string, storedExpr string, resolver model.MaskingFieldResolver) (string, *model.AppError) {
|
|
ret := _m.Called(rctx, submittedExpr, storedExpr, resolver)
|
|
|
|
if len(ret) == 0 {
|
|
panic("no return value specified for MergeExpressionWithMaskedValuesCanonical")
|
|
}
|
|
|
|
var r0 string
|
|
var r1 *model.AppError
|
|
if rf, ok := ret.Get(0).(func(request.CTX, string, string, model.MaskingFieldResolver) (string, *model.AppError)); ok {
|
|
return rf(rctx, submittedExpr, storedExpr, resolver)
|
|
}
|
|
if rf, ok := ret.Get(0).(func(request.CTX, string, string, model.MaskingFieldResolver) string); ok {
|
|
r0 = rf(rctx, submittedExpr, storedExpr, resolver)
|
|
} else {
|
|
r0 = ret.Get(0).(string)
|
|
}
|
|
|
|
if rf, ok := ret.Get(1).(func(request.CTX, string, string, model.MaskingFieldResolver) *model.AppError); ok {
|
|
r1 = rf(rctx, submittedExpr, storedExpr, resolver)
|
|
} else {
|
|
if ret.Get(1) != nil {
|
|
r1 = ret.Get(1).(*model.AppError)
|
|
}
|
|
}
|
|
|
|
return r0, r1
|
|
}
|
|
|
|
// NormalizePolicy provides a mock function with given fields: rctx, policy
|
|
func (_m *AccessControlServiceInterface) NormalizePolicy(rctx request.CTX, policy *model.AccessControlPolicy) (*model.AccessControlPolicy, *model.AppError) {
|
|
ret := _m.Called(rctx, policy)
|
|
|
|
if len(ret) == 0 {
|
|
panic("no return value specified for NormalizePolicy")
|
|
}
|
|
|
|
var r0 *model.AccessControlPolicy
|
|
var r1 *model.AppError
|
|
if rf, ok := ret.Get(0).(func(request.CTX, *model.AccessControlPolicy) (*model.AccessControlPolicy, *model.AppError)); ok {
|
|
return rf(rctx, policy)
|
|
}
|
|
if rf, ok := ret.Get(0).(func(request.CTX, *model.AccessControlPolicy) *model.AccessControlPolicy); ok {
|
|
r0 = rf(rctx, policy)
|
|
} else {
|
|
if ret.Get(0) != nil {
|
|
r0 = ret.Get(0).(*model.AccessControlPolicy)
|
|
}
|
|
}
|
|
|
|
if rf, ok := ret.Get(1).(func(request.CTX, *model.AccessControlPolicy) *model.AppError); ok {
|
|
r1 = rf(rctx, policy)
|
|
} else {
|
|
if ret.Get(1) != nil {
|
|
r1 = ret.Get(1).(*model.AppError)
|
|
}
|
|
}
|
|
|
|
return r0, r1
|
|
}
|
|
|
|
// OnPropertyFieldOptionsChanged provides a mock function with given fields: rctx, fieldID
|
|
func (_m *AccessControlServiceInterface) OnPropertyFieldOptionsChanged(rctx request.CTX, fieldID string) {
|
|
_m.Called(rctx, fieldID)
|
|
}
|
|
|
|
// QueryUsersForExpression provides a mock function with given fields: rctx, expression, opts
|
|
func (_m *AccessControlServiceInterface) QueryUsersForExpression(rctx request.CTX, expression string, opts model.SubjectSearchOptions) ([]*model.User, int64, *model.AppError) {
|
|
ret := _m.Called(rctx, expression, opts)
|
|
|
|
if len(ret) == 0 {
|
|
panic("no return value specified for QueryUsersForExpression")
|
|
}
|
|
|
|
var r0 []*model.User
|
|
var r1 int64
|
|
var r2 *model.AppError
|
|
if rf, ok := ret.Get(0).(func(request.CTX, string, model.SubjectSearchOptions) ([]*model.User, int64, *model.AppError)); ok {
|
|
return rf(rctx, expression, opts)
|
|
}
|
|
if rf, ok := ret.Get(0).(func(request.CTX, string, model.SubjectSearchOptions) []*model.User); ok {
|
|
r0 = rf(rctx, expression, opts)
|
|
} else {
|
|
if ret.Get(0) != nil {
|
|
r0 = ret.Get(0).([]*model.User)
|
|
}
|
|
}
|
|
|
|
if rf, ok := ret.Get(1).(func(request.CTX, string, model.SubjectSearchOptions) int64); ok {
|
|
r1 = rf(rctx, expression, opts)
|
|
} else {
|
|
r1 = ret.Get(1).(int64)
|
|
}
|
|
|
|
if rf, ok := ret.Get(2).(func(request.CTX, string, model.SubjectSearchOptions) *model.AppError); ok {
|
|
r2 = rf(rctx, expression, opts)
|
|
} else {
|
|
if ret.Get(2) != nil {
|
|
r2 = ret.Get(2).(*model.AppError)
|
|
}
|
|
}
|
|
|
|
return r0, r1, r2
|
|
}
|
|
|
|
// QueryUsersForResource provides a mock function with given fields: rctx, resourceID, action, opts
|
|
func (_m *AccessControlServiceInterface) QueryUsersForResource(rctx request.CTX, resourceID string, action string, opts model.SubjectSearchOptions) ([]*model.User, int64, *model.AppError) {
|
|
ret := _m.Called(rctx, resourceID, action, opts)
|
|
|
|
if len(ret) == 0 {
|
|
panic("no return value specified for QueryUsersForResource")
|
|
}
|
|
|
|
var r0 []*model.User
|
|
var r1 int64
|
|
var r2 *model.AppError
|
|
if rf, ok := ret.Get(0).(func(request.CTX, string, string, model.SubjectSearchOptions) ([]*model.User, int64, *model.AppError)); ok {
|
|
return rf(rctx, resourceID, action, opts)
|
|
}
|
|
if rf, ok := ret.Get(0).(func(request.CTX, string, string, model.SubjectSearchOptions) []*model.User); ok {
|
|
r0 = rf(rctx, resourceID, action, opts)
|
|
} else {
|
|
if ret.Get(0) != nil {
|
|
r0 = ret.Get(0).([]*model.User)
|
|
}
|
|
}
|
|
|
|
if rf, ok := ret.Get(1).(func(request.CTX, string, string, model.SubjectSearchOptions) int64); ok {
|
|
r1 = rf(rctx, resourceID, action, opts)
|
|
} else {
|
|
r1 = ret.Get(1).(int64)
|
|
}
|
|
|
|
if rf, ok := ret.Get(2).(func(request.CTX, string, string, model.SubjectSearchOptions) *model.AppError); ok {
|
|
r2 = rf(rctx, resourceID, action, opts)
|
|
} else {
|
|
if ret.Get(2) != nil {
|
|
r2 = ret.Get(2).(*model.AppError)
|
|
}
|
|
}
|
|
|
|
return r0, r1, r2
|
|
}
|
|
|
|
// SavePolicy provides a mock function with given fields: rctx, policy
|
|
func (_m *AccessControlServiceInterface) SavePolicy(rctx request.CTX, policy *model.AccessControlPolicy) (*model.AccessControlPolicy, *model.AppError) {
|
|
ret := _m.Called(rctx, policy)
|
|
|
|
if len(ret) == 0 {
|
|
panic("no return value specified for SavePolicy")
|
|
}
|
|
|
|
var r0 *model.AccessControlPolicy
|
|
var r1 *model.AppError
|
|
if rf, ok := ret.Get(0).(func(request.CTX, *model.AccessControlPolicy) (*model.AccessControlPolicy, *model.AppError)); ok {
|
|
return rf(rctx, policy)
|
|
}
|
|
if rf, ok := ret.Get(0).(func(request.CTX, *model.AccessControlPolicy) *model.AccessControlPolicy); ok {
|
|
r0 = rf(rctx, policy)
|
|
} else {
|
|
if ret.Get(0) != nil {
|
|
r0 = ret.Get(0).(*model.AccessControlPolicy)
|
|
}
|
|
}
|
|
|
|
if rf, ok := ret.Get(1).(func(request.CTX, *model.AccessControlPolicy) *model.AppError); ok {
|
|
r1 = rf(rctx, policy)
|
|
} else {
|
|
if ret.Get(1) != nil {
|
|
r1 = ret.Get(1).(*model.AppError)
|
|
}
|
|
}
|
|
|
|
return r0, r1
|
|
}
|
|
|
|
// SimulatePolicyForUsers provides a mock function with given fields: rctx, params
|
|
func (_m *AccessControlServiceInterface) SimulatePolicyForUsers(rctx request.CTX, params model.PolicySimulationByUsersParams) (*model.PolicySimulationResponse, *model.AppError) {
|
|
ret := _m.Called(rctx, params)
|
|
|
|
if len(ret) == 0 {
|
|
panic("no return value specified for SimulatePolicyForUsers")
|
|
}
|
|
|
|
var r0 *model.PolicySimulationResponse
|
|
var r1 *model.AppError
|
|
if rf, ok := ret.Get(0).(func(request.CTX, model.PolicySimulationByUsersParams) (*model.PolicySimulationResponse, *model.AppError)); ok {
|
|
return rf(rctx, params)
|
|
}
|
|
if rf, ok := ret.Get(0).(func(request.CTX, model.PolicySimulationByUsersParams) *model.PolicySimulationResponse); ok {
|
|
r0 = rf(rctx, params)
|
|
} else {
|
|
if ret.Get(0) != nil {
|
|
r0 = ret.Get(0).(*model.PolicySimulationResponse)
|
|
}
|
|
}
|
|
|
|
if rf, ok := ret.Get(1).(func(request.CTX, model.PolicySimulationByUsersParams) *model.AppError); ok {
|
|
r1 = rf(rctx, params)
|
|
} else {
|
|
if ret.Get(1) != nil {
|
|
r1 = ret.Get(1).(*model.AppError)
|
|
}
|
|
}
|
|
|
|
return r0, r1
|
|
}
|
|
|
|
// ValidateExpressionValuesForCaller provides a mock function with given fields: rctx, expression, resolver
|
|
func (_m *AccessControlServiceInterface) ValidateExpressionValuesForCaller(rctx request.CTX, expression string, resolver model.MaskingFieldResolver) *model.AppError {
|
|
ret := _m.Called(rctx, expression, resolver)
|
|
|
|
if len(ret) == 0 {
|
|
panic("no return value specified for ValidateExpressionValuesForCaller")
|
|
}
|
|
|
|
var r0 *model.AppError
|
|
if rf, ok := ret.Get(0).(func(request.CTX, string, model.MaskingFieldResolver) *model.AppError); ok {
|
|
r0 = rf(rctx, expression, resolver)
|
|
} else {
|
|
if ret.Get(0) != nil {
|
|
r0 = ret.Get(0).(*model.AppError)
|
|
}
|
|
}
|
|
|
|
return r0
|
|
}
|
|
|
|
// NewAccessControlServiceInterface creates a new instance of AccessControlServiceInterface. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
|
// The first argument is typically a *testing.T value.
|
|
func NewAccessControlServiceInterface(t interface {
|
|
mock.TestingT
|
|
Cleanup(func())
|
|
}) *AccessControlServiceInterface {
|
|
mock := &AccessControlServiceInterface{}
|
|
mock.Mock.Test(t)
|
|
|
|
t.Cleanup(func() { mock.AssertExpectations(t) })
|
|
|
|
return mock
|
|
}
|