Operations and processes¶
clsADUserServices implements 19 processes, one per published WebMethod, with no dispatcher or handler class between the SOAP entry point and the process logic — every operation calls its own process directly. Eight processes are gated by the network-origin allow-list documented in Authentication and authorization; the other eleven are directory reads and oracles with no application-layer gate. All processing is against Active Directory; there is no database and no process-wide shared state (see Architecture).
This page is the process catalog and hub. Each process's detailed, step-by-step logic lives in its own page under operations/.
Process catalog¶
| ID | Process | Entry operation | Trigger | Owning component | Rules |
|---|---|---|---|---|---|
| OP-01 | Hello World greeting | HelloWorld |
Any SOAP call | clsADUserServices.HelloWorld |
— |
| OP-02 | Create AD account | AddUser |
Caller requests account creation | clsADUserServices.AddUser |
BR-01, BR-05, BR-07–BR-13, BR-34 |
| OP-03 | Unlock AD account | UnlockAccount |
Caller requests unlock | clsADUserServices.UnlockAccount |
BR-01, BR-14, BR-15 |
| OP-04 | Grant group membership | AddUserToGroup |
Caller requests membership grant | clsADUserServices.AddUserToGroup |
BR-01, BR-16, BR-17, BR-33 |
| OP-05 | Delete AD account | DeleteUser |
Caller requests deletion | clsADUserServices.DeleteUser |
BR-01, BR-18 |
| OP-06 | Revoke group membership | DeleteUserFromGroup |
Caller requests membership revocation | clsADUserServices.DeleteUserFromGroup |
BR-01, BR-19, BR-20 |
| OP-07 | Test account existence | DoesUserExist |
Caller queries existence | clsADUserServices.DoesUserExist |
BR-06, BR-21 |
| OP-08 | Test transitive resource membership | DoesUserHaveResource |
Caller queries resource membership | clsADUserServices.DoesUserHaveResource |
BR-06, BR-22 |
| OP-09 | Update account attributes | ChangeUserAccount |
Caller requests an attribute change | clsADUserServices.ChangeUserAccount |
BR-01, BR-13, BR-23, BR-24 |
| OP-10 | Reset password (sentinel on failure) | ChangeUserPassword |
Caller requests a password reset | clsADUserServices.ChangeUserPassword |
BR-01, BR-25, BR-26 |
| OP-11 | Reset password (faulting variant) | ChangeUserPasswordOrGetException |
Caller requests a password reset and wants failures as faults | clsADUserServices.ChangeUserPasswordOrGetException |
BR-01, BR-25, BR-26 |
| OP-12 | Read email attribute | GetUserEmail |
Caller queries email | clsADUserServices.GetUserEmail |
BR-06, BR-27 |
| OP-13 | Read all group names | GetUserGroups |
Caller queries group membership | clsADUserServices.GetUserGroups |
BR-06, BR-28 |
| OP-14 | Read filtered resource group names | GetUserResources |
Caller queries resource entitlements | clsADUserServices.GetUserResources |
BR-06, BR-29 |
| OP-15 | Read fax attribute | GetUserFAX |
Caller queries fax number | clsADUserServices.GetUserFAX |
BR-06, BR-27 |
| OP-16 | Read last-logon timestamp | GetUserLastLogon |
Caller queries last logon | clsADUserServices.GetUserLastLogon |
BR-06, BR-30 |
| OP-17 | Read printer attribute (internal domain only) | GetUserPrinter |
Caller queries printer assignment | clsADUserServices.GetUserPrinter |
BR-06, BR-31 |
| OP-18 | Test direct group membership | IsUserInGroup |
Caller queries direct membership | clsADUserServices.IsUserInGroup |
BR-06, BR-32, BR-33 |
| OP-19 | Evaluate allow-list decision | CheckAccess |
Any SOAP call to CheckAccess, or internally from each of the eight gated operations |
clsADUserServices.CheckAccess |
BR-02–BR-04, BR-06 |
Cross-process flow diagram¶
The diagram below traces how a caller's operation request is routed through the OP-19 CheckAccess gate to either a mutating process or a read process, both of which operate against Active Directory.
flowchart TD
Caller["SOAP caller"] --> Gate{"Gated operation?<br>OP-02 OP-03 OP-04 OP-05<br>OP-06 OP-09 OP-10 OP-11"}
Gate -->|"Yes"| CheckAccess["OP-19 CheckAccess<br>local request or IP allow-list"]
CheckAccess -->|"Denied"| Denied["AccessDenied sentinel<br>Response = Failure"]
CheckAccess -->|"Approved"| Mutate["Execute mutating process<br>against external.saif.com"]
Gate -->|"No — read operation<br>OP-01 OP-07 OP-08 OP-12-18"| Read["Execute read process<br>against caller-selected domain"]
Mutate --> AD["Active Directory"]
Read --> AD
AD --> Response["ADServiceResponse / Boolean / ArrayList<br>returned to caller"]
Denied --> Response
Failure and edge-case behavior¶
- Access denied (OP-02–OP-06, OP-09–OP-11): caller receives
ADServiceResponse{Response=Failure, Message="Access Denied"}as a normal SOAP response, never a fault — see Faults and error pipeline. - Allow-list setting missing or environment service unreachable (any gated operation, via OP-19): the unhandled exception propagates as a framework SOAP fault out of the calling operation instead of returning
AccessDenied— see Tech debt TD-12. - User not found (most operations): reported as
UserDoesNotExist,False, or an empty list depending on the operation's return shape — the same signal a genuine directory failure produces via BR-34, so "not found" and "directory unreachable" are indistinguishable to the caller. - Group removal or resource lookup failure (OP-06, OP-08):
DeleteUserFromGroup's catch block deliberately swallows any exception and reportsSuccess(TD-20);DoesUserHaveResourcehas noTry/Catchat all and a directory failure surfaces as a framework SOAP fault. - No transactional rollback across two-stage writes (OP-02
AddUser, OP-09ChangeUserAccount): neither process opens a database transaction — there is no database — and each ofuserPrin.Save()/principal-levelSave()anddirEntry.CommitChanges()/directory-levelCommitChanges()commits independently, with no enclosing transaction and no rollback trigger; a failure between the two stages leaves the object partially applied in Active Directory, a tech-debt finding rather than a documented recovery mechanism (TD-18). - Partial write on exception (OP-02
AddUser): a caughtSave()failure setsResponse = Failurebut execution continues into the directory-attribute block, operating on an unsaved principal (TD-18). - Silent no-op on commit (OP-09
ChangeUserAccount): a request that changes onlycompanyand/orinfonever sets themodifiedflag, soCommitChanges()is skipped while the caller still receivesSuccess(TD-19). - Empty-catch swallow (OP-13
GetUserGroups, OP-14GetUserResources): any directory failure yields an emptyArrayList, indistinguishable from "user has no groups/resources" (TD-21).
Related documentation¶
- Service index
- Overview
- Architecture
- Activation and hosting
- Operations
- Authentication and authorization
- Business rules
- Configuration
- Dependencies
- Faults and error pipeline
- Operational runbook
- Tech debt
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¶
src\ADUserServices\clsADUserServices.asmx.vb.saifdocgen\state\runs\20260922-101326-aduserservices\analysis\aduserservices-analysis.md