Skip to content

Authorize a user for a policy

Decides whether the current user may view a policy, applying a different authorization strategy per user type: unconditional access for internal roles, agent/agency number match, policyholder parent-affiliation match, group/chapter membership, loss-control assignment match, or auditor access-window check.

Field Value
Operation ID op-07-authorize-user
Trigger Caller invokes clsPolicySecurity.IsPolicyValidForUser(inPolicyData) (or the policy-number overload, which retrieves the policy first)
Inputs clsPolicyData (or policy number), current UserType/SecurityPrincipal
Outputs Boolean
Primary components IsPolicyValidForUser, IsPolicyValidForParentPolicy, IsInGroup, CanAuditorAccessPolicy, CanSafetyConsultantAccessPolicy
Entry point SAIF.Business.View.Policy/clsPolicySecurity.vb

Steps

  1. IsPolicyValidForUser(inPolicyData) first checks the secure-policy carve-out: if inPolicyData.SecurePolicyCode = clsConstants.SAIF and the security principal is not authorized for "SAIFpolicyInfo", access is denied immediately (BR-VP-003).
  2. If Not inPolicyData.IsValid or inPolicyData.PolicyNum = 0, access is denied immediately (BR-VP-004).
  3. Otherwise, a Select Case on UserType.UserType decides access (BR-VP-005):
  4. SaifEmployee, MCO, MedProv, Bookkeeper → access granted unconditionally.
  5. Agent → access granted if UserType.UserNumber equals inPolicyData.AgentNum or inPolicyData.Agency.AgencySeqNum.
  6. PolicyHolder → delegates entirely to IsPolicyValidForParentPolicy(inPolicyData.PolicyNum) (BR-VP-009) — a comment notes this replaced an earlier direct-number/affiliate-list check.
  7. Group → delegates to IsInGroup(inPolicyData.PolicyNum, UserType.GroupID, UserType.GroupChapterID).
  8. LossControl → looks up the LossControlConsultant team assignment on inPolicyData.TeamAssignmentCollection; if present, compares either ta.UserIdName (for DemoLossControl access level) or ta.UserName against the current user number via CanSafetyConsultantAccessPolicy (BR-VP-007, BR-VP-008).
  9. Auditor → delegates to CanAuditorAccessPolicy(inPolicyData.PolicyNum, UserType.UserNumber).
  10. IsPolicyValidForParentPolicy(inPolicyNum): if the user's own number equals the requested policy number, returns True directly; otherwise builds the set of AssociationTypes for which the logged-in user's own policy (UsersPolicyData) is a parent, and returns True if any of the user's associations of those types point at inPolicyNum.
  11. IsInGroup executes cp_policy_in_group (SQL-023) as a scalar stored-procedure query on the SQL Server (BDS) data portal, binding @groupID, @Chapters, @policyNum; returns True if the count is greater than zero.
  12. CanAuditorAccessPolicy executes an inline pa_audit/pa_auditor/pa_policy_period count query (SQL-024) on Oracle, binding the vendor number and a 60-day access window (DPI.DataSourceDate.AddDays(-60)) against both cancel date and completed date (BR-VP-006); returns True if the count is greater than zero.
  13. CanSafetyConsultantAccessPolicy strips any "%"-delimited suffix from the current user's number and checks whether the team-assignment user name, trimmed and upper-cased, starts with that prefix (BR-VP-007).
  14. The obsolete SQL-013/GetParentPolicy lookup (SQL-013) is cited by the hub catalog against this operation but its call site was found in the affiliated-policy legacy path (see Retrieve affiliated policies (legacy)), not in IsPolicyValidForParentPolicy itself.*

Process flow

flowchart TD
    Start(["Caller invokes<br>IsPolicyValidForUser"]) --> A{Secure policy and<br>not SAIFpolicyInfo authorized?}
    A -->|Yes| Deny(["Access denied"])
    A -->|No| B{Invalid or<br>zero policy num?}
    B -->|Yes| Deny
    B -->|No| C{User type?}
    C -->|SaifEmployee/MCO/MedProv/Bookkeeper| Grant(["Access granted"])
    C -->|Agent| D{Agent/agency<br>number matches?}
    D -->|Yes| Grant
    D -->|No| Deny
    C -->|PolicyHolder| E["IsPolicyValidForParentPolicy"]
    E --> F{Match found?}
    F -->|Yes| Grant
    F -->|No| Deny
    C -->|Group| G["IsInGroup:<br>cp_policy_in_group"]
    G --> Grant
    C -->|LossControl| H["Team assignment lookup +<br>CanSafetyConsultantAccessPolicy"]
    H --> Grant
    C -->|Auditor| I["CanAuditorAccessPolicy:<br>60-day audit window"]
    I --> Grant

Failure and edge-case behavior

  • No exception is thrown on denial in any branch; the method always returns Boolean, and nothing in this library logs denied-access attempts.*
  • LossControl access silently returns False (falls through with hasAccess unset/False) if no LossControlConsultant team assignment exists on the policy — indistinguishable from an explicit denial.*
  • IsInGroup relies on the BDS (SQL Server) data portal initialized in clsPolicySecurity.Initialize(); if BDS_USER, bdsDatabase, or BDS_DATABASENAME configuration is missing or wrong, Initialize() still succeeds and the failure surfaces only when IsInGroup executes.*

Note: Statements marked with * were inferred from code structure, naming conventions, or contextual evidence where direct confirmation was not available in source artifacts. Statements marked with ** could not be confirmed; treat as unknown until verified.

Sources

  • SAIF.Business.View.Policy/clsPolicySecurity.vb