Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 11 additions & 5 deletions .github/workflows/validate-structure.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,21 +26,28 @@ jobs:
run: cp .github/scripts/validate-structure.js "$RUNNER_TEMP/validate-structure.js"

- name: Fetch pull request head
id: fetch_head
env:
PR_REMOTE_URL: https://x-access-token:${{ github.token }}@github.com/${{ github.event.pull_request.head.repo.full_name }}.git
PR_REMOTE_URL: https://github.com/${{ github.event.pull_request.head.repo.full_name }}.git
PR_HEAD_REF: ${{ github.event.pull_request.head.ref }}
run: |
git remote remove pr >/dev/null 2>&1 || true
git remote add pr "$PR_REMOTE_URL"
git fetch pr "$PR_HEAD_REF":pr-head --depth=1
git checkout pr-head
if git fetch pr "$PR_HEAD_REF":pr-head --depth=1; then
git checkout pr-head
echo "fetched=true" >> "$GITHUB_OUTPUT"
else
echo "::warning::Unable to fetch fork repository. Skipping structure validation."
echo "fetched=false" >> "$GITHUB_OUTPUT"
fi

- name: Use Node.js 18
uses: actions/setup-node@v4
with:
node-version: 18

- name: Validate folder layout
if: ${{ steps.fetch_head.outputs.fetched == 'true' }}
id: validate
continue-on-error: true
run: node "$RUNNER_TEMP/validate-structure.js" origin/${{ github.event.pull_request.base.ref }}...HEAD
Expand All @@ -59,7 +66,7 @@ jobs:
owner,
repo,
issue_number: pullNumber,
body: `Thank you for your contribution. However, it doesn't comply with our contributing guidelines. As a reminder, the general requirements (as outlined in the [CONTRIBUTING.md file](https://github.com/ServiceNowDevProgram/code-snippets/blob/main/CONTRIBUTING.md)) are the following: follow the folder+subfolder+snippetfolder guidelines and include a README.md file explaining what the code snippet does. Review your contribution against the guidelines and make the necessary adjustments. Closing this for now. Once you make additional changes, feel free to re-open this Pull Request or create a new one.`.trim()
body: `Thank you for your contribution. However, it doesn't comply with our contributing guidelines. As a reminder, the general requirements (as outlined in the [CONTRIBUTING.md file](https://github.com/ServiceNowDevProgram/code-snippets/blob/main/CONTRIBUTING.md)) are the following: follow the folder+subfolder guidelines and include a README.md file explaining what the code snippet does. Review your contribution against the guidelines and make the necessary adjustments. Closing this for now. Once you make additional changes, feel free to re-open this Pull Request or create a new one.`.trim()
});

await github.rest.pulls.update({
Expand All @@ -72,4 +79,3 @@ jobs:
- name: Mark job as failed if validation failed
if: ${{ steps.validate.outcome == 'failure' }}
run: exit 1

6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
.DS_Store
.DS_Store

# Claude Code settings
.claude/
settings.local.json
1 change: 1 addition & 0 deletions Core ServiceNow APIs/GlideAggregate/Snippet2/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
this is my readme file
1 change: 1 addition & 0 deletions Core ServiceNow APIs/GlideAggregate/Snippet2/snippet.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
//vargr
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Conditional Field Selection with GlideQuery

This snippet demonstrates how to dynamically select different sets of fields based on conditions using GlideQuery. This pattern is useful when you need to optimize queries by selecting only the fields you actually need based on runtime conditions, or when building flexible APIs that return different data sets based on user permissions or preferences.

## Use Cases

- **Permission-based field selection**: Select different fields based on user roles or permissions
- **Performance optimization**: Only fetch expensive fields when needed
- **API flexibility**: Return different data sets based on request parameters
- **Conditional aggregations**: Include summary fields only when specific conditions are met

## Key Benefits

- **Reduced data transfer**: Only fetch the fields you need
- **Performance optimization**: Avoid expensive field calculations when unnecessary
- **Security**: Dynamically exclude sensitive fields based on permissions
- **Maintainable code**: Centralized logic for field selection patterns

## Examples Included

1. **Role-based field selection**: Different fields for different user roles
2. **Performance-optimized queries**: Conditional inclusion of expensive fields
3. **Dynamic field arrays**: Building field lists programmatically
4. **Chained conditional selection**: Multiple condition-based selections
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
// Conditional Field Selection with GlideQuery
// Demonstrates dynamically selecting different fields based on runtime conditions

/**
* Example 1: Role-based Field Selection
* Select different incident fields based on user's role
*/
function getIncidentsByRole(userRole, assignedTo) {
// Define base fields that everyone can see
let baseFields = ['number', 'short_description', 'state', 'priority', 'sys_created_on'];

// Define additional fields based on role
let additionalFields = [];

if (userRole === 'admin' || userRole === 'security_admin') {
additionalFields = ['caller_id', 'assigned_to', 'assignment_group', 'work_notes', 'comments'];
} else if (userRole === 'itil') {
additionalFields = ['caller_id', 'assigned_to', 'assignment_group'];
} else if (userRole === 'agent') {
additionalFields = ['assigned_to', 'assignment_group'];
}

// Combine base and additional fields
let fieldsToSelect = baseFields.concat(additionalFields);

return new GlideQuery('incident')
.where('assigned_to', assignedTo)
.where('state', '!=', 7) // Not closed
.select(fieldsToSelect)
.orderByDesc('sys_created_on')
.toArray(50);
}

/**
* Example 2: Performance-optimized Field Selection
* Only include expensive fields when specifically requested
*/
function getTasksWithOptionalFields(options) {
options = options || {};

// Always include these lightweight fields
let fields = ['sys_id', 'number', 'short_description', 'state'];

// Conditionally add more expensive fields
if (options.includeUserDetails) {
fields.push('caller_id.name', 'caller_id.email', 'assigned_to.name');
}

if (options.includeTimeTracking) {
fields.push('work_start', 'work_end', 'business_duration');
}

if (options.includeApprovalInfo) {
fields.push('approval', 'approval_history');
}

if (options.includeRelatedRecords) {
fields.push('parent.number', 'caused_by.number');
}

let query = new GlideQuery('task')
.where('active', true)
.select(fields);

if (options.assignmentGroup) {
query.where('assignment_group', options.assignmentGroup);
}

return query.toArray(100);
}

/**
* Example 3: Dynamic Field Array Building
* Build field selection based on table structure and permissions
*/
function getDynamicFieldSelection(tableName, userPermissions, includeMetadata) {
let fields = [];

// Always include sys_id
fields.push('sys_id');

// Add fields based on table type
if (tableName === 'incident' || tableName === 'sc_request') {
fields.push('number', 'short_description', 'state', 'priority');

if (userPermissions.canViewCaller) {
fields.push('caller_id');
}

if (userPermissions.canViewAssignment) {
fields.push('assigned_to', 'assignment_group');
}
} else if (tableName === 'cmdb_ci') {
fields.push('name', 'operational_status', 'install_status');

if (userPermissions.canViewConfiguration) {
fields.push('ip_address', 'fqdn', 'serial_number');
}
}

// Add metadata fields if requested
if (includeMetadata) {
fields.push('sys_created_on', 'sys_created_by', 'sys_updated_on', 'sys_updated_by');
}

return new GlideQuery(tableName)
.select(fields)
.limit(100)
.toArray();
}

/**
* Example 4: Chained Conditional Selection with Method Chaining
* Demonstrate building complex queries with multiple conditions
*/
function getConditionalIncidentData(filters) {
let query = new GlideQuery('incident');

// Build base field list
let fields = ['sys_id', 'number', 'short_description', 'state'];

// Apply filters and modify field selection accordingly
if (filters.priority && filters.priority.length > 0) {
query.where('priority', 'IN', filters.priority);
fields.push('priority'); // Include priority field when filtering by it
}

if (filters.assignmentGroup) {
query.where('assignment_group', filters.assignmentGroup);
fields.push('assignment_group', 'assigned_to'); // Include assignment fields
}

if (filters.dateRange) {
query.where('sys_created_on', '>=', filters.dateRange.start)
.where('sys_created_on', '<=', filters.dateRange.end);
fields.push('sys_created_on'); // Include date when filtering by it
}

if (filters.includeComments) {
fields.push('comments', 'work_notes');
}

if (filters.includeResolution) {
fields.push('close_code', 'close_notes', 'resolved_by');
}

return query.select(fields)
.orderByDesc('sys_created_on')
.toArray(filters.limit || 50);
}

/**
* Example 5: Security-conscious Field Selection
* Exclude sensitive fields based on user context
*/
function getSecureUserData(requestingUser, targetUserId) {
let baseFields = ['sys_id', 'name', 'user_name', 'active'];

// Check if requesting user can see additional details
if (gs.hasRole('user_admin') || requestingUser === targetUserId) {
// Full access - include all standard fields
return new GlideQuery('sys_user')
.where('sys_id', targetUserId)
.select(['sys_id', 'name', 'user_name', 'email', 'phone', 'department', 'title', 'manager', 'active'])
.toArray(1);
} else if (gs.hasRole('hr_admin')) {
// HR access - include HR-relevant fields but not IT details
return new GlideQuery('sys_user')
.where('sys_id', targetUserId)
.select(['sys_id', 'name', 'user_name', 'department', 'title', 'manager', 'active'])
.toArray(1);
} else {
// Limited access - only public information
return new GlideQuery('sys_user')
.where('sys_id', targetUserId)
.select(baseFields)
.toArray(1);
}
}

// Usage Examples:

// Role-based selection
var adminIncidents = getIncidentsByRole('admin', gs.getUserID());

// Performance-optimized query
var tasksWithDetails = getTasksWithOptionalFields({
includeUserDetails: true,
includeTimeTracking: false,
assignmentGroup: 'hardware'
});

// Dynamic field building
var dynamicData = getDynamicFieldSelection('incident', {
canViewCaller: true,
canViewAssignment: false
}, true);

// Complex conditional query
var filteredIncidents = getConditionalIncidentData({
priority: [1, 2],
assignmentGroup: 'network',
includeComments: true,
limit: 25
});
Loading