We can use the group naming policy to enforce a consistent naming strategy for groups created by users in our organization. A naming policy can help us and our users identify the function of the group. We can use the policy to block specific words from being used in group names and aliases. But what if we need to find out the list of Office 365 groups created with user’s givenName or surname as their mail?
This Office 365 CLI sample script scans the Office 365 groups that may contain user’s givenName or surname as the group mail.

Note: The filter condition can be changed as per your requirement.

$groupsToFlag = @()

$users = o365 aad user list --properties 'displayName,givenName,surname' -o json | ConvertFrom-Json
$groups = o365 aad o365group list  -o json | ConvertFrom-Json

foreach ($user in $users) {
    $userGivenName = $user.givenName
    $userSurname = $user.surname

    $groupsMatch = $groups | Where-Object { $_.mail -like "*$userGivenName*" -or $_.mail -like "*$userSurname*" }

    foreach ($group in $groupsMatch) {
        $groupObject = New-Object -TypeName PSObject
        $groupObject | Add-Member -MemberType NoteProperty -Name "groupId" -Value $group.id
        $groupObject | Add-Member -MemberType NoteProperty -Name "groupMail" -Value $group.mail
        $groupObject | Add-Member -MemberType NoteProperty -Name "userGivenName" -Value $userGivenName
        $groupObject | Add-Member -MemberType NoteProperty -Name "userSurname" -Value $userSurname
        $groupsToFlag += $groupObject
    }
}

$groupsToFlag | Format-Table -AutoSize

Bash Script

#!/bin/bash
# requires jq: https://stedolan.github.io/jq/

defaultIFS=$IFS
IFS=$'\n'

groupsToFlag=()
users=`o365 aad user list --properties 'displayName,givenName,surname' -o json`
groups=`o365 aad o365group list  -o json`

for user in `echo $users | jq -c '.[]'`; do

    userGivenName=`echo $user | jq -r '.givenName'`
    userSurname=`echo $user | jq -r '.surname'`

    groupsMatch=$(echo $groups | jq -c --arg GivenName "$userGivenName" --arg Surname "$userSurname" 'map(select((.mail|ascii_downcase|contains($GivenName|ascii_downcase)) or (.mail|ascii_downcase|contains($Surname|ascii_downcase))))')

    for group in `echo $groupsMatch | jq -c '.[]'`; do
        groupId=`echo $group | jq  -r '.id'`
        groupMail=`echo $group | jq  -r '.mail'`
        groupObject=$(jq -n -c \
                --arg GroupId "$groupId" \
                --arg GroupMail "$groupMail" \
                --arg UserGivenName "$userGivenName" \
                --arg UserSurname "$userSurname" \
                '{groupId: $GroupId, groupMail: $GroupMail, userGivenName: $UserGivenName, userSurname: $UserSurname}')

        groupsToFlag+=($groupObject)
    done
done

echo ${groupsToFlag[@]} | jq -csr '(.[0] |keys_unsorted | @tsv), (.[]|.|map(.) |@tsv)' | column -s$'\t' -t

IFS=defaultIFS
exit 1

Background:

Out of the box, SharePoint provides add/edit item rights to the list as long as the user has contribute or full permission. Access policies can be scoped at the site, list and item levels. Since the user has contribute access to a list, it is possible for the user to add items from UI even if we associate a custom form using tools like PowerApps. This will mess up the custom logic or formulas we used in our PowerApps forms before saving the data in the respective list columns.

Requirement:

Restrict the smart user’s data entry on the SharePoint list which is associated with PowerApps using the out of the box approaches such as quick edit.

Solution:

Create a permission level

A quick way to create a new permission level is to make a copy of an existing permission level. We might want to do this when the existing permission level has permissions similar to what the new permission level will have. After we make the copy, we can add or remove the permissions we need the new permission level to have.

  1. On the Permission Levels page, click the Contribute permission level
  2. On the Edit Permission Level page, choose Copy Permission Level, which is at the bottom of the page after the Personal Permissions section.
  3. On the Copy Permission Level page, type a name as “Restrict Smart User Data Entry“ and description as “This is a custom permission level to restrict manual data entry.” for the new permission level.
  4. Uncheck the View Application Pages permission under List Permissions
  5. After you made the changes, click Submit.

Create Group & Add Users

  1. Click on the Settings icon and choose Site Settings from the drop-down menu.
  2. Go to Site Permissions listed under the Users and Permissions header.
  3. Click on the Create Group icon in the Grant section.
  4. Enter the necessary details in the create group page.
  5. Select the Restrict Smart User Data Entry permission level we created in the previous section.
  6. Click Create
  7. Add the necessary users in this group who can add/edit items in the list that is associated with the PowerApps App.

Configure Permission

  1. Go to the list associated with the PowerApps App
  2. Choose Settings icon and then List settings.
  3. Click Stop Inheriting Permissions to break permissions inheritance from the parent
  4. Click Grant Permissions on the Permissions tab.
  5. In the Share… dialog box, select the group created in the previous section and click share.
  6. Select the out of the box members group and click on remove user permission.
  7. We are all set, now user should not be able to open the list from the browser but can add/edit items from PowerApps app.

We are here to talk about different ideas for improving our process so apply your own permission mechanism based on your requirements to disable the unnecessary data entry on your list/items associated with a custom form.

In this article I am going to explain about the new presence API endpoints introduced by Microsoft Graph API team. We can use these endpoints to read availability(Possible values are Available, AvailableIdle, Away, BeRightBack, Busy, BusyIdle, DoNotDisturb, Offline, PresenceUnknown) and activity information(Possible values are Available, Away, BeRightBack,Busy, DoNotDisturb, InACall, InAConferenceCall, Inactive,InAMeeting, Offline, OffWork,OutOfOffice, PresenceUnknown,Presenting, UrgentInterruptionsOnly.) about the current logged in user or any other users (as long as we have proper permissions to access that user/s).

In order to access the presence API, we will need to configure Presence.Read and Presence.Read.All permission scopes in Azure AD Application. Unfortunately, application permission type is not currently supported for these endpoints but feel free to vote for this idea in the user voice site.

Disclaimer: Presence API endpoints are currently under the beta version. That means these endpoints are subject to change and not recommended to use in production.

Use case 1 – Get current user presence details

MethodGET
Endpointhttps://graph.microsoft.com/beta/me/presence
HeaderAuthorization  Bearer {token}
Requesthttps://graph.microsoft.com/beta/me/presence
Response“id”: “44285e03-f57e-42da-9069-724602c31f6b”, “availability”: “DoNotDisturb”, “activity”: “Presenting”

Use case 2 – Get other user’s presence details

MethodGET
Endpointhttps://graph.microsoft.com/beta/users/{userid}/presence
HeaderAuthorization  Bearer {token}
Requesthttps://graph.microsoft.com/beta/users/55285e03-f57e-42da-9069-724602c31f6b/presence
Response“id”: “55285e03-f57e-42da-9069-724602c31f6b”, “availability”: “DoNotDisturb”, “activity”: “Presenting”

Use case 3 – Get more than one user presence details

MethodPOST
Endpointhttps://graph.microsoft.com/beta/communications/getPresencesByUserId
HeaderAuthorization: Bearer {token} Content-Type: application/json
Requesthttps://graph.microsoft.com/beta/communications/getPresencesByUserId
Body{ “ids”: [“33285e03-f57e-42da-9069-724602c31f6b“, “55285e03-f57e-42da-9069-724602c31f6b“] }
Response{             “value”: [{                                     “id”: “33285e03-f57e-42da-9069-724602c31f6b“,                                     “availability”: “Busy”,                                     “activity”: “InAMeeting”                         },                         {                                     “id”: “55285e03-f57e-42da-9069-724602c31f6b“,                                     “availability”: ” DoNotDisturb “,                                     “activity”: ” Presenting ”                         }             ] }

Hope you found this article helpful! Let me know if I might have missed anything or can be done better.

We are going to learn how to connect Team Foundation Server/Visual Studio Online using a .Net Console Application in this article.

Create a project

  1. Open Visual Studio
  2. On the start window, choose Create a new project.
  3. On the Create a new project window, enter or type console in the search box. Next, choose Console App (.NET Framework) Visual C# from the list, and then click Ok.

Install and use a package

NuGet packages contain reusable code that other developers make available to you for use in your projects.

  1. In Solution Explorer, right-click References and choose Manage NuGet Packages.
  2. Choose “nuget.org” as the Package source, select the Browse tab, search for Microsoft.TeamFoundationServer.Client, select that package in the list, and select Install
  3. Select the Browse tab, search for Microsoft.TeamFoundationServer.ExtendedClient, select that package in the list, and select Install:

Add code

Make sure to include the following headers in your Program.cs file

  • Microsoft.TeamFoundation.Client
  • Microsoft.TeamFoundation.SourceControl.WebApi
  • System
  • System.Collections.Generic
  • System.IO
  • System.Linq
  • System.Net
  • System.Xml.Linq

Add the following code to connect your console application code with TFS and make sure you are able to generate the client context.

TfsTeamProjectCollection context = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri("https://{yourtfs}.visualstudio.com"));
NetworkCredential myCred = new NetworkCredential("your_username", "your_password");
context.Credentials = myCred;
context.Authenticate();
TfvcHttpClient client = context.GetClient<TfvcHttpClient>();

Add the following code to get all the files within the given project path

List<TfvcItem> items = client.GetItemsAsync("$/Sample/Data", VersionControlRecursionType.None).Result;
foreach(TfvcItem item in items.Where(f => f.IsFolder == false))
{
    Console.WriteLine($"Path  =>  {item.Path}   Change Date  =>  {item.ChangeDate}   Changeset Version  =>  {item.ChangesetVersion}");
}

Add the following code to get the file content for the given file path

Stream fileContent = client.GetItemTextAsync("$/Sample/Data/sample.xml").Result;
XDocument glossaryXml = XDocument.Load(fileContent);
Console.WriteLine(glossaryXml);

Add the following code to get the changesets applied on the given file path

TfvcChangesetSearchCriteria searchCriteria = new TfvcChangesetSearchCriteria();
searchCriteria.ItemPath = "$/Sample/Data/sample.xml";
List<TfvcChangesetRef> changeSets = client.GetChangesetsAsync(maxCommentLength: null, skip: null, 
    top: null, orderby: null, searchCriteria: searchCriteria).Result;

Add the following code to filter the changesets applied by a specific code author

List<string> authors = new List<string>();
authors.Add("Joseph Velliah");
List<TfvcChangesetRef> changeSetsFilteredByAuthor = changeSets.Where(a => authors.Contains(a.Author.DisplayName)).ToList();

Add the following code to get the file content of a specific file version based on changeset ID

List<TfvcChange> changesetChanges = client.GetChangesetChangesAsync(changeSetsFilteredByAuthor[0].ChangesetId).Result;
TfvcVersionDescriptor versionDescriptor = new TfvcVersionDescriptor(versionOption: null, versionType: TfvcVersionType.Changeset,
                version: changeSetsFilteredByAuthor[0].ChangesetId.ToString());

List<TfvcChange> changesetChangesFilteredByPath = changesetChanges.
                Where(f => f.Item.Path.Equals("$/Sample/Data/sample.xml")).ToList();

Stream content = client.GetItemContentAsync(path: changesetChangesFilteredByPath[0].Item.Path, versionDescriptor: versionDescriptor).Result;

Hope you found this article helpful! Let me know if I might have missed anything or can be done better.

Developing apps with Power Apps helps the business users solve business problems with easy-to-use tools that don’t require code / less code. In this article I am going to explain how to use a single form control associated with a SharePoint list to add/edit/view items using PowerApps.

I would assume you have the following setup

  • SharePoint list
  • Power App List Form connected with your SharePoint list

Following are the steps I am going to use to convert my form to support add/edit/view functionalities

Step – 1

The Param function retrieves a parameter passed to the app when it was launched. If the named parameter wasn’t passed, Param returns blank. The user will be redirected to the respective form based on ID and Mode parameters.

Step – 2

Assign the CurrentItem variable we have calculated in Step 1 here

Step – 3

Add a Label control and change its visibility expression as shown below:

Step – 4

Add a button outside the form control to create a record in SharePoint and change its visibility expression as shown below:

Change the button’s OnSelect property as shown below:

Step – 5

Add a button outside the form control to update an existing record in SharePoint based on ID parameter and change its visibility expression as shown below:

Change the button’s OnSelect property as shown below:

Demo of overall functionalities

I hope you find this article helpful. Contact me if you have any questions.

Requirement

  1. Create new row/s for each user entered in Users column in SharePoint list item if the record does not exist in Excel table
  2. Update existing row/s based on the SharePoint list item modifications if the record exist in Excel table

Solution

SharePoint List

Excel Sheet with Table

Flow attached to SharePoint List with Complete a custom action for the selected item template

Flow First Time Execution

Flow Second Time Execution with list item modifications

OpenID Connect describes a metadata document that contains most of the information required for an app to do sign-in. This includes information such as the authorization endpoint, token endpoint, tenant region scope, etc. For the discovery endpoint, this is the OpenID Connect metadata document you should use:

The {domain} can take one of two values:

ValueDescription
commonUsers with both a personal Microsoft account and a work or school account from Azure AD can sign in to the application.
contoso.comThe friendly domain name of the Office 365 tenant

The metadata is a simple JSON. See the following snippet for an example.

To get the tenant ID, we just need to parse the token_endpoint property as shown below:

We will get the following JSON for the invalid domain name.

Sample PowerApps using the above mentioned endpoint

Hope this helps. Sharing is Caring !