Skip to content

Commit

Permalink
Zip Backup and Message Time to IMG and App create
Browse files Browse the repository at this point in the history
- Zip backup for each team
- IMG set dates to message created
- Nuget update + MS Graph fix
- Publish script
- AAD App Creation
  • Loading branch information
marcoscheel committed Jan 24, 2021
1 parent 86fd219 commit 3254993
Show file tree
Hide file tree
Showing 19 changed files with 183 additions and 18 deletions.
33 changes: 33 additions & 0 deletions deploy/create-aadapp-cli.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Azure CLI must be installed
# https://docs.microsoft.com/en-us/cli/azure/install-azure-cli-windows?tabs=azure-cli
# User must be able to create apps and consent (Global Admin, ...)

$appName = "dev-GKMM-msteamsbackup-app"; #Change for example GKMM to your tenant
$servicePrincipalName = "Microsoft Graph";
$servicePrincipalNameOauth2Permissions = @("Channel.ReadBasic.All", "ChannelMember.Read.All", "ChannelMessage.Read.All", "ChannelSettings.Read.All", "Group.Read.All", "GroupMember.Read.All", "Team.ReadBasic.All", "TeamMember.Read.All", "TeamSettings.Read.All", "TeamsTab.Read.All");

az login --use-device-code --allow-no-subscriptions

$servicePrincipalId = az ad sp list --filter "displayname eq '$servicePrincipalName'" --query '[0].appId' | ConvertFrom-Json

$reqGraph = @{
resourceAppId = $servicePrincipalId
resourceAccess = @()
}

(az ad sp show --id $servicePrincipalId --query oauth2Permissions | ConvertFrom-Json) | ? { $_.value -in $servicePrincipalNameOauth2Permissions} | % {
$permission = $_

$delPermission = @{
id = $permission.Id
type = "Scope"
}
$reqGraph.resourceAccess += $delPermission
}

Set-Content ./required_resource_accesses.json -Value ("[" + ($reqGraph | ConvertTo-Json) + "]")
$newapp = az ad app create --display-name $appName --available-to-other-tenants false --native-app true --required-resource-accesses `@required_resource_accesses.json | ConvertFrom-Json
az ad app permission admin-consent --id $newapp.appId

"ClientId: " + $newapp.appId;
"TenantId: " + (az account show | ConvertFrom-Json).tenantId;
31 changes: 31 additions & 0 deletions deploy/create-aadapp.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Requires AzureADPreview Module;
# Install-Module AzureADPreview
# User must be able to create apps and consent (Global Admin, ...)

$appName = "dev-GKMM-msteamsbackup-app"; #Change for example GKMM to your tenant
$servicePrincipalName = "Microsoft Graph";
$servicePrincipalNameOauth2Permissions = @("Channel.ReadBasic.All", "ChannelMember.Read.All", "ChannelMessage.Read.All", "ChannelSettings.Read.All", "Group.Read.All", "GroupMember.Read.All", "Team.ReadBasic.All", "TeamMember.Read.All", "TeamSettings.Read.All", "TeamsTab.Read.All");

# login
Connect-AzureAD;

# Get MS Graph
$servicePrincipal = Get-AzureADServicePrincipal -All $true | ? { $_.DisplayName -eq $servicePrincipalName };

# Thanks http://blog.octavie.nl/index.php/2017/09/19/create-azure-ad-app-registration-with-powershell-part-2
$reqGraph = New-Object -TypeName "Microsoft.Open.AzureAD.Model.RequiredResourceAccess";
$reqGraph.ResourceAppId = $servicePrincipal.AppId;

$servicePrincipal.Oauth2Permissions | ? { $_.Value -in $servicePrincipalNameOauth2Permissions} | % {
$permission = $_
$delPermission = New-Object -TypeName "Microsoft.Open.AzureAD.Model.ResourceAccess" -ArgumentList $permission.Id,"Scope" #delegate permission (oauth) are always "Scope"
$reqGraph.ResourceAccess += $delPermission
}

New-AzureADApplication -DisplayName $appName -AvailableToOtherTenants:$false -PublicClient:$true -RequiredResourceAccess $reqGraph;
$newapp = Get-AzureADApplication -SearchString $appName;
"ClientId: " + $newapp.AppId;
"TenantId: " + (Get-AzureADTenantDetail).ObjectId;

"TODO: Consent in portal";
"Check AAD app: https://portal.azure.com/#blade/Microsoft_AAD_RegisteredApps/ApplicationMenuBlade/CallAnAPI/appId/" + $newapp.AppId + "/objectId/" + $newapp.ObjectId + "/isMSAApp/";
29 changes: 29 additions & 0 deletions deploy/publish-BackupConsole.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#Build release
$corePathToProject = "..\src\BackupConsole";
$configNames = @("Release");

foreach($configName in $configNames){
$configName;
$publishLocation = ".\$configName-output";
$publishLocationApp = $publishLocation + "\M365.TeamsBackup.BackupConsole.exe";


dotnet publish $corePathToProject --configuration $configName --output $publishLocation;

Remove-Item "$publishLocation/appsettings.Development.json";
Remove-Item "$publishLocation/appsettings.Production.json";

if (Test-Path $publishLocationApp){

if ((Test-Path $configName) -eq $false){
mkdir $configName;
}

$version2publish = [System.Diagnostics.FileVersionInfo]::GetVersionInfo((Get-Location).ToString() + $publishLocationApp).FileVersion.ToString().Replace(".", "-");

$thisZipVersion = ".\" + $configName + "\M365.TeamsBackup.BackupConsole-V-" + $version2publish + "-" + $configName + ".zip";

Compress-Archive ($publishLocation + "\*") $thisZipVersion -CompressionLevel Fastest;
Remove-Item $publishLocation -Recurse:$true
}
}
29 changes: 29 additions & 0 deletions deploy/publish-BackupToHtmlConsole.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#Build release
$corePathToProject = "..\src\BackupToHtmlConsole";
$configNames = @("Release");

foreach($configName in $configNames){
$configName;
$publishLocation = ".\$configName-output";
$publishLocationApp = $publishLocation + "\M365.TeamsBackup.BackupToHtmlConsole.exe";


dotnet publish $corePathToProject --configuration $configName --output $publishLocation;

Remove-Item "$publishLocation/appsettings.Development.json";
Remove-Item "$publishLocation/appsettings.Production.json";

if (Test-Path $publishLocationApp){

if ((Test-Path $configName) -eq $false){
mkdir $configName;
}

$version2publish = [System.Diagnostics.FileVersionInfo]::GetVersionInfo((Get-Location).ToString() + $publishLocationApp).FileVersion.ToString().Replace(".", "-");

$thisZipVersion = ".\" + $configName + "\M365.TeamsBackup.BackupToHtmlConsole-V-" + $version2publish + "-" + $configName + ".zip";

Compress-Archive ($publishLocation + "\*") $thisZipVersion -CompressionLevel Fastest;
Remove-Item $publishLocation -Recurse:$true
}
}
8 changes: 7 additions & 1 deletion src/BackupConsole/BackupConsole.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<AssemblyName>M365.TeamsBackup.BackupConsole</AssemblyName>
<RootNamespace>M365.TeamsBackup.BackupConsole</RootNamespace>
<Authors>Marco Scheel</Authors>
<Version>0.1.3</Version>
<Version>0.1.4</Version>
<Product>M365.TeamsBackup</Product>
<Description>Backup from MS Graph Beta to Local JSON</Description>
</PropertyGroup>
Expand All @@ -33,4 +33,10 @@
<ProjectReference Include="..\Core\Core.csproj" />
</ItemGroup>

<ItemGroup>
<None Update="appsettings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>

</Project>
2 changes: 1 addition & 1 deletion src/BackupConsole/Properties/launchSettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"profiles": {
"BackupConsole": {
"commandName": "Project",
"commandLineArgs": "--environment Production"
"commandLineArgs": "--environment Development"
}
}
}
4 changes: 2 additions & 2 deletions src/BackupConsole/appsettings.Development.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@
},
"AzureAd": {
"Instance": "https://login.microsoftonline.com",
"ClientId": "12c9d807-90dd-42d8-abb3-b5f15a03d492",
"ClientId": "fdc12731-7742-4c3d-a3ab-f3b358ba2e09",
"TenantId": "052c8489-1e3c-450e-9b79-233d8604e40a",
"ReplyUri": "msal12c9d807-90dd-42d8-abb3-b5f15a03d492://auth",
"Scope": [ "https://graph.microsoft.com/.default" ]
},
"M365": {
"Backup": {
"Path": "C:\\Code\\M365.TeamsBackup\\data\\development",
"ShouldZip": true,
"JsonWriteIndented": true,
"TeamId": "872265e1-0c5a-48ea-9355-0710869db8cb"
}
Expand Down
2 changes: 1 addition & 1 deletion src/BackupConsole/appsettings.Production.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@
"Instance": "https://login.microsoftonline.com",
"ClientId": "4c50ca04-1ecf-4a02-8ac0-c8698a818701",
"TenantId": "cb9543bb-9168-4dc6-b17f-766487518a6a",
"ReplyUri": "msal4c50ca04-1ecf-4a02-8ac0-c8698a818701://auth",
"Scope": [ "https://graph.microsoft.com/.default" ]
},
"M365": {
"Backup": {
"Path": "C:\\Code\\M365.TeamsBackup\\data\\production",
"JsonWriteIndented": false,
"ShouldZip": true,
"TeamId": "8b04f653-e2ba-4b57-92b7-3d1247073927"
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/BackupConsole/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@
"Instance": "https://login.microsoftonline.com",
"ClientId": "YOUR AAD CLIENT ID",
"TenantId": "YOUR AAD TENANT ID",
"ReplyUri": "YOUR AAD APP REPLY URI",
"Scope": [ "https://graph.microsoft.com/.default" ]
},
"M365": {
"Backup": {
"Path": "C:\\M365.TeamsBackup\\data",
"JsonWriteIndented": false,
"ShouldZip": false,
"TeamId": "YOUR TEAM ID TO BACKUP"
}
}
Expand Down
8 changes: 7 additions & 1 deletion src/BackupToHtmlConsole/BackupToHtmlConsole.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<TargetFramework>net5.0</TargetFramework>
<AssemblyName>M365.TeamsBackup.BackupToHtmlConsole</AssemblyName>
<RootNamespace>M365.TeamsBackup.BackupToHtmlConsole</RootNamespace>
<Version>0.1.3</Version>
<Version>0.1.4</Version>
<Authors>Marco Scheel</Authors>
<Product>M365.TeamsBackup</Product>
<Description>Convert an existing JSON based backup to HTML</Description>
Expand Down Expand Up @@ -33,4 +33,10 @@
<ProjectReference Include="..\Core\Core.csproj" />
</ItemGroup>

<ItemGroup>
<None Update="appsettings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>

</Project>
2 changes: 1 addition & 1 deletion src/BackupToHtmlConsole/Properties/launchSettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"profiles": {
"BackupToHtmlConsole": {
"commandName": "Project",
"commandLineArgs": "--environment Production"
"commandLineArgs": "--environment Development"
}
}
}
2 changes: 1 addition & 1 deletion src/BackupToHtmlConsole/appsettings.Development.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"SourcePath": "C:\\Code\\M365.TeamsBackup\\data\\development",
"TargetPath": "C:\\Code\\M365.TeamsBackup\\data\\development-html",
"TemplateFile": "C:\\Code\\M365.TeamsBackup\\template\\template.html",
"UseInlineImages": true,
"UseInlineImages": false,
"CreateSingleHtmlForMessage": true
}
}
Expand Down
1 change: 0 additions & 1 deletion src/Core/Config/AzureAD.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ public class AzureAd
public string Instance { get; set; }
public string ClientId { get; set; }
public string TenantId { get; set; }
public string ReplyUri { get; set; }
public string[] Scope { get; set; }
}
}
4 changes: 3 additions & 1 deletion src/Core/Config/Backup.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using Microsoft.Graph;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
Expand All @@ -11,6 +12,7 @@ namespace M365.TeamsBackup.Core.Config
public class Backup
{
public string Path { get; set; }
public bool ShouldZip { get; set; }
public string TeamId { get; set; }
public bool JsonWriteIndented { get; set; }

Expand Down
6 changes: 3 additions & 3 deletions src/Core/Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,18 @@
<TargetFramework>net5.0</TargetFramework>
<AssemblyName>M365.TeamsBackup.Core</AssemblyName>
<RootNamespace>M365.TeamsBackup.Core</RootNamespace>
<Version>0.1.3</Version>
<Version>0.1.4</Version>
<Authors>Marco Scheel</Authors>
<Product>M365.TeamsBackup</Product>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="HtmlAgilityPack" Version="1.11.28" />
<PackageReference Include="HtmlAgilityPack" Version="1.11.29" />
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.Options" Version="5.0.0" />
<PackageReference Include="Microsoft.Graph.Auth" Version="1.0.0-preview.6" />
<PackageReference Include="Microsoft.Graph.Beta" Version="0.35.0-preview" />
<PackageReference Include="Microsoft.Graph.Beta" Version="0.36.0-preview" />
<PackageReference Include="System.Security.Cryptography.ProtectedData" Version="5.0.0" />
</ItemGroup>

Expand Down
2 changes: 2 additions & 0 deletions src/Core/Data/HtmlTeamChannelMessage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,8 @@ private void GetHtmlForPost(HtmlNode threadNode, ChatMessage message)

}
System.IO.File.Copy(blobFileName, outFilename, true);
System.IO.File.SetCreationTime(outFilename, message.CreatedDateTime.Value.DateTime);
System.IO.File.SetLastWriteTime(outFilename, message.CreatedDateTime.Value.DateTime);

imgNode.SetAttributeValue("src", $"./img/{System.IO.Path.GetFileName(outFilename)}");
}
Expand Down
7 changes: 7 additions & 0 deletions src/Core/Data/MgTeam.cs
Original file line number Diff line number Diff line change
Expand Up @@ -111,11 +111,18 @@ public static string GetBackupPath(string root, string teamId)
System.IO.Directory.CreateDirectory(fullpath);
return fullpath;
}

public static string GetBackupTeamFile(string root, string teamId)
{
var fullpath = System.IO.Path.Combine(GetBackupPath(root, teamId), "team.json");
return fullpath;
}
public static string GetBackupTeamZipFile(string root, string teamId)
{
var fullpath = System.IO.Path.Combine(root, $"{teamId}.zip");
return fullpath;
}

public static string GetBackupTeamMembersFile(string root, string teamId)
{
var fullpath = System.IO.Path.Combine(GetBackupPath(root, teamId), "team.members.json");
Expand Down
28 changes: 25 additions & 3 deletions src/Core/Services/BackupFromGraphService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,10 @@ public BackupFromGraphService(ILogger<BackupFromGraphService> logger, ILogger<Mg
public async Task Execute()
{
_Logger.LogInformation($"Version: {Core.Config.App.Version}");
_Logger.LogInformation($"Start backup at folder: {_Options.Path}");

if (_Options.ShouldZip)
{
_Logger.LogInformation($"Zip backup folder: {_Options.Path}");
}

//Get teams
var teamsPageRequestBase =
Expand All @@ -56,7 +58,7 @@ public async Task Execute()
_Logger.LogTrace($"GraphUri: {teamsPageRequest.RequestUrl}");


IUserJoinedTeamsCollectionPage teamsPage = null;
IUserJoinedTeamsCollectionWithReferencesPage teamsPage = null;
for (int i = 1; i <= MgGraphRequester.MaxRetry; i++)
{
try
Expand Down Expand Up @@ -187,6 +189,26 @@ public async Task Execute()
channelPageRequest = channelPage.NextPageRequest;
}
while (channelPageRequest != null);


if (_Options.ShouldZip)
{
var zipfile = MgTeam.GetBackupTeamZipFile(_Options.Path, team.Id);

try
{
_Logger.LogInformation($"Zip Team: {team.Id} - {team.DisplayName} - {zipfile}");
if (System.IO.File.Exists(zipfile))
{
System.IO.File.Delete(zipfile);
}
System.IO.Compression.ZipFile.CreateFromDirectory(MgTeam.GetBackupPath(_Options.Path, team.Id), zipfile);
}
catch (Exception ex)
{
_Logger.LogError(ex, $"Team zip error: {zipfile}");
}
}
}
teamsPageRequest = teamsPage.NextPageRequest;
}
Expand Down
1 change: 0 additions & 1 deletion src/Core/Services/GraphClientService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ public GraphServiceClient GetGraphClient(ILogger logger)
_PublicClientApplication = PublicClientApplicationBuilder
.Create(_Options.ClientId)
.WithAuthority(new Uri($"{_Options.Instance}/{_Options.TenantId}"))
.WithRedirectUri(_Options.ReplyUri)
.Build();
TokenCacheHelper.EnableSerialization(_PublicClientApplication.UserTokenCache);

Expand Down

0 comments on commit 3254993

Please sign in to comment.