---
title: "Build a user's authorized menu"
summary: "Loads the authorized menu for one user or the all-users snapshot."
status: draft
owner: SAIF documentation team
last_reviewed: 2026-08-17
library: SAIF.Business.Menu
reference_type: package
operation_id: OP-MENU-001
trigger: "Caller requests authorized navigation."
---

# Build a user's authorized menu

Loads the authorized menu for one user or the all-users snapshot.

| Field | Value |
| --- | --- |
| **Operation ID** | OP-MENU-001 |
| **Trigger** | Caller requests authorized navigation. |
| **Inputs** | `IDataPortalInfo`, optional `MenuUser` |
| **Outputs** | Typed `clsMenuAuthorizedItemCollection` |
| **Primary components** | `clsMenuAuthorizedItemCollection` |
| **Entry point** | `SAIF.Business.Menu\clsMenuAuthorizedItemCollection.vb` |

## Steps

1. Accept `IDataPortalInfo` and optional `MenuUser`, then choose [SQL-MENU-043](../sql/SQL-MENU-043-retrieve-authorized-menu-items-for-user.md) for a user-scoped request or [SQL-MENU-044](../sql/SQL-MENU-044-retrieve-all-authorized-menu-items.md) for the all-users snapshot.
2. Join [MENU_ITEM](../database-tables.md#menuitem), [MENU_SECURITY](../database-tables.md#menusecurity), [MENU_SECURITY_USER](../database-tables.md#menusecurityuser), [MENU_PAGE](../database-tables.md#menupage), [BUSONLINE_APPS_CODE](../database-tables.md#busonlineappscode), and [MENU_CATEGORY_CODE](../database-tables.md#menucategorycode) so only matching user/item group intersections survive ([BR-MENU-003](../business-rules.md#br-menu-003-security-group-matching-is-case-insensitive)).
3. Add the public-item branch that returns rows with no [MENU_SECURITY](../database-tables.md#menusecurity) assignment ([BR-MENU-002](../business-rules.md#br-menu-002-unsecured-menu-items-are-visible-by-default)).
4. When the query is user-scoped, union active favorites from [MENU_FAVORITE](../database-tables.md#menufavorite) ([BR-MENU-004](../business-rules.md#br-menu-004-favorites-are-always-included-and-ordered)).
5. Materialize each row into `clsMenuAuthorizedItem`, then expose filtered views such as `Favorites`, `ApplicationItems`, `AppItemsByCategory`, and `SecuredAppItems`.
6. Preserve the `UNSECURED` sentinel used by `Contains(userId, menuItem)` when the all-users snapshot is built ([BR-MENU-006](../business-rules.md#br-menu-006-retrieve-all-uses-the-unsecured-wildcard-sentinel)).

## Process flow

The following diagram visualizes this operation's control flow.

```mermaid
flowchart TD
    Start([Caller requests menu]) --> Choose{MenuUser supplied?}

    Choose -->|Yes| UserSQL["SQL-MENU-043: retrieve authorized<br/>menu items for one user"]
    UserSQL --> UserJoin["Join MENU_ITEM, MENU_SECURITY,<br/>MENU_SECURITY_USER, MENU_PAGE,<br/>BUSONLINE_APPS_CODE, MENU_CATEGORY_CODE<br/>filtered to this user's security groups<br/>(BR-MENU-003: case-insensitive match)"]
    UserJoin --> UserPublic["Include public items with<br/>no MENU_SECURITY assignment<br/>(BR-MENU-002)"]
    UserPublic --> UserFav["Union active MENU_FAVORITE rows<br/>for this user<br/>(BR-MENU-004: favorites always included)"]
    UserFav --> Materialize

    Choose -->|No| AllSQL["SQL-MENU-044: retrieve all<br/>authorized menu items (all users)"]
    AllSQL --> AllJoin["Join same tables using the<br/>UNSECURED wildcard sentinel in place<br/>of a specific user's groups<br/>(BR-MENU-006)"]
    AllJoin --> AllPublic["Include public items with<br/>no MENU_SECURITY assignment<br/>(BR-MENU-002)"]
    AllPublic --> AllNoFav["No favorites union — all-users<br/>snapshot omits MENU_FAVORITE rows"]
    AllNoFav --> Materialize

    Materialize["Materialize each row into<br/>clsMenuAuthorizedItem"] --> Views["Expose filtered views:<br/>Favorites, ApplicationItems,<br/>AppItemsByCategory, SecuredAppItems"]
    Views --> Done([Return clsMenuAuthorizedItemCollection])
```

## Failure and edge-case behavior

- Missing group matches do not throw; the collection simply omits secured rows that fail [BR-MENU-003](../business-rules.md#br-menu-003-security-group-matching-is-case-insensitive).
- Public rows remain visible through the `NOT EXISTS` branch used by [BR-MENU-002](../business-rules.md#br-menu-002-unsecured-menu-items-are-visible-by-default).
- The all-users snapshot omits favorites because [SQL-MENU-044](../sql/SQL-MENU-044-retrieve-all-authorized-menu-items.md) has no favorites union.

## Related documentation
- [Index](../index.md)
- [Overview](../overview.md)
- [Architecture](../architecture.md)
- [Dependencies](../dependencies.md)
- [Operations and processes](../operations-processes.md)
- [Business rules](../business-rules.md)
- [Security and authorization](../security-authorization.md)
- [Database tables](../database-tables.md)
- [SQL catalog](../sql/index.md)
- [API reference](../api/index.md)

## Sources
- `SAIF.Business.Menu\clsMenuAuthorizedItemCollection.vb`
