This commit is contained in:
Isaiah Williams 2017-05-13 14:01:46 +00:00
Родитель 2c37f4a1f3
Коммит fd5c2c325c
47 изменённых файлов: 1649 добавлений и 331 удалений

74
.editorconfig Normal file
Просмотреть файл

@ -0,0 +1,74 @@
# EditorConfig is awesome:http://EditorConfig.org
# top-most EditorConfig file
root = true
# Don't use tabs for indentation.
[*]
indent_style = space
# (Please don't specify an indent_size here; that has too many unintended consequences.)
# Code files
[*.{cs,csx,vb,vbx}]
indent_size = 4
# Xml project files
[*.{csproj,vbproj,vcxproj,vcxproj.filters,proj,projitems,shproj}]
indent_size = 2
# Xml config files
[*.{props,targets,ruleset,config,nuspec,resx,vsixmanifest,vsct}]
indent_size = 2
# Dotnet code style settings:
[*.{cs,vb}]
# Sort using and Import directives with System.* appearing first
dotnet_sort_system_directives_first = true
# Avoid "this." and "Me." if not necessary
dotnet_style_qualification_for_field = false:suggestion
dotnet_style_qualification_for_property = false:suggestion
dotnet_style_qualification_for_method = false:suggestion
dotnet_style_qualification_for_event = false:suggestion
# Use language keywords instead of framework type names for type references
dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
dotnet_style_predefined_type_for_member_access = true:suggestion
# Suggest more modern language features when available
dotnet_style_object_initializer = true:suggestion
dotnet_style_collection_initializer = true:suggestion
dotnet_style_coalesce_expression = true:suggestion
dotnet_style_null_propagation = true:suggestion
dotnet_style_explicit_tuple_names = true:suggestion
# CSharp code style settings:
[*.cs]
# Prefer "var" everywhere
csharp_style_var_for_built_in_types = false:suggestion
csharp_style_var_when_type_is_apparent = false:suggestion
csharp_style_var_elsewhere = false:suggestion
# Prefer method-like constructs to have a block body
csharp_style_expression_bodied_methods = false:none
csharp_style_expression_bodied_constructors = false:none
csharp_style_expression_bodied_operators = false:none
# Prefer property-like constructs to have an expression-body
csharp_style_expression_bodied_properties = true:none
csharp_style_expression_bodied_indexers = true:none
csharp_style_expression_bodied_accessors = true:none
# Suggest more modern language features when available
csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
csharp_style_inlined_variable_declaration = true:suggestion
csharp_style_throw_expression = true:suggestion
csharp_style_conditional_delegate_call = true:suggestion
# Newline settings
csharp_new_line_before_open_brace = all
csharp_new_line_before_else = true
csharp_new_line_before_catch = true
csharp_new_line_before_finally = true
csharp_new_line_before_members_in_object_initializers = true
csharp_new_line_before_members_in_anonymous_types = true

Просмотреть файл

@ -1,10 +1,13 @@
 
Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15 # Visual Studio 15
VisualStudioVersion = 15.0.26228.4 VisualStudioVersion = 15.0.26430.6
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{2C543791-022E-451C-BBB4-D756A459B91A}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{2C543791-022E-451C-BBB4-D756A459B91A}"
ProjectSection(SolutionItems) = preProject ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
azuredeploy.json = azuredeploy.json
azuredeploy.parameters.json = azuredeploy.parameters.json
CONTRIBUTING.md = CONTRIBUTING.md CONTRIBUTING.md = CONTRIBUTING.md
LICENSE = LICENSE LICENSE = LICENSE
Partner-Center-Bot.json = Partner-Center-Bot.json Partner-Center-Bot.json = Partner-Center-Bot.json

Просмотреть файл

@ -22,6 +22,9 @@ This makes it where the user can get answers to commonly asked questions.
## Deployment ## Deployment
Please review the [Deployment](docs/Deployment.md) guide for details on how to deploy this solution. Please review the [Deployment](docs/Deployment.md) guide for details on how to deploy this solution.
[![Deploy to Azure](http://azuredeploy.net/deploybutton.png)](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FMicrosoft%2FPartner-Center-Bot%2Fmaster%2Fazuredeploy.json)
[![Visualize](http://armviz.io/visualizebutton.png)](http://armviz.io/#/?load=https%3A%2F%2Fraw.githubusercontent.com%2FMicrosoft%2FPartner-Center-Bot%2Fmaster%2Fazuredeploy.json)
## Code of Conduct ## Code of Conduct
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more
information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact

409
azuredeploy.json Normal file
Просмотреть файл

@ -0,0 +1,409 @@
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"appInsightsLocation": {
"type": "string",
"defaultValue": "South Central US",
"allowedValues": [
"South Central US",
"West Europe",
"East US",
"North Europe"
],
"metadata": {
"description": "Location for the instance of App Insights."
}
},
"applicationId": {
"type": "string",
"minLength": 1
},
"applicationSecret": {
"type": "string",
"minLength": 1
},
"applicationTenantId": {
"type": "string",
"minLength": 1
},
"branch": {
"type": "string"
},
"cacheSKUName": {
"type": "string",
"allowedValues": [
"Basic",
"Standard"
],
"defaultValue": "Basic",
"metadata": {
"description": "The pricing tier of the new Azure Redis Cache."
}
},
"cacheSKUFamily": {
"type": "string",
"allowedValues": [
"C"
],
"defaultValue": "C",
"metadata": {
"description": "The family for the SKU."
}
},
"cacheSKUCapacity": {
"type": "int",
"allowedValues": [
0,
1,
2,
3,
4,
5,
6
],
"defaultValue": 0,
"metadata": {
"description": "The size of the new Azure Redis Cache instance."
}
},
"hostingPlanName": {
"type": "string",
"minLength": 1
},
"keyVaultApplicationCertThumbprint": {
"type": "string",
"metadata": {
"description": "Thumbprint for the certificate used to access Key Vault"
},
"minLength": 1
},
"keyVaultApplicationId": {
"type": "string",
"metadata": {
"description": "Identifier of the application used to access Key Vault"
},
"minLength": 1
},
"keyVaultName": {
"type": "string",
"minLength": 1
},
"keyVaultSkuName": {
"type": "string",
"defaultValue": "Standard",
"allowedValues": [
"Standard",
"Premium"
],
"metadata": {
"description": "SKU for the vault"
}
},
"keyVaultTenantId": {
"type": "string",
"minLength": 1
},
"luisAppId": {
"type": "string",
"minLength": 1
},
"luisApiKey": {
"type": "string",
"minLength": 1
},
"microsoftAppId": {
"type": "string",
"minLength": 1
},
"microsoftAppPassword": {
"type": "string",
"minLength": 1
},
"partnerCenterApplicationId": {
"type": "string",
"minLength": 1
},
"partnerCenterApplicationSecret": {
"type": "string",
"minLength": 1
},
"partnerCenterApplicationTenantId": {
"type": "string",
"minLength": 1
},
"qnAKnowledgebaseId": {
"type": "string",
"minLength": 1
},
"qnASubscriptionKey": {
"type": "string",
"minLength": 1
},
"repoUrl": {
"type": "string"
},
"siteName": {
"type": "string",
"minLength": 1
},
"skuName": {
"type": "string",
"defaultValue": "B1",
"allowedValues": [
"B1",
"B2",
"B3",
"S1",
"S2",
"S3",
"P1",
"P2",
"P3",
"P4"
],
"metadata": {
"description": "Describes the plan's pricing tier and capacity. Check details at https://azure.microsoft.com/en-us/pricing/details/app-service/"
}
},
"skuCapacity": {
"type": "int",
"defaultValue": 1,
"minValue": 1,
"metadata": {
"description": "Describes the plan's instance count"
}
},
"storageAccountType": {
"type": "string",
"defaultValue": "Standard_LRS",
"allowedValues": [
"Standard_LRS",
"Standard_GRS",
"Standard_ZRS",
"Premium_LRS"
],
"metadata": {
"description": "Storage Account Type"
}
}
},
"variables": {
"cacheName": "[concat('cache', uniqueString(resourceGroup().id))]",
"storageAccountName": "[concat('storage', uniqueString(resourceGroup().id))]"
},
"resources": [
{
"type": "Microsoft.KeyVault/vaults",
"name": "[parameters('keyVaultName')]",
"apiVersion": "2015-06-01",
"location": "[resourceGroup().location]",
"properties": {
"tenantId": "[parameters('keyVaultTenantId')]",
"accessPolicies": [],
"sku": {
"name": "[parameters('keyVaultSkuName')]",
"family": "A"
}
}
},
{
"type": "Microsoft.KeyVault/vaults/secrets",
"name": "[concat(parameters('keyVaultName'), '/', 'ApplicationSecret')]",
"apiVersion": "2015-06-01",
"properties": {
"contentType": "text/plain",
"value": "[parameters('applicationSecret')]"
},
"dependsOn": [
"[concat('Microsoft.KeyVault/vaults/', parameters('keyVaultName'))]"
]
},
{
"type": "Microsoft.KeyVault/vaults/secrets",
"name": "[concat(parameters('keyVaultName'), '/', 'LuisApiKey')]",
"apiVersion": "2015-06-01",
"properties": {
"contentType": "text/plain",
"value": "[parameters('luisApiKey')]"
},
"dependsOn": [
"[concat('Microsoft.KeyVault/vaults/', parameters('keyVaultName'))]"
]
},
{
"type": "Microsoft.KeyVault/vaults/secrets",
"name": "[concat(parameters('keyVaultName'), '/', 'MicrosoftAppPassword')]",
"apiVersion": "2015-06-01",
"properties": {
"contentType": "text/plain",
"value": "[parameters('microsoftAppPassword')]"
},
"dependsOn": [
"[concat('Microsoft.KeyVault/vaults/', parameters('keyVaultName'))]"
]
},
{
"type": "Microsoft.KeyVault/vaults/secrets",
"name": "[concat(parameters('keyVaultName'), '/', 'PartnerCenterApplicationSecret')]",
"apiVersion": "2015-06-01",
"properties": {
"contentType": "text/plain",
"value": "[parameters('partnerCenterApplicationSecret')]"
},
"dependsOn": [
"[concat('Microsoft.KeyVault/vaults/', parameters('keyVaultName'))]"
]
},
{
"type": "Microsoft.KeyVault/vaults/secrets",
"name": "[concat(parameters('keyVaultName'), '/', 'QnASubscriptionKey')]",
"apiVersion": "2015-06-01",
"properties": {
"contentType": "text/plain",
"value": "[parameters('qnASubscriptionKey')]"
},
"dependsOn": [
"[concat('Microsoft.KeyVault/vaults/', parameters('keyVaultName'))]"
]
},
{
"type": "Microsoft.KeyVault/vaults/secrets",
"name": "[concat(parameters('keyVaultName'), '/', 'StorageConnectionString')]",
"apiVersion": "2015-06-01",
"properties": {
"contentType": "text/plain",
"value": "[Concat('DefaultEndpointsProtocol=https;AccountName=',variables('StorageAccountName'),';AccountKey=',listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('StorageAccountName')), providers('Microsoft.Storage', 'storageAccounts').apiVersions[0]).keys[0].value)]"
},
"dependsOn": [
"[concat('Microsoft.KeyVault/vaults/', parameters('keyVaultName'))]",
"[concat('Microsoft.Storage/storageAccounts/', variables('StorageAccountName'))]"
]
},
{
"name": "[variables('cacheName')]",
"type": "Microsoft.Cache/Redis",
"location": "[resourceGroup().location]",
"apiVersion": "2016-04-01",
"dependsOn": [],
"tags": {
"displayName": "cache"
},
"properties": {
"sku": {
"name": "[parameters('cacheSKUName')]",
"family": "[parameters('cacheSKUFamily')]",
"capacity": "[parameters('cacheSKUCapacity')]"
}
}
},
{
"type": "Microsoft.Storage/storageAccounts",
"name": "[variables('storageAccountName')]",
"apiVersion": "2016-01-01",
"location": "[resourceGroup().location]",
"sku": {
"name": "[parameters('storageAccountType')]"
},
"kind": "Storage",
"properties": {
}
},
{
"apiVersion": "2015-08-01",
"name": "[parameters('hostingPlanName')]",
"type": "Microsoft.Web/serverfarms",
"location": "[resourceGroup().location]",
"tags": {
"displayName": "HostingPlan"
},
"sku": {
"name": "[parameters('skuName')]",
"capacity": "[parameters('skuCapacity')]"
},
"properties": {
"name": "[parameters('hostingPlanName')]"
}
},
{
"apiVersion": "2015-08-01",
"name": "[parameters('siteName')]",
"type": "Microsoft.Web/sites",
"location": "[resourceGroup().location]",
"tags": {
"[concat('hidden-related:', resourceGroup().id, '/providers/Microsoft.Web/serverfarms/', parameters('hostingPlanName'))]": "Resource",
"displayName": "Website"
},
"dependsOn": [
"[concat('Microsoft.Web/serverfarms/', parameters('hostingPlanName'))]"
],
"properties": {
"name": "[parameters('siteName')]",
"serverFarmId": "[resourceId('Microsoft.Web/serverfarms', parameters('hostingPlanName'))]"
},
"resources": [
{
"name": "web",
"type": "sourcecontrols",
"location": "[resourceGroup().location]",
"apiVersion": "2015-08-01",
"dependsOn": [
"[concat('Microsoft.Web/sites/', parameters('siteName'))]",
"[concat('Microsoft.Web/Sites/', parameters('siteName'), '/config/appsettings')]"
],
"tags": {
"displayName": "CustomerPortal"
},
"properties": {
"RepoUrl": "[parameters('repoUrl')]",
"branch": "[parameters('branch')]",
"IsManualIntegration": true
}
},
{
"name": "appsettings",
"type": "config",
"apiVersion": "2015-08-01",
"dependsOn": [
"[concat('Microsoft.Web/sites/', parameters('siteName'))]",
"[concat('Microsoft.Insights/components/', parameters('siteName'))]",
"[concat('Microsoft.Cache/Redis/', variables('cacheName'))]"
],
"tags": {
"displayName": "ApplicationSettings"
},
"properties": {
"ApplicationId": "[parameters('applicationId')]",
"ApplicationTenantId": "[parameters('applicationTenantId')]",
"InstrumentationKey": "[reference(concat('Microsoft.Insights/components/', parameters('siteName'))).InstrumentationKey]",
"PartnerCenterApplicationId": "[parameters('partnerCenterApplicationId')]",
"PartnerCenterApplicationTenantId": "[parameters('partnerCenterApplicationTenantId')]",
"VaultApplicationCertThumbprint": "[parameters('keyVaultApplicationCertThumbprint')]",
"VaultApplicationId": "[parameters('keyVaultApplicationId')]",
"VaultApplicationTenantId": "[parameters('keyVaultTenantId')]",
"VaultBaseAddress": "[concat('https://', parameters('keyVaultName'), '.vault.azure.net')]"
}
}
]
},
{
"apiVersion": "2014-04-01",
"name": "[parameters('siteName')]",
"type": "Microsoft.Insights/components",
"location": "[parameters('appInsightsLocation')]",
"tags": {
"[concat('hidden-link:', resourceGroup().id, '/providers/Microsoft.Web/sites/', parameters('siteName'))]": "Resource",
"displayName": "AppInsightsComponent"
},
"properties": {
"applicationId": "[parameters('siteName')]"
}
}
],
"outputs": {
"WebsiteUrl": {
"type": "string",
"value": "[concat('https://',reference(resourceId('Microsoft.Web/sites', parameters('siteName'))).hostNames[0])]"
}
}
}

Просмотреть файл

@ -0,0 +1,60 @@
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"appInsightsLocation": {
"value": "South Central US"
},
"applicationId": {
"value": ""
},
"applicationSecret": {
"value": ""
},
"applicationTenantId": {
"value": ""
},
"branch": {
"value": "master"
},
"hostingPlanName": {
"value": ""
},
"keyVaultApplicationCertThumbprint": {
"value": ""
},
"keyVaultApplicationId": {
"value": ""
},
"keyVaultName": {
"value": ""
},
"keyVaultSkuName": {
"value": "Standard"
},
"keyVaultTenantId": {
"value": ""
},
"partnerCenterApplicationId": {
"value": ""
},
"partnerCenterApplicationSecret": {
"value": ""
},
"partnerCenterApplicationTenantId": {
"value": ""
},
"repoUrl": {
"value": "https://github.com/Microsoft/Partner-Center-Bot"
},
"siteName": {
"value": ""
},
"skuName": {
"value": "B1"
},
"skuCapacity": {
"value": 1
}
}
}

Просмотреть файл

@ -20,7 +20,20 @@
<Add Type="Microsoft.ApplicationInsights.Web.SessionTelemetryInitializer, Microsoft.AI.Web"/> <Add Type="Microsoft.ApplicationInsights.Web.SessionTelemetryInitializer, Microsoft.AI.Web"/>
</TelemetryInitializers> </TelemetryInitializers>
<TelemetryModules> <TelemetryModules>
<Add Type="Microsoft.ApplicationInsights.DependencyCollector.DependencyTrackingTelemetryModule, Microsoft.AI.DependencyCollector"/> <Add Type="Microsoft.ApplicationInsights.DependencyCollector.DependencyTrackingTelemetryModule, Microsoft.AI.DependencyCollector">
<ExcludeComponentCorrelationHttpHeadersOnDomains>
<!--
Requests to the following hostnames will not be modified by adding correlation headers.
This is only applicable if Profiler is installed via either StatusMonitor or Azure Extension.
Add entries here to exclude additional hostnames.
NOTE: this configuration will be lost upon NuGet upgrade.
-->
<Add>core.windows.net</Add>
<Add>core.chinacloudapi.cn</Add>
<Add>core.cloudapi.de</Add>
<Add>core.usgovcloudapi.net</Add>
</ExcludeComponentCorrelationHttpHeadersOnDomains>
</Add>
<Add Type="Microsoft.ApplicationInsights.Extensibility.PerfCounterCollector.PerformanceCollectorModule, Microsoft.AI.PerfCounterCollector"> <Add Type="Microsoft.ApplicationInsights.Extensibility.PerfCounterCollector.PerformanceCollectorModule, Microsoft.AI.PerfCounterCollector">
<!-- <!--
Use the following syntax here to collect additional performance counters: Use the following syntax here to collect additional performance counters:

Просмотреть файл

@ -54,91 +54,105 @@
<Reference Include="Microsoft.AI.Agent.Intercept, Version=2.0.7.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> <Reference Include="Microsoft.AI.Agent.Intercept, Version=2.0.7.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.ApplicationInsights.Agent.Intercept.2.0.7\lib\net45\Microsoft.AI.Agent.Intercept.dll</HintPath> <HintPath>..\..\packages\Microsoft.ApplicationInsights.Agent.Intercept.2.0.7\lib\net45\Microsoft.AI.Agent.Intercept.dll</HintPath>
</Reference> </Reference>
<Reference Include="Microsoft.AI.DependencyCollector, Version=2.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> <Reference Include="Microsoft.AI.DependencyCollector, Version=2.3.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.ApplicationInsights.DependencyCollector.2.2.0\lib\net45\Microsoft.AI.DependencyCollector.dll</HintPath> <HintPath>..\..\packages\Microsoft.ApplicationInsights.DependencyCollector.2.3.0\lib\net45\Microsoft.AI.DependencyCollector.dll</HintPath>
</Reference> </Reference>
<Reference Include="Microsoft.AI.PerfCounterCollector, Version=2.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> <Reference Include="Microsoft.AI.PerfCounterCollector, Version=2.3.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.ApplicationInsights.PerfCounterCollector.2.2.0\lib\net45\Microsoft.AI.PerfCounterCollector.dll</HintPath> <HintPath>..\..\packages\Microsoft.ApplicationInsights.PerfCounterCollector.2.3.0\lib\net45\Microsoft.AI.PerfCounterCollector.dll</HintPath>
</Reference> </Reference>
<Reference Include="Microsoft.AI.ServerTelemetryChannel, Version=2.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> <Reference Include="Microsoft.AI.ServerTelemetryChannel, Version=2.3.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.ApplicationInsights.WindowsServer.TelemetryChannel.2.2.0\lib\net45\Microsoft.AI.ServerTelemetryChannel.dll</HintPath> <HintPath>..\..\packages\Microsoft.ApplicationInsights.WindowsServer.TelemetryChannel.2.3.0\lib\net45\Microsoft.AI.ServerTelemetryChannel.dll</HintPath>
</Reference> </Reference>
<Reference Include="Microsoft.AI.Web, Version=2.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> <Reference Include="Microsoft.AI.Web, Version=2.3.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.ApplicationInsights.Web.2.2.0\lib\net45\Microsoft.AI.Web.dll</HintPath> <HintPath>..\..\packages\Microsoft.ApplicationInsights.Web.2.3.0\lib\net45\Microsoft.AI.Web.dll</HintPath>
</Reference> </Reference>
<Reference Include="Microsoft.AI.WindowsServer, Version=2.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> <Reference Include="Microsoft.AI.WindowsServer, Version=2.3.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.ApplicationInsights.WindowsServer.2.2.0\lib\net45\Microsoft.AI.WindowsServer.dll</HintPath> <HintPath>..\..\packages\Microsoft.ApplicationInsights.WindowsServer.2.3.0\lib\net45\Microsoft.AI.WindowsServer.dll</HintPath>
</Reference> </Reference>
<Reference Include="Microsoft.ApplicationInsights, Version=2.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> <Reference Include="Microsoft.ApplicationInsights, Version=2.3.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.ApplicationInsights.2.2.0\lib\net46\Microsoft.ApplicationInsights.dll</HintPath> <HintPath>..\..\packages\Microsoft.ApplicationInsights.2.3.0\lib\net46\Microsoft.ApplicationInsights.dll</HintPath>
</Reference> </Reference>
<Reference Include="Microsoft.Azure.KeyVault, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> <Reference Include="Microsoft.Azure.KeyVault, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Azure.KeyVault.2.0.6\lib\net45\Microsoft.Azure.KeyVault.dll</HintPath> <HintPath>..\..\packages\Microsoft.Azure.KeyVault.2.0.6\lib\net45\Microsoft.Azure.KeyVault.dll</HintPath>
</Reference> </Reference>
<Reference Include="Microsoft.Azure.KeyVault.WebKey, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> <Reference Include="Microsoft.Azure.KeyVault.WebKey, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Azure.KeyVault.WebKey.2.0.4\lib\net45\Microsoft.Azure.KeyVault.WebKey.dll</HintPath> <HintPath>..\..\packages\Microsoft.Azure.KeyVault.WebKey.2.0.5\lib\net452\Microsoft.Azure.KeyVault.WebKey.dll</HintPath>
</Reference> </Reference>
<Reference Include="Microsoft.Bot.Builder, Version=3.5.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> <Reference Include="Microsoft.Bot.Builder, Version=3.8.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Bot.Builder.3.5.5\lib\net46\Microsoft.Bot.Builder.dll</HintPath> <HintPath>..\..\packages\Microsoft.Bot.Builder.3.8.0\lib\net46\Microsoft.Bot.Builder.dll</HintPath>
</Reference> </Reference>
<Reference Include="Microsoft.Bot.Builder.Autofac, Version=3.5.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> <Reference Include="Microsoft.Bot.Builder.Autofac, Version=3.8.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Bot.Builder.3.5.5\lib\net46\Microsoft.Bot.Builder.Autofac.dll</HintPath> <HintPath>..\..\packages\Microsoft.Bot.Builder.3.8.0\lib\net46\Microsoft.Bot.Builder.Autofac.dll</HintPath>
</Reference> </Reference>
<Reference Include="Microsoft.Bot.Builder.CognitiveServices.QnAMaker, Version=1.0.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> <Reference Include="Microsoft.Bot.Builder.CognitiveServices.QnAMaker, Version=1.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Bot.Builder.CognitiveServices.1.0.3\lib\net46\Microsoft.Bot.Builder.CognitiveServices.QnAMaker.dll</HintPath> <HintPath>..\..\packages\Microsoft.Bot.Builder.CognitiveServices.1.1.0\lib\net46\Microsoft.Bot.Builder.CognitiveServices.QnAMaker.dll</HintPath>
</Reference> </Reference>
<Reference Include="Microsoft.Bot.Connector, Version=3.5.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> <Reference Include="Microsoft.Bot.Connector, Version=3.8.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Bot.Builder.3.5.5\lib\net46\Microsoft.Bot.Connector.dll</HintPath> <HintPath>..\..\packages\Microsoft.Bot.Builder.3.8.0\lib\net46\Microsoft.Bot.Connector.dll</HintPath>
</Reference> </Reference>
<Reference Include="Microsoft.CSharp" /> <Reference Include="Microsoft.CSharp" />
<Reference Include="Microsoft.Graph, Version=1.2.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> <Reference Include="Microsoft.Graph, Version=1.3.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Graph.1.2.1\lib\portable45-net45+win8+wpa81\Microsoft.Graph.dll</HintPath> <HintPath>..\..\packages\Microsoft.Graph.1.3.0\lib\net45\Microsoft.Graph.dll</HintPath>
</Reference> </Reference>
<Reference Include="Microsoft.Graph.Core, Version=1.3.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> <Reference Include="Microsoft.Graph.Core, Version=1.4.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Graph.Core.1.3.0\lib\portable45-net45+win8+wpa81\Microsoft.Graph.Core.dll</HintPath> <HintPath>..\..\packages\Microsoft.Graph.Core.1.4.0\lib\net45\Microsoft.Graph.Core.dll</HintPath>
</Reference> </Reference>
<Reference Include="Microsoft.IdentityModel.Clients.ActiveDirectory, Version=3.13.8.999, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> <Reference Include="Microsoft.IdentityModel.Clients.ActiveDirectory, Version=3.13.9.1126, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.IdentityModel.Clients.ActiveDirectory.3.13.8\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.dll</HintPath> <HintPath>..\..\packages\Microsoft.IdentityModel.Clients.ActiveDirectory.3.13.9\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.dll</HintPath>
</Reference> </Reference>
<Reference Include="Microsoft.IdentityModel.Clients.ActiveDirectory.Platform, Version=3.13.8.999, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> <Reference Include="Microsoft.IdentityModel.Clients.ActiveDirectory.Platform, Version=3.13.9.1126, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.IdentityModel.Clients.ActiveDirectory.3.13.8\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll</HintPath> <HintPath>..\..\packages\Microsoft.IdentityModel.Clients.ActiveDirectory.3.13.9\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll</HintPath>
</Reference> </Reference>
<Reference Include="Microsoft.IdentityModel.Protocol.Extensions, Version=1.0.2.33, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> <Reference Include="Microsoft.IdentityModel.Protocol.Extensions, Version=1.0.40306.1554, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.IdentityModel.Protocol.Extensions.1.0.2.206221351\lib\net45\Microsoft.IdentityModel.Protocol.Extensions.dll</HintPath> <HintPath>..\..\packages\Microsoft.IdentityModel.Protocol.Extensions.1.0.4.403061554\lib\net45\Microsoft.IdentityModel.Protocol.Extensions.dll</HintPath>
</Reference> </Reference>
<Reference Include="Microsoft.Rest.ClientRuntime, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> <Reference Include="Microsoft.Rest.ClientRuntime, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Rest.ClientRuntime.2.3.6\lib\net45\Microsoft.Rest.ClientRuntime.dll</HintPath> <HintPath>..\..\packages\Microsoft.Rest.ClientRuntime.2.3.7\lib\net452\Microsoft.Rest.ClientRuntime.dll</HintPath>
</Reference> </Reference>
<Reference Include="Microsoft.Rest.ClientRuntime.Azure, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> <Reference Include="Microsoft.Rest.ClientRuntime.Azure, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Rest.ClientRuntime.Azure.3.3.5\lib\net45\Microsoft.Rest.ClientRuntime.Azure.dll</HintPath> <HintPath>..\..\packages\Microsoft.Rest.ClientRuntime.Azure.3.3.6\lib\net452\Microsoft.Rest.ClientRuntime.Azure.dll</HintPath>
</Reference> </Reference>
<Reference Include="Microsoft.Store.PartnerCenter, Version=1.3.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> <Reference Include="Microsoft.Store.PartnerCenter, Version=1.4.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Store.PartnerCenter.1.3.0.0\lib\net45\Microsoft.Store.PartnerCenter.dll</HintPath> <HintPath>..\..\packages\Microsoft.Store.PartnerCenter.1.4.0\lib\net45\Microsoft.Store.PartnerCenter.dll</HintPath>
</Reference> </Reference>
<Reference Include="Microsoft.Store.PartnerCenter.Extensions, Version=1.3.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> <Reference Include="Microsoft.Store.PartnerCenter.Extensions, Version=1.4.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Store.PartnerCenter.1.3.0.0\lib\net45\Microsoft.Store.PartnerCenter.Extensions.dll</HintPath> <HintPath>..\..\packages\Microsoft.Store.PartnerCenter.1.4.0\lib\net45\Microsoft.Store.PartnerCenter.Extensions.dll</HintPath>
</Reference> </Reference>
<Reference Include="Microsoft.Store.PartnerCenter.Models, Version=1.3.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> <Reference Include="Microsoft.Store.PartnerCenter.Models, Version=1.4.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Store.PartnerCenter.1.3.0.0\lib\net45\Microsoft.Store.PartnerCenter.Models.dll</HintPath> <HintPath>..\..\packages\Microsoft.Store.PartnerCenter.1.4.0\lib\net45\Microsoft.Store.PartnerCenter.Models.dll</HintPath>
</Reference> </Reference>
<Reference Include="Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL"> <Reference Include="Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll</HintPath> <HintPath>..\..\packages\Newtonsoft.Json.10.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference> </Reference>
<Reference Include="StackExchange.Redis.StrongName, Version=1.2.1.0, Culture=neutral, PublicKeyToken=c219ff1ca8c2ce46, processorArchitecture=MSIL"> <Reference Include="StackExchange.Redis.StrongName, Version=1.2.3.0, Culture=neutral, PublicKeyToken=c219ff1ca8c2ce46, processorArchitecture=MSIL">
<HintPath>..\..\packages\StackExchange.Redis.StrongName.1.2.1\lib\net46\StackExchange.Redis.StrongName.dll</HintPath> <HintPath>..\..\packages\StackExchange.Redis.StrongName.1.2.3\lib\net46\StackExchange.Redis.StrongName.dll</HintPath>
</Reference> </Reference>
<Reference Include="System.Data.DataSetExtensions" /> <Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.IdentityModel.Tokens.Jwt, Version=4.0.20622.1351, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> <Reference Include="System.IdentityModel.Tokens.Jwt, Version=4.0.40306.1554, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.IdentityModel.Tokens.Jwt.4.0.2.206221351\lib\net45\System.IdentityModel.Tokens.Jwt.dll</HintPath> <HintPath>..\..\packages\System.IdentityModel.Tokens.Jwt.4.0.4.403061554\lib\net45\System.IdentityModel.Tokens.Jwt.dll</HintPath>
</Reference> </Reference>
<Reference Include="System.IO.Compression" /> <Reference Include="System.IO.Compression" />
<Reference Include="System.Net" /> <Reference Include="System.Net" />
<Reference Include="System.Net.Http" /> <Reference Include="System.Net.Http, Version=4.1.1.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.Net.Http.4.3.2\lib\net46\System.Net.Http.dll</HintPath>
</Reference>
<Reference Include="System.Net.Http.Formatting, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> <Reference Include="System.Net.Http.Formatting, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.AspNet.WebApi.Client.5.2.3\lib\net45\System.Net.Http.Formatting.dll</HintPath> <HintPath>..\..\packages\Microsoft.AspNet.WebApi.Client.5.2.3\lib\net45\System.Net.Http.Formatting.dll</HintPath>
</Reference> </Reference>
<Reference Include="System.Net.Http.WebRequest" /> <Reference Include="System.Net.Http.WebRequest" />
<Reference Include="System.Runtime.Serialization" /> <Reference Include="System.Runtime.Serialization" />
<Reference Include="System.Security.Cryptography.Algorithms, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.Security.Cryptography.Algorithms.4.3.0\lib\net461\System.Security.Cryptography.Algorithms.dll</HintPath>
</Reference>
<Reference Include="System.Security.Cryptography.Encoding, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.Security.Cryptography.Encoding.4.3.0\lib\net46\System.Security.Cryptography.Encoding.dll</HintPath>
</Reference>
<Reference Include="System.Security.Cryptography.Primitives, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.Security.Cryptography.Primitives.4.3.0\lib\net46\System.Security.Cryptography.Primitives.dll</HintPath>
</Reference>
<Reference Include="System.Security.Cryptography.X509Certificates, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.Security.Cryptography.X509Certificates.4.3.0\lib\net461\System.Security.Cryptography.X509Certificates.dll</HintPath>
</Reference>
<Reference Include="System.Threading.Tasks.Extensions, Version=4.1.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL"> <Reference Include="System.Threading.Tasks.Extensions, Version=4.1.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.Threading.Tasks.Extensions.4.3.0\lib\portable-net45+win8+wp8+wpa81\System.Threading.Tasks.Extensions.dll</HintPath> <HintPath>..\..\packages\System.Threading.Tasks.Extensions.4.3.0\lib\portable-net45+win8+wp8+wpa81\System.Threading.Tasks.Extensions.dll</HintPath>
</Reference> </Reference>
@ -199,11 +213,17 @@
<Compile Include="Intents\IntentService.cs" /> <Compile Include="Intents\IntentService.cs" />
<Compile Include="Intents\ListCustomersIntent.cs" /> <Compile Include="Intents\ListCustomersIntent.cs" />
<Compile Include="Intents\ListSubscriptionsIntent.cs" /> <Compile Include="Intents\ListSubscriptionsIntent.cs" />
<Compile Include="Intents\OfficeIssuesIntent.cs" />
<Compile Include="Intents\QuestionIntent.cs" /> <Compile Include="Intents\QuestionIntent.cs" />
<Compile Include="Intents\SelectCustomerIntent.cs" /> <Compile Include="Intents\SelectCustomerIntent.cs" />
<Compile Include="Intents\SelectSubscriptionIntent.cs" /> <Compile Include="Intents\SelectSubscriptionIntent.cs" />
<Compile Include="Logic\AiExceptionLogger.cs" /> <Compile Include="Logic\AiExceptionLogger.cs" />
<Compile Include="Logic\CommunicationException.cs" />
<Compile Include="Logic\IPartnerOperations.cs" /> <Compile Include="Logic\IPartnerOperations.cs" />
<Compile Include="Logic\Office\HealthEvent.cs" />
<Compile Include="Logic\Office\IServiceCommunications.cs" />
<Compile Include="Logic\Office\ODataResponse.cs" />
<Compile Include="Logic\Office\ServiceCommunications.cs" />
<Compile Include="Logic\OperationContext.cs" /> <Compile Include="Logic\OperationContext.cs" />
<Compile Include="Logic\PartnerOperations.cs" /> <Compile Include="Logic\PartnerOperations.cs" />
<Compile Include="Security\AuthenticationProvider.cs" /> <Compile Include="Security\AuthenticationProvider.cs" />
@ -242,9 +262,6 @@
<Content Include="ApplicationInsights.config"> <Content Include="ApplicationInsights.config">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
<Content Include="Settings.StyleCop">
<SubType>Designer</SubType>
</Content>
<EmbeddedResource Include="Resources.de.resx"> <EmbeddedResource Include="Resources.de.resx">
<SubType>Designer</SubType> <SubType>Designer</SubType>
</EmbeddedResource> </EmbeddedResource>
@ -299,13 +316,6 @@
</FlavorProperties> </FlavorProperties>
</VisualStudio> </VisualStudio>
</ProjectExtensions> </ProjectExtensions>
<Import Project="..\..\packages\Visual-StyleCop.MSBuild.4.7.59.0\build\Visual-StyleCop.MSBuild.Targets" Condition="Exists('..\..\packages\Visual-StyleCop.MSBuild.4.7.59.0\build\Visual-StyleCop.MSBuild.Targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\..\packages\Visual-StyleCop.MSBuild.4.7.59.0\build\Visual-StyleCop.MSBuild.Targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Visual-StyleCop.MSBuild.4.7.59.0\build\Visual-StyleCop.MSBuild.Targets'))" />
</Target>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets. Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild"> <Target Name="BeforeBuild">

Просмотреть файл

@ -85,6 +85,11 @@ namespace Microsoft.Store.PartnerCenter.Bot.Configuration
/// </summary> /// </summary>
public string MicrosoftAppPassword => this.GetConfigurationValue("MicrosoftAppPassword"); public string MicrosoftAppPassword => this.GetConfigurationValue("MicrosoftAppPassword");
/// <summary>
/// Gets the Office 365 management endpoint address.
/// </summary>
public string OfficeManagementEndpoint => ConfigurationManager.AppSettings["OfficeManagementEndpoint"];
/// <summary> /// <summary>
/// Gets the Partner Center API endpoint. /// Gets the Partner Center API endpoint.
/// </summary> /// </summary>

Просмотреть файл

@ -61,6 +61,11 @@ namespace Microsoft.Store.PartnerCenter.Bot.Configuration
/// </summary> /// </summary>
string MicrosoftAppPassword { get; } string MicrosoftAppPassword { get; }
/// <summary>
/// Gets the Office 365 management endpoint address.
/// </summary>
string OfficeManagementEndpoint { get; }
/// <summary> /// <summary>
/// Gets the Partner Center API endpoint. /// Gets the Partner Center API endpoint.
/// </summary> /// </summary>

Просмотреть файл

@ -47,6 +47,7 @@ namespace Microsoft.Store.PartnerCenter.Bot.Controllers
[Route("")] [Route("")]
public async Task<HttpResponseMessage> PostAsync([FromBody]Activity activity) public async Task<HttpResponseMessage> PostAsync([FromBody]Activity activity)
{ {
ConnectorClient client;
DateTime startTime; DateTime startTime;
Dictionary<string, double> eventMeasurements; Dictionary<string, double> eventMeasurements;
Dictionary<string, string> eventProperties; Dictionary<string, string> eventProperties;
@ -55,9 +56,23 @@ namespace Microsoft.Store.PartnerCenter.Bot.Controllers
{ {
startTime = DateTime.Now; startTime = DateTime.Now;
if (activity.Type == ActivityTypes.ConversationUpdate)
{
if (activity.MembersAdded.Any(o => o.Id == activity.Recipient.Id))
{
client = new ConnectorClient(
new Uri(activity.ServiceUrl),
new MicrosoftAppCredentials(
Service.Configuration.MicrosoftAppId,
Service.Configuration.MicrosoftAppPassword));
await client.Conversations.ReplyToActivityAsync(activity.CreateReply(Resources.Welcome));
}
}
if (activity.Type == ActivityTypes.Message) if (activity.Type == ActivityTypes.Message)
{ {
await Conversation.SendAsync(activity, () => new ActionDialog(this.Service)); await Conversation.SendAsync(activity, () => new ActionDialog(Service));
} }
// Capture the request for the customer summary for analysis. // Capture the request for the customer summary for analysis.
@ -74,12 +89,13 @@ namespace Microsoft.Store.PartnerCenter.Bot.Controllers
{ "ElapsedMilliseconds", DateTime.Now.Subtract(startTime).TotalMilliseconds } { "ElapsedMilliseconds", DateTime.Now.Subtract(startTime).TotalMilliseconds }
}; };
this.Service.Telemetry.TrackEvent("api/messages", eventProperties, eventMeasurements); Service.Telemetry.TrackEvent("api/messages", eventProperties, eventMeasurements);
return new HttpResponseMessage(HttpStatusCode.Accepted); return new HttpResponseMessage(HttpStatusCode.Accepted);
} }
finally finally
{ {
client = null;
eventMeasurements = null; eventMeasurements = null;
eventProperties = null; eventProperties = null;
} }

Просмотреть файл

@ -94,14 +94,14 @@ namespace Microsoft.Store.PartnerCenter.Bot.Controllers
botData = scope.Resolve<IBotData>(); botData = scope.Resolve<IBotData>();
await botData.LoadAsync(cancellationToken); await botData.LoadAsync(cancellationToken);
if (!this.Validate(botData, stateData)) if (!Validate(botData, stateData))
{ {
return Request.CreateErrorResponse( return Request.CreateErrorResponse(
HttpStatusCode.BadRequest, HttpStatusCode.BadRequest,
new InvalidOperationException(Resources.InvalidAuthenticationException)); new InvalidOperationException(Resources.InvalidAuthenticationException));
} }
principal = await this.GetCustomerPrincipalAsync(code); principal = await GetCustomerPrincipalAsync(code);
if (principal == null) if (principal == null)
{ {
@ -134,7 +134,7 @@ namespace Microsoft.Store.PartnerCenter.Bot.Controllers
{ "NumberOfRoles", principal.Roles.Count } { "NumberOfRoles", principal.Roles.Count }
}; };
this.Service.Telemetry.TrackEvent("api/OAuthCallback", eventProperties, eventMeasurements); Service.Telemetry.TrackEvent("api/OAuthCallback", eventProperties, eventMeasurements);
response = Request.CreateResponse(HttpStatusCode.OK); response = Request.CreateResponse(HttpStatusCode.OK);
response.Content = new StringContent(Resources.SuccessfulAuthentication); response.Content = new StringContent(Resources.SuccessfulAuthentication);
@ -142,7 +142,7 @@ namespace Microsoft.Store.PartnerCenter.Bot.Controllers
} }
catch (Exception ex) catch (Exception ex)
{ {
this.Service.Telemetry.TrackException(ex); Service.Telemetry.TrackException(ex);
response = Request.CreateErrorResponse(HttpStatusCode.BadRequest, ex); response = Request.CreateErrorResponse(HttpStatusCode.BadRequest, ex);
} }
finally finally
@ -182,20 +182,20 @@ namespace Microsoft.Store.PartnerCenter.Bot.Controllers
redirectUri = redirectUri =
new Uri($"{HttpContext.Current.Request.Url.Scheme}://{HttpContext.Current.Request.Url.Host}:{HttpContext.Current.Request.Url.Port}/{BotConstants.CallbackPath}"); new Uri($"{HttpContext.Current.Request.Url.Scheme}://{HttpContext.Current.Request.Url.Host}:{HttpContext.Current.Request.Url.Port}/{BotConstants.CallbackPath}");
authResult = await this.Service.TokenManagement.GetTokenByAuthorizationCodeAsync( authResult = await Service.TokenManagement.GetTokenByAuthorizationCodeAsync(
$"{this.Service.Configuration.ActiveDirectoryEndpoint}/{BotConstants.AuthorityEndpoint}", $"{Service.Configuration.ActiveDirectoryEndpoint}/{BotConstants.AuthorityEndpoint}",
code, code,
this.Service.Configuration.GraphEndpoint, Service.Configuration.GraphEndpoint,
redirectUri); redirectUri);
client = new GraphClient(this.Service, authResult.TenantId); client = new GraphClient(Service, authResult.TenantId);
roles = await client.GetDirectoryRolesAsync(authResult.UserInfo.UniqueId); roles = await client.GetDirectoryRolesAsync(authResult.UserInfo.UniqueId);
principal = new CustomerPrincipal principal = new CustomerPrincipal
{ {
AccessToken = authResult.AccessToken, AccessToken = authResult.AccessToken,
AvailableIntents = (from intent in this.Service.Intent.Intents AvailableIntents = (from intent in Service.Intent.Intents
let roleList = Permissions.GetRoles(intent.Value.Permissions) let roleList = Permissions.GetRoles(intent.Value.Permissions)
from r in roleList from r in roleList
where roles.SingleOrDefault(x => x.DisplayName.Equals(r)) != null where roles.SingleOrDefault(x => x.DisplayName.Equals(r)) != null
@ -207,11 +207,11 @@ namespace Microsoft.Store.PartnerCenter.Bot.Controllers
Roles = roles Roles = roles
}; };
if (!this.Service.Configuration.ApplicationTenantId.Equals( if (!Service.Configuration.ApplicationTenantId.Equals(
authResult.TenantId, authResult.TenantId,
StringComparison.CurrentCultureIgnoreCase)) StringComparison.CurrentCultureIgnoreCase))
{ {
await this.Service.PartnerOperations.GetCustomerAsync(principal, authResult.TenantId); await Service.PartnerOperations.GetCustomerAsync(principal, authResult.TenantId);
} }
return principal; return principal;
@ -245,12 +245,10 @@ namespace Microsoft.Store.PartnerCenter.Bot.Controllers
/// </exception> /// </exception>
private bool Validate(IBotData botData, IDictionary<string, string> stateData) private bool Validate(IBotData botData, IDictionary<string, string> stateData)
{ {
string uniqueId;
botData.AssertNotNull(nameof(botData)); botData.AssertNotNull(nameof(botData));
stateData.AssertNotNull(nameof(stateData)); stateData.AssertNotNull(nameof(stateData));
if (botData.PrivateConversationData.TryGetValue(BotConstants.UniqueIdentifierKey, out uniqueId)) if (botData.PrivateConversationData.TryGetValue(BotConstants.UniqueIdentifierKey, out string uniqueId))
{ {
if (!uniqueId.Equals(stateData[BotConstants.UniqueIdentifierKey], StringComparison.CurrentCultureIgnoreCase)) if (!uniqueId.Equals(stateData[BotConstants.UniqueIdentifierKey], StringComparison.CurrentCultureIgnoreCase))
{ {

Просмотреть файл

@ -11,8 +11,10 @@ namespace Microsoft.Store.PartnerCenter.Bot.Dialogs
using System.Text; using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Forms;
using Logic; using Logic;
using Microsoft.Bot.Builder.Dialogs; using Microsoft.Bot.Builder.Dialogs;
using Microsoft.Bot.Builder.FormFlow;
using Microsoft.Bot.Builder.Luis; using Microsoft.Bot.Builder.Luis;
using Microsoft.Bot.Builder.Luis.Models; using Microsoft.Bot.Builder.Luis.Models;
using Microsoft.Bot.Connector; using Microsoft.Bot.Connector;
@ -82,7 +84,7 @@ namespace Microsoft.Store.PartnerCenter.Bot.Dialogs
} }
await context.PostAsync(message); await context.PostAsync(message);
context.Wait(this.MessageReceived); context.Wait(MessageReceived);
} }
finally finally
{ {
@ -113,22 +115,22 @@ namespace Microsoft.Store.PartnerCenter.Bot.Dialogs
{ {
key = result.TopScoringIntent.Intent.ToCamelCase(); key = result.TopScoringIntent.Intent.ToCamelCase();
principal = await context.GetCustomerPrincipalAsync(this.service); principal = await context.GetCustomerPrincipalAsync(service);
if (principal == null) if (principal == null)
{ {
await this.HelpAsync(context); await HelpAsync(context);
return; return;
} }
if (principal.AvailableIntents.ContainsKey(key)) if (principal.AvailableIntents.ContainsKey(key))
{ {
await principal.AvailableIntents[key] await principal.AvailableIntents[key]
.ExecuteAsync(context, message, result, this.service); .ExecuteAsync(context, message, result, service);
} }
else else
{ {
await this.HelpAsync(context); await HelpAsync(context);
} }
} }
finally finally
@ -154,14 +156,14 @@ namespace Microsoft.Store.PartnerCenter.Bot.Dialogs
if (message.Text.Equals(Resources.Login, StringComparison.CurrentCultureIgnoreCase)) if (message.Text.Equals(Resources.Login, StringComparison.CurrentCultureIgnoreCase))
{ {
await context.Forward( await context.Forward(
new AuthDialog(this.service, message), new AuthDialog(service, message),
this.ResumeAfterAuth, ResumeAfterAuth,
message, message,
CancellationToken.None); CancellationToken.None);
} }
else if (message.Text.Equals(Resources.Help, StringComparison.CurrentCultureIgnoreCase)) else if (message.Text.Equals(Resources.Help, StringComparison.CurrentCultureIgnoreCase))
{ {
await this.HelpAsync(context); await HelpAsync(context);
} }
else else
{ {
@ -183,7 +185,8 @@ namespace Microsoft.Store.PartnerCenter.Bot.Dialogs
/// <exception cref="ArgumentNullException"> /// <exception cref="ArgumentNullException">
/// <paramref name="context"/> is null. /// <paramref name="context"/> is null.
/// or /// or
/// <paramref name="result"/> is null.</exception> /// <paramref name="result"/> is null.
/// </exception>
private async Task ResumeAfterAuth(IDialogContext context, IAwaitable<string> result) private async Task ResumeAfterAuth(IDialogContext context, IAwaitable<string> result)
{ {
context.AssertNotNull(nameof(context)); context.AssertNotNull(nameof(context));
@ -192,7 +195,7 @@ namespace Microsoft.Store.PartnerCenter.Bot.Dialogs
string message = await result; string message = await result;
await context.PostAsync(message); await context.PostAsync(message);
await this.HelpAsync(context); await HelpAsync(context);
} }
} }
} }

Просмотреть файл

@ -49,7 +49,7 @@ namespace Microsoft.Store.PartnerCenter.Bot.Dialogs
message.AssertNotNull(nameof(message)); message.AssertNotNull(nameof(message));
this.service = service; this.service = service;
this.conversationReference = message.ToConversationReference(); conversationReference = message.ToConversationReference();
} }
/// <summary> /// <summary>
@ -63,7 +63,7 @@ namespace Microsoft.Store.PartnerCenter.Bot.Dialogs
public async Task StartAsync(IDialogContext context) public async Task StartAsync(IDialogContext context)
{ {
context.AssertNotNull(nameof(context)); context.AssertNotNull(nameof(context));
await this.AuthenticateAsync(context); await AuthenticateAsync(context);
} }
/// <summary> /// <summary>
@ -87,7 +87,7 @@ namespace Microsoft.Store.PartnerCenter.Bot.Dialogs
} }
else else
{ {
context.Wait(this.MessageReceivedAsync); context.Wait(MessageReceivedAsync);
} }
} }
finally finally
@ -115,12 +115,12 @@ namespace Microsoft.Store.PartnerCenter.Bot.Dialogs
{ {
redirectUri = new Uri($"{HttpContext.Current.Request.Url.Scheme}://{HttpContext.Current.Request.Url.Host}:{HttpContext.Current.Request.Url.Port}/{BotConstants.CallbackPath}"); redirectUri = new Uri($"{HttpContext.Current.Request.Url.Scheme}://{HttpContext.Current.Request.Url.Host}:{HttpContext.Current.Request.Url.Port}/{BotConstants.CallbackPath}");
state = $"&state={this.GenerateState(context)}"; state = $"&state={GenerateState(context)}";
authUrl = await this.service.TokenManagement.GetAuthorizationRequestUrlAsync( authUrl = await service.TokenManagement.GetAuthorizationRequestUrlAsync(
$"{this.service.Configuration.ActiveDirectoryEndpoint}/{BotConstants.AuthorityEndpoint}", $"{service.Configuration.ActiveDirectoryEndpoint}/{BotConstants.AuthorityEndpoint}",
redirectUri, redirectUri,
this.service.Configuration.GraphEndpoint, service.Configuration.GraphEndpoint,
state); state);
message = context.MakeMessage(); message = context.MakeMessage();
@ -129,7 +129,7 @@ namespace Microsoft.Store.PartnerCenter.Bot.Dialogs
Resources.SigninCardText, Resources.LoginCaptial, authUrl).ToAttachment()); Resources.SigninCardText, Resources.LoginCaptial, authUrl).ToAttachment());
await context.PostAsync(message); await context.PostAsync(message);
context.Wait(this.MessageReceivedAsync); context.Wait(MessageReceivedAsync);
} }
finally finally
{ {
@ -156,12 +156,12 @@ namespace Microsoft.Store.PartnerCenter.Bot.Dialogs
{ {
state = new Dictionary<string, string> state = new Dictionary<string, string>
{ {
{ BotConstants.BotIdKey, this.conversationReference.Bot.Id }, { BotConstants.BotIdKey, conversationReference.Bot.Id },
{ BotConstants.ChannelIdKey, this.conversationReference.ChannelId }, { BotConstants.ChannelIdKey, conversationReference.ChannelId },
{ BotConstants.ConversationIdKey, this.conversationReference.Conversation.Id }, { BotConstants.ConversationIdKey, conversationReference.Conversation.Id },
{ BotConstants.UniqueIdentifierKey, uniqueId.ToString() }, { BotConstants.UniqueIdentifierKey, uniqueId.ToString() },
{ BotConstants.ServiceUrlKey, this.conversationReference.ServiceUrl }, { BotConstants.ServiceUrlKey, conversationReference.ServiceUrl },
{ BotConstants.UserIdKey, this.conversationReference.User.Id } { BotConstants.UserIdKey, conversationReference.User.Id }
}; };
// Save the unique identifier in the user's private conversation store. This value will be // Save the unique identifier in the user's private conversation store. This value will be

Просмотреть файл

@ -7,6 +7,7 @@
namespace Microsoft.Store.PartnerCenter.Bot.Dialogs namespace Microsoft.Store.PartnerCenter.Bot.Dialogs
{ {
using System; using System;
using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Logic; using Logic;
using Microsoft.Bot.Builder.CognitiveServices.QnAMaker; using Microsoft.Bot.Builder.CognitiveServices.QnAMaker;
@ -32,7 +33,7 @@ namespace Microsoft.Store.PartnerCenter.Bot.Dialogs
{ {
service.AssertNotNull(nameof(service)); service.AssertNotNull(nameof(service));
this.QnAService = new QnAMakerService(new QnAMakerAttribute( QnAService = new QnAMakerService(new QnAMakerAttribute(
service.Configuration.QnASubscriptionKey, service.Configuration.QnASubscriptionKey,
service.Configuration.QnAKnowledgebaseId, service.Configuration.QnAKnowledgebaseId,
"default message", "default message",
@ -53,7 +54,7 @@ namespace Microsoft.Store.PartnerCenter.Bot.Dialogs
{ {
context.AssertNotNull(nameof(context)); context.AssertNotNull(nameof(context));
context.Wait(this.MessageReceivedAsync); context.Wait(MessageReceivedAsync);
} }
#pragma warning restore 1998 #pragma warning restore 1998
@ -71,7 +72,7 @@ namespace Microsoft.Store.PartnerCenter.Bot.Dialogs
public async Task MessageReceivedAsync(IDialogContext context, IAwaitable<IMessageActivity> argument) public async Task MessageReceivedAsync(IDialogContext context, IAwaitable<IMessageActivity> argument)
{ {
IMessageActivity message; IMessageActivity message;
QnAMakerResult result = null; QnAMakerResults result = null;
context.AssertNotNull(nameof(context)); context.AssertNotNull(nameof(context));
argument.AssertNotNull(nameof(argument)); argument.AssertNotNull(nameof(argument));
@ -82,11 +83,11 @@ namespace Microsoft.Store.PartnerCenter.Bot.Dialogs
if (!string.IsNullOrEmpty(message?.Text)) if (!string.IsNullOrEmpty(message?.Text))
{ {
result = await this.QnAService.QueryServiceAsync(message.Text); result = await QnAService.QueryServiceAsync(message.Text);
} }
message = context.MakeMessage(); message = context.MakeMessage();
message.Text = result == null ? Resources.RewordQuestion : result.Answer; message.Text = result == null ? Resources.RewordQuestion : result.Answers.First().Answer;
context.Done(message); context.Done(message);
} }

Просмотреть файл

@ -26,6 +26,11 @@ namespace Microsoft.Store.PartnerCenter.Bot.Intents
/// </summary> /// </summary>
public const string ListSubscriptions = "ListSubscriptions"; public const string ListSubscriptions = "ListSubscriptions";
/// <summary>
/// Intent name for the office issues intent.
/// </summary>
public const string OfficeIssues = "OfficeIssues";
/// <summary> /// <summary>
/// Intent name for the question and answer intent. /// Intent name for the question and answer intent.
/// </summary> /// </summary>

Просмотреть файл

@ -56,7 +56,7 @@ namespace Microsoft.Store.PartnerCenter.Bot.Intents
try try
{ {
this.intents = new Dictionary<string, IIntent>(); intents = new Dictionary<string, IIntent>();
intentTypes = Assembly.GetExecutingAssembly().GetTypes().Where(t => t.IsClass && t.GetInterface("IIntent") != null); intentTypes = Assembly.GetExecutingAssembly().GetTypes().Where(t => t.IsClass && t.GetInterface("IIntent") != null);
foreach (Type t in intentTypes) foreach (Type t in intentTypes)
@ -68,8 +68,8 @@ namespace Microsoft.Store.PartnerCenter.Bot.Intents
continue; continue;
} }
this.intents.Add(intent.Name, intent); intents.Add(intent.Name, intent);
this.service.Telemetry.TrackTrace($"Initialized {intent.Name} intent."); service.Telemetry.TrackTrace($"Initialized {intent.Name} intent.");
} }
} }
finally finally

Просмотреть файл

@ -61,7 +61,7 @@ namespace Microsoft.Store.PartnerCenter.Bot.Intents
Customer customer = null; Customer customer = null;
CustomerPrincipal principal; CustomerPrincipal principal;
DateTime startTime; DateTime startTime;
Dictionary<string, double> eventMeasurements; Dictionary<string, double> eventMetrics;
Dictionary<string, string> eventProperties; Dictionary<string, string> eventProperties;
IMessageActivity response; IMessageActivity response;
List<Subscription> subscriptions; List<Subscription> subscriptions;
@ -94,6 +94,13 @@ namespace Microsoft.Store.PartnerCenter.Bot.Intents
await context.PostAsync(response); await context.PostAsync(response);
// Track the event measurements for analysis.
eventMetrics = new Dictionary<string, double>
{
{ "ElapsedMilliseconds", DateTime.Now.Subtract(startTime).TotalMilliseconds },
{ "NumberOfSubscriptions", response.Attachments.Count }
};
// Capture the request for the customer summary for analysis. // Capture the request for the customer summary for analysis.
eventProperties = new Dictionary<string, string> eventProperties = new Dictionary<string, string>
{ {
@ -103,19 +110,12 @@ namespace Microsoft.Store.PartnerCenter.Bot.Intents
{ "UserId", principal.ObjectId } { "UserId", principal.ObjectId }
}; };
// Track the event measurements for analysis. service.Telemetry.TrackEvent("ListCustomers/Execute", eventProperties, eventMetrics);
eventMeasurements = new Dictionary<string, double>
{
{ "ElapsedMilliseconds", DateTime.Now.Subtract(startTime).TotalMilliseconds },
{ "NumberOfSubscriptions", response.Attachments.Count }
};
service.Telemetry.TrackEvent("ListCustomers/Execute", eventProperties, eventMeasurements);
} }
finally finally
{ {
customer = null; customer = null;
eventMeasurements = null; eventMetrics = null;
eventProperties = null; eventProperties = null;
principal = null; principal = null;
response = null; response = null;

Просмотреть файл

@ -0,0 +1,140 @@
// -----------------------------------------------------------------------
// <copyright file="OfficeIssuesIntent.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
namespace Microsoft.Store.PartnerCenter.Bot.Intents
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Logic;
using Logic.Office;
using Microsoft.Bot.Builder.Dialogs;
using Microsoft.Bot.Builder.Luis.Models;
using Microsoft.Bot.Connector;
using Security;
/// <summary>
/// Processes the request to list Office 365 issues.
/// </summary>
/// <seealso cref="IIntent" />
public class OfficeIssuesIntent : IIntent
{
/// <summary>
/// Gets the message to be displayed when help has been requested.
/// </summary>
public string HelpMessage => Resources.OfficeIssuesHelpMessage;
/// <summary>
/// Gets the name of the intent.
/// </summary>
public string Name => IntentConstants.OfficeIssues;
/// <summary>
/// Gets the permissions required to perform the operation represented by this intent.
/// </summary>
public UserRoles Permissions => UserRoles.Partner | UserRoles.GlobalAdmin;
/// <summary>
/// Performs the operation represented by this intent.
/// </summary>
/// <param name="context">The context of the conversational process.</param>
/// <param name="message">The message from the authenticated user.</param>
/// <param name="result">The result from Language Understanding cognitive service.</param>
/// <param name="service">Provides access to core services;.</param>
/// <returns>An instance of <see cref="Task"/> that represents the asynchronous operation.</returns>
/// <exception cref="ArgumentNullException">
/// <paramref name="context"/> is null.
/// or
/// <paramref name="message"/> is null.
/// or
/// <paramref name="result"/> is null.
/// or
/// <paramref name="service"/> is null.
/// </exception>
public async Task ExecuteAsync(IDialogContext context, IAwaitable<IMessageActivity> message, LuisResult result, IBotService service)
{
AuthenticationToken token;
CustomerPrincipal principal;
DateTime startTime;
Dictionary<string, double> eventMetrics;
Dictionary<string, string> eventProperties;
IMessageActivity response;
List<HealthEvent> healthEvents;
context.AssertNotNull(nameof(context));
message.AssertNotNull(nameof(message));
result.AssertNotNull(nameof(result));
service.AssertNotNull(nameof(service));
try
{
startTime = DateTime.Now;
principal = await context.GetCustomerPrincipalAsync(service);
if (principal.CustomerId.Equals(service.Configuration.PartnerCenterApplicationTenantId, StringComparison.CurrentCultureIgnoreCase))
{
principal.AssertValidCustomerContext(Resources.SelectCustomerFirst);
token = await service.TokenManagement.GetAppOnlyTokenAsync(
$"{service.Configuration.ActiveDirectoryEndpoint}/{principal.Operation.CustomerId}",
service.Configuration.OfficeManagementEndpoint);
healthEvents = await service.ServiceCommunications.GetCurrentStatusAsync(principal.Operation.CustomerId, token.Token);
}
else
{
token = await service.TokenManagement.GetAppOnlyTokenAsync(
$"{service.Configuration.ActiveDirectoryEndpoint}/{principal.CustomerId}",
service.Configuration.OfficeManagementEndpoint);
healthEvents = await service.ServiceCommunications.GetCurrentStatusAsync(principal.CustomerId, token.Token);
}
response = context.MakeMessage();
response.AttachmentLayout = AttachmentLayoutTypes.Carousel;
response.Attachments = healthEvents.Select(e => e.ToAttachment()).ToList();
await context.PostAsync(response);
// Track the event measurements for analysis.
eventMetrics = new Dictionary<string, double>
{
{ "ElapsedMilliseconds", DateTime.Now.Subtract(startTime).TotalMilliseconds },
{ "NumberOfSubscriptions", response.Attachments.Count }
};
// Capture the request for the customer summary for analysis.
eventProperties = new Dictionary<string, string>
{
{ "ChannelId", context.Activity.ChannelId },
{ "CustomerId", principal.CustomerId },
{ "LocalTimeStamp", context.Activity.LocalTimestamp.ToString() },
{ "UserId", principal.ObjectId }
};
service.Telemetry.TrackEvent("OfficeIssues/Execute", eventProperties, eventMetrics);
}
catch (CommunicationException ex)
{
response = context.MakeMessage();
response.Text = Resources.ErrorMessage;
service.Telemetry.TrackException(ex);
await context.PostAsync(response);
}
finally
{
eventMetrics = null;
eventProperties = null;
principal = null;
response = null;
}
}
}
}

Просмотреть файл

@ -24,7 +24,7 @@ namespace Microsoft.Store.PartnerCenter.Bot.Intents
/// <summary> /// <summary>
/// Gets the message to be displayed when help has been requested. /// Gets the message to be displayed when help has been requested.
/// </summary> /// </summary>
public string HelpMessage => string.Empty; public string HelpMessage => Resources.QuestionHelpMessage;
/// <summary> /// <summary>
/// Gets the name of the intent. /// Gets the name of the intent.
@ -34,7 +34,7 @@ namespace Microsoft.Store.PartnerCenter.Bot.Intents
/// <summary> /// <summary>
/// Gets the permissions required to perform the operation represented by this intent. /// Gets the permissions required to perform the operation represented by this intent.
/// </summary> /// </summary>
public UserRoles Permissions => UserRoles.AdminAgents; public UserRoles Permissions => UserRoles.Any;
/// <summary> /// <summary>
/// Performs the operation represented by this intent. /// Performs the operation represented by this intent.

Просмотреть файл

@ -14,6 +14,7 @@ namespace Microsoft.Store.PartnerCenter.Bot.Intents
using Microsoft.Bot.Builder.Luis; using Microsoft.Bot.Builder.Luis;
using Microsoft.Bot.Builder.Luis.Models; using Microsoft.Bot.Builder.Luis.Models;
using Microsoft.Bot.Connector; using Microsoft.Bot.Connector;
using PartnerCenter.Models.Subscriptions;
using Security; using Security;
/// <summary> /// <summary>
@ -58,10 +59,11 @@ namespace Microsoft.Store.PartnerCenter.Bot.Intents
{ {
CustomerPrincipal principal; CustomerPrincipal principal;
DateTime startTime; DateTime startTime;
Dictionary<string, double> eventMeasurements; Dictionary<string, double> eventMetrics;
Dictionary<string, string> eventProperties; Dictionary<string, string> eventProperties;
EntityRecommendation indentifierEntity; EntityRecommendation indentifierEntity;
IMessageActivity response; IMessageActivity response;
Subscription subscription;
string subscriptionId = string.Empty; string subscriptionId = string.Empty;
context.AssertNotNull(nameof(context)); context.AssertNotNull(nameof(context));
@ -80,8 +82,18 @@ namespace Microsoft.Store.PartnerCenter.Bot.Intents
{ {
subscriptionId = indentifierEntity.Entity.Replace(" ", string.Empty); subscriptionId = indentifierEntity.Entity.Replace(" ", string.Empty);
principal.Operation.SubscriptionId = subscriptionId; principal.Operation.SubscriptionId = subscriptionId;
subscription = await service.PartnerOperations.GetSubscriptionAsync(principal);
if (subscription == null)
{
response.Text = Resources.UnableToLocateSubscription;
}
else
{
context.StoreCustomerPrincipal(principal); context.StoreCustomerPrincipal(principal);
} }
}
if (string.IsNullOrEmpty(subscriptionId)) if (string.IsNullOrEmpty(subscriptionId))
{ {
@ -94,6 +106,12 @@ namespace Microsoft.Store.PartnerCenter.Bot.Intents
await context.PostAsync(response); await context.PostAsync(response);
// Track the event measurements for analysis.
eventMetrics = new Dictionary<string, double>
{
{ "ElapsedMilliseconds", DateTime.Now.Subtract(startTime).TotalMilliseconds }
};
// Capture the request for the customer summary for analysis. // Capture the request for the customer summary for analysis.
eventProperties = new Dictionary<string, string> eventProperties = new Dictionary<string, string>
{ {
@ -104,20 +122,15 @@ namespace Microsoft.Store.PartnerCenter.Bot.Intents
{ "UserId", principal.ObjectId } { "UserId", principal.ObjectId }
}; };
// Track the event measurements for analysis. service.Telemetry.TrackEvent("SelectSubscription/ExecuteAsync", eventProperties, eventMetrics);
eventMeasurements = new Dictionary<string, double>
{
{ "ElapsedMilliseconds", DateTime.Now.Subtract(startTime).TotalMilliseconds }
};
service.Telemetry.TrackEvent("SelectSubscription/ExecuteAsync", eventProperties, eventMeasurements);
} }
finally finally
{ {
indentifierEntity = null; indentifierEntity = null;
eventMeasurements = null; eventMetrics = null;
eventProperties = null; eventProperties = null;
message = null; message = null;
subscription = null;
} }
} }
} }

Просмотреть файл

@ -14,6 +14,7 @@ namespace Microsoft.Store.PartnerCenter.Bot.Logic
using Intents; using Intents;
using Microsoft.Bot.Builder.Dialogs; using Microsoft.Bot.Builder.Dialogs;
using Microsoft.Bot.Connector; using Microsoft.Bot.Connector;
using Office;
using Security; using Security;
using Telemetry; using Telemetry;
@ -54,6 +55,11 @@ namespace Microsoft.Store.PartnerCenter.Bot.Logic
/// </summary> /// </summary>
private static IPartnerOperations partnerOperations; private static IPartnerOperations partnerOperations;
/// <summary>
/// Provides the ability to communicate with the Office 365 Service Communications API.
/// </summary>
private static IServiceCommunications serviceCommunications;
/// <summary> /// <summary>
/// Provides the ability to track telemetry data. /// Provides the ability to track telemetry data.
/// </summary> /// </summary>
@ -99,6 +105,11 @@ namespace Microsoft.Store.PartnerCenter.Bot.Logic
/// </summary> /// </summary>
public IPartnerOperations PartnerOperations => partnerOperations ?? (partnerOperations = new PartnerOperations(this)); public IPartnerOperations PartnerOperations => partnerOperations ?? (partnerOperations = new PartnerOperations(this));
/// <summary>
/// Gets the ability to communicate with the Office 365 Service Communications API.
/// </summary>
public IServiceCommunications ServiceCommunications => serviceCommunications ?? (serviceCommunications = new ServiceCommunications(this));
/// <summary> /// <summary>
/// Gets the telemetry service reference. /// Gets the telemetry service reference.
/// </summary> /// </summary>
@ -111,7 +122,7 @@ namespace Microsoft.Store.PartnerCenter.Bot.Logic
return telemetry; return telemetry;
} }
if (string.IsNullOrEmpty(this.Configuration.InstrumentationKey)) if (string.IsNullOrEmpty(Configuration.InstrumentationKey))
{ {
telemetry = new EmptyTelemetryProvider(); telemetry = new EmptyTelemetryProvider();
} }
@ -157,8 +168,8 @@ namespace Microsoft.Store.PartnerCenter.Bot.Logic
builder.Register(c => builder.Register(c =>
{ {
return new MicrosoftAppCredentials( return new MicrosoftAppCredentials(
this.Configuration.MicrosoftAppId, Configuration.MicrosoftAppId,
this.Configuration.MicrosoftAppPassword); Configuration.MicrosoftAppPassword);
}).SingleInstance(); }).SingleInstance();
#pragma warning disable 0618 #pragma warning disable 0618

Просмотреть файл

@ -0,0 +1,105 @@
// -----------------------------------------------------------------------
// <copyright file="CommunicationException.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
namespace Microsoft.Store.PartnerCenter.Bot.Logic
{
using System;
using System.Net;
using System.Runtime.Serialization;
/// <summary>
/// User defined exception type that is thrown when an error is encountered communication with the Partner Center API.
/// </summary>
/// <seealso cref="Exception" />
/// <seealso cref="ISerializable" />
[Serializable]
public class CommunicationException : Exception
{
/// <summary>
/// Initializes a new instance of the <see cref="CommunicationException"/> class.
/// </summary>
public CommunicationException()
{
HttpStatusCode = HttpStatusCode.InternalServerError;
}
/// <summary>
/// Initializes a new instance of the <see cref="CommunicationException"/> class.
/// </summary>
/// <param name="message">The message that describes the error.</param>
public CommunicationException(string message) : base(message)
{
HttpStatusCode = HttpStatusCode.BadRequest;
}
/// <summary>
/// Initializes a new instance of the <see cref="CommunicationException" /> class.
/// </summary>
/// <param name="message">The message that describes the error.</param>
/// <param name="httpStatusCode">The HTTP status code that was encountered with the error.</param>
public CommunicationException(string message, HttpStatusCode httpStatusCode) : base(message)
{
HttpStatusCode = httpStatusCode;
}
/// <summary>
/// Initializes a new instance of the <see cref="CommunicationException"/> class.
/// </summary>
/// <param name="message">The error message that explains the reason for the exception.</param>
/// <param name="innerException">The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified.</param>
public CommunicationException(string message, Exception innerException) : base(message, innerException)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="CommunicationException" /> class.
/// </summary>
/// <param name="message">The error message that explains the reason for the exception.</param>
/// <param name="innerException">The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified.</param>
/// <param name="httpStatusCode">The HTTP status code that was encountered with the error.</param>
public CommunicationException(string message, Exception innerException, HttpStatusCode httpStatusCode)
: base(message, innerException)
{
HttpStatusCode = httpStatusCode;
}
/// <summary>
/// Initializes a new instance of the <see cref="CommunicationException"/> class.
/// </summary>
/// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo" /> that holds the serialized object data about the exception being thrown.</param>
/// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext" /> that contains contextual information about the source or destination.</param>
protected CommunicationException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
}
/// <summary>
/// Gets or sets the HTTP status code associated with the exception.
/// </summary>
public HttpStatusCode HttpStatusCode { get; protected set; }
/// <summary>
/// When overridden in a derived class, sets the <see cref="T:System.Runtime.Serialization.SerializationInfo" /> with information about the exception.
/// </summary>
/// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo" /> that holds the serialized object data about the exception being thrown.</param>
/// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext" /> that contains contextual information about the source or destination.</param>
/// <PermissionSet>
/// <IPermission class="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Read="*AllFiles*" PathDiscovery="*AllFiles*" />
/// <IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="SerializationFormatter" />
/// </PermissionSet>
public override void GetObjectData(SerializationInfo info, StreamingContext context)
{
if (info == null)
{
throw new ArgumentNullException(nameof(info));
}
info.AddValue("HttpStatusCode", (int)HttpStatusCode);
base.GetObjectData(info, context);
}
}
}

Просмотреть файл

@ -15,6 +15,7 @@ namespace Microsoft.Store.PartnerCenter.Bot.Logic
using IdentityModel.Clients.ActiveDirectory; using IdentityModel.Clients.ActiveDirectory;
using Microsoft.Bot.Builder.Dialogs; using Microsoft.Bot.Builder.Dialogs;
using Microsoft.Bot.Connector; using Microsoft.Bot.Connector;
using Office;
using PartnerCenter.Models.Subscriptions; using PartnerCenter.Models.Subscriptions;
using Security; using Security;
@ -94,6 +95,22 @@ namespace Microsoft.Store.PartnerCenter.Bot.Logic
} }
} }
/// <summary>
/// Transforms an instance of <see cref="HealthEvent"/> into an instance of <see cref="Attachment"/>
/// </summary>
/// <param name="healthEvent">An instance of <see cref="HealthEvent"/> to be transformed.</param>
/// <returns>An instance of <see cref="Attachment"/> that represents the health event.</returns>
public static Attachment ToAttachment(this HealthEvent healthEvent)
{
HeroCard card = new HeroCard
{
Subtitle = healthEvent.Status,
Title = healthEvent.WorkloadDisplayName
};
return card.ToAttachment();
}
/// <summary> /// <summary>
/// Transforms an instance of <see cref="Subscription"/> into an instance of <see cref="Attachment"/> /// Transforms an instance of <see cref="Subscription"/> into an instance of <see cref="Attachment"/>
/// </summary> /// </summary>
@ -189,6 +206,12 @@ namespace Microsoft.Store.PartnerCenter.Bot.Logic
/// </summary> /// </summary>
/// <param name="principalToValidate">An instance of <see cref="CustomerPrincipal"/> to validate.</param> /// <param name="principalToValidate">An instance of <see cref="CustomerPrincipal"/> to validate.</param>
/// <param name="message">The message to report in the exception.</param> /// <param name="message">The message to report in the exception.</param>
/// <exception cref="ArgumentNullException">
/// <paramref name="principalToValidate"/> is null.
/// </exception>
/// <exception cref="InvalidOperationException">
/// <paramref name="principalToValidate"/> does not contain a valid customer identifier.
/// </exception>
public static void AssertValidCustomerContext(this CustomerPrincipal principalToValidate, string message) public static void AssertValidCustomerContext(this CustomerPrincipal principalToValidate, string message)
{ {
principalToValidate.AssertNotNull(nameof(principalToValidate)); principalToValidate.AssertNotNull(nameof(principalToValidate));
@ -199,6 +222,27 @@ namespace Microsoft.Store.PartnerCenter.Bot.Logic
} }
} }
/// <summary>
/// Ensures the given <see cref="CustomerPrincipal"/> has a valid subscription context.
/// </summary>
/// <param name="principalToValidate">An instance of <see cref="CustomerPrincipal"/> to validate.</param>
/// <param name="message">The message to report in the exception.</param>
/// <exception cref="ArgumentNullException">
/// <paramref name="principalToValidate"/> is null.
/// </exception>
/// <exception cref="InvalidOperationException">
/// <paramref name="principalToValidate"/> does not contain a valid subscription identifier.
/// </exception>
public static void AssertValidSubscriptionContext(this CustomerPrincipal principalToValidate, string message)
{
principalToValidate.AssertNotNull(nameof(principalToValidate));
if (string.IsNullOrEmpty(principalToValidate.Operation.SubscriptionId))
{
throw new InvalidOperationException(message);
}
}
/// <summary> /// <summary>
/// Stores an instance of <see cref="CustomerPrincipal"/> in the private bot data associated with the user. /// Stores an instance of <see cref="CustomerPrincipal"/> in the private bot data associated with the user.
/// </summary> /// </summary>

Просмотреть файл

@ -53,7 +53,7 @@ namespace Microsoft.Store.PartnerCenter.Bot.Logic
this.customerId = customerId; this.customerId = customerId;
this.service = service; this.service = service;
this.client = new GraphServiceClient(new AuthenticationProvider(this.service, customerId)); client = new GraphServiceClient(new AuthenticationProvider(this.service, customerId));
} }
/// <summary> /// <summary>
@ -100,7 +100,7 @@ namespace Microsoft.Store.PartnerCenter.Bot.Logic
{ {
startTime = DateTime.Now; startTime = DateTime.Now;
directoryGroups = await this.client.Users[objectId].MemberOf.Request().GetAsync(); directoryGroups = await client.Users[objectId].MemberOf.Request().GetAsync();
roles = new List<RoleModel>(); roles = new List<RoleModel>();
do do
@ -116,7 +116,7 @@ namespace Microsoft.Store.PartnerCenter.Bot.Logic
})); }));
} }
if (this.customerId.Equals(this.service.Configuration.PartnerCenterApplicationTenantId)) if (customerId.Equals(service.Configuration.PartnerCenterApplicationTenantId))
{ {
groups = directoryGroups.CurrentPage.OfType<Group>().Where( groups = directoryGroups.CurrentPage.OfType<Group>().Where(
g => g.DisplayName.Equals("AdminAgents") || g.DisplayName.Equals("HelpdeskAgents") || g.DisplayName.Equals("SalesAgent")).ToList(); g => g.DisplayName.Equals("AdminAgents") || g.DisplayName.Equals("HelpdeskAgents") || g.DisplayName.Equals("SalesAgent")).ToList();
@ -143,7 +143,7 @@ namespace Microsoft.Store.PartnerCenter.Bot.Logic
// Capture the request for the customer summary for analysis. // Capture the request for the customer summary for analysis.
eventProperties = new Dictionary<string, string> eventProperties = new Dictionary<string, string>
{ {
{ "CustomerId", this.customerId }, { "CustomerId", customerId },
{ "ObjectId", objectId } { "ObjectId", objectId }
}; };
@ -154,7 +154,7 @@ namespace Microsoft.Store.PartnerCenter.Bot.Logic
{ "NumberOfRoles", roles.Count } { "NumberOfRoles", roles.Count }
}; };
this.service.Telemetry.TrackEvent("GetDirectoryRolesAsync", eventProperties, eventMeasurements); service.Telemetry.TrackEvent("GetDirectoryRolesAsync", eventProperties, eventMeasurements);
return roles; return roles;
} }

Просмотреть файл

@ -10,6 +10,7 @@ namespace Microsoft.Store.PartnerCenter.Bot.Logic
using Cache; using Cache;
using Configuration; using Configuration;
using Intents; using Intents;
using Office;
using Security; using Security;
using Telemetry; using Telemetry;
@ -48,6 +49,11 @@ namespace Microsoft.Store.PartnerCenter.Bot.Logic
/// </summary> /// </summary>
IPartnerOperations PartnerOperations { get; } IPartnerOperations PartnerOperations { get; }
/// <summary>
/// Gets a reference t the service communications service.
/// </summary>
IServiceCommunications ServiceCommunications { get; }
/// <summary> /// <summary>
/// Gets the telemetry service reference. /// Gets the telemetry service reference.
/// </summary> /// </summary>

Просмотреть файл

@ -56,6 +56,13 @@ namespace Microsoft.Store.PartnerCenter.Bot.Logic
/// <returns>An instance of <see cref="LegalBusinessProfile"/> that represents the partner's legal business profile.</returns> /// <returns>An instance of <see cref="LegalBusinessProfile"/> that represents the partner's legal business profile.</returns>
Task<LegalBusinessProfile> GetLegalBusinessProfileAsync(); Task<LegalBusinessProfile> GetLegalBusinessProfileAsync();
/// <summary>
/// Gets the specified subscription.
/// </summary>
/// <param name="principal">Security principal for the calling user.</param>
/// <returns>An instance of <see cref="Subscription"/> that represents the specified subscription.</returns>
Task<Subscription> GetSubscriptionAsync(CustomerPrincipal principal);
/// <summary> /// <summary>
/// Gets the available subscriptions. /// Gets the available subscriptions.
/// </summary> /// </summary>

Просмотреть файл

@ -0,0 +1,41 @@
// -----------------------------------------------------------------------
// <copyright file="HealthEvent.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
namespace Microsoft.Store.PartnerCenter.Bot.Logic.Office
{
using System;
/// <summary>
/// Represents a health event obtained from Office 365 Service Communications API.
/// </summary>
public class HealthEvent
{
/// <summary>
/// Gets or sets the identifier.
/// </summary>
public string Id { get; set; }
/// <summary>
/// Gets or sets the event status.
/// </summary>
public string Status { get; set; }
/// <summary>
/// Gets or sets the status time.
/// </summary>
public DateTime StatusTime { get; set; }
/// <summary>
/// Gets or sets the workload.
/// </summary>
public string Workload { get; set; }
/// <summary>
/// Gets or sets the display name for the workload.
/// </summary>
public string WorkloadDisplayName { get; set; }
}
}

Просмотреть файл

@ -0,0 +1,25 @@
// -----------------------------------------------------------------------
// <copyright file="IServiceCommunications.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
namespace Microsoft.Store.PartnerCenter.Bot.Logic.Office
{
using System.Collections.Generic;
using System.Threading.Tasks;
/// <summary>
/// Represents the ability to interact with Office 365 Service Communications API.
/// </summary>
public interface IServiceCommunications
{
/// <summary>
/// Gets the current status information for the specified customer.
/// </summary>
/// <param name="customerId">Identifier for the customer.</param>
/// <param name="token">Access token to be utilized in the request.</param>
/// <returns>A list of <see cref="HealthEvent"/> objects that represent the current health events for the specified customer.</returns>
Task<List<HealthEvent>> GetCurrentStatusAsync(string customerId, string token);
}
}

Просмотреть файл

@ -0,0 +1,22 @@
// -----------------------------------------------------------------------
// <copyright file="ODataResponse.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
namespace Microsoft.Store.PartnerCenter.Bot.Logic.Office
{
using System.Collections.Generic;
/// <summary>
/// Represents a response from an OData endpoint.
/// </summary>
/// <typeparam name="T">Type returned from the API.</typeparam>
internal class ODataResponse<T>
{
/// <summary>
/// Gets or sets the value returned from the API.
/// </summary>
public List<T> Value { get; set; }
}
}

Просмотреть файл

@ -0,0 +1,102 @@
// -----------------------------------------------------------------------
// <copyright file="ServiceCommunications.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
namespace Microsoft.Store.PartnerCenter.Bot.Logic.Office
{
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using Newtonsoft.Json;
/// <summary>
/// Provides the ability to interact with Office 365 Service Communications API.
/// </summary>
public class ServiceCommunications : IServiceCommunications
{
/// <summary>
/// Provides access to core services.
/// </summary>
private readonly IBotService service;
/// <summary>
/// Initializes a new instance of the <see cref="ServiceCommunications" /> class.
/// </summary>
/// <param name="service">Provides access to core services.</param>
/// <exception cref="ArgumentNullException">
/// <paramref name="service"/> is null.
/// </exception>
public ServiceCommunications(IBotService service)
{
service.AssertNotNull(nameof(service));
this.service = service;
}
/// <summary>
/// Gets the current status information for the specified customer.
/// </summary>
/// <param name="customerId">Identifier for the customer.</param>
/// <param name="token">Access token to be utilized in the request.</param>
/// <returns>A list of <see cref="HealthEvent"/> objects that represent the current health events for the specified customer.</returns>
public async Task<List<HealthEvent>> GetCurrentStatusAsync(string customerId, string token)
{
DateTime startTime;
Dictionary<string, double> eventMetrics;
Dictionary<string, string> eventProperties;
HttpResponseMessage response;
ODataResponse<HealthEvent> odataResponse;
string content;
string requestUri;
try
{
startTime = DateTime.Now;
using (HttpClient client = new HttpClient())
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
requestUri = $"{service.Configuration.OfficeManagementEndpoint}/api/v1.0/{customerId}/ServiceComms/CurrentStatus";
response = await client.GetAsync(requestUri);
content = await response.Content.ReadAsStringAsync();
if (!response.IsSuccessStatusCode)
{
throw new CommunicationException(content, response.StatusCode);
}
odataResponse = JsonConvert.DeserializeObject<ODataResponse<HealthEvent>>(content);
// Track the event measurements for analysis.
eventMetrics = new Dictionary<string, double>
{
{ "ElapsedMilliseconds", DateTime.Now.Subtract(startTime).TotalMilliseconds },
{ "NumberOfHealthEvents", odataResponse.Value.Count }
};
// Capture the request for the customer summary for analysis.
eventProperties = new Dictionary<string, string>
{
{ "CustomerId", customerId },
{ "RequestUri", requestUri }
};
service.Telemetry.TrackEvent("GetCurrentStatusAsync", eventProperties, eventMetrics);
return odataResponse.Value;
}
}
finally
{
eventMetrics = null;
eventProperties = null;
response = null;
}
}
}
}

Просмотреть файл

@ -10,6 +10,7 @@ namespace Microsoft.Store.PartnerCenter.Bot.Logic
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using PartnerCenter.Enumerators; using PartnerCenter.Enumerators;
using PartnerCenter.Exceptions;
using PartnerCenter.Models; using PartnerCenter.Models;
using PartnerCenter.Models.CountryValidationRules; using PartnerCenter.Models.CountryValidationRules;
using PartnerCenter.Models.Customers; using PartnerCenter.Models.Customers;
@ -244,7 +245,7 @@ namespace Microsoft.Store.PartnerCenter.Bot.Logic
{ "ParternCenterCorrelationId", correlationId.ToString() } { "ParternCenterCorrelationId", correlationId.ToString() }
}; };
this.service.Telemetry.TrackEvent("GetCustomersAsync", eventProperties, eventMetrics); service.Telemetry.TrackEvent("GetCustomersAsync", eventProperties, eventMetrics);
return customers; return customers;
} }
@ -277,14 +278,14 @@ namespace Microsoft.Store.PartnerCenter.Bot.Logic
try try
{ {
if (this.service.Initialized) if (service.Initialized)
{ {
throw new InvalidOperationException(Resources.ServiceInitializedException); throw new InvalidOperationException(Resources.ServiceInitializedException);
} }
startTime = DateTime.Now; startTime = DateTime.Now;
correlationId = Guid.NewGuid(); correlationId = Guid.NewGuid();
operations = await this.GetAppOperationsAsync(correlationId); operations = await GetAppOperationsAsync(correlationId);
profile = await operations.Profiles.LegalBusinessProfile.GetAsync(); profile = await operations.Profiles.LegalBusinessProfile.GetAsync();
@ -300,7 +301,7 @@ namespace Microsoft.Store.PartnerCenter.Bot.Logic
{ "ParternCenterCorrelationId", correlationId.ToString() } { "ParternCenterCorrelationId", correlationId.ToString() }
}; };
this.service.Telemetry.TrackEvent("GetLegalBusinessProfileAsync", eventProperties, eventMetrics); service.Telemetry.TrackEvent("GetLegalBusinessProfileAsync", eventProperties, eventMetrics);
return profile; return profile;
} }
@ -312,6 +313,77 @@ namespace Microsoft.Store.PartnerCenter.Bot.Logic
} }
} }
/// <summary>
/// Gets the specified subscription.
/// </summary>
/// <param name="principal">Security principal for the calling user.</param>
/// <returns>An instance of <see cref="Subscription"/> that represents the specified subscription.</returns>
/// <exception cref="ArgumentException">
/// The operation context from <paramref name="principal"/> does not contain a valid customer identifier.
/// or
/// The operation context from <paramref name="principal"/> does not contain a valid subscription identifier.
/// </exception>
/// <exception cref="ArgumentNullException">
/// <paramref name="principal"/> is null.
/// </exception>
public async Task<Subscription> GetSubscriptionAsync(CustomerPrincipal principal)
{
DateTime startTime;
Dictionary<string, double> eventMetrics;
Dictionary<string, string> eventProperties;
Guid correlationId;
IPartner operations;
Subscription subscription = null;
principal.AssertNotNull(nameof(principal));
principal.Operation.CustomerId.AssertNotEmpty(nameof(principal.Operation.CustomerId));
principal.Operation.SubscriptionId.AssertNotEmpty(nameof(principal.Operation.SubscriptionId));
try
{
startTime = DateTime.Now;
correlationId = Guid.NewGuid();
operations = await GetAppOperationsAsync(correlationId);
try
{
subscription = await operations.Customers.ById(principal.Operation.CustomerId)
.Subscriptions.ById(principal.Operation.SubscriptionId).GetAsync();
}
catch (PartnerException ex)
{
if (ex.ErrorCategory != PartnerErrorCategory.NotFound)
{
throw;
}
}
// Track the event measurements for analysis.
eventMetrics = new Dictionary<string, double>
{
{ "ElapsedMilliseconds", DateTime.Now.Subtract(startTime).TotalMilliseconds }
};
// Capture the request for the customer summary for analysis.
eventProperties = new Dictionary<string, string>
{
{ "CustomerId", principal.CustomerId },
{ "ObjectId", principal.ObjectId },
{ "ParternCenterCorrelationId", correlationId.ToString() }
};
service.Telemetry.TrackEvent("GetSubscriptionAsync", eventProperties, eventMetrics);
return subscription;
}
finally
{
eventMetrics = null;
eventProperties = null;
operations = null;
}
}
/// <summary> /// <summary>
/// Gets the available subscriptions. /// Gets the available subscriptions.
/// </summary> /// </summary>
@ -335,9 +407,9 @@ namespace Microsoft.Store.PartnerCenter.Bot.Logic
{ {
startTime = DateTime.Now; startTime = DateTime.Now;
correlationId = Guid.NewGuid(); correlationId = Guid.NewGuid();
operations = await this.GetAppOperationsAsync(correlationId); operations = await GetAppOperationsAsync(correlationId);
if (principal.CustomerId.Equals(this.service.Configuration.PartnerCenterApplicationTenantId)) if (principal.CustomerId.Equals(service.Configuration.PartnerCenterApplicationTenantId))
{ {
principal.AssertValidCustomerContext(Resources.InvalidCustomerContextException); principal.AssertValidCustomerContext(Resources.InvalidCustomerContextException);
subscriptions = await operations.Customers.ById(principal.Operation.CustomerId).Subscriptions.GetAsync(); subscriptions = await operations.Customers.ById(principal.Operation.CustomerId).Subscriptions.GetAsync();
@ -362,7 +434,7 @@ namespace Microsoft.Store.PartnerCenter.Bot.Logic
{ "ParternCenterCorrelationId", correlationId.ToString() } { "ParternCenterCorrelationId", correlationId.ToString() }
}; };
this.service.Telemetry.TrackEvent("GetCustomersAsync", eventProperties, eventMetrics); service.Telemetry.TrackEvent("GetCustomersAsync", eventProperties, eventMetrics);
return new List<Subscription>(subscriptions.Items); return new List<Subscription>(subscriptions.Items);
} }
@ -383,19 +455,19 @@ namespace Microsoft.Store.PartnerCenter.Bot.Logic
/// <returns>An instance of the partner service.</returns> /// <returns>An instance of the partner service.</returns>
private async ValueTask<IPartner> GetAppOperationsAsync(Guid correlationId) private async ValueTask<IPartner> GetAppOperationsAsync(Guid correlationId)
{ {
if (this.appOperations == null || this.appOperations.Credentials.ExpiresAt > DateTime.UtcNow) if (appOperations == null || appOperations.Credentials.ExpiresAt > DateTime.UtcNow)
{ {
IPartnerCredentials credentials = await this.service.TokenManagement IPartnerCredentials credentials = await service.TokenManagement
.GetPartnerCenterAppOnlyCredentialsAsync( .GetPartnerCenterAppOnlyCredentialsAsync(
$"{this.service.Configuration.ActiveDirectoryEndpoint}/{this.service.Configuration.PartnerCenterApplicationTenantId}"); $"{service.Configuration.ActiveDirectoryEndpoint}/{service.Configuration.PartnerCenterApplicationTenantId}");
lock (this.appLock) lock (appLock)
{ {
this.appOperations = PartnerService.Instance.CreatePartnerOperations(credentials); appOperations = PartnerService.Instance.CreatePartnerOperations(credentials);
} }
} }
return this.appOperations.With(RequestContextFactory.Instance.Create(correlationId)); return appOperations.With(RequestContextFactory.Instance.Create(correlationId));
} }
} }
} }

Просмотреть файл

@ -36,4 +36,4 @@ using System.Runtime.InteropServices;
// //
// You can specify all the values or you can default the Revision and Build Numbers // You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
[assembly: AssemblyVersion("0.0.3.*")] [assembly: AssemblyVersion("0.0.5.*")]

47
src/Bot/Resources.Designer.cs сгенерированный
Просмотреть файл

@ -87,6 +87,15 @@ namespace Microsoft.Store.PartnerCenter.Bot {
} }
} }
/// <summary>
/// Looks up a localized string similar to There appears to be an issue preventing me from fulfilling this request. Please try again later.
/// </summary>
internal static string ErrorMessage {
get {
return ResourceManager.GetString("ErrorMessage", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to help. /// Looks up a localized string similar to help.
/// </summary> /// </summary>
@ -123,6 +132,15 @@ namespace Microsoft.Store.PartnerCenter.Bot {
} }
} }
/// <summary>
/// Looks up a localized string similar to You must select a subscription before attempting this operation. Please type ** list subscriptions**, select a subscription, and then try again..
/// </summary>
internal static string InvalidSubscriptionContextException {
get {
return ResourceManager.GetString("InvalidSubscriptionContextException", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to list customers. /// Looks up a localized string similar to list customers.
/// </summary> /// </summary>
@ -142,7 +160,7 @@ namespace Microsoft.Store.PartnerCenter.Bot {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to subscriptions. /// Looks up a localized string similar to list subscriptions.
/// </summary> /// </summary>
internal static string ListSubscriptionssHelpMessage { internal static string ListSubscriptionssHelpMessage {
get { get {
@ -186,6 +204,24 @@ namespace Microsoft.Store.PartnerCenter.Bot {
} }
} }
/// <summary>
/// Looks up a localized string similar to Ask are there any issues with Office 365?.
/// </summary>
internal static string OfficeIssuesHelpMessage {
get {
return ResourceManager.GetString("OfficeIssuesHelpMessage", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Ask questions such as what is EMS?.
/// </summary>
internal static string QuestionHelpMessage {
get {
return ResourceManager.GetString("QuestionHelpMessage", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Failed to connect to the specified instance.. /// Looks up a localized string similar to Failed to connect to the specified instance..
/// </summary> /// </summary>
@ -213,6 +249,15 @@ namespace Microsoft.Store.PartnerCenter.Bot {
} }
} }
/// <summary>
/// Looks up a localized string similar to You must select a customer before attempting this operation. Please send **list customers**, select a customer, and then try again..
/// </summary>
internal static string SelectCustomerFirst {
get {
return ResourceManager.GetString("SelectCustomerFirst", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Cannot invoke this function after the bot service has been initialized.. /// Looks up a localized string similar to Cannot invoke this function after the bot service has been initialized..
/// </summary> /// </summary>

Просмотреть файл

@ -120,15 +120,27 @@
<data name="AuthenticationSuccessDoneMessage" xml:space="preserve"> <data name="AuthenticationSuccessDoneMessage" xml:space="preserve">
<value>Hallo {0}! Was möchten Sie tun?</value> <value>Hallo {0}! Was möchten Sie tun?</value>
</data> </data>
<data name="CustomerContext" xml:space="preserve">
<value>Kundenkontext ist nun so konfiguriert</value>
</data>
<data name="DataProtectionUnprotectException" xml:space="preserve"> <data name="DataProtectionUnprotectException" xml:space="preserve">
<value>Fehler beim Aufheben der angegebenen Daten.</value> <value>Fehler beim Aufheben der angegebenen Daten.</value>
</data> </data>
<data name="Help" xml:space="preserve">
<value>Hilfe</value>
</data>
<data name="HelpMessage" xml:space="preserve"> <data name="HelpMessage" xml:space="preserve">
<value>Sie können mit mir in folgender Weise interagieren:</value> <value>Sie können mit mir in folgender Weise interagieren:</value>
</data> </data>
<data name="InvalidAuthenticationException" xml:space="preserve"> <data name="InvalidAuthenticationException" xml:space="preserve">
<value>Die Authentifizierungsanforderung war ungültig. Versuchen Sie, erneut zu authentifizieren, wenn das Problem weiterhin bestehen wenden Sie sich bitte an Support.</value> <value>Die Authentifizierungsanforderung war ungültig. Versuchen Sie, erneut zu authentifizieren, wenn das Problem weiterhin bestehen wenden Sie sich bitte an Support.</value>
</data> </data>
<data name="InvalidCustomerContextException" xml:space="preserve">
<value>Sie müssen einen Kunden auswählen, bevor Sie versuchen, diesen Vorgang. Bitte geben Sie ** Liste Kunden **, wählen Sie einen Kunden und versuchen Sie es erneut.</value>
</data>
<data name="InvalidSubscriptionContextException" xml:space="preserve">
<value>Sie müssen ein Abonnement vor dem Versuch diesen Vorgang auswählen. Bitte geben Sie ** Liste Abonnements **, wählen Sie ein Abonnement, und versuchen Sie es erneut.</value>
</data>
<data name="ListCustomersHelpMessage" xml:space="preserve"> <data name="ListCustomersHelpMessage" xml:space="preserve">
<value>Liste-Kunden</value> <value>Liste-Kunden</value>
</data> </data>
@ -136,7 +148,7 @@
<value>Liste</value> <value>Liste</value>
</data> </data>
<data name="ListSubscriptionssHelpMessage" xml:space="preserve"> <data name="ListSubscriptionssHelpMessage" xml:space="preserve">
<value>Abonnements</value> <value>Liste-Abonnements</value>
</data> </data>
<data name="Login" xml:space="preserve"> <data name="Login" xml:space="preserve">
<value>Login</value> <value>Login</value>
@ -150,46 +162,49 @@
<data name="NotAuthenticatedHelpMessage" xml:space="preserve"> <data name="NotAuthenticatedHelpMessage" xml:space="preserve">
<value>Müssen Sie sich zuerst anmelden bevor Sie Interaktion mit mir. Bitte geben Sie ** Login ** zu authentifizieren. Wenn Sie noch, Typ Hilfe benötigen ** Hilfe ** nach erfolgreich authentifizieren.</value> <value>Müssen Sie sich zuerst anmelden bevor Sie Interaktion mit mir. Bitte geben Sie ** Login ** zu authentifizieren. Wenn Sie noch, Typ Hilfe benötigen ** Hilfe ** nach erfolgreich authentifizieren.</value>
</data> </data>
<data name="OfficeIssuesHelpMessage" xml:space="preserve">
<value>Fragen gibt es Probleme mit Office 365?</value>
</data>
<data name="QuestionHelpMessage" xml:space="preserve">
<value>Fragen wie was EMS ist?</value>
</data>
<data name="RedisCacheConnectionException" xml:space="preserve"> <data name="RedisCacheConnectionException" xml:space="preserve">
<value>Fehler beim Verbinden mit der angegebenen Instanz.</value> <value>Fehler beim Verbinden mit der angegebenen Instanz.</value>
</data> </data>
<data name="RewordQuestion" xml:space="preserve">
<value>Bitte formulieren Sie Ihre Frage und versuchen Sie es erneut.</value>
</data>
<data name="SelectCaptial" xml:space="preserve">
<value>Wählen Sie</value>
</data>
<data name="ServiceInitializedException" xml:space="preserve">
<value>Diese Funktion kann nicht aufgerufen werden, nachdem der Bot-Dienst initialisiert wurde.</value>
</data>
<data name="SigninCardText" xml:space="preserve"> <data name="SigninCardText" xml:space="preserve">
<value>Klicken Sie bitte unten auf Login.</value> <value>Klicken Sie bitte unten auf Login.</value>
</data> </data>
<data name="SubscriptionContext" xml:space="preserve">
<value>Abonnement-Kontext ist nun so konfiguriert</value>
</data>
<data name="SubscriptionRequestMessage" xml:space="preserve">
<value>Hier sind die Abonnements für {0}</value>
</data>
<data name="SuccessfulAuthentication" xml:space="preserve"> <data name="SuccessfulAuthentication" xml:space="preserve">
<value>Sie haben erfolgreich authentifiziert! Wenden Sie sich bitte dieses Fenster schließen und weiter im Gespräch mit dem Bot.</value> <value>Sie haben erfolgreich authentifiziert! Wenden Sie sich bitte dieses Fenster schließen und weiter im Gespräch mit dem Bot.</value>
</data> </data>
<data name="UnableToLocateCustomer" xml:space="preserve"> <data name="UnableToLocateCustomer" xml:space="preserve">
<value>Nicht in der Lage, den ausgewählten Kunden zu finden. Bitte geben Sie ** Liste Kunden ** und versuchen Sie es erneut.</value> <value>Nicht in der Lage, den ausgewählten Kunden zu finden. Bitte geben Sie ** Liste Kunden ** und versuchen Sie es erneut.</value>
</data> </data>
<data name="Help" xml:space="preserve">
<value>Hilfe</value>
</data>
<data name="RewordQuestion" xml:space="preserve">
<value>Bitte formulieren Sie Ihre Frage und versuchen Sie es erneut.</value>
</data>
<data name="InvalidCustomerContextException" xml:space="preserve">
<value>Sie müssen einen Kunden auswählen, bevor Sie versuchen, diesen Vorgang. Bitte geben Sie ** Liste Kunden **, wählen Sie einen Kunden und versuchen Sie es erneut.</value>
</data>
<data name="SubscriptionRequestMessage" xml:space="preserve">
<value>Hier sind die Abonnements für {0}</value>
</data>
<data name="ServiceInitializedException" xml:space="preserve">
<value>Diese Funktion kann nicht aufgerufen werden, nachdem der Bot-Dienst initialisiert wurde.</value>
</data>
<data name="CustomerContext" xml:space="preserve">
<value>Kundenkontext ist nun so konfiguriert</value>
</data>
<data name="SelectCaptial" xml:space="preserve">
<value>Wählen Sie</value>
</data>
<data name="SubscriptionContext" xml:space="preserve">
<value>Abonnement-Kontext ist nun so konfiguriert</value>
</data>
<data name="UnableToLocateSubscription" xml:space="preserve"> <data name="UnableToLocateSubscription" xml:space="preserve">
<value>Nicht in der Lage, das ausgewählte Abonnement zu finden. Bitte geben Sie ** Abonnements Liste ** und versuchen Sie es erneut.</value> <value>Nicht in der Lage, das ausgewählte Abonnement zu finden. Bitte geben Sie ** Abonnements Liste ** und versuchen Sie es erneut.</value>
</data> </data>
<data name="Welcome" xml:space="preserve"> <data name="Welcome" xml:space="preserve">
<value>Willkommen bei der Partner-Center Bot. Müssen Sie sich zuerst anmelden bevor Sie Interaktion mit mir. Bitte geben Sie ** Login ** zu authentifizieren. Wenn Sie noch, Typ Hilfe benötigen ** Hilfe ** nach erfolgreich authentifizieren.</value> <value>Willkommen bei der Partner-Center Bot. Müssen Sie sich zuerst anmelden bevor Sie Interaktion mit mir. Bitte geben Sie ** Login ** zu authentifizieren. Wenn Sie noch, Typ Hilfe benötigen ** Hilfe ** nach erfolgreich authentifizieren.</value>
</data> </data>
<data name="ErrorMessage" xml:space="preserve">
<value>Es scheint ein Problem, das mich daran hindert, diese Anforderung zu erfüllen. Bitte versuchen Sie es später noch einmal</value>
</data>
<data name="SelectCustomerFirst" xml:space="preserve">
<value>Sie müssen einen Kunden auswählen, bevor Sie versuchen, diesen Vorgang. Bitte senden Sie ** Liste Kunden **, wählen Sie einen Kunden und versuchen Sie es erneut.</value>
</data>
</root> </root>

Просмотреть файл

@ -120,15 +120,27 @@
<data name="AuthenticationSuccessDoneMessage" xml:space="preserve"> <data name="AuthenticationSuccessDoneMessage" xml:space="preserve">
<value>Hola {0}! ¿Qué gustaría hacer?</value> <value>Hola {0}! ¿Qué gustaría hacer?</value>
</data> </data>
<data name="CustomerContext" xml:space="preserve">
<value>Contexto de cliente ya está configurado para</value>
</data>
<data name="DataProtectionUnprotectException" xml:space="preserve"> <data name="DataProtectionUnprotectException" xml:space="preserve">
<value>Error al desproteger los datos especificados.</value> <value>Error al desproteger los datos especificados.</value>
</data> </data>
<data name="Help" xml:space="preserve">
<value>Ayuda</value>
</data>
<data name="HelpMessage" xml:space="preserve"> <data name="HelpMessage" xml:space="preserve">
<value>Se puede interactuar conmigo de las siguientes maneras:</value> <value>Se puede interactuar conmigo de las siguientes maneras:</value>
</data> </data>
<data name="InvalidAuthenticationException" xml:space="preserve"> <data name="InvalidAuthenticationException" xml:space="preserve">
<value>La solicitud de autenticación no es válida. Tratar de autenticar nuevamente si el problema persiste póngase en contacto con.</value> <value>La solicitud de autenticación no es válida. Tratar de autenticar nuevamente si el problema persiste póngase en contacto con.</value>
</data> </data>
<data name="InvalidCustomerContextException" xml:space="preserve">
<value>Debe seleccionar a un cliente antes de intentar esta operación. Por favor, escriba ** lista clientes **, seleccione un cliente y vuelva a intentarlo.</value>
</data>
<data name="InvalidSubscriptionContextException" xml:space="preserve">
<value>Debe seleccionar una suscripción antes de intentar esta operación. Por favor, escriba ** lista de suscripciones **, una suscripción y vuelva a intentarlo.</value>
</data>
<data name="ListCustomersHelpMessage" xml:space="preserve"> <data name="ListCustomersHelpMessage" xml:space="preserve">
<value>clientes de la lista</value> <value>clientes de la lista</value>
</data> </data>
@ -136,7 +148,7 @@
<value>lista</value> <value>lista</value>
</data> </data>
<data name="ListSubscriptionssHelpMessage" xml:space="preserve"> <data name="ListSubscriptionssHelpMessage" xml:space="preserve">
<value>suscripciones</value> <value>suscripciones de lista</value>
</data> </data>
<data name="Login" xml:space="preserve"> <data name="Login" xml:space="preserve">
<value>Inicio de sesión</value> <value>Inicio de sesión</value>
@ -150,46 +162,49 @@
<data name="NotAuthenticatedHelpMessage" xml:space="preserve"> <data name="NotAuthenticatedHelpMessage" xml:space="preserve">
<value>Usted debe primero iniciar sesión antes de interactuar conmigo. Por favor, escriba ** usuario ** para autenticar. Si usted todavía necesita ayuda tipo ** ayuda ** después de la autenticación con éxito.</value> <value>Usted debe primero iniciar sesión antes de interactuar conmigo. Por favor, escriba ** usuario ** para autenticar. Si usted todavía necesita ayuda tipo ** ayuda ** después de la autenticación con éxito.</value>
</data> </data>
<data name="OfficeIssuesHelpMessage" xml:space="preserve">
<value>Pregunta ¿hay algún problema con Office 365?</value>
</data>
<data name="QuestionHelpMessage" xml:space="preserve">
<value>Preguntas como ¿qué es EMS?</value>
</data>
<data name="RedisCacheConnectionException" xml:space="preserve"> <data name="RedisCacheConnectionException" xml:space="preserve">
<value>No se pudo conectar a la instancia especificada.</value> <value>No se pudo conectar a la instancia especificada.</value>
</data> </data>
<data name="RewordQuestion" xml:space="preserve">
<value>Por favor, redactar su pregunta y vuelva a intentarlo.</value>
</data>
<data name="SelectCaptial" xml:space="preserve">
<value>Seleccione</value>
</data>
<data name="ServiceInitializedException" xml:space="preserve">
<value>No puede invocar esta función después de que el servicio de bot se ha inicializado.</value>
</data>
<data name="SigninCardText" xml:space="preserve"> <data name="SigninCardText" xml:space="preserve">
<value>Por favor haga clic en el botón de abajo para iniciar sesión.</value> <value>Por favor haga clic en el botón de abajo para iniciar sesión.</value>
</data> </data>
<data name="SubscriptionContext" xml:space="preserve">
<value>Contexto de la suscripción está configurada ahora para</value>
</data>
<data name="SubscriptionRequestMessage" xml:space="preserve">
<value>Aquí están las suscripciones para {0}</value>
</data>
<data name="SuccessfulAuthentication" xml:space="preserve"> <data name="SuccessfulAuthentication" xml:space="preserve">
<value>¡Ha autenticado correctamente! No dude en cerrar esta ventana y continuar hablando con el bot.</value> <value>¡Ha autenticado correctamente! No dude en cerrar esta ventana y continuar hablando con el bot.</value>
</data> </data>
<data name="UnableToLocateCustomer" xml:space="preserve"> <data name="UnableToLocateCustomer" xml:space="preserve">
<value>No se puede localizar al cliente seleccionado. Por favor, escriba ** lista clientes ** e inténtelo de nuevo.</value> <value>No se puede localizar al cliente seleccionado. Por favor, escriba ** lista clientes ** e inténtelo de nuevo.</value>
</data> </data>
<data name="Help" xml:space="preserve">
<value>Ayuda</value>
</data>
<data name="RewordQuestion" xml:space="preserve">
<value>Por favor, redactar su pregunta y vuelva a intentarlo.</value>
</data>
<data name="InvalidCustomerContextException" xml:space="preserve">
<value>Debe seleccionar a un cliente antes de intentar esta operación. Por favor, escriba ** lista clientes **, seleccione un cliente y vuelva a intentarlo.</value>
</data>
<data name="SubscriptionRequestMessage" xml:space="preserve">
<value>Aquí están las suscripciones para {0}</value>
</data>
<data name="ServiceInitializedException" xml:space="preserve">
<value>No puede invocar esta función después de que el servicio de bot se ha inicializado.</value>
</data>
<data name="CustomerContext" xml:space="preserve">
<value>Contexto de cliente ya está configurado para</value>
</data>
<data name="SelectCaptial" xml:space="preserve">
<value>Seleccione</value>
</data>
<data name="SubscriptionContext" xml:space="preserve">
<value>Contexto de la suscripción está configurada ahora para</value>
</data>
<data name="UnableToLocateSubscription" xml:space="preserve"> <data name="UnableToLocateSubscription" xml:space="preserve">
<value>No se puede localizar la suscripción seleccionada. Por favor, escriba ** lista de suscripciones ** e inténtelo de nuevo.</value> <value>No se puede localizar la suscripción seleccionada. Por favor, escriba ** lista de suscripciones ** e inténtelo de nuevo.</value>
</data> </data>
<data name="Welcome" xml:space="preserve"> <data name="Welcome" xml:space="preserve">
<value>¡Bienvenido al Bot de centro asociado. Usted debe primero iniciar sesión antes de interactuar conmigo. Por favor, escriba ** usuario ** para autenticar. Si usted todavía necesita ayuda tipo ** ayuda ** después de la autenticación con éxito.</value> <value>¡Bienvenido al Bot de centro asociado. Usted debe primero iniciar sesión antes de interactuar conmigo. Por favor, escriba ** usuario ** para autenticar. Si usted todavía necesita ayuda tipo ** ayuda ** después de la autenticación con éxito.</value>
</data> </data>
<data name="ErrorMessage" xml:space="preserve">
<value>Parece ser un problema que me impide cumplir con esta solicitud. Por favor Inténtalo más tarde</value>
</data>
<data name="SelectCustomerFirst" xml:space="preserve">
<value>Debe seleccionar a un cliente antes de intentar esta operación. Por favor enviar ** lista clientes **, seleccione un cliente y vuelva a intentarlo.</value>
</data>
</root> </root>

Просмотреть файл

@ -120,15 +120,27 @@
<data name="AuthenticationSuccessDoneMessage" xml:space="preserve"> <data name="AuthenticationSuccessDoneMessage" xml:space="preserve">
<value>Salut {0} ! Que voulez-vous faire ?</value> <value>Salut {0} ! Que voulez-vous faire ?</value>
</data> </data>
<data name="CustomerContext" xml:space="preserve">
<value>Contexte client est maintenant configuré pour</value>
</data>
<data name="DataProtectionUnprotectException" xml:space="preserve"> <data name="DataProtectionUnprotectException" xml:space="preserve">
<value>Échec de déprotéger les données spécifiées.</value> <value>Échec de déprotéger les données spécifiées.</value>
</data> </data>
<data name="Help" xml:space="preserve">
<value>Aide</value>
</data>
<data name="HelpMessage" xml:space="preserve"> <data name="HelpMessage" xml:space="preserve">
<value>Vous pouvez interagir avec moi de la manière suivante :</value> <value>Vous pouvez interagir avec moi de la manière suivante :</value>
</data> </data>
<data name="InvalidAuthenticationException" xml:space="preserve"> <data name="InvalidAuthenticationException" xml:space="preserve">
<value>La demande dauthentification nétait pas valide. Essayer dauthentifier à nouveau si le problème persiste contactez le support.</value> <value>La demande dauthentification nétait pas valide. Essayer dauthentifier à nouveau si le problème persiste contactez le support.</value>
</data> </data>
<data name="InvalidCustomerContextException" xml:space="preserve">
<value>Vous devez sélectionner un client avant deffectuer cette opération. Veuillez tapez ** liste clients **, sélectionner un client et puis essayez à nouveau.</value>
</data>
<data name="InvalidSubscriptionContextException" xml:space="preserve">
<value>Vous devez sélectionner un abonnement avant deffectuer cette opération. Veuillez tapez ** abonnements ** la liste, sélectionnez un abonnement et puis essayez à nouveau.</value>
</data>
<data name="ListCustomersHelpMessage" xml:space="preserve"> <data name="ListCustomersHelpMessage" xml:space="preserve">
<value>liste clients</value> <value>liste clients</value>
</data> </data>
@ -136,7 +148,7 @@
<value>liste</value> <value>liste</value>
</data> </data>
<data name="ListSubscriptionssHelpMessage" xml:space="preserve"> <data name="ListSubscriptionssHelpMessage" xml:space="preserve">
<value>abonnements</value> <value>abonnements de la liste</value>
</data> </data>
<data name="Login" xml:space="preserve"> <data name="Login" xml:space="preserve">
<value>ouverture de session</value> <value>ouverture de session</value>
@ -150,46 +162,49 @@
<data name="NotAuthenticatedHelpMessage" xml:space="preserve"> <data name="NotAuthenticatedHelpMessage" xml:space="preserve">
<value>Vous devez dabord se connecter avant dinteragir avec moi. Veuillez tapez ** login ** pour sauthentifier. Si vous avez encore besoin daide type ** aide ** après authentification, avec succès.</value> <value>Vous devez dabord se connecter avant dinteragir avec moi. Veuillez tapez ** login ** pour sauthentifier. Si vous avez encore besoin daide type ** aide ** après authentification, avec succès.</value>
</data> </data>
<data name="OfficeIssuesHelpMessage" xml:space="preserve">
<value>Demander à y a-t-il des problèmes avec Office 365 ?</value>
</data>
<data name="QuestionHelpMessage" xml:space="preserve">
<value>Poser des questions comme quoi EMS ?</value>
</data>
<data name="RedisCacheConnectionException" xml:space="preserve"> <data name="RedisCacheConnectionException" xml:space="preserve">
<value>Impossible de se connecter à linstance spécifiée.</value> <value>Impossible de se connecter à linstance spécifiée.</value>
</data> </data>
<data name="RewordQuestion" xml:space="preserve">
<value>Veuillez reformuler votre question et essayez à nouveau.</value>
</data>
<data name="SelectCaptial" xml:space="preserve">
<value>Sélectionnez</value>
</data>
<data name="ServiceInitializedException" xml:space="preserve">
<value>Ne peut invoquer cette fonction après que le service de la bot a été initialisé.</value>
</data>
<data name="SigninCardText" xml:space="preserve"> <data name="SigninCardText" xml:space="preserve">
<value>Sil vous plaît cliquez sur le bouton ci-dessous pour vous connecter.</value> <value>Sil vous plaît cliquez sur le bouton ci-dessous pour vous connecter.</value>
</data> </data>
<data name="SubscriptionContext" xml:space="preserve">
<value>Contexte de labonnement est maintenant configuré pour</value>
</data>
<data name="SubscriptionRequestMessage" xml:space="preserve">
<value>Voici les abonnements pour {0}</value>
</data>
<data name="SuccessfulAuthentication" xml:space="preserve"> <data name="SuccessfulAuthentication" xml:space="preserve">
<value>Vous avez authentifié avec succès ! Sil vous plaît nhésitez pas à fermer cette fenêtre et continuer à parler avec le bot.</value> <value>Vous avez authentifié avec succès ! Sil vous plaît nhésitez pas à fermer cette fenêtre et continuer à parler avec le bot.</value>
</data> </data>
<data name="UnableToLocateCustomer" xml:space="preserve"> <data name="UnableToLocateCustomer" xml:space="preserve">
<value>Impossible de localiser le client sélectionné. Veuillez tapez ** liste clients ** et essayez à nouveau.</value> <value>Impossible de localiser le client sélectionné. Veuillez tapez ** liste clients ** et essayez à nouveau.</value>
</data> </data>
<data name="Help" xml:space="preserve">
<value>Aide</value>
</data>
<data name="RewordQuestion" xml:space="preserve">
<value>Veuillez reformuler votre question et essayez à nouveau.</value>
</data>
<data name="InvalidCustomerContextException" xml:space="preserve">
<value>Vous devez sélectionner un client avant deffectuer cette opération. Veuillez tapez ** liste clients **, sélectionner un client et puis essayez à nouveau.</value>
</data>
<data name="SubscriptionRequestMessage" xml:space="preserve">
<value>Voici les abonnements pour {0}</value>
</data>
<data name="ServiceInitializedException" xml:space="preserve">
<value>Ne peut invoquer cette fonction après que le service de la bot a été initialisé.</value>
</data>
<data name="CustomerContext" xml:space="preserve">
<value>Contexte client est maintenant configuré pour</value>
</data>
<data name="SelectCaptial" xml:space="preserve">
<value>Sélectionnez</value>
</data>
<data name="SubscriptionContext" xml:space="preserve">
<value>Contexte de labonnement est maintenant configuré pour</value>
</data>
<data name="UnableToLocateSubscription" xml:space="preserve"> <data name="UnableToLocateSubscription" xml:space="preserve">
<value>Impossible de localiser labonnement sélectionné. Veuillez tapez ** liste abonnements ** et essayez à nouveau.</value> <value>Impossible de localiser labonnement sélectionné. Veuillez tapez ** liste abonnements ** et essayez à nouveau.</value>
</data> </data>
<data name="Welcome" xml:space="preserve"> <data name="Welcome" xml:space="preserve">
<value>Bienvenue sur le Bot Partner Center. Vous devez dabord se connecter avant dinteragir avec moi. Veuillez tapez ** login ** pour sauthentifier. Si vous avez encore besoin daide type ** aide ** après authentification, avec succès.</value> <value>Bienvenue sur le Bot Partner Center. Vous devez dabord se connecter avant dinteragir avec moi. Veuillez tapez ** login ** pour sauthentifier. Si vous avez encore besoin daide type ** aide ** après authentification, avec succès.</value>
</data> </data>
<data name="ErrorMessage" xml:space="preserve">
<value>Il semble être un problème mempêche de satisfaire cette demande. Veuillez réessayer ultérieurement</value>
</data>
<data name="SelectCustomerFirst" xml:space="preserve">
<value>Vous devez sélectionner un client avant deffectuer cette opération. Sil vous plaît envoyer ** liste clients **, sélectionner un client et puis essayez à nouveau.</value>
</data>
</root> </root>

Просмотреть файл

@ -120,15 +120,27 @@
<data name="AuthenticationSuccessDoneMessage" xml:space="preserve"> <data name="AuthenticationSuccessDoneMessage" xml:space="preserve">
<value>こんにちは {0}!どうしたいですか。</value> <value>こんにちは {0}!どうしたいですか。</value>
</data> </data>
<data name="CustomerContext" xml:space="preserve">
<value>よう顧客のコンテキストに設定します。</value>
</data>
<data name="DataProtectionUnprotectException" xml:space="preserve"> <data name="DataProtectionUnprotectException" xml:space="preserve">
<value>指定されたデータの保護を解除できませんでした。</value> <value>指定されたデータの保護を解除できませんでした。</value>
</data> </data>
<data name="Help" xml:space="preserve">
<value>ヘルプ</value>
</data>
<data name="HelpMessage" xml:space="preserve"> <data name="HelpMessage" xml:space="preserve">
<value>私は、次の方法でやり取りすることができます。</value> <value>私は、次の方法でやり取りすることができます。</value>
</data> </data>
<data name="InvalidAuthenticationException" xml:space="preserve"> <data name="InvalidAuthenticationException" xml:space="preserve">
<value>認証要求が無効でした。問題が持続する場合、再度認証をしようとサポートに問い合わせてください。</value> <value>認証要求が無効でした。問題が持続する場合、再度認証をしようとサポートに問い合わせてください。</value>
</data> </data>
<data name="InvalidCustomerContextException" xml:space="preserve">
<value>この操作を行う前に顧客を選択する必要があります。入力してください * * 顧客リスト * *、顧客を選択し、もう一度やり直して。</value>
</data>
<data name="InvalidSubscriptionContextException" xml:space="preserve">
<value>この操作を試行する前にサブスクリプションを選択する必要があります。入力してください * * リスト サブスクリプション * *、サブスクリプションを選択して、もう一度やり直して。</value>
</data>
<data name="ListCustomersHelpMessage" xml:space="preserve"> <data name="ListCustomersHelpMessage" xml:space="preserve">
<value>顧客リスト</value> <value>顧客リスト</value>
</data> </data>
@ -136,7 +148,7 @@
<value>リスト</value> <value>リスト</value>
</data> </data>
<data name="ListSubscriptionssHelpMessage" xml:space="preserve"> <data name="ListSubscriptionssHelpMessage" xml:space="preserve">
<value>サブスクリプション</value> <value>リストの購読</value>
</data> </data>
<data name="Login" xml:space="preserve"> <data name="Login" xml:space="preserve">
<value>ログイン</value> <value>ログイン</value>
@ -150,46 +162,49 @@
<data name="NotAuthenticatedHelpMessage" xml:space="preserve"> <data name="NotAuthenticatedHelpMessage" xml:space="preserve">
<value>まず私と対話する前にログイン。入力してください * * ログイン * * を認証します。あなたはまだ型を助ける必要がある場合 * * ヘルプ * * 正常に認証した後。</value> <value>まず私と対話する前にログイン。入力してください * * ログイン * * を認証します。あなたはまだ型を助ける必要がある場合 * * ヘルプ * * 正常に認証した後。</value>
</data> </data>
<data name="OfficeIssuesHelpMessage" xml:space="preserve">
<value>求める Office 365 で任意の問題はありますか?</value>
</data>
<data name="QuestionHelpMessage" xml:space="preserve">
<value>EMS などの質問?</value>
</data>
<data name="RedisCacheConnectionException" xml:space="preserve"> <data name="RedisCacheConnectionException" xml:space="preserve">
<value>指定したインスタンスへの接続に失敗しました。</value> <value>指定したインスタンスへの接続に失敗しました。</value>
</data> </data>
<data name="RewordQuestion" xml:space="preserve">
<value>あなたの質問の言い回しを変更して、もう一度やり直してください。</value>
</data>
<data name="SelectCaptial" xml:space="preserve">
<value>選択します。</value>
</data>
<data name="ServiceInitializedException" xml:space="preserve">
<value>ボット サービスが初期化された後、この関数を呼び出すことはできません。</value>
</data>
<data name="SigninCardText" xml:space="preserve"> <data name="SigninCardText" xml:space="preserve">
<value>ログインには、下のボタンをクリックしてください。</value> <value>ログインには、下のボタンをクリックしてください。</value>
</data> </data>
<data name="SubscriptionContext" xml:space="preserve">
<value>ようサブスクリプションのコンテキストに設定します。</value>
</data>
<data name="SubscriptionRequestMessage" xml:space="preserve">
<value>ここでは、{0} のサブスクリプション</value>
</data>
<data name="SuccessfulAuthentication" xml:space="preserve"> <data name="SuccessfulAuthentication" xml:space="preserve">
<value>正常に認証!お気軽にこのウィンドウを閉じるし、ボットに話し続けます。</value> <value>正常に認証!お気軽にこのウィンドウを閉じるし、ボットに話し続けます。</value>
</data> </data>
<data name="UnableToLocateCustomer" xml:space="preserve"> <data name="UnableToLocateCustomer" xml:space="preserve">
<value>選択した顧客を見つけることができません。入力してください * * 顧客リスト * * もう一度やり直してください。</value> <value>選択した顧客を見つけることができません。入力してください * * 顧客リスト * * もう一度やり直してください。</value>
</data> </data>
<data name="Help" xml:space="preserve">
<value>ヘルプ</value>
</data>
<data name="RewordQuestion" xml:space="preserve">
<value>あなたの質問の言い回しを変更して、もう一度やり直してください。</value>
</data>
<data name="InvalidCustomerContextException" xml:space="preserve">
<value>この操作を行う前に顧客を選択する必要があります。入力してください * * 顧客リスト * *、顧客を選択し、もう一度やり直して。</value>
</data>
<data name="SubscriptionRequestMessage" xml:space="preserve">
<value>ここでは、{0} のサブスクリプション</value>
</data>
<data name="ServiceInitializedException" xml:space="preserve">
<value>ボット サービスが初期化された後、この関数を呼び出すことはできません。</value>
</data>
<data name="CustomerContext" xml:space="preserve">
<value>よう顧客のコンテキストに設定します。</value>
</data>
<data name="SelectCaptial" xml:space="preserve">
<value>選択します。</value>
</data>
<data name="SubscriptionContext" xml:space="preserve">
<value>ようサブスクリプションのコンテキストに設定します。</value>
</data>
<data name="UnableToLocateSubscription" xml:space="preserve"> <data name="UnableToLocateSubscription" xml:space="preserve">
<value>選択したサブスクリプションが見つかりません。入力してください * * サブスクリプションを一覧表示 * * もう一度やり直してください。</value> <value>選択したサブスクリプションが見つかりません。入力してください * * サブスクリプションを一覧表示 * * もう一度やり直してください。</value>
</data> </data>
<data name="Welcome" xml:space="preserve"> <data name="Welcome" xml:space="preserve">
<value>パートナー センター ボットへようこそ。まず私と対話する前にログイン。入力してください * * ログイン * * を認証します。あなたはまだ型を助ける必要がある場合 * * ヘルプ * * 正常に認証した後。</value> <value>パートナー センター ボットへようこそ。まず私と対話する前にログイン。入力してください * * ログイン * * を認証します。あなたはまだ型を助ける必要がある場合 * * ヘルプ * * 正常に認証した後。</value>
</data> </data>
<data name="ErrorMessage" xml:space="preserve">
<value>この要求を満たすから私を妨げている問題をするようです。もう一度やり直してください。</value>
</data>
<data name="SelectCustomerFirst" xml:space="preserve">
<value>この操作を行う前に顧客を選択する必要があります。送信してください * * リストお客様 * *、顧客を選択して、もう一度やり直して。</value>
</data>
</root> </root>

Просмотреть файл

@ -126,6 +126,9 @@
<data name="DataProtectionUnprotectException" xml:space="preserve"> <data name="DataProtectionUnprotectException" xml:space="preserve">
<value>Failed to unprotect the specified data.</value> <value>Failed to unprotect the specified data.</value>
</data> </data>
<data name="ErrorMessage" xml:space="preserve">
<value>There appears to be an issue preventing me from fulfilling this request. Please try again later</value>
</data>
<data name="Help" xml:space="preserve"> <data name="Help" xml:space="preserve">
<value>help</value> <value>help</value>
</data> </data>
@ -138,6 +141,9 @@
<data name="InvalidCustomerContextException" xml:space="preserve"> <data name="InvalidCustomerContextException" xml:space="preserve">
<value>You must select a customer before attempting this operation. Please type ** list customers **, select a customer, and then try again.</value> <value>You must select a customer before attempting this operation. Please type ** list customers **, select a customer, and then try again.</value>
</data> </data>
<data name="InvalidSubscriptionContextException" xml:space="preserve">
<value>You must select a subscription before attempting this operation. Please type ** list subscriptions**, select a subscription, and then try again.</value>
</data>
<data name="ListCustomersHelpMessage" xml:space="preserve"> <data name="ListCustomersHelpMessage" xml:space="preserve">
<value>list customers</value> <value>list customers</value>
</data> </data>
@ -145,7 +151,7 @@
<value>list</value> <value>list</value>
</data> </data>
<data name="ListSubscriptionssHelpMessage" xml:space="preserve"> <data name="ListSubscriptionssHelpMessage" xml:space="preserve">
<value>subscriptions</value> <value>list subscriptions</value>
</data> </data>
<data name="Login" xml:space="preserve"> <data name="Login" xml:space="preserve">
<value>login</value> <value>login</value>
@ -159,6 +165,12 @@
<data name="NotAuthenticatedHelpMessage" xml:space="preserve"> <data name="NotAuthenticatedHelpMessage" xml:space="preserve">
<value>You must first login before interacting with me. Please type ** login ** to authenticate. If you still need help type ** help ** after successfully authenticating.</value> <value>You must first login before interacting with me. Please type ** login ** to authenticate. If you still need help type ** help ** after successfully authenticating.</value>
</data> </data>
<data name="OfficeIssuesHelpMessage" xml:space="preserve">
<value>Ask are there any issues with Office 365?</value>
</data>
<data name="QuestionHelpMessage" xml:space="preserve">
<value>Ask questions such as what is EMS?</value>
</data>
<data name="RedisCacheConnectionException" xml:space="preserve"> <data name="RedisCacheConnectionException" xml:space="preserve">
<value>Failed to connect to the specified instance.</value> <value>Failed to connect to the specified instance.</value>
</data> </data>
@ -168,6 +180,9 @@
<data name="SelectCaptial" xml:space="preserve"> <data name="SelectCaptial" xml:space="preserve">
<value>Select</value> <value>Select</value>
</data> </data>
<data name="SelectCustomerFirst" xml:space="preserve">
<value>You must select a customer before attempting this operation. Please send **list customers**, select a customer, and then try again.</value>
</data>
<data name="ServiceInitializedException" xml:space="preserve"> <data name="ServiceInitializedException" xml:space="preserve">
<value>Cannot invoke this function after the bot service has been initialized.</value> <value>Cannot invoke this function after the bot service has been initialized.</value>
</data> </data>

Просмотреть файл

@ -33,8 +33,8 @@ namespace Microsoft.Store.PartnerCenter.Bot.Security
{ {
IBotService service = scope.Resolve<IBotService>(); IBotService service = scope.Resolve<IBotService>();
this.MicrosoftAppId = service.Configuration.MicrosoftAppId; MicrosoftAppId = service.Configuration.MicrosoftAppId;
this.MicrosoftAppPassword = service.Configuration.MicrosoftAppPassword; MicrosoftAppPassword = service.Configuration.MicrosoftAppPassword;
} }
return base.OnActionExecutingAsync(actionContext, cancellationToken); return base.OnActionExecutingAsync(actionContext, cancellationToken);

Просмотреть файл

@ -60,8 +60,8 @@ namespace Microsoft.Store.PartnerCenter.Bot.Security
/// </summary> /// </summary>
public OperationContext Operation public OperationContext Operation
{ {
get { return this.operationContext ?? (this.operationContext = new OperationContext()); } get { return operationContext ?? (operationContext = new OperationContext()); }
set { this.operationContext = value; } set { operationContext = value; }
} }
/// <summary> /// <summary>

Просмотреть файл

@ -48,7 +48,7 @@ namespace Microsoft.Store.PartnerCenter.Bot.Security
try try
{ {
buffer = Encoding.ASCII.GetBytes(data); buffer = Encoding.ASCII.GetBytes(data);
return Convert.ToBase64String(MachineKey.Protect(buffer, this.purposes)); return Convert.ToBase64String(MachineKey.Protect(buffer, purposes));
} }
finally finally
{ {
@ -74,7 +74,7 @@ namespace Microsoft.Store.PartnerCenter.Bot.Security
try try
{ {
buffer = Convert.FromBase64String(data); buffer = Convert.FromBase64String(data);
decrypt = MachineKey.Unprotect(buffer, this.purposes); decrypt = MachineKey.Unprotect(buffer, purposes);
if (decrypt == null) if (decrypt == null)
{ {

Просмотреть файл

@ -74,7 +74,7 @@ namespace Microsoft.Store.PartnerCenter.Bot.Security
authResult = await authContext.AcquireTokenSilentAsync( authResult = await authContext.AcquireTokenSilentAsync(
resource, resource,
this.service.Configuration.ApplicationId, service.Configuration.ApplicationId,
objectUserId); objectUserId);
return authResult; return authResult;
@ -107,9 +107,9 @@ namespace Microsoft.Store.PartnerCenter.Bot.Security
try try
{ {
if (this.service.Cache.IsEnabled) if (service.Cache.IsEnabled)
{ {
tokenCache = new DistributedTokenCache(this.service, resource, $"AppOnly::{resource}"); tokenCache = new DistributedTokenCache(service, resource, $"AppOnly::{resource}");
authContext = new AuthenticationContext(authority, tokenCache); authContext = new AuthenticationContext(authority, tokenCache);
} }
else else
@ -120,8 +120,8 @@ namespace Microsoft.Store.PartnerCenter.Bot.Security
authResult = await authContext.AcquireTokenAsync( authResult = await authContext.AcquireTokenAsync(
resource, resource,
new ClientCredential( new ClientCredential(
this.service.Configuration.ApplicationId, service.Configuration.ApplicationId,
this.service.Configuration.ApplicationSecret)); service.Configuration.ApplicationSecret));
return new AuthenticationToken(authResult.AccessToken, authResult.ExpiresOn); return new AuthenticationToken(authResult.AccessToken, authResult.ExpiresOn);
} }
@ -158,12 +158,12 @@ namespace Microsoft.Store.PartnerCenter.Bot.Security
{ {
authContext = new AuthenticationContext(authority); authContext = new AuthenticationContext(authority);
certificate = FindCertificateByThumbprint(this.service.Configuration.VaultApplicationCertThumbprint); certificate = FindCertificateByThumbprint(service.Configuration.VaultApplicationCertThumbprint);
authResult = await authContext.AcquireTokenAsync( authResult = await authContext.AcquireTokenAsync(
resource, resource,
new ClientAssertionCertificate( new ClientAssertionCertificate(
this.service.Configuration.VaultApplicationId, service.Configuration.VaultApplicationId,
certificate)); certificate));
return authResult.AccessToken; return authResult.AccessToken;
@ -206,9 +206,9 @@ namespace Microsoft.Store.PartnerCenter.Bot.Security
{ {
key = $"AppPlusUser::{resource}::{principal.ObjectId}"; key = $"AppPlusUser::{resource}::{principal.ObjectId}";
if (this.service.Cache.IsEnabled) if (service.Cache.IsEnabled)
{ {
tokenCache = new DistributedTokenCache(this.service, resource, key); tokenCache = new DistributedTokenCache(service, resource, key);
authContext = new AuthenticationContext(authority, tokenCache); authContext = new AuthenticationContext(authority, tokenCache);
} }
else else
@ -221,21 +221,21 @@ namespace Microsoft.Store.PartnerCenter.Bot.Security
authResult = await authContext.AcquireTokenAsync( authResult = await authContext.AcquireTokenAsync(
resource, resource,
new ClientCredential( new ClientCredential(
this.service.Configuration.ApplicationId, service.Configuration.ApplicationId,
this.service.Configuration.ApplicationSecret), service.Configuration.ApplicationSecret),
new UserAssertion(principal.AccessToken, AssertionType)); new UserAssertion(principal.AccessToken, AssertionType));
} }
catch (AdalServiceException ex) catch (AdalServiceException ex)
{ {
if (ex.ErrorCode.Equals("AADSTS70002", StringComparison.CurrentCultureIgnoreCase)) if (ex.ErrorCode.Equals("AADSTS70002", StringComparison.CurrentCultureIgnoreCase))
{ {
await this.service.Cache.DeleteAsync(CacheDatabaseType.Authentication, key); await service.Cache.DeleteAsync(CacheDatabaseType.Authentication, key);
authResult = await authContext.AcquireTokenAsync( authResult = await authContext.AcquireTokenAsync(
resource, resource,
new ClientCredential( new ClientCredential(
this.service.Configuration.ApplicationId, service.Configuration.ApplicationId,
this.service.Configuration.ApplicationSecret), service.Configuration.ApplicationSecret),
new UserAssertion(principal.AccessToken, AssertionType)); new UserAssertion(principal.AccessToken, AssertionType));
} }
else else
@ -285,7 +285,7 @@ namespace Microsoft.Store.PartnerCenter.Bot.Security
authUri = await authContext.GetAuthorizationRequestUrlAsync( authUri = await authContext.GetAuthorizationRequestUrlAsync(
resource, resource,
this.service.Configuration.ApplicationId, service.Configuration.ApplicationId,
redirectUri, redirectUri,
UserIdentifier.AnyUser, UserIdentifier.AnyUser,
extraQueryParameters); extraQueryParameters);
@ -315,7 +315,7 @@ namespace Microsoft.Store.PartnerCenter.Bot.Security
// Attempt to obtain the Partner Center token from the cache. // Attempt to obtain the Partner Center token from the cache.
IPartnerCredentials credentials = IPartnerCredentials credentials =
await this.service.Cache.FetchAsync<PartnerCenterTokenModel>( await service.Cache.FetchAsync<PartnerCenterTokenModel>(
CacheDatabaseType.Authentication, BotConstants.PartnerCenterAppOnlyKey); CacheDatabaseType.Authentication, BotConstants.PartnerCenterAppOnlyKey);
if (credentials != null && !credentials.IsExpired()) if (credentials != null && !credentials.IsExpired())
@ -325,11 +325,11 @@ namespace Microsoft.Store.PartnerCenter.Bot.Security
// The access token has expired, so a new one must be requested. // The access token has expired, so a new one must be requested.
credentials = await PartnerCredentials.Instance.GenerateByApplicationCredentialsAsync( credentials = await PartnerCredentials.Instance.GenerateByApplicationCredentialsAsync(
this.service.Configuration.PartnerCenterApplicationId, service.Configuration.PartnerCenterApplicationId,
this.service.Configuration.PartnerCenterApplicationSecret, service.Configuration.PartnerCenterApplicationSecret,
this.service.Configuration.PartnerCenterApplicationTenantId); service.Configuration.PartnerCenterApplicationTenantId);
await this.service.Cache.StoreAsync( await service.Cache.StoreAsync(
CacheDatabaseType.Authentication, BotConstants.PartnerCenterAppOnlyKey, credentials); CacheDatabaseType.Authentication, BotConstants.PartnerCenterAppOnlyKey, credentials);
return credentials; return credentials;
@ -357,7 +357,7 @@ namespace Microsoft.Store.PartnerCenter.Bot.Security
string key = $"AppPlusUser::PartnerCenter::{principal.ObjectId}"; string key = $"AppPlusUser::PartnerCenter::{principal.ObjectId}";
IPartnerCredentials credentials = IPartnerCredentials credentials =
await this.service.Cache.FetchAsync<PartnerCenterTokenModel>( await service.Cache.FetchAsync<PartnerCenterTokenModel>(
CacheDatabaseType.Authentication, key); CacheDatabaseType.Authentication, key);
if (credentials != null && !credentials.IsExpired()) if (credentials != null && !credentials.IsExpired())
@ -365,15 +365,15 @@ namespace Microsoft.Store.PartnerCenter.Bot.Security
return credentials; return credentials;
} }
AuthenticationToken token = await this.GetAppPlusUserTokenAsync( AuthenticationToken token = await GetAppPlusUserTokenAsync(
principal, principal,
authority, authority,
this.service.Configuration.PartnerCenterEndpoint); service.Configuration.PartnerCenterEndpoint);
credentials = await PartnerCredentials.Instance.GenerateByUserCredentialsAsync( credentials = await PartnerCredentials.Instance.GenerateByUserCredentialsAsync(
this.service.Configuration.PartnerCenterApplicationId, token); service.Configuration.PartnerCenterApplicationId, token);
await this.service.Cache.StoreAsync( await service.Cache.StoreAsync(
CacheDatabaseType.Authentication, key, credentials); CacheDatabaseType.Authentication, key, credentials);
return credentials; return credentials;
@ -414,8 +414,8 @@ namespace Microsoft.Store.PartnerCenter.Bot.Security
code, code,
redirectUri, redirectUri,
new ClientCredential( new ClientCredential(
this.service.Configuration.ApplicationId, service.Configuration.ApplicationId,
this.service.Configuration.ApplicationSecret), service.Configuration.ApplicationSecret),
resource); resource);
} }
finally finally

Просмотреть файл

@ -52,6 +52,11 @@ namespace Microsoft.Store.PartnerCenter.Bot.Security
/// </summary> /// </summary>
UserAdministrator = 32, UserAdministrator = 32,
/// <summary>
/// Combination of all available roles.
/// </summary>
Any = AdminAgents | BillingAdmin | GlobalAdmin | HelpdeskAgent | SalesAgent | User | UserAdministrator,
/// <summary> /// <summary>
/// Combination of the available partner roles. /// Combination of the available partner roles.
/// </summary> /// </summary>

Просмотреть файл

@ -1,22 +0,0 @@
<StyleCopSettings Version="105">
<GlobalSettings>
<CollectionProperty Name="RecognizedWords">
<Value>cloneable</Value>
<Value>Redis</Value>
</CollectionProperty>
<BooleanProperty Name="AutoCheckForUpdate">False</BooleanProperty>
</GlobalSettings>
<Parsers>
<Parser ParserId="StyleCop.CSharp.CsParser">
<ParserSettings>
<BooleanProperty Name="AnalyzeDesignerFiles">False</BooleanProperty>
<CollectionProperty Name="GeneratedFileFilters">
<Value>\.g\.cs$</Value>
<Value>\.generated\.cs$</Value>
<Value>\.g\.i\.cs$</Value>
<Value>TemporaryGeneratedFile_.*\.cs$</Value>
</CollectionProperty>
</ParserSettings>
</Parser>
</Parsers>
</StyleCopSettings>

Просмотреть файл

@ -9,6 +9,8 @@
<add key="ActiveDirectoryEndpoint" value="https://login.microsoftonline.com" /> <add key="ActiveDirectoryEndpoint" value="https://login.microsoftonline.com" />
<!-- Microsoft Graph endpoint address --> <!-- Microsoft Graph endpoint address -->
<add key="MicrosoftGraphEndpoint" value="https://graph.microsoft.com/" /> <add key="MicrosoftGraphEndpoint" value="https://graph.microsoft.com/" />
<!-- Office 365 Management API endpoint address utilized by the application -->
<add key="OfficeManagementEndpoint" value="https://manage.office.com" />
<!-- Partner Center API endpoint address --> <!-- Partner Center API endpoint address -->
<add key="PartnerCenterEndpoint" value="https://api.partnercenter.microsoft.com" /> <add key="PartnerCenterEndpoint" value="https://api.partnercenter.microsoft.com" />
@ -69,7 +71,7 @@
</dependentAssembly> </dependentAssembly>
<dependentAssembly> <dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" /> <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-9.0.0.0" newVersion="9.0.0.0" /> <bindingRedirect oldVersion="0.0.0.0-10.0.0.0" newVersion="10.0.0.0" />
</dependentAssembly> </dependentAssembly>
<dependentAssembly> <dependentAssembly>
<assemblyIdentity name="System.Net.Http.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" /> <assemblyIdentity name="System.Net.Http.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
@ -85,7 +87,7 @@
</dependentAssembly> </dependentAssembly>
<dependentAssembly> <dependentAssembly>
<assemblyIdentity name="Microsoft.IdentityModel.Clients.ActiveDirectory" publicKeyToken="31bf3856ad364e35" culture="neutral" /> <assemblyIdentity name="Microsoft.IdentityModel.Clients.ActiveDirectory" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.13.8.999" newVersion="3.13.8.999" /> <bindingRedirect oldVersion="0.0.0.0-3.13.9.1126" newVersion="3.13.9.1126" />
</dependentAssembly> </dependentAssembly>
<dependentAssembly> <dependentAssembly>
<assemblyIdentity name="Microsoft.AI.Agent.Intercept" publicKeyToken="31bf3856ad364e35" culture="neutral" /> <assemblyIdentity name="Microsoft.AI.Agent.Intercept" publicKeyToken="31bf3856ad364e35" culture="neutral" />
@ -97,11 +99,27 @@
</dependentAssembly> </dependentAssembly>
<dependentAssembly> <dependentAssembly>
<assemblyIdentity name="Microsoft.Bot.Builder" publicKeyToken="31bf3856ad364e35" culture="neutral" /> <assemblyIdentity name="Microsoft.Bot.Builder" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.5.3.0" newVersion="3.5.3.0" /> <bindingRedirect oldVersion="0.0.0.0-3.8.0.0" newVersion="3.8.0.0" />
</dependentAssembly> </dependentAssembly>
<dependentAssembly> <dependentAssembly>
<assemblyIdentity name="Microsoft.Bot.Connector" publicKeyToken="31bf3856ad364e35" culture="neutral" /> <assemblyIdentity name="Microsoft.Bot.Connector" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.5.3.0" newVersion="3.5.3.0" /> <bindingRedirect oldVersion="0.0.0.0-3.8.0.0" newVersion="3.8.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.IdentityModel.Tokens.Jwt" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.40306.1554" newVersion="4.0.40306.1554" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.IdentityModel.Protocol.Extensions" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.0.40306.1554" newVersion="1.0.40306.1554" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.1.1" newVersion="4.1.1.1" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Bot.Builder.Autofac" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.8.0.0" newVersion="3.8.0.0" />
</dependentAssembly> </dependentAssembly>
</assemblyBinding> </assemblyBinding>
</runtime> </runtime>

Просмотреть файл

@ -3,31 +3,35 @@
<package id="Autofac" version="3.5.2" targetFramework="net461" /> <package id="Autofac" version="3.5.2" targetFramework="net461" />
<package id="Autofac.WebApi2" version="4.0.1" targetFramework="net461" /> <package id="Autofac.WebApi2" version="4.0.1" targetFramework="net461" />
<package id="Chronic.Signed" version="0.3.2" targetFramework="net461" /> <package id="Chronic.Signed" version="0.3.2" targetFramework="net461" />
<package id="Microsoft.ApplicationInsights" version="2.2.0" targetFramework="net461" /> <package id="Microsoft.ApplicationInsights" version="2.3.0" targetFramework="net461" />
<package id="Microsoft.ApplicationInsights.Agent.Intercept" version="2.0.7" targetFramework="net461" /> <package id="Microsoft.ApplicationInsights.Agent.Intercept" version="2.0.7" targetFramework="net461" />
<package id="Microsoft.ApplicationInsights.DependencyCollector" version="2.2.0" targetFramework="net461" /> <package id="Microsoft.ApplicationInsights.DependencyCollector" version="2.3.0" targetFramework="net461" />
<package id="Microsoft.ApplicationInsights.PerfCounterCollector" version="2.2.0" targetFramework="net461" /> <package id="Microsoft.ApplicationInsights.PerfCounterCollector" version="2.3.0" targetFramework="net461" />
<package id="Microsoft.ApplicationInsights.Web" version="2.2.0" targetFramework="net461" /> <package id="Microsoft.ApplicationInsights.Web" version="2.3.0" targetFramework="net461" />
<package id="Microsoft.ApplicationInsights.WindowsServer" version="2.2.0" targetFramework="net461" /> <package id="Microsoft.ApplicationInsights.WindowsServer" version="2.3.0" targetFramework="net461" />
<package id="Microsoft.ApplicationInsights.WindowsServer.TelemetryChannel" version="2.2.0" targetFramework="net461" /> <package id="Microsoft.ApplicationInsights.WindowsServer.TelemetryChannel" version="2.3.0" targetFramework="net461" />
<package id="Microsoft.AspNet.WebApi" version="5.2.3" targetFramework="net461" /> <package id="Microsoft.AspNet.WebApi" version="5.2.3" targetFramework="net461" />
<package id="Microsoft.AspNet.WebApi.Client" version="5.2.3" targetFramework="net461" /> <package id="Microsoft.AspNet.WebApi.Client" version="5.2.3" targetFramework="net461" />
<package id="Microsoft.AspNet.WebApi.Core" version="5.2.3" targetFramework="net461" /> <package id="Microsoft.AspNet.WebApi.Core" version="5.2.3" targetFramework="net461" />
<package id="Microsoft.AspNet.WebApi.WebHost" version="5.2.3" targetFramework="net461" /> <package id="Microsoft.AspNet.WebApi.WebHost" version="5.2.3" targetFramework="net461" />
<package id="Microsoft.Azure.KeyVault" version="2.0.6" targetFramework="net461" /> <package id="Microsoft.Azure.KeyVault" version="2.0.6" targetFramework="net461" />
<package id="Microsoft.Azure.KeyVault.WebKey" version="2.0.4" targetFramework="net461" /> <package id="Microsoft.Azure.KeyVault.WebKey" version="2.0.5" targetFramework="net461" />
<package id="Microsoft.Bot.Builder" version="3.5.5" targetFramework="net461" /> <package id="Microsoft.Bot.Builder" version="3.8.0" targetFramework="net461" />
<package id="Microsoft.Bot.Builder.CognitiveServices" version="1.0.3" targetFramework="net461" /> <package id="Microsoft.Bot.Builder.CognitiveServices" version="1.1.0" targetFramework="net461" />
<package id="Microsoft.Graph" version="1.2.1" targetFramework="net461" /> <package id="Microsoft.Graph" version="1.3.0" targetFramework="net461" />
<package id="Microsoft.Graph.Core" version="1.3.0" targetFramework="net461" /> <package id="Microsoft.Graph.Core" version="1.4.0" targetFramework="net461" />
<package id="Microsoft.IdentityModel.Clients.ActiveDirectory" version="3.13.8" targetFramework="net461" /> <package id="Microsoft.IdentityModel.Clients.ActiveDirectory" version="3.13.9" targetFramework="net461" />
<package id="Microsoft.IdentityModel.Protocol.Extensions" version="1.0.2.206221351" targetFramework="net461" /> <package id="Microsoft.IdentityModel.Protocol.Extensions" version="1.0.4.403061554" targetFramework="net461" />
<package id="Microsoft.Rest.ClientRuntime" version="2.3.6" targetFramework="net461" /> <package id="Microsoft.Rest.ClientRuntime" version="2.3.7" targetFramework="net461" />
<package id="Microsoft.Rest.ClientRuntime.Azure" version="3.3.5" targetFramework="net461" /> <package id="Microsoft.Rest.ClientRuntime.Azure" version="3.3.6" targetFramework="net461" />
<package id="Microsoft.Store.PartnerCenter" version="1.3.0.0" targetFramework="net461" /> <package id="Microsoft.Store.PartnerCenter" version="1.4.0" targetFramework="net461" />
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="net461" /> <package id="Newtonsoft.Json" version="10.0.2" targetFramework="net461" />
<package id="StackExchange.Redis.StrongName" version="1.2.1" targetFramework="net461" /> <package id="StackExchange.Redis.StrongName" version="1.2.3" targetFramework="net461" />
<package id="System.IdentityModel.Tokens.Jwt" version="4.0.2.206221351" targetFramework="net461" /> <package id="System.IdentityModel.Tokens.Jwt" version="4.0.4.403061554" targetFramework="net461" />
<package id="System.Net.Http" version="4.3.2" targetFramework="net461" />
<package id="System.Security.Cryptography.Algorithms" version="4.3.0" targetFramework="net461" />
<package id="System.Security.Cryptography.Encoding" version="4.3.0" targetFramework="net461" />
<package id="System.Security.Cryptography.Primitives" version="4.3.0" targetFramework="net461" />
<package id="System.Security.Cryptography.X509Certificates" version="4.3.0" targetFramework="net461" />
<package id="System.Threading.Tasks.Extensions" version="4.3.0" targetFramework="net461" /> <package id="System.Threading.Tasks.Extensions" version="4.3.0" targetFramework="net461" />
<package id="Visual-StyleCop.MSBuild" version="4.7.59.0" targetFramework="net461" />
</packages> </packages>