Class ::ms::Graph

::ms::Graph[i] create ... \
           [ -client_id client_id ] \
           [ -client_secret client_secret ] \
           [ -tenant tenant ] \
           [ -version (default "v1.0") ]

The "tenant" identifies an organization within azure. One OpenACS installation might talk to different tenants at the same time, in which case multiple instances of the Ms Class (or one of its subclasses) must be created. Possible values for the "tenant" property: - "common": Allows users with both personal Microsoft accounts and work/school accounts from Azure AD to sign into the application. - "organizations": Allows only users with work/school accounts from Azure AD to sign into the application. - "consumers": Allows only users with personal Microsoft accounts (MSA) to sign into the application. - tenant GUID identifier, or friendly domain name of the Azure AD, such as e.g. xxxx.onmicrosoft.com Details: https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-v2-protocols
Defined in packages/xooauth/tcl/ms-procs.tcl

Class Relations

  • class: ::nx::Class[i]
  • superclass: ::xo::REST[i]
::nx::Class create ::ms::Graph \
     -superclass ::xo::REST

Methods (to be applied on the object)

  • run_donecallback (scripted, public)

     ms::Graph[i] run_donecallback serialized_app_obj location callback

    Helper method for running callbacks. In general, we cannot rely that the interface object (typically ms::app) exists also in the job-queue, where atjobs are executed. Therefore, the class method receives everything to reconstruct the used interface object.

    Parameters:
    serialized_app_obj
    location
    callback

    Partial Call Graph (max 5 caller/called nodes):
    %3

    Testcases:
    No testcase defined.
    set name [eval $serialized_app_obj]
    #ns_log notice "serialized_app_obj $serialized_app_obj ===> $name"
    $name run_donecallback $location $callback

Methods (to be applied on instances)

  • application get (scripted, public)

     <instance of ms::Graph[i]> application get [ -select select ] \
        application_id

    Get the properties and relationships of an application object. Details: https://docs.microsoft.com/graph/api/application-list

    Switches:
    -select
    (optional)
    return selected attributes, e.g. id,appId,keyCredentials
    Parameters:
    application_id

    Partial Call Graph (max 5 caller/called nodes):
    %3

    Testcases:
    No testcase defined.
    set r [:request -method GET -token [:token]  -url /applications/${application_id}?[:params {select}]]
    return [:expect_status_code $r 200]
  • application list (scripted, public)

     <instance of ms::Graph[i]> application list [ -count count ] \
        [ -expand expand ] [ -filter filter ] [ -orderby orderby ] \
        [ -search search ] [ -select select ] [ -top top ]

    Get the list of applications in this organization. Details: https://docs.microsoft.com/graph/api/application-list

    Switches:
    -count
    (optional)
    boolean, retrieves the total count of matching resources
    -expand
    (optional)
    retrieve related information via navigation property, e.g. members
    -filter
    (optional)
    retrieve a filtered subset of the tuples
    -orderby
    (optional)
    order tuples by some attribute
    -search
    (optional)
    returns results based on search criteria.
    -select
    (optional)
    return selected attributes, e.g. id,appId,keyCredentials
    -top
    (optional)
    sets the page size of results

    Partial Call Graph (max 5 caller/called nodes):
    %3

    Testcases:
    No testcase defined.
    set r [:request -method GET -token [:token]  -url /applications?[:params {
                   count expand filter orderby search select top}]]
    return [:expect_status_code $r 200]
  • chat get (scripted, public)

     <instance of ms::Graph[i]> chat get chat_id

    Retrieve the properties and relationships of user object. Details: https://docs.microsoft.com/en-us/graph/api/chat-get

    Parameters:
    chat_id

    Partial Call Graph (max 5 caller/called nodes):
    %3

    Testcases:
    No testcase defined.
    set r [:request -method GET -token [:token]  -url /chats/$chat_id]
    return [:expect_status_code $r 200]
  • chat messages (scripted, public)

     <instance of ms::Graph[i]> chat messages [ -top top ] chat_id

    Retrieve the properties and relationships of user object. Details: https://docs.microsoft.com/en-us/graph/api/chat-list-messages

    Switches:
    -top
    (optional)
    sets the page size of results (for chat, max is 50)
    Parameters:
    chat_id

    Partial Call Graph (max 5 caller/called nodes):
    %3

    Testcases:
    No testcase defined.
    set r [:request -method GET -token [:token]  -url /chats/$chat_id/messages?[:params {top}]]
    return [:expect_status_code $r 200]
  • group deleted (scripted, public)

     <instance of ms::Graph[i]> group deleted [ -count count ] \
        [ -expand expand ] [ -filter filter ] [ -orderby orderby ] \
        [ -search search ] [ -select select ] [ -top top ]

    List deleted groups. Since groups are large objects, use $select to only get the properties of the group you care about. Details: https://docs.microsoft.com/graph/api/directory-deleteditems-list

    Switches:
    -count
    (optional)
    boolean, retrieves the total count of matching resources
    -expand
    (optional)
    retrieve related information via navigation property, e.g. members
    -filter
    (optional)
    retrieve a filtered subset of the tuples
    -orderby
    (optional)
    order tuples by some attribute
    -search
    (optional)
    returns results based on search criteria.
    -select
    (defaults to "id,displayName,deletedDateTime") (optional)
    return selected attributes, e.g. id,displayName,userPrincipalName
    -top
    (optional)
    sets the page size of results

    Partial Call Graph (max 5 caller/called nodes):
    %3

    Testcases:
    No testcase defined.
    # set filter "startsWith(displayName,'Information Systems') and resourceProvisioningOptions/Any(x:x eq 'Team')"
    set r [:request -method GET -token [:token]  -url /directory/deletedItems/microsoft.graph.group?[:params {
                   count expand filter orderby search select top}]]
    return [:expect_status_code $r 200]
  • group get (scripted, public)

     <instance of ms::Graph[i]> group get [ -select select ] group_id

    Get the properties and relationships of a group object. To get properties that are not returned by default, specify them in a -select OData query option. Details: https://docs.microsoft.com/en-us/graph/api/group-get

    Switches:
    -select
    (optional)
    return selected attributes, e.g. displayName,mail,visibility
    Parameters:
    group_id

    Partial Call Graph (max 5 caller/called nodes):
    %3

    Testcases:
    No testcase defined.
    set r [:request -method GET -token [:token]  -url /groups/$group_id?[:params {select}]]
    return [:expect_status_code $r 200]
  • group list (scripted, public)

     <instance of ms::Graph[i]> group list [ -count count ] \
        [ -expand expand ] [ -filter filter ] [ -orderby orderby ] \
        [ -search search ] [ -select select ] [ -max_entries max_entries ] \
        [ -top top ]

    To get a list of all groups in the organization that have teams, filter by the resourceProvisioningOptions property that contains "Team" (needs beta API): resourceProvisioningOptions/Any(x:x eq 'Team') Otherwise, one has to get the full list and filter manually. Since groups are large objects, use $select to only get the properties of the group you care about. Details: https://docs.microsoft.com/graph/teams-list-all-teams https://docs.microsoft.com/en-us/graph/query-parameters#filter-parameter

    Switches:
    -count
    (optional)
    boolean, retrieves the total count of matching resources
    -expand
    (optional)
    retrieve related information via navigation property, e.g. members
    -filter
    (optional)
    retrieve a filtered subset of the tuples
    -orderby
    (optional)
    order tuples by some attribute
    -search
    (optional)
    returns results based on search criteria.
    -select
    (defaults to "id,displayName,userPrincipalName") (optional)
    return selected attributes, e.g. id,displayName,userPrincipalName
    -max_entries
    (optional)
    retrieve this desired number of tuples (potentially multiple API calls)
    -top
    (optional)
    return up this number of tuples per request (page size)

    Partial Call Graph (max 5 caller/called nodes):
    %3

    Testcases:
    No testcase defined.
    # set filter "startsWith(displayName,'Information Systems') and resourceProvisioningOptions/Any(x:x eq 'Team')"
    # "contains()" seems not supported
    # set filter "contains(displayName,'Information Systems')"
    # set select {$select=id,displayName,resourceProvisioningOptions}
    
    set r [:request -method GET -token [:token]  -url https://graph.microsoft.com/beta/groups?[:params {
                   count expand select filter orderby search top}]]
    return [:paginated_result_list -max_entries $max_entries $r 200]
  • group member add (scripted, public)

     <instance of ms::Graph[i]> group member add group_id principals

    Add a conversationMember to a group. Details: https://docs.microsoft.com/en-us/graph/api/group-post-members

    Parameters:
    group_id
    principals

    Partial Call Graph (max 5 caller/called nodes):
    %3

    Testcases:
    No testcase defined.
    if {[llength $principals] > 20} {
        error "max 20 users can be added in one call"
    }
    set members@odata.bind [lmap id $principals {
        set _ "https://graph.microsoft.com/v1.0/directoryObjects/${id}"
    }]
    set r [:request -method PATCH -token [:token]  -vars {members@odata.bind:array}  -url /groups/${group_id}]
    return [:expect_status_code $r 204]
  • group member list (scripted, public)

     <instance of ms::Graph[i]> group member list [ -count count ] \
        [ -filter filter ] [ -search search ] [ -max_entries max_entries ] \
        [ -top top ] group_id

    Get a list of the group's direct members. A group can have users, organizational contacts, devices, service principals and other groups as members. Currently service principals are not listed as group members due to staged roll-out of service principals on Graph V1.0 endpoint. Details: https://docs.microsoft.com/en-us/graph/api/group-list-members

    Switches:
    -count
    (optional)
    boolean, retrieves the total count of matching resources
    -filter
    (optional)
    retrieve a filtered subset of the tuples
    -search
    (optional)
    returns results based on search criteria.
    -max_entries
    (optional)
    retrieve this desired number of tuples (potentially multiple API calls)
    -top
    (optional)
    sets the page size of results
    Parameters:
    group_id

    Partial Call Graph (max 5 caller/called nodes):
    %3

    Testcases:
    No testcase defined.
    set r [:request -method GET -token [:token]  -url /groups/${group_id}/members?[:params {count filter search top}]]
    return [:paginated_result_list -max_entries $max_entries $r 200]
  • group member remove (scripted, public)

     <instance of ms::Graph[i]> group member remove group_id principal

    Remove group member Details: https://docs.microsoft.com/en-us/graph/api/group-delete-members

    Parameters:
    group_id
    principal

    Partial Call Graph (max 5 caller/called nodes):
    %3

    Testcases:
    No testcase defined.
    set r [:request -method DELETE -token [:token]  -url /groups/${group_id}/members/${principal}/\$ref]
    return [:expect_status_code $r 204]
  • group memberof (scripted, public)

     <instance of ms::Graph[i]> group memberof [ -count count ] \
        [ -filter filter ] [ -orderby orderby ] [ -search search ] \
        group_id

    Get groups that the group is a direct member of. Details: https://docs.microsoft.com/en-us/graph/api/group-list-memberof

    Switches:
    -count
    (optional)
    when "true" return just a count
    -filter
    (optional)
    filter citerion
    -orderby
    (optional)
    sorting criterion, e.g. displayName
    -search
    (optional)
    search criterion, e.g. displayName:Video
    Parameters:
    group_id

    Partial Call Graph (max 5 caller/called nodes):
    %3

    Testcases:
    No testcase defined.
    set r [:request -method GET -token [:token]  -url /groups/${group_id}/memberOf?[:params {
                   count filter orderby search}]]
    return [:expect_status_code $r 200]
  • group owner add (scripted, public)

     <instance of ms::Graph[i]> group owner add group_id principal

    add an owner to a group. Details: https://docs.microsoft.com/en-us/graph/api/group-post-owners

    Parameters:
    group_id
    principal

    Partial Call Graph (max 5 caller/called nodes):
    %3

    Testcases:
    No testcase defined.
    set @odata.id "https://graph.microsoft.com/v1.0/users/${principal}"
    set r [:request -method POST -token [:token]  -vars {@odata.id}  -url /groups/${group_id}/owners/\$ref]
    return [:expect_status_code $r 204]
  • group owner list (scripted, public)

     <instance of ms::Graph[i]> group owner list group_id

    Retrieve a list of the group's owners. Details: https://docs.microsoft.com/en-us/graph/api/group-list-owners

    Parameters:
    group_id

    Partial Call Graph (max 5 caller/called nodes):
    %3

    Testcases:
    No testcase defined.
    set r [:request -method GET -token [:token]  -url /groups/${group_id}/owners]
    return [:expect_status_code $r 200]
  • group owner remove (scripted, public)

     <instance of ms::Graph[i]> group owner remove group_id user_id

    Remove group owner Details: https://docs.microsoft.com/en-us/graph/api/group-delete-owners

    Parameters:
    group_id
    user_id

    Partial Call Graph (max 5 caller/called nodes):
    %3

    Testcases:
    No testcase defined.
    set r [:request -method DELETE -token [:token]  -url /groups/${group_id}/owners/${user_id}/\$ref]
    return [:expect_status_code $r 204]
  • run_donecallback (scripted, public)

     <instance of ms::Graph[i]> run_donecallback location callback

    Method to be finally executes the donecallback. First, we have to check whether the async operation has already finished. If this operation is still in progress, reschedule this operation.

    Parameters:
    location
    callback

    Partial Call Graph (max 5 caller/called nodes):
    %3

    Testcases:
    No testcase defined.
    #ns_log notice "RUNNING donecallback <$callback>"
    set operationStatus [:check_async_operation $location]
    if {$operationStatus eq "inProgress"} {
        :schedule_donecallback 60 $location $callback
    } else {
        {*}$callback [expr {$operationStatus eq "succeeded"}] $operationStatus
    }
  • schedule_donecallback (scripted, public)

     <instance of ms::Graph[i]> schedule_donecallback secs location \
        callback

    Add an atjob for the for the done callback. The job is persisted, such that even for long running operations and server restarts, the operation will continue after the server restart.

    Parameters:
    secs
    location
    callback

    Partial Call Graph (max 5 caller/called nodes):
    %3

    Testcases:
    No testcase defined.
    #ns_log notice "--- schedule_donecallback $secs $location $callback"
    set j [::xowf::atjob new  -url [xo::cc url]  -party_id [xo::cc user_id]  -cmd $callback  -time [clock format [expr {[clock seconds] + $secs}]]]
    $j persist
  • team archive (scripted, public)

     <instance of ms::Graph[i]> team archive \
        [ -shouldSetSpoSiteReadOnlyForMembers shouldSetSpoSiteReadOnlyForMembers ] \
        [ -donecallback donecallback ] [ -wait ] team_id

    Archive the specified team. When a team is archived, users can no longer send or like messages on any channel in the team, edit the team's name, description, or other settings, or in general make most changes to the team. Membership changes to the team continue to be allowed. Details: https://docs.microsoft.com/en-us/graph/api/team-archive

    Switches:
    -shouldSetSpoSiteReadOnlyForMembers
    (optional)
    This optional parameter defines whether to set permissions for team members to read-only on the SharePoint Online site associated with the team. Setting it to false or omitting the body altogether will result in this step being skipped.
    -donecallback
    (optional)
    cmd to be executed when the async command succeeded or failed. One additional argument is passed to the callback indicating the result status.
    -wait
    (defaults to "false") (optional)
    when specified, perform up to 10 requests checking the status of the async command
    Parameters:
    team_id

    Partial Call Graph (max 5 caller/called nodes):
    %3

    Testcases:
    No testcase defined.
    set r [:request -method POST -token [:token]  -url /teams/$team_id/archive?[:params {shouldSetSpoSiteReadOnlyForMembers}]]
    return [:async_operation_status -wait=$wait -donecallback $donecallback $r]
  • team channel list (scripted, public)

     <instance of ms::Graph[i]> team channel list [ -filter filter ] \
        [ -select select ] [ -expand expand ] team_id

    Retrieve the list of channels in this team. Details: https://docs.microsoft.com/en-us/graph/api/channel-list

    Switches:
    -filter
    (optional)
    retrieve a filtered subset of the tuples, e.g. "membershipType eq 'private'"
    -select
    (optional)
    select subset of attributes
    -expand
    (optional)
    retrieve related information via navigation property, e.g. members
    Parameters:
    team_id

    Partial Call Graph (max 5 caller/called nodes):
    %3

    Testcases:
    No testcase defined.
    set r [:request -method GET -token [:token]  -url /teams/${team_id}/channels?[:params {filter select expand}]]
    return [:expect_status_code $r 200]
  • team clone (scripted, public)

     <instance of ms::Graph[i]> team clone \
        [ -classification classification ] [ -description description ] \
        -displayName displayName  -mailNickname mailNickname  \
        -partsToClone partsToClone  [ -visibility visibility ] \
        [ -donecallback donecallback ] [ -wait ] team_id

    Create a copy of a team specified by "team_id". It is possible to copy just some parts of the old team (such as "apps", "channels", "members", "settings", or "tabs", or a comma-separated combination).

    Switches:
    -classification
    (optional)
    -description
    (optional)
    -displayName
    (required)
    -mailNickname
    (required)
    -partsToClone
    (required)
    specify e.g. as "apps,tabs,settings,channels"
    -visibility
    (optional)
    -donecallback
    (optional)
    cmd to be executed when the async command succeeded or failed. One additional argument is passed to the callback indicating the result status. Details: https://docs.microsoft.com/en-us/graph/api/team-clone
    -wait
    (defaults to "false") (optional)
    when specified, perform up to 10 requests checking the status of the async command
    Parameters:
    team_id - of the team to be cloned (might be a template)

    Partial Call Graph (max 5 caller/called nodes):
    %3

    Testcases:
    No testcase defined.
    set r [:request -method POST -token [:token]  -vars {
                   classification
                   description
                   displayName
                   mailNickname
                   partsToClone
                   visibility
               }  -url /teams/${team_id}/clone]
    return [:async_operation_status -wait=$wait -donecallback $donecallback $r]
  • team create (scripted, public)

     <instance of ms::Graph[i]> team create [ -description description ] \
        -displayName displayName  [ -visibility visibility ] -owner owner  \
        [ -donecallback donecallback ] [ -wait ]

    Create a new team. A team owner must be provided when creating a team in an application context. Details: https://docs.microsoft.com/en-us/graph/api/team-post

    Switches:
    -description
    (optional)
    -displayName
    (required)
    -visibility
    (optional)
    -owner
    (required)
    -donecallback
    (optional)
    cmd to be executed when the async command succeeded or failed. One additional argument is passed to the callback indicating the result status.
    -wait
    (defaults to "false") (optional)
    when specified, perform up to 10 requests checking the status of the async command

    Partial Call Graph (max 5 caller/called nodes):
    %3

    Testcases:
    No testcase defined.
    set template@odata.bind "https://graph.microsoft.com/v1.0/teamsTemplates('standard')"
    set members [subst {{
        @odata.type string "#microsoft.graph.aadUserConversationMember"
        roles array {0 string owner}
        user@odata.bind string "https://graph.microsoft.com/v1.0/users('$owner')"
    }}]
    set r [:request -method POST -token [:token]  -vars {template@odata.bind description displayName visibility members:array,document}  -url /teams]
    return [:async_operation_status -wait=$wait -donecallback $donecallback $r]
  • team delete (scripted, public)

     <instance of ms::Graph[i]> team delete team_id

    Delete group/team. When deleted, Microsoft 365 groups are moved to a temporary container and can be restored within 30 days. After that time, they're permanently deleted. Details: https://docs.microsoft.com/en-us/graph/api/group-delete

    Parameters:
    team_id

    Partial Call Graph (max 5 caller/called nodes):
    %3

    Testcases:
    No testcase defined.
    set r [:request -method DELETE -token [:token]  -url /groups/$team_id]
    return [:expect_status_code $r 204]
  • team get (scripted, public)

     <instance of ms::Graph[i]> team get [ -expand expand ] \
        [ -select select ] team_id

    Retrieve the properties and relationships of the specified team. Every team is associated with a group. The group has the same ID as the team - for example, /groups/{id}/team is the same as /teams/{id}. For more information about working with groups and members in teams, Details: https://docs.microsoft.com/en-us/graph/api/team-get

    Switches:
    -expand
    (optional)
    retrieve related information via navigation property, e.g. members
    -select
    (optional)
    select subset of attributes
    Parameters:
    team_id

    Partial Call Graph (max 5 caller/called nodes):
    %3

    Testcases:
    No testcase defined.
    set r [:request -method GET -token [:token]  -url /teams/$team_id?[:params {expand select}]]
    return [:expect_status_code $r 200]
  • team member add (scripted, public)

     <instance of ms::Graph[i]> team member add [ -roles roles ] team_id \
        principal

    Add a conversationMember to the collection of a team. Details: https://docs.microsoft.com/en-us/graph/api/team-post-members

    Switches:
    -roles
    (defaults to "member") (optional)
    Parameters:
    team_id
    principal

    Partial Call Graph (max 5 caller/called nodes):
    %3

    Testcases:
    No testcase defined.
    set @odata.type "#microsoft.graph.aadUserConversationMember"
    set roles $roles
    set user@odata.bind "https://graph.microsoft.com/v1.0/users('${principal}')"
    
    set r [:request -method POST -token [:token]  -vars {@odata.type roles:array user@odata.bind}  -url https://graph.microsoft.com/${:version}/teams/${team_id}/members]
    return [:expect_status_code $r 201]
  • team member list (scripted, public)

     <instance of ms::Graph[i]> team member list [ -filter filter ] \
        [ -select select ] team_id

    Get the conversationMember collection of a team. Details: https://docs.microsoft.com/en-us/graph/api/team-list-members

    Switches:
    -filter
    (optional)
    restrict answers to a subset of tuples, e.g. (microsoft.graph.aadUserConversationMember/displayName eq 'Harry Johnson')
    -select
    (optional)
    select subset of attributes
    Parameters:
    team_id

    Partial Call Graph (max 5 caller/called nodes):
    %3

    Testcases:
    No testcase defined.
    set r [:request -method GET -token [:token]  -url /teams/${team_id}/members?[:params {filter select}]]
    return [:expect_status_code $r 200]
  • team member remove (scripted, public)

     <instance of ms::Graph[i]> team member remove team_id principal

    Remove a conversationMember from a team. Details: https://docs.microsoft.com/en-us/graph/api/group-delete-members

    Parameters:
    team_id
    principal

    Partial Call Graph (max 5 caller/called nodes):
    %3

    Testcases:
    No testcase defined.
    set r [:request -method DELETE -token [:token]  -url /teams/${team_id}/members/${principal}]
    return [:expect_status_code $r 204]
  • team unarchive (scripted, public)

     <instance of ms::Graph[i]> team unarchive \
        [ -donecallback donecallback ] [ -wait ] team_id

    Restore an archived team. This restores users' ability to send messages and edit the team, abiding by tenant and team settings. Teams are archived using the archive API. Details: https://docs.microsoft.com/en-us/graph/api/team-unarchive

    Switches:
    -donecallback
    (optional)
    cmd to be executed when the async command succeeded or failed. One additional argument is passed to the callback indicating the result status.
    -wait
    (defaults to "false") (optional)
    when specified, perform up to 10 requests checking the status of the async command
    Parameters:
    team_id

    Partial Call Graph (max 5 caller/called nodes):
    %3

    Testcases:
    No testcase defined.
    set r [:request -method POST -token [:token]  -url /teams/$team_id/unarchive]
    return [:async_operation_status -wait=$wait -donecallback $donecallback $r]
  • token (scripted, public)

     <instance of ms::Graph[i]> token [ -grant_type grant_type ] \
        [ -scope scope ] [ -assertion assertion ] \
        [ -requested_token_use requested_token_use ]

    Get bearer token (access token) from the /oauth2/v2.0/token endpoint, with timestamp validation (based on "expires_in") result. Obtaining the access token is MsGraph dependent. Probably, some of this can be factored out later to one of the super classes.

    Switches:
    -grant_type
    (defaults to "client_credentials") (optional)
    -scope
    (defaults to "https://graph.microsoft.com/.default") (optional)
    with prefconfigured permissions: use "https://graph.microsoft.com/.default" Comment: This method performs its own caching via nsvs. It would be better to use the ns_cache framework with it's built-in expiration methods via ns_cache_eval, but we get the expiration time provided from the non-cached call and not upfront, before this call. We do not want to use a hack with double ns_cache calls, so we leave this for the time being.
    -assertion
    (optional)
    -requested_token_use
    (optional)

    Partial Call Graph (max 5 caller/called nodes):
    %3

    Testcases:
    No testcase defined.
    if {[nsv_get app_token [self] tokenDict] && $tokenDict ne ""} {
        set access_token [dict get $tokenDict access_token]
        set expiration_date [dict get $tokenDict expiration_date]
        #
        # If access token exists and is not expired we simply
        # return it here
        #
        if {$access_token != "" && $expiration_date > [clock seconds]} {
            #ns_log notice "---- using token and expiration_date from nsv: "  #    "$access_token / $expiration_date (vs. now: [clock seconds])"
            return $access_token
        }
    }
    
    #
    # Get the access-token from /token endpoint.
    # Details: https://docs.microsoft.com/en-us/graph/auth-v2-service
    #
    set r [:request -method POST  -content_type "application/x-www-form-urlencoded"  -vars {
                   {client_secret ${:client_secret}}
                   {client_id ${:client_id}}
                   scope
                   grant_type
                   assertion
                   requested_token_use
               }  -url https://login.microsoftonline.com/${:tenant}/oauth2/v2.0/token]
    
    ns_log notice "/token POST Request Answer: $r"
    if {[dict get $r status] != "200"} {
        error "[self] authentication request returned status code [dict get $r status]"
    }
    
    set jsonDict [dict get $r JSON]
    if {![dict exists $jsonDict access_token]} {
        error "[self] authentication must return access_token. Got: [dict keys $jsonDict]"
    }
    
    if {[dict exists $jsonDict expires_in]} {
        set expire_secs [dict get $jsonDict expires_in]
    } else {
        #
        # No "expires_in" specified, fall back to some default.
        #
        set expire_secs 99999
    }
    
    #
    # Save access-token and expiration date for this request
    #
    set access_token [dict get $jsonDict access_token]
    set expiration_date [clock add [clock seconds] $expire_secs seconds]
    nsv_set app_token [self] [list  access_token $access_token  expiration_date $expiration_date]
    return $access_token
  • user get (scripted, public)

     <instance of ms::Graph[i]> user get [ -select select ] principal

    Retrieve the properties and relationships of user object. Details: https://docs.microsoft.com/en-us/graph/api/user-get

    Switches:
    -select
    (optional)
    return selected attributes, e.g. displayName,givenName,postalCode
    Parameters:
    principal

    Partial Call Graph (max 5 caller/called nodes):
    %3

    Testcases:
    No testcase defined.
    set r [:request -method GET -token [:token]  -url /users/$principal?[:params {select}]]
    return [:expect_status_code $r 200]
  • user list (scripted, public)

     <instance of ms::Graph[i]> user list [ -select select ] \
        [ -filter filter ] [ -max_entries max_entries ] [ -top top ]

    Retrieve the properties and relationships of user object. For the users collection the default page size is 100, the max page size is 999, if you try $top=1000 you'll get an error for invalid page size. Details: https://docs.microsoft.com/en-us/graph/api/user-list

    Switches:
    -select
    (defaults to "displayName,userPrincipalName,id") (optional)
    return selected attributes, e.g. displayName,givenName,postalCode
    -filter
    (optional)
    restrict answers to a subset, e.g. "startsWith(displayName,'Neumann')"
    -max_entries
    (optional)
    retrieve this desired number of tuples (potentially multiple API calls)
    -top
    (optional)
    return up this number of tuples per request (page size)

    Partial Call Graph (max 5 caller/called nodes):
    %3

    Testcases:
    No testcase defined.
    set r [:request -method GET -token [:token]  -url /users?[:params {select filter top}]]
    return [:paginated_result_list -max_entries $max_entries $r 200]
  • user me (scripted, public)

     <instance of ms::Graph[i]> user me [ -select select ] \
        [ -token token ]

    Retrieve the properties and relationships of the current user identified by the token. The "me" request is only valid with delegated authentication flow. Details: https://docs.microsoft.com/en-us/graph/api/user-get

    Switches:
    -select
    (optional)
    return selected attributes, e.g. displayName,givenName,postalCode
    -token
    (optional)

    Partial Call Graph (max 5 caller/called nodes):
    %3

    Testcases:
    No testcase defined.
    if {$token eq ""} {
        set token [:token]
    }
    set r [:request -method GET -token $token  -url /me?[:params {select}]]
    return [:expect_status_code $r 200]
  • user memberof (scripted, public)

     <instance of ms::Graph[i]> user memberof [ -count count ] \
        [ -filter filter ] [ -orderby orderby ] [ -search search ] \
        principal

    Get groups, directory roles, and administrative units that the user is a direct member of. Details: https://docs.microsoft.com/en-us/graph/api/user-list-memberof

    Switches:
    -count
    (optional)
    when "true" return just a count
    -filter
    (optional)
    filter citerion
    -orderby
    (optional)
    sorting criterion, e.g. displayName
    -search
    (optional)
    search criterion, e.g. displayName:Video
    Parameters:
    principal

    Partial Call Graph (max 5 caller/called nodes):
    %3

    Testcases:
    No testcase defined.
    set r [:request -method GET -token [:token]  -url /users/${principal}/memberOf?[:params {
                   count filter orderby search}]]
    return [:expect_status_code $r 200]