EmbedReports { get; set; }
15 |
16 | // Embed Token for the Power BI report
17 | public EmbedToken EmbedToken { get; set; }
18 | }
19 | }
--------------------------------------------------------------------------------
/.NET Framework/Embed for your customers/AppOwnsData/Models/TileEmbedConfig.cs:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------------
2 | // Copyright (c) Microsoft Corporation.
3 | // Licensed under the MIT license.
4 | // ----------------------------------------------------------------------------
5 |
6 | namespace AppOwnsData.Models
7 | {
8 | using Microsoft.PowerBI.Api.Models;
9 | using System;
10 |
11 | public class TileEmbedConfig
12 | {
13 | public Guid TileId { get; set; }
14 |
15 | public string EmbedUrl { get; set; }
16 |
17 | public EmbedToken EmbedToken { get; set; }
18 |
19 | public Guid DashboardId { get; set; }
20 | }
21 | }
--------------------------------------------------------------------------------
/.NET Framework/Embed for your customers/AppOwnsData/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("AppOwnsData")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("AppOwnsData")]
13 | [assembly: AssemblyCopyright("Copyright © 2017")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("26b5a5ab-d61b-4db6-9474-ccb43e0312bc")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Revision and Build Numbers
33 | // by using the '*' as shown below:
34 | [assembly: AssemblyVersion("1.0.0.0")]
35 | [assembly: AssemblyFileVersion("1.0.0.0")]
36 |
--------------------------------------------------------------------------------
/.NET Framework/Embed for your customers/AppOwnsData/Views/Home/AdditionalLinks.cshtml:
--------------------------------------------------------------------------------
1 | @*
2 | ----------------------------------------------------------------------------
3 | Copyright (c) Microsoft Corporation.
4 | Licensed under the MIT license.
5 | ----------------------------------------------------------------------------
6 | *@
7 |
8 |
--------------------------------------------------------------------------------
/.NET Framework/Embed for your customers/AppOwnsData/Views/Home/Error.cshtml:
--------------------------------------------------------------------------------
1 | @*
2 | ----------------------------------------------------------------------------
3 | Copyright (c) Microsoft Corporation.
4 | Licensed under the MIT license.
5 | ----------------------------------------------------------------------------
6 | *@
7 |
8 | @model AppOwnsData.Models.ErrorModel
9 |
10 | @{
11 | ViewBag.Title = "Error";
12 | }
13 |
14 |
15 |
16 |
17 |
18 | Error
19 |
20 |
21 |
22 |
23 | Error
24 |
25 |
26 |
27 | @Model.ErrorMessage
28 |
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/.NET Framework/Embed for your customers/AppOwnsData/Views/Home/Index.cshtml:
--------------------------------------------------------------------------------
1 | @*
2 | ----------------------------------------------------------------------------
3 | Copyright (c) Microsoft Corporation.
4 | Licensed under the MIT license.
5 | ----------------------------------------------------------------------------
6 | *@
7 |
8 | @model AppOwnsData.Models.IndexConfig
9 |
10 | @{
11 | ViewBag.Title = "Index";
12 | Layout = "~/Views/Shared/_Layout.cshtml";
13 | }
14 |
15 |
33 |
--------------------------------------------------------------------------------
/.NET Framework/Embed for your customers/AppOwnsData/Views/Shared/_Layout.cshtml:
--------------------------------------------------------------------------------
1 | @*
2 | ----------------------------------------------------------------------------
3 | Copyright (c) Microsoft Corporation.
4 | Licensed under the MIT license.
5 | ----------------------------------------------------------------------------
6 | *@
7 |
8 |
9 |
10 |
11 |
12 |
13 | Power BI Embedded sample
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | @RenderBody()
23 |
24 |
25 |
--------------------------------------------------------------------------------
/.NET Framework/Embed for your customers/AppOwnsData/Views/_ViewStart.cshtml:
--------------------------------------------------------------------------------
1 | @*
2 | ----------------------------------------------------------------------------
3 | Copyright (c) Microsoft Corporation.
4 | Licensed under the MIT license.
5 | ----------------------------------------------------------------------------
6 | *@
7 |
8 | @{
9 | Layout = "~/Views/Shared/_Layout.cshtml";
10 | }
11 |
--------------------------------------------------------------------------------
/.NET Framework/Embed for your customers/AppOwnsData/Web.Debug.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
17 |
18 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/.NET Framework/Embed for your customers/AppOwnsData/Web.Release.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
17 |
18 |
19 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/.NET Framework/Embed for your customers/AppOwnsData/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/PowerBI-Developer-Samples/2970f6581bb6e6aa3403be858ffd968357807f5d/.NET Framework/Embed for your customers/AppOwnsData/favicon.ico
--------------------------------------------------------------------------------
/.NET Framework/Embed for your customers/AppOwnsData/libman.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "1.0",
3 | "defaultProvider": "cdnjs",
4 | "libraries": [
5 | {
6 | "provider": "jsdelivr",
7 | "library": "powerbi-client@2.16.5",
8 | "destination": "Content/lib/powerbi-client/",
9 | "files": [
10 | "LICENSE.txt",
11 | "dist/powerbi.min.js"
12 | ]
13 | },
14 | {
15 | "provider": "jsdelivr",
16 | "library": "jquery@3.5.1",
17 | "destination": "Content/lib/jquery/",
18 | "files": [
19 | "LICENSE.txt",
20 | "dist/jquery.min.js"
21 | ]
22 | }
23 | ]
24 | }
--------------------------------------------------------------------------------
/.NET Framework/Embed for your customers/AppOwnsData/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/.NET Framework/Embed for your organization/CloudConfigs/Power BI Global/Cloud.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/.NET Framework/Embed for your organization/CloudConfigs/Power BI US Government/Cloud.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/.NET Framework/Embed for your organization/CloudConfigs/Power BI in Germany/Cloud.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/.NET Framework/Embed for your organization/CloudConfigs/Power BI operated by 21Vianet in China/Cloud.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/.NET Framework/Embed for your organization/UserOwnsData.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.29613.14
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UserOwnsData", "UserOwnsData\UserOwnsData.csproj", "{550BDA61-848F-4422-8E36-E13C82787B4D}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {550BDA61-848F-4422-8E36-E13C82787B4D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {550BDA61-848F-4422-8E36-E13C82787B4D}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {550BDA61-848F-4422-8E36-E13C82787B4D}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {550BDA61-848F-4422-8E36-E13C82787B4D}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ExtensibilityGlobals) = postSolution
23 | SolutionGuid = {D8231DEE-150D-4CA0-9475-18572BA5FD7A}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/.NET Framework/Embed for your organization/UserOwnsData/App_Start/RouteConfig.cs:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------------
2 | // Copyright (c) Microsoft Corporation.
3 | // Licensed under the MIT license.
4 | // ----------------------------------------------------------------------------
5 |
6 | namespace UserOwnsData
7 | {
8 | using System.Web.Mvc;
9 | using System.Web.Routing;
10 |
11 | public class RouteConfig
12 | {
13 | public static void RegisterRoutes(RouteCollection routes)
14 | {
15 | routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
16 |
17 | routes.MapRoute(
18 | name: "Default",
19 | url: "{controller}/{action}/{id}",
20 | defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
21 | );
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/.NET Framework/Embed for your organization/UserOwnsData/Content/img/spinner.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/.NET Framework/Embed for your organization/UserOwnsData/Controllers/EmbedInfoController.cs:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------------
2 | // Copyright (c) Microsoft Corporation.
3 | // Licensed under the MIT license.
4 | // ----------------------------------------------------------------------------
5 |
6 | namespace UserOwnsData.Controllers
7 | {
8 | using System;
9 | using System.Net;
10 | using System.Security.Claims;
11 | using System.Web.Mvc;
12 | using UserOwnsData.Models;
13 | using UserOwnsData.Services;
14 | using UserOwnsData.Services.Security;
15 |
16 | public class EmbedInfoController : Controller
17 | {
18 | ///
19 | /// Returns Embed view when client is authorized
20 | ///
21 | /// Returns Embed view with authentication details
22 | [Authorize]
23 | public ActionResult Embed()
24 | {
25 | try
26 | {
27 | var userName = ClaimsPrincipal.Current.FindFirst("name").Value;
28 |
29 | var accessToken = TokenManager.GetAccessToken(PowerBIPermissionScopes.ReadUserWorkspaces);
30 |
31 | AuthDetails authDetails = new AuthDetails
32 | {
33 | UserName = userName,
34 | AccessToken = accessToken
35 | };
36 |
37 | return View("embed", authDetails);
38 | }
39 | catch (Exception ex)
40 | {
41 | ErrorModel errorModel = Utils.GetErrorModel((HttpStatusCode)500, ex.ToString());
42 | return View("Error", errorModel);
43 | }
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/.NET Framework/Embed for your organization/UserOwnsData/Controllers/HomeController.cs:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------------
2 | // Copyright (c) Microsoft Corporation.
3 | // Licensed under the MIT license.
4 | // ----------------------------------------------------------------------------
5 |
6 | namespace UserOwnsData.Controllers
7 | {
8 | using System.Net;
9 | using System.Web.Mvc;
10 | using UserOwnsData.Models;
11 | using UserOwnsData.Services;
12 |
13 | public class HomeController : Controller
14 | {
15 | ///
16 | /// Returns Index view to the client after validating app configurations
17 | ///
18 | /// Returns Index view
19 | public ActionResult Index()
20 | {
21 | // Validate sanctity of configuration before proceeding
22 | string configValidationResult = ConfigValidatorService.ValidateConfig();
23 | if (configValidationResult != null)
24 | {
25 | ErrorModel errorModel = Utils.GetErrorModel((HttpStatusCode)400, configValidationResult);
26 | return View("Error", errorModel);
27 | }
28 | return View();
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/.NET Framework/Embed for your organization/UserOwnsData/Models/AuthDetails.cs:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------------
2 | // Copyright (c) Microsoft Corporation.
3 | // Licensed under the MIT license.
4 | // ----------------------------------------------------------------------------
5 |
6 | namespace UserOwnsData.Models
7 | {
8 | public class AuthDetails
9 | {
10 | public string UserName { get; set; }
11 | public string AccessToken { get; set; }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/.NET Framework/Embed for your organization/UserOwnsData/Models/ErrorModel.cs:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------------
2 | // Copyright (c) Microsoft Corporation.
3 | // Licensed under the MIT license.
4 | // ----------------------------------------------------------------------------
5 |
6 | namespace UserOwnsData.Models
7 | {
8 | using System.Net;
9 |
10 | public class ErrorModel
11 | {
12 | public HttpStatusCode ErrorCode { get; set; }
13 | public string ErrorMessage { get; set; }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/.NET Framework/Embed for your organization/UserOwnsData/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("UserOwnsData")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("UserOwnsData")]
13 | [assembly: AssemblyCopyright("Copyright © 2020")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("550bda61-848f-4422-8e36-e13c82787b4d")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Revision and Build Numbers
33 | // by using the '*' as shown below:
34 | [assembly: AssemblyVersion("1.0.0.0")]
35 | [assembly: AssemblyFileVersion("1.0.0.0")]
36 |
--------------------------------------------------------------------------------
/.NET Framework/Embed for your organization/UserOwnsData/Scripts/error.js:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------------
2 | // Copyright (c) Microsoft Corporation.
3 | // Licensed under the MIT license.
4 | // ----------------------------------------------------------------------------
5 |
6 | // Show error to the user
7 | function showError(err) {
8 | let errorContainer = $("#error-container");
9 | globals.reportWrapper.hide();
10 | globals.dashboardWrapper.hide();
11 | globals.tileWrapper.hide();
12 | $(".config-container").hide();
13 | $("header").hide();
14 |
15 | // Show error container
16 | errorContainer.show();
17 |
18 | // Format error message
19 | let errHeader = document.createTextNode("Error Details:");
20 | let strong = document.createElement("strong");
21 | strong.appendChild(errHeader);
22 |
23 | // Create paragraph element to store error header and error message
24 | let errorMessage = document.createElement("p");
25 | errorMessage.appendChild(strong);
26 |
27 | // Break error message around \n and appends break element at the corresponding index
28 | let arr = err.responseText.split("\n");
29 | for (let i = 0; i < arr.length; i++) {
30 | let br = document.createElement("br");
31 |
32 | // Create node element to store individual line from the error message
33 | // along with the break element
34 | let node = document.createTextNode(arr[i]);
35 | errorMessage.appendChild(br);
36 | errorMessage.appendChild(node);
37 | }
38 |
39 | // Show error message on UI
40 | errorContainer.get(0).appendChild(errorMessage);
41 | }
--------------------------------------------------------------------------------
/.NET Framework/Embed for your organization/UserOwnsData/Services/Security/PowerBiPermissionScopes.cs:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------------
2 | // Copyright (c) Microsoft Corporation.
3 | // Licensed under the MIT license.
4 | // ----------------------------------------------------------------------------
5 |
6 | namespace UserOwnsData.Services.Security
7 | {
8 | using System.Configuration;
9 |
10 | public class PowerBIPermissionScopes
11 | {
12 | private static readonly string scopeBase = ConfigurationManager.AppSettings["scopeBase"];
13 |
14 | public static readonly string[] ReadUserWorkspaces = new string[] {
15 | scopeBase + "Workspace.Read.All",
16 | scopeBase + "Report.Read.All",
17 | scopeBase + "Dashboard.Read.All"
18 | };
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/.NET Framework/Embed for your organization/UserOwnsData/Services/Utils.cs:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------------
2 | // Copyright (c) Microsoft Corporation.
3 | // Licensed under the MIT license.
4 | // ----------------------------------------------------------------------------
5 |
6 | namespace UserOwnsData.Services
7 | {
8 | using System.Net;
9 | using UserOwnsData.Models;
10 |
11 | public class Utils
12 | {
13 | ///
14 | /// Creates error model
15 | ///
16 | /// HTTP status code of the error
17 | /// Error details
18 | /// Object of ErrorModel containing error code and error message
19 | public static ErrorModel GetErrorModel(HttpStatusCode errorCode, string errorMessage) {
20 | ErrorModel errorModel = new ErrorModel
21 | {
22 | ErrorCode = errorCode,
23 | ErrorMessage = errorMessage
24 | };
25 |
26 | return errorModel;
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/.NET Framework/Embed for your organization/UserOwnsData/Startup.cs:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------------
2 | // Copyright (c) Microsoft Corporation.
3 | // Licensed under the MIT license.
4 | // ----------------------------------------------------------------------------
5 |
6 | namespace UserOwnsData
7 | {
8 | using UserOwnsData.Services.Security;
9 | using Owin;
10 | using System.Web.Mvc;
11 | using System.Web.Routing;
12 |
13 | public class Startup
14 | {
15 | public void Configuration(IAppBuilder app)
16 | {
17 |
18 | // init ASP.NET MVC routes
19 | AreaRegistration.RegisterAllAreas();
20 | RouteConfig.RegisterRoutes(RouteTable.Routes);
21 |
22 | // init OpenId Connect settings
23 | OwinOpenIdConnect.ConfigureAuth(app);
24 | }
25 | }
26 | }
--------------------------------------------------------------------------------
/.NET Framework/Embed for your organization/UserOwnsData/Views/Home/Error.cshtml:
--------------------------------------------------------------------------------
1 | @* Copyright (c) Microsoft Corporation.
2 | Licensed under the MIT license. *@
3 |
4 | @model UserOwnsData.Models.ErrorModel
5 |
6 | @{
7 | ViewBag.Title = "Error";
8 | Layout = "~/Views/Shared/_Layout.cshtml";
9 | }
10 |
11 | Error: @Model.ErrorCode
12 | @Model.ErrorMessage
13 |
--------------------------------------------------------------------------------
/.NET Framework/Embed for your organization/UserOwnsData/Views/Home/Index.cshtml:
--------------------------------------------------------------------------------
1 | @* Copyright (c) Microsoft Corporation.
2 | Licensed under the MIT license. *@
3 |
4 | @{
5 | ViewBag.Title = "Index";
6 | Layout = "~/Views/Shared/_Layout.cshtml";
7 | }
8 |
9 |
17 |
18 |
19 |
20 |
Sign in to Power BI
21 |
Sign in
22 |
23 |
--------------------------------------------------------------------------------
/.NET Framework/Embed for your organization/UserOwnsData/Views/Shared/_Layout.cshtml:
--------------------------------------------------------------------------------
1 | @* Copyright (c) Microsoft Corporation.
2 | Licensed under the MIT license. *@
3 |
4 |
5 |
6 |
7 |
8 |
9 | Power BI Embedded sample
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | @RenderBody()
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/.NET Framework/Embed for your organization/UserOwnsData/Views/_ViewStart.cshtml:
--------------------------------------------------------------------------------
1 | @* Copyright (c) Microsoft Corporation.
2 | icensed under the MIT license. *@
3 |
4 | @{
5 | Layout = "~/Views/Shared/_Layout.cshtml";
6 | }
--------------------------------------------------------------------------------
/.NET Framework/Embed for your organization/UserOwnsData/Views/web.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/.NET Framework/Embed for your organization/UserOwnsData/Web.Debug.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
17 |
18 |
29 |
30 |
--------------------------------------------------------------------------------
/.NET Framework/Embed for your organization/UserOwnsData/Web.Release.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
17 |
18 |
19 |
30 |
31 |
--------------------------------------------------------------------------------
/.NET Framework/Embed for your organization/UserOwnsData/libman.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "1.0",
3 | "defaultProvider": "cdnjs",
4 | "libraries": [
5 | {
6 | "provider": "jsdelivr",
7 | "library": "jquery@3.5.1",
8 | "destination": "Content/lib/jquery/",
9 | "files": [
10 | "LICENSE.txt",
11 | "dist/jquery.min.js"
12 | ]
13 | },
14 | {
15 | "provider": "jsdelivr",
16 | "library": "bootstrap@4.5.2",
17 | "destination": "Content/lib/bootstrap/",
18 | "files": [
19 | "dist/css/bootstrap.min.css",
20 | "dist/css/bootstrap.min.css.map",
21 | "dist/js/bootstrap.min.js",
22 | "dist/js/bootstrap.min.js.map",
23 | "LICENSE"
24 | ]
25 | },
26 | {
27 | "provider": "jsdelivr",
28 | "library": "powerbi-client@2.16.5",
29 | "destination": "Content/lib/powerbi-client/",
30 | "files": [
31 | "LICENSE.txt",
32 | "dist/powerbi.min.js"
33 | ]
34 | }
35 | ]
36 | }
--------------------------------------------------------------------------------
/.NET Framework/Embed for your organization/UserOwnsData/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .vscode/launch.json
2 | .vscode/tasks.json
3 |
--------------------------------------------------------------------------------
/Install-Package:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/PowerBI-Developer-Samples/2970f6581bb6e6aa3403be858ffd968357807f5d/Install-Package
--------------------------------------------------------------------------------
/Java/.gitignore:
--------------------------------------------------------------------------------
1 | *.java.hsp
2 | *.sonarj
3 | *.sw*
4 | .DS_Store
5 | .springBeans
6 | build.sh
7 | integration-repo
8 | ivy-cache
9 | jxl.log
10 | jmx.log
11 | derby.log
12 | spring-test/test-output/
13 | .gradle
14 | argfile*
15 | activemq-data/
16 |
17 | classes/
18 | /build
19 | buildSrc/build
20 | /spring-*/build
21 | /spring-core/kotlin-coroutines/build
22 | /framework-bom/build
23 | /integration-tests/build
24 | /src/asciidoc/build
25 |
26 | target/
27 |
28 | # remove .map files
29 | *.map
30 |
31 | # Eclipse artifacts, including WTP generated manifests
32 | .classpath
33 | .project
34 | spring-*/src/main/java/META-INF/MANIFEST.MF
35 |
36 | # IDEA artifacts and output dirs
37 | *.iml
38 | *.ipr
39 | *.iws
40 | .idea
41 | out
42 | test-output
43 | atlassian-ide-plugin.xml
44 | .gradletasknamecache
45 |
46 | ### Eclipse ###
47 | .metadata
48 | bin/
49 | tmp/
50 | *.tmp
51 | *.bak
52 | *.swp
53 | *~.nib
54 | local.properties
55 | .settings/
56 | .loadpath
57 | .recommenders
58 |
59 | # External tool builders
60 | .externalToolBuilders/
61 |
62 | # Locally stored "Eclipse launch configurations"
63 | *.launch
64 |
65 | # Java annotation processor (APT)
66 | .factorypath
67 |
68 | # PDT-specific (PHP Development Tools)
69 | .buildpath
70 |
71 | # sbteclipse plugin
72 | .target
73 |
74 | # Tern plugin
75 | .tern-project
76 |
77 | # TeXlipse plugin
78 | .texlipse
79 |
80 | # STS (Spring Tool Suite)
81 | .springBeans
82 |
83 | # Code Recommenders
84 | .recommenders/
85 |
86 | # Annotation Processing
87 | .apt_generated/
88 |
89 | ### Maven ###
90 | pom.xml.tag
91 | pom.xml.releaseBackup
92 | pom.xml.versionsBackup
93 | pom.xml.next
94 | release.properties
95 | dependency-reduced-pom.xml
96 | buildNumber.properties
97 | .mvn/timing.properties
98 | .mvn/wrapper/maven-wrapper.jar
99 | .flattened-pom.xml
--------------------------------------------------------------------------------
/Java/Embed for your customers/AppOwnsData/3rd Party Licenses.md:
--------------------------------------------------------------------------------
1 | # Links to licenses for the 3rd party softwares used:
2 | |Software|License|
3 | |--|--|
4 | |Spring framework|[Apache License 2.0](https://github.com/spring-projects/spring-framework/blob/master/LICENSE.txt)|
5 | |Apache tomcat|[Apache License 2.0](http://www.apache.org/licenses/LICENSE-2.0)|
6 | |SLF4J|[MIT](http://www.slf4j.org/license.html)|
7 | |org.json|[MIT](https://github.com/stleary/JSON-java/blob/master/LICENSE)|
8 | |Bootstrap|[MIT](https://github.com/twbs/bootstrap/blob/v4.0.0/LICENSE)|
9 | |jQuery|[MIT](https://jquery.org/license/)|
--------------------------------------------------------------------------------
/Java/Embed for your customers/AppOwnsData/pom.xml:
--------------------------------------------------------------------------------
1 |
2 | 4.0.0
3 | com.embedsample
4 | appownsdatasample
5 | 0.0.1-SNAPSHOT
6 | war
7 | App Owns Data
8 | http://maven.apache.org
9 |
10 | appownsdatasample
11 | src/main/java
12 |
13 |
14 | maven-compiler-plugin
15 | 3.8.1
16 |
17 | 1.8
18 | 1.8
19 |
20 |
21 |
22 | maven-war-plugin
23 | 3.3.1
24 |
25 | src/main/webapp
26 |
27 |
28 |
29 |
30 |
31 | 5.2.9.RELEASE
32 |
33 |
34 |
35 | org.springframework
36 | spring-webmvc
37 | ${spring.version}
38 |
39 |
40 |
41 | javax.servlet
42 | jstl
43 | 1.2
44 |
45 |
46 |
47 | org.json
48 | json
49 | 20200518
50 |
51 |
52 |
53 |
54 | com.microsoft.azure
55 | msal4j
56 | 1.7.1
57 |
58 |
59 |
60 |
61 | org.slf4j
62 | slf4j-jdk14
63 | 1.7.30
64 |
65 |
66 |
--------------------------------------------------------------------------------
/Java/Embed for your customers/AppOwnsData/src/main/java/com/embedsample/appownsdata/config/Config.java:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------------
2 | // Copyright (c) Microsoft Corporation.
3 | // Licensed under the MIT license.
4 | // ----------------------------------------------------------------------------
5 |
6 | package com.embedsample.appownsdata.config;
7 |
8 | /**
9 | * Configuration class
10 | */
11 | public abstract class Config {
12 |
13 | // Set this to true, to show debug statements in console
14 | public static final boolean DEBUG = false;
15 |
16 | // Two possible Authentication methods:
17 | // - For authentication with master user credential choose MasterUser as AuthenticationType.
18 | // - For authentication with app secret choose ServicePrincipal as AuthenticationType.
19 | // More details here: https://aka.ms/EmbedServicePrincipal
20 | public static final String authenticationType = "";
21 |
22 | // Common configuration properties for both authentication types
23 | // Enter workspaceId / groupId
24 | public static final String workspaceId = "";
25 |
26 | // The id of the report to embed.
27 | public static final String reportId = "";
28 |
29 | // Enter Application Id / Client Id
30 | public static final String clientId = "";
31 |
32 | // Enter MasterUser credentials
33 | public static final String pbiUsername = "";
34 | public static final String pbiPassword = "";
35 |
36 | // Enter ServicePrincipal credentials
37 | public static final String tenantId = "";
38 | public static final String appSecret = "";
39 |
40 | // DO NOT CHANGE
41 | public static final String authorityUrl = "https://login.microsoftonline.com/";
42 | public static final String scopeBase = "https://analysis.windows.net/powerbi/api/.default";
43 |
44 |
45 | private Config(){
46 | //Private Constructor will prevent the instantiation of this class directly
47 | throw new IllegalStateException("Config class");
48 | }
49 |
50 | }
--------------------------------------------------------------------------------
/Java/Embed for your customers/AppOwnsData/src/main/java/com/embedsample/appownsdata/models/EmbedConfig.java:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------------
2 | // Copyright (c) Microsoft Corporation.
3 | // Licensed under the MIT license.
4 | // ----------------------------------------------------------------------------
5 |
6 | package com.embedsample.appownsdata.models;
7 |
8 | import java.util.List;
9 |
10 | /**
11 | * Properties for embedding the report
12 | */
13 | public class EmbedConfig {
14 | public List embedReports;
15 |
16 | public EmbedToken embedToken;
17 |
18 | public String errorMessage;
19 | }
20 |
--------------------------------------------------------------------------------
/Java/Embed for your customers/AppOwnsData/src/main/java/com/embedsample/appownsdata/models/EmbedToken.java:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------------
2 | // Copyright (c) Microsoft Corporation.
3 | // Licensed under the MIT license.
4 | // ----------------------------------------------------------------------------
5 |
6 | package com.embedsample.appownsdata.models;
7 |
8 | /**
9 | * EmbedToken holds fields related to the embed token response
10 | */
11 | public class EmbedToken {
12 |
13 | // token
14 | public String token;
15 |
16 | // token id
17 | public String tokenId;
18 |
19 | // token expiration time
20 | public String expiration;
21 | }
22 |
--------------------------------------------------------------------------------
/Java/Embed for your customers/AppOwnsData/src/main/java/com/embedsample/appownsdata/models/ReportConfig.java:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------------
2 | // Copyright (c) Microsoft Corporation.
3 | // Licensed under the MIT license.
4 | // ----------------------------------------------------------------------------
5 |
6 | package com.embedsample.appownsdata.models;
7 |
8 | import org.json.JSONException;
9 | import org.json.JSONObject;
10 | import org.slf4j.Logger;
11 | import org.slf4j.LoggerFactory;
12 |
13 | import com.embedsample.appownsdata.controllers.EmbedController;
14 |
15 | /**
16 | * Properties for embedding the report
17 | */
18 | public class ReportConfig {
19 | static final Logger logger = LoggerFactory.getLogger(EmbedController.class);
20 |
21 | public String reportId = "";
22 |
23 | public String embedUrl = "";
24 |
25 | public String reportName = "";
26 |
27 | public Boolean isEffectiveIdentityRolesRequired = false;
28 |
29 | public Boolean isEffectiveIdentityRequired = false;
30 |
31 | public Boolean enableRLS = false;
32 |
33 | public String username;
34 |
35 | public String roles;
36 |
37 | public JSONObject getJSONObject() {
38 | JSONObject jsonObj = new JSONObject();
39 | try {
40 | jsonObj.put("reportId", reportId);
41 | jsonObj.put("embedUrl", embedUrl);
42 | jsonObj.put("reportName", reportName);
43 | } catch (JSONException e) {
44 | logger.error("DefaultListItem.toString JSONException: " + e.getMessage());
45 | }
46 | return jsonObj;
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/Java/Embed for your customers/AppOwnsData/src/main/webapp/WEB-INF/appownsdatasample-servlet.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/Java/Embed for your customers/AppOwnsData/src/main/webapp/WEB-INF/web.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 | App Owns Data
8 |
9 |
10 | appownsdatasample
11 | org.springframework.web.servlet.DispatcherServlet
12 |
13 | 1
14 |
15 |
16 |
17 | appownsdatasample
18 | /
19 |
20 |
--------------------------------------------------------------------------------
/Java/Embed for your customers/AppOwnsData/src/main/webapp/resources/css/style.css:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Microsoft Corporation.
2 | Licensed under the MIT license. */
3 |
4 | header {
5 | background-color: #007FFF;
6 | height: 75px;
7 | width: 100%;
8 | }
9 |
10 | header > div {
11 | color: #FFFFFF;
12 | font: bold 1.6em "segoe ui", arial, sans-serif;
13 | margin-left: 32px;
14 | padding-top: 19px;
15 | }
16 |
17 | main {
18 | margin: 0 auto;
19 | width: 100%;
20 | }
21 |
22 | section#text-container > div > div {
23 | font: 1.2em "segoe ui", arial, sans-serif;
24 | }
25 |
26 | section#report-container {
27 | height: calc(0.5625 * 60vw); /* 16:9 aspect ratio */
28 | }
29 |
30 | @media only screen and (max-width: 575px) {
31 | section#report-container {
32 | height: calc(0.5625 * 100vw); /* 16:9 aspect ratio */
33 | }
34 | }
35 |
36 | footer > p {
37 | font: 1em "segoe ui", arial, sans-serif;
38 | }
39 |
40 | iframe {
41 | border: none;
42 | }
--------------------------------------------------------------------------------
/Java/EncryptCredentials/3rd Party Licenses.md:
--------------------------------------------------------------------------------
1 | # Links to licenses for the 3rd party softwares used:
2 | |Software|License|
3 | |--|--|
4 | |Spring framework|[Apache License 2.0](https://github.com/spring-projects/spring-framework/blob/master/LICENSE.txt)|
5 | |Apache tomcat|[Apache License 2.0](http://www.apache.org/licenses/LICENSE-2.0)|
6 | |SLF4J|[MIT](http://www.slf4j.org/license.html)|
7 | |org.json|[MIT](https://github.com/stleary/JSON-java/blob/master/LICENSE)|
8 | |Bootstrap|[MIT](https://github.com/twbs/bootstrap/blob/v4.0.0/LICENSE)|
9 | |jQuery|[MIT](https://jquery.org/license/)|
--------------------------------------------------------------------------------
/Java/EncryptCredentials/CloudConfigs/Power BI Global/Config.java:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------------
2 | // Copyright (c) Microsoft Corporation.
3 | // Licensed under the MIT license.
4 | // ----------------------------------------------------------------------------
5 |
6 | //Replace these configs with the one in the Config.java file for sovereign cloud
7 |
8 | public abstract class Config {
9 |
10 | public static final String authorityUrl = "https://login.microsoftonline.com/";
11 | public static final String powerBiApiUrl = "https://api.powerbi.com/";
12 | public static final String scopeBase = "https://analysis.windows.net/powerbi/api/.default";
13 | }
--------------------------------------------------------------------------------
/Java/EncryptCredentials/CloudConfigs/Power BI US Government/Config.java:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------------
2 | // Copyright (c) Microsoft Corporation.
3 | // Licensed under the MIT license.
4 | // ----------------------------------------------------------------------------
5 |
6 | //Replace these configs with the one in the Config.java file for sovereign cloud
7 |
8 | public abstract class Config {
9 |
10 | public static final String authorityUrl = "https://login.microsoftonline.com/";
11 | public static final String powerBiApiUrl = "https://api.powerbigov.us/";
12 | public static final String scopeBase = "https://analysis.usgovcloudapi.net/powerbi/api/.default";
13 | }
--------------------------------------------------------------------------------
/Java/EncryptCredentials/CloudConfigs/Power BI in Germany/Config.java:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------------
2 | // Copyright (c) Microsoft Corporation.
3 | // Licensed under the MIT license.
4 | // ----------------------------------------------------------------------------
5 |
6 | //Replace these configs with the one in the Config.java file for sovereign cloud
7 |
8 | public abstract class Config {
9 |
10 | public static final String authorityUrl = "https://login.microsoftonline.de/";
11 | public static final String powerBiApiUrl = "https://api.powerbi.de/";
12 | public static final String scopeBase = "https://analysis.cloudapi.de/powerbi/api/.default";
13 | }
--------------------------------------------------------------------------------
/Java/EncryptCredentials/CloudConfigs/Power BI operated by 21Vianet in China/Config.java:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------------
2 | // Copyright (c) Microsoft Corporation.
3 | // Licensed under the MIT license.
4 | // ----------------------------------------------------------------------------
5 |
6 | //Replace these configs with the one in the Config.java file for sovereign cloud
7 |
8 | public abstract class Config {
9 |
10 | public static final String authorityUrl = "https://login.chinacloudapi.cn/";
11 | public static final String powerBiApiUrl = "https://api.powerbi.cn/";
12 | public static final String scopeBase = "https://analysis.chinacloudapi.cn/powerbi/api/.default";
13 | }
--------------------------------------------------------------------------------
/Java/EncryptCredentials/src/main/java/com/encryptcredentialsample/encryptcredential/config/Config.java:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------------
2 | // Copyright (c) Microsoft Corporation.
3 | // Licensed under the MIT license.
4 | // ----------------------------------------------------------------------------
5 |
6 | package com.encryptcredentialsample.encryptcredential.config;
7 |
8 | /**
9 | * Configuration class
10 | */
11 | public abstract class Config {
12 |
13 | // Set this to true, to show debug statements in console
14 | public static final boolean DEBUG = false;
15 |
16 | // Two possible Authentication methods:
17 | // - For authentication with master user credential choose MasterUser as
18 | // AuthenticationType.
19 | // - For authentication with app secret choose ServicePrincipal as
20 | // AuthenticationType.
21 | // More details here: https://aka.ms/EmbedServicePrincipal
22 | public static final String authenticationType = "ServicePrincipal";
23 |
24 | // Common configuration properties for both authentication types
25 | // Enter Application Id
26 | public static final String clientId = "";
27 |
28 | // Enter MasterUser credentials
29 | public static final String pbiUsername = "";
30 | public static final String pbiPassword = "";
31 |
32 | // Enter ServicePrincipal credentials
33 | public static final String tenantId = "";
34 | public static final String clientSecret = "";
35 |
36 | // DO NOT CHANGE
37 | public static final String authorityUrl = "https://login.microsoftonline.com/";
38 | public static final String powerBiApiUrl = "https://api.powerbi.com/";
39 | public static final String scopeBase = "https://analysis.windows.net/powerbi/api/.default";
40 |
41 | private Config() {
42 | // Private Constructor will prevent the instantiation of this class directly
43 | throw new IllegalStateException("Config class");
44 | }
45 | }
--------------------------------------------------------------------------------
/Java/EncryptCredentials/src/main/java/com/encryptcredentialsample/encryptcredential/models/AddDatasourceRequest.java:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------------
2 | // Copyright (c) Microsoft Corporation.
3 | // Licensed under the MIT license.
4 | // ----------------------------------------------------------------------------
5 |
6 | package com.encryptcredentialsample.encryptcredential.models;
7 |
8 | public class AddDatasourceRequest {
9 |
10 | public String gatewayId;
11 |
12 | public String dataSourceType;
13 |
14 | public String connectionDetails;
15 |
16 | public String dataSourceName;
17 |
18 | public String credType;
19 |
20 | public String privacyLevel;
21 |
22 | public String[] credentialsArray;
23 | }
24 |
--------------------------------------------------------------------------------
/Java/EncryptCredentials/src/main/java/com/encryptcredentialsample/encryptcredential/models/CredentialDetails.java:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------------
2 | // Copyright (c) Microsoft Corporation.
3 | // Licensed under the MIT license.
4 | // ----------------------------------------------------------------------------
5 |
6 | package com.encryptcredentialsample.encryptcredential.models;
7 |
8 | public class CredentialDetails {
9 |
10 | public String credentialType;
11 |
12 | public String credentials;
13 |
14 | public String encryptedConnection;
15 |
16 | public String encryptionAlgorithm;
17 |
18 | public String privacyLevel;
19 |
20 | public CredentialDetails(String credentialType, String serializedCredentials, String encryptedConnection, String privacyLevel) {
21 | this.credentialType = credentialType;
22 | this.credentials = serializedCredentials;
23 | this.encryptedConnection = encryptedConnection;
24 | this.encryptionAlgorithm = "RSA-OAEP";
25 | this.privacyLevel = privacyLevel;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/Java/EncryptCredentials/src/main/java/com/encryptcredentialsample/encryptcredential/models/CredentialDetailsRequestBody.java:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------------
2 | // Copyright (c) Microsoft Corporation.
3 | // Licensed under the MIT license.
4 | // ----------------------------------------------------------------------------
5 |
6 | package com.encryptcredentialsample.encryptcredential.models;
7 |
8 | public class CredentialDetailsRequestBody {
9 | public CredentialDetails credentialDetails;
10 |
11 | public CredentialDetailsRequestBody(CredentialDetails CredentialDetails) {
12 | this.credentialDetails = CredentialDetails;
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/Java/EncryptCredentials/src/main/java/com/encryptcredentialsample/encryptcredential/models/DatasourceConfig.java:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------------
2 | // Copyright (c) Microsoft Corporation.
3 | // Licensed under the MIT license.
4 | // ----------------------------------------------------------------------------
5 |
6 | package com.encryptcredentialsample.encryptcredential.models;
7 |
8 | public class DatasourceConfig {
9 | public String gatewayId;
10 | public String datasourceId;
11 | public DatasourceConnectionDetails connectionDetails;
12 | }
13 |
--------------------------------------------------------------------------------
/Java/EncryptCredentials/src/main/java/com/encryptcredentialsample/encryptcredential/models/DatasourceConnectionDetails.java:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------------
2 | // Copyright (c) Microsoft Corporation.
3 | // Licensed under the MIT license.
4 | // ----------------------------------------------------------------------------
5 |
6 | package com.encryptcredentialsample.encryptcredential.models;
7 |
8 | public class DatasourceConnectionDetails {
9 | public String database;
10 | public String server;
11 | public String url;
12 | }
13 |
--------------------------------------------------------------------------------
/Java/EncryptCredentials/src/main/java/com/encryptcredentialsample/encryptcredential/models/Gateway.java:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------------
2 | // Copyright (c) Microsoft Corporation.
3 | // Licensed under the MIT license.
4 | // ----------------------------------------------------------------------------
5 |
6 | package com.encryptcredentialsample.encryptcredential.models;
7 |
8 | public class Gateway {
9 | public String name;
10 | public GatewayPublicKey publicKey;
11 | }
12 |
--------------------------------------------------------------------------------
/Java/EncryptCredentials/src/main/java/com/encryptcredentialsample/encryptcredential/models/GatewayPublicKey.java:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------------
2 | // Copyright (c) Microsoft Corporation.
3 | // Licensed under the MIT license.
4 | // ----------------------------------------------------------------------------
5 |
6 | package com.encryptcredentialsample.encryptcredential.models;
7 |
8 | public class GatewayPublicKey {
9 | public String exponent;
10 | public String modulus;
11 |
12 | public GatewayPublicKey(String Exponent, String Modulus) {
13 | exponent = Exponent;
14 | modulus = Modulus;
15 | }
16 |
17 | public GatewayPublicKey() {}
18 | }
19 |
--------------------------------------------------------------------------------
/Java/EncryptCredentials/src/main/java/com/encryptcredentialsample/encryptcredential/models/GetDatasourcesResponse.java:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------------
2 | // Copyright (c) Microsoft Corporation.
3 | // Licensed under the MIT license.
4 | // ----------------------------------------------------------------------------
5 |
6 | package com.encryptcredentialsample.encryptcredential.models;
7 |
8 | import java.util.ArrayList;
9 |
10 | public class GetDatasourcesResponse {
11 | public ArrayList value;
12 | }
13 |
--------------------------------------------------------------------------------
/Java/EncryptCredentials/src/main/java/com/encryptcredentialsample/encryptcredential/models/PublicKeyConfig.java:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------------
2 | // Copyright (c) Microsoft Corporation.
3 | // Licensed under the MIT license.
4 | // ----------------------------------------------------------------------------
5 |
6 | package com.encryptcredentialsample.encryptcredential.models;
7 |
8 | public class PublicKeyConfig {
9 | public GatewayPublicKey publicKey;
10 | public String gatewayId;
11 | }
12 |
--------------------------------------------------------------------------------
/Java/EncryptCredentials/src/main/java/com/encryptcredentialsample/encryptcredential/models/PublishDatasourceToGatewayRequest.java:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------------
2 | // Copyright (c) Microsoft Corporation.
3 | // Licensed under the MIT license.
4 | // ----------------------------------------------------------------------------
5 |
6 | package com.encryptcredentialsample.encryptcredential.models;
7 |
8 | public class PublishDatasourceToGatewayRequest {
9 |
10 | public String dataSourceType;
11 | public String connectionDetails;
12 | public CredentialDetails credentialDetails;
13 | public String dataSourceName;
14 |
15 | public PublishDatasourceToGatewayRequest(
16 | String dataSourceType,
17 | String connectionDetails,
18 | CredentialDetails credentialDetails,
19 | String dataSourceName) {
20 | this.dataSourceType = dataSourceType;
21 | this.connectionDetails = connectionDetails;
22 | this.credentialDetails = credentialDetails;
23 | this.dataSourceName = dataSourceName;
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/Java/EncryptCredentials/src/main/java/com/encryptcredentialsample/encryptcredential/models/UpdateDatasourceCredentialsRequest.java:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------------
2 | // Copyright (c) Microsoft Corporation.
3 | // Licensed under the MIT license.
4 | // ----------------------------------------------------------------------------
5 |
6 | package com.encryptcredentialsample.encryptcredential.models;
7 |
8 | public class UpdateDatasourceCredentialsRequest {
9 |
10 | public String datasourceId;
11 |
12 | public String credType;
13 |
14 | public String privacyLevel;
15 |
16 | public String[] credentialsArray;
17 |
18 | public String gatewayId;
19 | }
20 |
--------------------------------------------------------------------------------
/Java/EncryptCredentials/src/main/java/com/encryptcredentialsample/encryptcredential/services/AsymmetricKeyEncryptorService.java:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------------
2 | // Copyright (c) Microsoft Corporation.
3 | // Licensed under the MIT license.
4 | // ----------------------------------------------------------------------------
5 |
6 | package com.encryptcredentialsample.encryptcredential.services;
7 |
8 | import java.util.Base64;
9 |
10 | import com.encryptcredentialsample.encryptcredential.helper.Asymmetric1024KeyEncryptionHelper;
11 | import com.encryptcredentialsample.encryptcredential.helper.AsymmetricHigherKeyEncryptionHelper;
12 | import com.encryptcredentialsample.encryptcredential.models.GatewayPublicKey;
13 |
14 | public class AsymmetricKeyEncryptorService {
15 |
16 | private static int MODULUS_SIZE = 128;
17 | private GatewayPublicKey publicKey;
18 |
19 | public AsymmetricKeyEncryptorService(GatewayPublicKey gatewayPubKey) throws Exception {
20 |
21 | if (gatewayPubKey == null) {
22 | throw new Exception("publicKey");
23 | }
24 |
25 | if (gatewayPubKey.exponent == null || (gatewayPubKey.exponent).isEmpty()) {
26 | throw new Exception("gatewayPubKey.Exponent");
27 | }
28 |
29 | if (gatewayPubKey.modulus == null || (gatewayPubKey.modulus).isEmpty()) {
30 | throw new Exception("gatewayPubKey.Modulus");
31 | }
32 |
33 | this.publicKey = gatewayPubKey;
34 | }
35 |
36 | // Encrypt the credential data using encryption helpers
37 | public String encodeCredentials(String credentialData) throws Exception {
38 | if (credentialData == null || credentialData.isEmpty()) {
39 | throw new Exception("credentialData");
40 | }
41 |
42 | byte[] plainTextBytes = credentialData.getBytes("UTF8");
43 | byte[] modulusBytes = Base64.getDecoder().decode(this.publicKey.modulus);
44 | byte[] exponentBytes = Base64.getDecoder().decode(this.publicKey.exponent);
45 |
46 | // Call the encryption helper based on the modulus size
47 | return modulusBytes.length == MODULUS_SIZE
48 | ? Asymmetric1024KeyEncryptionHelper.Encrypt(plainTextBytes, modulusBytes, exponentBytes)
49 | : AsymmetricHigherKeyEncryptionHelper.Encrypt(plainTextBytes, modulusBytes, exponentBytes);
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/Java/EncryptCredentials/src/main/java/com/encryptcredentialsample/encryptcredential/services/Utils.java:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------------
2 | // Copyright (c) Microsoft Corporation.
3 | // Licensed under the MIT license.
4 | // ----------------------------------------------------------------------------
5 |
6 | package com.encryptcredentialsample.encryptcredential.services;
7 |
8 | import java.util.Arrays;
9 |
10 | import org.springframework.http.HttpHeaders;
11 |
12 | public class Utils {
13 | public static String serializeCredentials(String[] credentialsArray, String credType) throws Exception {
14 | String serializedCredentials;
15 |
16 | // Build credentials string as per docs: https://docs.microsoft.com/en-us/rest/api/power-bi/gateways/updatedatasource#examples
17 | switch (credType) {
18 | case "Key":
19 | serializedCredentials = "{\"credentialData\":[{\"name\":\"key\",\"value\":\"" + credentialsArray[0] + "\"}]}";
20 | break;
21 |
22 | case "Windows":
23 | serializedCredentials = "{\"credentialData\":[{\"name\":\"username\",\"value\":\"" + credentialsArray[0] + "\"},{\"name\":\"password\",\"value\":\"" + credentialsArray[1] + "\"}]}";
24 | break;
25 |
26 | case "OAuth2":
27 | serializedCredentials = "{\"credentialData\":[{\"name\":\"accessToken\",\"value\":\"" + credentialsArray[0] + "\"}]}";
28 | break;
29 |
30 | case "Basic":
31 | serializedCredentials = "{\"credentialData\":[{\"name\":\"username\",\"value\":\"" + credentialsArray[0] + "\"},{\"name\":\"password\",\"value\":\"" + credentialsArray[1] + "\"}]}";
32 | break;
33 |
34 | default:
35 | throw new Exception("Invalid credentials type");
36 | }
37 |
38 | return serializedCredentials;
39 | }
40 |
41 | public static HttpHeaders generateAuthorizationHeaders(String accessToken) {
42 | HttpHeaders reqHeader = new HttpHeaders();
43 | reqHeader.put("Content-Type", Arrays.asList("application/json"));
44 | reqHeader.put("Authorization", Arrays.asList("Bearer " + accessToken));
45 | return reqHeader;
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/Java/EncryptCredentials/src/main/webapp/WEB-INF/encryptcredential-servlet.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/Java/EncryptCredentials/src/main/webapp/WEB-INF/web.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 | Encrypt Credential
8 |
9 |
10 | encryptcredential
11 | org.springframework.web.servlet.DispatcherServlet
12 |
13 | 1
14 |
15 |
16 |
17 | encryptcredential
18 | /
19 |
20 |
--------------------------------------------------------------------------------
/Java/EncryptCredentials/src/main/webapp/resources/css/style.css:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Microsoft Corporation.
2 | Licensed under the MIT license. */
3 |
4 | header {
5 | background-color: #007FFF;
6 | height: 75px;
7 | width: 100%;
8 | }
9 |
10 | header > div {
11 | color: #FFFFFF;
12 | font: bold 25.6px "segoe ui", arial, sans-serif;
13 | margin-left: 32px;
14 | padding-top: 19px;
15 | }
16 |
17 | main {
18 | margin: 0 auto;
19 | width: 100%;
20 | }
21 |
22 | section#text-container > div > div {
23 | font: 19px "segoe ui", arial, sans-serif;
24 | }
25 |
26 | .id-container {
27 | margin: 0 12px 0 16px;
28 | }
29 |
30 | .input-element {
31 | height: 30px;
32 | width: 280px;
33 | padding: 2px;
34 | }
35 |
36 | .send-button {
37 | width: 200px;
38 | }
39 |
40 | .password-text {
41 | margin-left: 24px;
42 | }
43 |
44 | #task-container {
45 | margin-bottom: 15px;
46 | }
47 |
48 | section#text-container {
49 | margin: 24px 40px;
50 | }
51 |
52 | footer > p {
53 | font: 16px "segoe ui", arial, sans-serif;
54 | }
55 |
56 | #get-datasources {
57 | margin-top: 20px;
58 | }
59 |
60 | .gateway-container {
61 | margin-top: 20px;
62 | display: none;
63 | }
64 |
65 | .success-container {
66 | margin-left: 0;
67 | margin-right: 0;
68 | }
69 |
70 | .error-container {
71 | margin-left: 0;
72 | margin-right: 0;
73 | }
74 |
75 | .modal-dialog {
76 | max-width: min-content;
77 | min-width: 500px;
78 | }
79 |
80 | .add-datasource-container,
81 | .encrypt-credentials-container,
82 | #credential-windows,
83 | #credential-oauth2,
84 | #credential-basic {
85 | display: none;
86 | }
87 |
88 | #credential-key {
89 | display: block;
90 | }
91 |
92 | .inactive-text {
93 | color: #808080;
94 | }
95 |
96 | .active-text {
97 | color: #000000;
98 | }
99 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) Microsoft Corporation. All rights reserved.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE
22 |
--------------------------------------------------------------------------------
/NodeJS/Embed for your customers/AppOwnsData/config/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "authenticationMode": "MasterUser",
3 | "authorityUrl": "https://login.microsoftonline.com/",
4 | "scopeBase": "https://analysis.windows.net/powerbi/api/.default",
5 | "powerBiApiUrl": "https://api.powerbi.com/",
6 | "clientId": "",
7 | "workspaceId": "",
8 | "reportId": "",
9 | "pbiUsername": "",
10 | "pbiPassword": "",
11 | "clientSecret": "",
12 | "tenantId": ""
13 | }
--------------------------------------------------------------------------------
/NodeJS/Embed for your customers/AppOwnsData/models/embedConfig.js:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------------
2 | // Copyright (c) Microsoft Corporation.
3 | // Licensed under the MIT license.
4 | // ----------------------------------------------------------------------------
5 |
6 | // Properties for embedding the report
7 | class EmbedConfig {
8 | constructor(type, reportsDetail, embedToken) {
9 | this.type = type;
10 | this.reportsDetail = reportsDetail;
11 | this.embedToken = embedToken;
12 | }
13 | }
14 |
15 | module.exports = EmbedConfig;
--------------------------------------------------------------------------------
/NodeJS/Embed for your customers/AppOwnsData/models/embedReportConfig.js:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------------
2 | // Copyright (c) Microsoft Corporation.
3 | // Licensed under the MIT license.
4 | // ----------------------------------------------------------------------------
5 |
6 | // Configurations of the embedded reports
7 | class PowerBiReportDetails {
8 | constructor(reportId, reportName, embedUrl) {
9 | this.reportId = reportId;
10 | this.reportName = reportName;
11 | this.embedUrl = embedUrl;
12 | }
13 | }
14 |
15 | module.exports = PowerBiReportDetails;
--------------------------------------------------------------------------------
/NodeJS/Embed for your customers/AppOwnsData/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "embedding-sample",
3 | "version": "1.0.0",
4 | "description": "Generate Embed Token, URL and Embed the Report.",
5 | "main": "./src/server.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "dev": "nodemon ./src/server.js",
9 | "start": "nodemon ./src/server.js"
10 | },
11 | "author": "",
12 | "license": "ISC",
13 | "dependencies": {
14 | "@azure/msal-node": "^1.12.0",
15 | "body-parser": "^1.19.0",
16 | "bootstrap": "^4.4.1",
17 | "express": "^4.17.1",
18 | "guid": "0.0.12",
19 | "jquery": "^3.5.1",
20 | "node-fetch": "^2.6.1",
21 | "path": "^0.12.7",
22 | "powerbi-client": "^2.16.5"
23 | },
24 | "devDependencies": {
25 | "nodemon": "^2.0.2"
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/NodeJS/Embed for your customers/AppOwnsData/public/css/index.css:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Microsoft Corporation.
2 | Licensed under the MIT license. */
3 |
4 | header {
5 | background-color: #007FFF;
6 | height: 75px;
7 | width: 100%;
8 | }
9 |
10 | header > p {
11 | color: #FFFFFF;
12 | font: bold 1.6em "segoe ui", arial, sans-serif;
13 | margin-left: 31px;
14 | padding-top: 20px;
15 | }
16 |
17 | main {
18 | margin: 0 auto;
19 | width: 100%;
20 | }
21 |
22 | section#text-container > div > p {
23 | font: 1.2em "segoe ui", arial, sans-serif;
24 | }
25 |
26 | section#report-container {
27 | height: calc(0.5625 * 61vw); /* 16:9 aspect ratio */
28 | }
29 |
30 | @media only screen and (max-width: 575px) {
31 | section#report-container {
32 | height: calc(0.5625 * 100vw); /* 16:9 aspect ratio */
33 | }
34 | }
35 |
36 | footer > p {
37 | font: 1em "segoe ui", arial, sans-serif;
38 | }
39 |
40 | iframe {
41 | border: none;
42 | }
--------------------------------------------------------------------------------
/NodeJS/Embed for your customers/AppOwnsData/src/authentication.js:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------------
2 | // Copyright (c) Microsoft Corporation.
3 | // Licensed under the MIT license.
4 | // ----------------------------------------------------------------------------
5 |
6 | const getAccessToken = async function () {
7 | // Create a config variable that store credentials from config.json
8 | const config = require(__dirname + "/../config/config.json");
9 |
10 | // Use MSAL.js for authentication
11 | const msal = require("@azure/msal-node");
12 |
13 | const msalConfig = {
14 | auth: {
15 | clientId: config.clientId,
16 | authority: `${config.authorityUrl}${config.tenantId}`,
17 | }
18 | };
19 |
20 | // Check for the MasterUser Authentication
21 | if (config.authenticationMode.toLowerCase() === "masteruser") {
22 | const clientApplication = new msal.PublicClientApplication(msalConfig);
23 |
24 | const usernamePasswordRequest = {
25 | scopes: [config.scopeBase],
26 | username: config.pbiUsername,
27 | password: config.pbiPassword
28 | };
29 |
30 | return clientApplication.acquireTokenByUsernamePassword(usernamePasswordRequest);
31 |
32 | };
33 |
34 | // Service Principal auth is the recommended by Microsoft to achieve App Owns Data Power BI embedding
35 | if (config.authenticationMode.toLowerCase() === "serviceprincipal") {
36 | msalConfig.auth.clientSecret = config.clientSecret
37 | const clientApplication = new msal.ConfidentialClientApplication(msalConfig);
38 |
39 | const clientCredentialRequest = {
40 | scopes: [config.scopeBase],
41 | };
42 |
43 | return clientApplication.acquireTokenByClientCredential(clientCredentialRequest);
44 | }
45 | }
46 |
47 | module.exports.getAccessToken = getAccessToken;
--------------------------------------------------------------------------------
/NodeJS/Embed for your customers/AppOwnsData/src/server.js:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------------
2 | // Copyright (c) Microsoft Corporation.
3 | // Licensed under the MIT license.
4 | // ----------------------------------------------------------------------------
5 |
6 | let path = require('path');
7 | let embedToken = require(__dirname + '/embedConfigService.js');
8 | const utils = require(__dirname + "/utils.js");
9 | const express = require("express");
10 | const bodyParser = require("body-parser");
11 | const app = express();
12 |
13 | // Prepare server for Bootstrap, jQuery and PowerBI files
14 | app.use('/js', express.static('./node_modules/bootstrap/dist/js/')); // Redirect bootstrap JS
15 | app.use('/js', express.static('./node_modules/jquery/dist/')); // Redirect JS jQuery
16 | app.use('/js', express.static('./node_modules/powerbi-client/dist/')) // Redirect JS PowerBI
17 | app.use('/css', express.static('./node_modules/bootstrap/dist/css/')); // Redirect CSS bootstrap
18 | app.use('/public', express.static('./public/')); // Use custom JS and CSS files
19 |
20 | const port = process.env.PORT || 5300;
21 |
22 | app.use(bodyParser.json());
23 |
24 | app.use(bodyParser.urlencoded({
25 | extended: true
26 | }));
27 |
28 | app.get('/', function (req, res) {
29 | res.sendFile(path.join(__dirname + '/../views/index.html'));
30 | });
31 |
32 | app.get('/getEmbedToken', async function (req, res) {
33 |
34 | // Validate whether all the required configurations are provided in config.json
35 | configCheckResult = utils.validateConfig();
36 | if (configCheckResult) {
37 | return res.status(400).send({
38 | "error": configCheckResult
39 | });
40 | }
41 | // Get the details like Embed URL, Access token and Expiry
42 | let result = await embedToken.getEmbedInfo();
43 |
44 | // result.status specified the statusCode that will be sent along with the result object
45 | res.status(result.status).send(result);
46 | });
47 |
48 | app.listen(port, () => console.log(`Listening on port ${port}`));
--------------------------------------------------------------------------------
/NodeJS/README.md:
--------------------------------------------------------------------------------
1 | # Power BI Embedded sample in Node JS
2 |
3 | ## Embed for your customers
4 |
5 | ### Requirements
6 |
7 | 1. [Node JS](https://nodejs.org/en/download/)
8 |
9 | 2. IDE/code editor. We recommend using Visual Studio Code.
10 |
11 | ### Set up a Power BI app
12 |
13 | Follow the steps on [aka.ms/EmbedForCustomer](https://aka.ms/embedforcustomer)
14 |
15 | ### Run the application on localhost
16 |
17 | 1. Open IDE.
18 |
19 | 2. Open [AppOwnsData](./Embed%20for%20your%20customers/AppOwnsData) folder.
20 |
21 | 3. Open terminal and install required dependencies by executing the following command.
22 | `npm install`
23 |
24 | 4. Fill in the required parameters in the [config.json](./Embed%20for%20your%20customers/AppOwnsData/config/config.json) file related to AAD app, Power BI report, workspace, and user account information.
25 |
26 | 5. Run the following command in CMD/PowerShell to start the application.
27 | `npm start`
28 |
29 | 6. Open **http://localhost:5300** in browser or refer to logs to check the port on which the application is running.
30 |
31 | #### Supported browsers:
32 |
33 | 1. Google Chrome
34 |
35 | 2. Microsoft Edge
36 |
37 | 3. Mozilla Firefox
38 |
39 | ## Important
40 |
41 | For security reasons, in a real world application, passwords and secrets should not be stored in config files. Instead, consider securing your credentials with an application such as Key Vault.
42 |
--------------------------------------------------------------------------------
/PowerShell Scripts/Admin-Create-Workspace-Inventory-Report.ps1:
--------------------------------------------------------------------------------
1 | # this script requires user to be Power BI Service administrator or global tenant admin
2 | Write-Host
3 |
4 | Connect-PowerBIServiceAccount | Out-Null
5 |
6 | # update $workspaceName variable with name of target workspace
7 | $workspaceName = "YOUR_WORKSPACE_NAME"
8 |
9 | $workspace = Get-PowerBIWorkspace -Name $workspaceName -Scope Organization -Include All
10 | $workspaceId = $workspace.Id
11 |
12 | $outputFile = "$PSScriptRoot/WorkspaceReport.txt"
13 | "Inventory Report for $workspaceName ($workspaceId)" | Out-File $outputFile
14 |
15 | "`n- Users:" | Out-File $outputFile -Append
16 | foreach($user in $workspace.Users){
17 | $userId = $user.Identifier
18 | $userAccessRight = $user.AccessRight
19 | " - $userId ($userAccessRight)" | Out-File $outputFile -Append
20 | }
21 |
22 | "`n- Datasets:" | Out-File $outputFile -Append
23 | foreach($dataset in $workspace.Datasets){
24 | $dataset | select *
25 | $datasetName = $dataset.Name
26 | $datasetId = $dataset.Id
27 | $ConfiguredBy = $dataset.ConfiguredBy
28 | $ContentProviderType = $dataset.ContentProviderType
29 | " - $datasetName ($datasetId) - $ContentProviderType - Configured by $ConfiguredBy " | Out-File $outputFile -Append
30 | }
31 |
32 | "`n- Reports:" | Out-File $outputFile -Append
33 | foreach($report in $workspace.Reports){
34 | $reportName = $report.Name
35 | $reportId = $report.Id
36 | $datasetId = $report.DatasetId
37 | " - $reportName (ReportId:$reportId - DatasetId:$datasetId) " | Out-File $outputFile -Append
38 | }
39 |
40 | notepad.exe $outputFile
--------------------------------------------------------------------------------
/PowerShell Scripts/Admin-Get-All-Workspaces-in-Tenant.ps1:
--------------------------------------------------------------------------------
1 | # this script requires user to be Power BI Service administrator or global tenant admin
2 | Write-Host
3 |
4 | Connect-PowerBIServiceAccount | Out-Null
5 |
6 | # adding -Scope Organization is what requires admin permissions
7 | Get-PowerBIWorkspace -Scope Organization -Filter "state eq 'Active'" | Format-Table Name, Type, Id
--------------------------------------------------------------------------------
/PowerShell Scripts/Create-Workspace-and-Add-Workspace-Users.ps1:
--------------------------------------------------------------------------------
1 | Write-Host
2 |
3 | Connect-PowerBIServiceAccount | Out-Null
4 |
5 | $workspaceName = "Test Workspace 1"
6 |
7 | $workspace = Get-PowerBIWorkspace -Name $workspaceName
8 |
9 | if($workspace) {
10 | Write-Host "The workspace named $workspaceName already exists"
11 | }
12 | else {
13 | Write-Host "Creating new workspace named $workspaceName"
14 | $workspace = New-PowerBIGroup -Name $workspaceName
15 | }
16 |
17 | # add user as workspace member
18 | $userEmail = "user1@tenant1.onMicrosoft.com"
19 |
20 | Add-PowerBIWorkspaceUser -Id $workspace.Id -UserEmailAddress $userEmail -AccessRight Contributor
21 |
--------------------------------------------------------------------------------
/PowerShell Scripts/Create-Workspace.ps1:
--------------------------------------------------------------------------------
1 | Write-Host
2 |
3 | Connect-PowerBIServiceAccount | Out-Null
4 |
5 | $workspaceName = "Test Workspace 1"
6 |
7 | $workspace = New-PowerBIGroup -Name $workspaceName
8 |
9 | $workspace | select *
--------------------------------------------------------------------------------
/PowerShell Scripts/DeploymentPipelines-WaitForDeployment.ps1:
--------------------------------------------------------------------------------
1 | # This sample script calls the Power BI API to programmatically monitor the progress of a deployment operation.
2 |
3 | # For documentation, please see:
4 | # https://docs.microsoft.com/rest/api/power-bi/pipelines/getpipelineoperation
5 |
6 | # Instructions:
7 | # 1. Install PowerShell (https://msdn.microsoft.com/en-us/powershell/scripting/setup/installing-windows-powershell)
8 | # and the Power BI PowerShell cmdlets (Install-Module MicrosoftPowerBIMgmt)
9 | # https://docs.microsoft.com/en-us/powershell/power-bi/overview?view=powerbi-ps
10 | # 2. Run PowerShell as an administrator
11 | # 3. Fill in the parameters below
12 | # 4. Change PowerShell directory to where this script is saved
13 | # 5. > ./DeploymentPipelines-WaitForDeployment.ps1
14 |
15 | # Parameters - fill these in before running the script!
16 | # =====================================================
17 |
18 | $pipelineName = " FILL ME IN " # The name of the pipeline
19 | $operationId = " FILL ME IN " # The operation id - can be obtained from the output of deploy scripts
20 |
21 | # End Parameters =======================================
22 |
23 | # Login to the Power BI service
24 | Connect-PowerBIServiceAccount | Out-Null
25 |
26 | try {
27 | # Get pipelines
28 | $pipelines = (Invoke-PowerBIRestMethod -Url "pipelines" -Method Get | ConvertFrom-Json).value
29 |
30 | # Try to find the pipeline by display name
31 | $pipeline = $pipelines | Where-Object {$_.DisplayName -eq $pipelineName}
32 |
33 | if(!$pipeline) {
34 | Write-Host "A pipeline with the requested name was not found"
35 | return
36 | }
37 |
38 | # Get the deployment operation details
39 | $url = "pipelines/{0}/Operations/{1}" -f $pipeline.Id,$operationId
40 | $operation = Invoke-PowerBIRestMethod -Url $url -Method Get | ConvertFrom-Json
41 |
42 | while($operation.Status -eq "NotStarted" -or $operation.Status -eq "Executing")
43 | {
44 | # Sleep for 5 seconds
45 | Start-Sleep -s 5
46 |
47 | $operation = Invoke-PowerBIRestMethod -Url $url -Method Get | ConvertFrom-Json
48 | }
49 |
50 | "Deployment completed with status: {0}" -f $operation.Status
51 | } catch {
52 | $errmsg = Resolve-PowerBIError -Last
53 | $errmsg.Message
54 | }
--------------------------------------------------------------------------------
/PowerShell Scripts/Export-PowerBIReport.ps1:
--------------------------------------------------------------------------------
1 | ########################################################################
2 | # Script created by Jerry Tang
3 | # 30/03/2023
4 | #
5 | # Instructions:
6 | # 1. Install PowerShell (https://msdn.microsoft.com/en-us/powershell/scripting/setup/installing-windows-powershell)
7 | # and the Power BI PowerShell cmdlets (Install-Module MicrosoftPowerBIMgmt)
8 | # https://docs.microsoft.com/en-us/powershell/power-bi/overview?view=powerbi-ps
9 | # 2. Run PowerShell as an administrator
10 | # 3. Fill in the parameters below
11 | # 4. Change PowerShell directory to where this script is saved
12 | #
13 | # REST API: Reports - Export Report In Group https://learn.microsoft.com/en-us/rest/api/power-bi/reports/export-report-in-group
14 | # If the file is large so the export takes long time to complete, then we might reach the timeout (can happen not just in Try-It).
15 | # As a result the preferefClientRouting is required as a workaround to skip the timeout limitation (see https://learn.microsoft.com/en-us/power-bi/developer/embedded/troubleshoot-rest-api#fix-timeout-exceptions-when-using-import-and-export-apis), or use this PowerShell script.
16 | ########################################################################
17 |
18 | # Connect to Power BI
19 | Connect-PowerBIServiceAccount
20 |
21 | $workspaceName = ""
22 | $workspace = Get-PowerBIWorkspace -Name $workspaceName
23 | $reportId = ""
24 |
25 | if($workspace) {
26 | Write-Host "The workspace named $workspaceName already exists."
27 |
28 | #https://learn.microsoft.com/en-us/powershell/module/microsoftpowerbimgmt.reports/export-powerbireport?view=powerbi-ps
29 | Export-PowerBIReport -Id $reportId -WorkspaceId $workspace.Id -OutFile .\ExportReportByPowershell.pbix -Verbose
30 | }
31 | else {
32 | Write-Host "The workspace named $workspaceName does not exist."
33 | return
34 | }
35 |
--------------------------------------------------------------------------------
/PowerShell Scripts/Import-PBIX-File.ps1:
--------------------------------------------------------------------------------
1 | Write-Host
2 |
3 | Connect-PowerBIServiceAccount | Out-Null
4 |
5 | $workspaceName = "Test Workspace 1"
6 |
7 | $workspace = Get-PowerBIWorkspace -Name $workspaceName
8 |
9 | if($workspace) {
10 | Write-Host "The workspace named $workspaceName already exists"
11 | }
12 | else {
13 | Write-Host "Creating new workspace named $workspaceName"
14 | $workspace = New-PowerBIGroup -Name $workspaceName
15 | }
16 |
17 | # update script with file path to PBIX file
18 | $pbixFilePath = "$PSScriptRoot\MyReport.pbix"
19 |
20 | $import = New-PowerBIReport -Path $pbixFilePath -Workspace $workspace -ConflictAction CreateOrOverwrite
21 |
22 | $import | select *
--------------------------------------------------------------------------------
/PowerShell Scripts/Login-User-Interactively.ps1:
--------------------------------------------------------------------------------
1 | # log into Power BI interactively as script begins to run
2 | $user = Connect-PowerBIServiceAccount
3 |
4 | $userName = $user.UserName
5 |
6 | Write-Host
7 | Write-Host "Now logged in as $userName"
8 |
9 | Get-PowerBIWorkspace | Format-Table Name, Id
--------------------------------------------------------------------------------
/PowerShell Scripts/Patch-Anonymous-Datasource-Credentials-and-Refresh.ps1:
--------------------------------------------------------------------------------
1 | Write-Host
2 |
3 | Connect-PowerBIServiceAccount | Out-Null
4 |
5 | # update these parameters for target workspace and dataset
6 | $workspaceName = "YOUR_WORKSPACE_NAME"
7 | $datasetName = "YOUR_DATASET_NAME"
8 |
9 | $workspace = Get-PowerBIWorkspace -Name $workspaceName
10 |
11 | $dataset = Get-PowerBIDataset -WorkspaceId $workspace.Id | Where-Object Name -eq $datasetName
12 |
13 | $workspaceId = $workspace.Id
14 | $datasetId = $dataset.Id
15 |
16 | $datasources = Get-PowerBIDatasource -WorkspaceId $workspaceId -DatasetId $datasetId
17 |
18 | foreach($datasource in $datasources) {
19 |
20 | # parse together REST URL to reference datasource to be patched
21 | $gatewayId = $datasource.gatewayId
22 | $datasourceId = $datasource.datasourceId
23 | $datasourePatchUrl = "gateways/$gatewayId/datasources/$datasourceId"
24 |
25 | Write-Host "Patching credentials for $datasourceId"
26 |
27 | # create HTTP request body to patch datasource credentials
28 | $patchBody = @{
29 | "credentialDetails" = @{
30 | "credentials" = "{""credentialData"":""""}"
31 | "credentialType" = "Anonymous"
32 | "encryptedConnection" = "NotEncrypted"
33 | "encryptionAlgorithm" = "None"
34 | "privacyLevel" = "Public"
35 | }
36 | }
37 |
38 | # convert body contents to JSON
39 | $patchBodyJson = ConvertTo-Json -InputObject $patchBody -Depth 6 -Compress
40 |
41 | # execute PATCH operation to set datasource credentials
42 | Invoke-PowerBIRestMethod -Method Patch -Url $datasourePatchUrl -Body $patchBodyJson
43 | }
44 |
45 | # parse REST URL for dataset refresh
46 | $datasetRefreshUrl = "groups/$workspaceId/datasets/$datasetId/refreshes"
47 |
48 | Write-Host "Starting refresh operation"
49 |
50 | # execute POST to begin dataset refresh
51 | Invoke-PowerBIRestMethod -Method Post -Url $datasetRefreshUrl -WarningAction Ignore
--------------------------------------------------------------------------------
/PowerShell Scripts/Update-Dataset-Parameters.ps1:
--------------------------------------------------------------------------------
1 | Write-Host
2 |
3 | Connect-PowerBIServiceAccount | Out-Null
4 |
5 | # update these parameters for target workspace and dataset
6 | $workspaceName = "YOUR_WORKSPACE_NAME"
7 | $datasetName = "YOUR_DATASET_NAME"
8 |
9 | $workspace = Get-PowerBIWorkspace -Name $workspaceName
10 |
11 | $dataset = Get-PowerBIDataset -WorkspaceId $workspace.Id | Where-Object Name -eq $datasetName
12 |
13 | $workspaceId = $workspace.Id
14 | $datasetId = $dataset.Id
15 |
16 | # create REST URL to update State parameter for newly-imported dataset
17 | $datasetParametersUrl = "groups/$workspaceId/datasets/$datasetId/Default.UpdateParameters"
18 |
19 | # parse together JSON for POST body to update dataset parameters
20 | $parameterName = "myParameterName"
21 | $newParameterValue = "New Parameter Value"
22 | $postBody = "{updateDetails:[{name:'$parameterName', newValue:'$newParameterValue'}]}"
23 |
24 | # invoke POST operation to update dataset parameters
25 | Invoke-PowerBIRestMethod -Url:$datasetParametersUrl -Method:Post -Body:$postBody `
26 | -ContentType:'application/json'
27 |
28 | # if parameter updates change connection information (e.g. server path, database name), you will
29 | # then be required to patch datasource credentials before you can refresh the dataset
--------------------------------------------------------------------------------
/PowerShell Scripts/takeOverDataset.ps1:
--------------------------------------------------------------------------------
1 | # This sample script calls the Power BI API to programmatically take over a dataset.
2 |
3 | # For documentation, please see:
4 | # https://docs.microsoft.com/rest/api/power-bi/datasets/takeoveringroup
5 |
6 | # Instructions:
7 | # 1. Install PowerShell (https://msdn.microsoft.com/en-us/powershell/scripting/setup/installing-windows-powershell)
8 | # and the Power BI PowerShell cmdlets (Install-Module MicrosoftPowerBIMgmt)
9 | # https://docs.microsoft.com/en-us/powershell/power-bi/overview?view=powerbi-ps
10 | # 2. Run PowerShell as an administrator
11 | # 3. Fill in the parameters below
12 | # 4. Change PowerShell directory to where this script is saved
13 | # 5. > ./takeOverDataset.ps1
14 |
15 | # Parameters - fill these in before running the script!
16 | # =====================================================
17 |
18 | $groupId = " FILL ME IN " # the ID of the group (workspace) that hosts the dataset.
19 | $datasetId = " FILL ME IN " # the ID of dataset to rebind
20 |
21 | # End Parameters =======================================
22 |
23 | # Login to the Power BI service with your Power BI credentials
24 | Login-PowerBI
25 |
26 | # Make the request to bind to a gateway
27 | $uri = "groups/$groupId/datasets/$datasetId/Default.TakeOver"
28 |
29 | # Try to bind to a new gateway
30 | try {
31 | Invoke-PowerBIRestMethod -Url $uri -Method Post
32 |
33 | # Show error if we had a non-terminating error which catch won't catch
34 | if (-Not $?)
35 | {
36 | $errmsg = Resolve-PowerBIError -Last
37 | $errmsg.Message
38 | }
39 | } catch {
40 |
41 | $errmsg = Resolve-PowerBIError -Last
42 | $errmsg.Message
43 | }
--------------------------------------------------------------------------------
/Python/.gitignore:
--------------------------------------------------------------------------------
1 | .vscode/
2 | *.py[co]
3 | *.DS_*
4 | # Packages
5 | *.egg
6 | *.egg-info
7 | dist
8 | build
9 | eggs
10 | parts
11 | bin
12 | var
13 | sdist
14 | develop-eggs
15 | .installed.cfg
16 | pip-log.txt
17 | .coverage
18 | .tox
19 | *.mo
20 | venv
21 | *.pyc
22 | build
--------------------------------------------------------------------------------
/Python/Embed for your customers/AppOwnsData/app.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Microsoft Corporation.
2 | # Licensed under the MIT license.
3 |
4 | from services.pbiembedservice import PbiEmbedService
5 | from utils import Utils
6 | from flask import Flask, render_template, send_from_directory
7 | import json
8 | import os
9 |
10 | # Initialize the Flask app
11 | app = Flask(__name__)
12 |
13 | # Load configuration
14 | app.config.from_object('config.BaseConfig')
15 |
16 | @app.route('/')
17 | def index():
18 | '''Returns a static HTML page'''
19 |
20 | return render_template('index.html')
21 |
22 | @app.route('/getembedinfo', methods=['GET'])
23 | def get_embed_info():
24 | '''Returns report embed configuration'''
25 |
26 | config_result = Utils.check_config(app)
27 | if config_result is not None:
28 | return json.dumps({'errorMsg': config_result}), 500
29 |
30 | try:
31 | embed_info = PbiEmbedService().get_embed_params_for_single_report(app.config['WORKSPACE_ID'], app.config['REPORT_ID'])
32 | return embed_info
33 | except Exception as ex:
34 | return json.dumps({'errorMsg': str(ex)}), 500
35 |
36 | @app.route('/favicon.ico', methods=['GET'])
37 | def getfavicon():
38 | '''Returns path of the favicon to be rendered'''
39 |
40 | return send_from_directory(os.path.join(app.root_path, 'static'), 'img/favicon.ico', mimetype='image/vnd.microsoft.icon')
41 |
42 | if __name__ == '__main__':
43 | app.run()
--------------------------------------------------------------------------------
/Python/Embed for your customers/AppOwnsData/cgmanifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "Registrations": [
3 | {
4 | "Component": {
5 | "Type": "other",
6 | "Other": {
7 | "Name": "jquery",
8 | "Version": "3.5.1",
9 | "DownloadUrl": "https://code.jquery.com/jquery-3.5.1.min.js"
10 | }
11 | }
12 | },
13 | {
14 | "Component": {
15 | "Type": "other",
16 | "Other": {
17 | "Name": "bootstrap",
18 | "Version": "4.5.3",
19 | "DownloadUrl": "https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/js/bootstrap.min.js"
20 | }
21 | }
22 | },
23 | {
24 | "Component": {
25 | "Type": "other",
26 | "Other": {
27 | "Name": "bootstrap",
28 | "Version": "4.5.3",
29 | "DownloadUrl": "https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css"
30 | }
31 | }
32 | },
33 | {
34 | "Component": {
35 | "Type": "other",
36 | "Other": {
37 | "Name": "powerbi-client",
38 | "Version": "2.16.5",
39 | "DownloadUrl": "https://cdnjs.cloudflare.com/ajax/libs/powerbi-client/2.15.1/powerbi.min.js"
40 | }
41 | }
42 | }
43 | ],
44 | "$schema": "https://json.schemastore.org/component-detection-manifest.json"
45 | }
--------------------------------------------------------------------------------
/Python/Embed for your customers/AppOwnsData/config.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Microsoft Corporation.
2 | # Licensed under the MIT license.
3 |
4 | class BaseConfig(object):
5 |
6 | # Can be set to 'MasterUser' or 'ServicePrincipal'
7 | AUTHENTICATION_MODE = 'ServicePrincipal'
8 |
9 | # Workspace Id in which the report is present
10 | WORKSPACE_ID = ''
11 |
12 | # Report Id for which Embed token needs to be generated
13 | REPORT_ID = ''
14 |
15 | # Id of the Azure tenant in which AAD app and Power BI report is hosted. Required only for ServicePrincipal authentication mode.
16 | TENANT_ID = ''
17 |
18 | # Client Id (Application Id) of the AAD app
19 | CLIENT_ID = ''
20 |
21 | # Client Secret (App Secret) of the AAD app. Required only for ServicePrincipal authentication mode.
22 | CLIENT_SECRET = ''
23 |
24 | # Scope Base of AAD app. Use the below configuration to use all the permissions provided in the AAD app through Azure portal.
25 | SCOPE_BASE = ['https://analysis.windows.net/powerbi/api/.default']
26 |
27 | # URL used for initiating authorization request
28 | AUTHORITY_URL = 'https://login.microsoftonline.com/organizations'
29 |
30 | # Master user email address. Required only for MasterUser authentication mode.
31 | POWER_BI_USER = ''
32 |
33 | # Master user email password. Required only for MasterUser authentication mode.
34 | POWER_BI_PASS = ''
--------------------------------------------------------------------------------
/Python/Embed for your customers/AppOwnsData/models/embedconfig.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Microsoft Corporation.
2 | # Licensed under the MIT license
3 |
4 | class EmbedConfig:
5 |
6 | # Camel casing is used for the member variables as they are going to be serialized and camel case is standard for JSON keys
7 |
8 | tokenId = None
9 | accessToken = None
10 | tokenExpiry = None
11 | reportConfig = None
12 |
13 | def __init__(self, token_id, access_token, token_expiry, report_config):
14 | self.tokenId = token_id
15 | self.accessToken = access_token
16 | self.tokenExpiry = token_expiry
17 | self.reportConfig = report_config
--------------------------------------------------------------------------------
/Python/Embed for your customers/AppOwnsData/models/embedtoken.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Microsoft Corporation.
2 | # Licensed under the MIT license
3 |
4 | class EmbedToken:
5 |
6 | # Camel casing is used for the member variables as they are going to be serialized and camel case is standard for JSON keys
7 |
8 | tokenId = None
9 | token = None
10 | tokenExpiry = None
11 |
12 | def __init__(self, token_id, token, token_expiry):
13 | self.tokenId = token_id
14 | self.token = token
15 | self.tokenExpiry = token_expiry
--------------------------------------------------------------------------------
/Python/Embed for your customers/AppOwnsData/models/embedtokenrequestbody.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Microsoft Corporation.
2 | # Licensed under the MIT license
3 |
4 | class EmbedTokenRequestBody:
5 |
6 | # Camel casing is used for the member variables as they are going to be serialized and camel case is standard for JSON keys
7 |
8 | datasets = None
9 | reports = None
10 | targetWorkspaces = None
11 |
12 | def __init__(self):
13 | self.datasets = []
14 | self.reports = []
15 | self.targetWorkspaces = []
--------------------------------------------------------------------------------
/Python/Embed for your customers/AppOwnsData/models/reportconfig.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Microsoft Corporation.
2 | # Licensed under the MIT license
3 |
4 | class ReportConfig:
5 |
6 | # Camel casing is used for the member variables as they are going to be serialized and camel case is standard for JSON keys
7 |
8 | reportId = None
9 | reportName = None
10 | embedUrl = None
11 | datasetId = None
12 |
13 | def __init__(self, report_id, report_name, embed_url, dataset_id = None):
14 | self.reportId = report_id
15 | self.reportName = report_name
16 | self.embedUrl = embed_url
17 | self.datasetId = dataset_id
--------------------------------------------------------------------------------
/Python/Embed for your customers/AppOwnsData/services/aadservice.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Microsoft Corporation.
2 | # Licensed under the MIT license.
3 |
4 | from flask import current_app as app
5 | import msal
6 |
7 | class AadService:
8 |
9 | def get_access_token():
10 | '''Generates and returns Access token
11 |
12 | Returns:
13 | string: Access token
14 | '''
15 |
16 | response = None
17 | try:
18 | if app.config['AUTHENTICATION_MODE'].lower() == 'masteruser':
19 |
20 | # Create a public client to authorize the app with the AAD app
21 | clientapp = msal.PublicClientApplication(app.config['CLIENT_ID'], authority=app.config['AUTHORITY_URL'])
22 | accounts = clientapp.get_accounts(username=app.config['POWER_BI_USER'])
23 |
24 | if accounts:
25 | # Retrieve Access token from user cache if available
26 | response = clientapp.acquire_token_silent(app.config['SCOPE_BASE'], account=accounts[0])
27 |
28 | if not response:
29 | # Make a client call if Access token is not available in cache
30 | response = clientapp.acquire_token_by_username_password(app.config['POWER_BI_USER'], app.config['POWER_BI_PASS'], scopes=app.config['SCOPE_BASE'])
31 |
32 | # Service Principal auth is the recommended by Microsoft to achieve App Owns Data Power BI embedding
33 | elif app.config['AUTHENTICATION_MODE'].lower() == 'serviceprincipal':
34 | authority = app.config['AUTHORITY_URL'].replace('organizations', app.config['TENANT_ID'])
35 | clientapp = msal.ConfidentialClientApplication(app.config['CLIENT_ID'], client_credential=app.config['CLIENT_SECRET'], authority=authority)
36 |
37 | # Make a client call if Access token is not available in cache
38 | response = clientapp.acquire_token_for_client(scopes=app.config['SCOPE_BASE'])
39 |
40 | try:
41 | return response['access_token']
42 | except KeyError:
43 | raise Exception(response['error_description'])
44 |
45 | except Exception as ex:
46 | raise Exception('Error retrieving Access token\n' + str(ex))
--------------------------------------------------------------------------------
/Python/Embed for your customers/AppOwnsData/static/css/index.css:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) Microsoft Corporation.
3 | Licensed under the MIT license.
4 | */
5 |
6 | header {
7 | background-color: #007FFF;
8 | height: 75px;
9 | width: 100%;
10 | }
11 |
12 | header > p {
13 | color: #FFFFFF;
14 | font: bold 1.6em "segoe ui", arial, sans-serif;
15 | margin-left: 31px;
16 | padding-top: 20px;
17 | }
18 |
19 | main {
20 | margin: 0 auto;
21 | width: 100%;
22 | }
23 |
24 | section#text-container > div > p {
25 | font: 1.2em "segoe ui", arial, sans-serif;
26 | }
27 |
28 | section#report-container {
29 | height: calc(0.5625 * 60vw); /* 16:9 aspect ratio */
30 | }
31 |
32 | @media only screen and (max-width: 575px) {
33 | section#report-container {
34 | height: calc(0.5625 * 100vw); /* 16:9 aspect ratio */
35 | }
36 | }
37 |
38 | footer > p {
39 | font: 1em "segoe ui", arial, sans-serif;
40 | }
41 |
42 | iframe {
43 | border: none;
44 | }
--------------------------------------------------------------------------------
/Python/Embed for your customers/AppOwnsData/static/img/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/PowerBI-Developer-Samples/2970f6581bb6e6aa3403be858ffd968357807f5d/Python/Embed for your customers/AppOwnsData/static/img/favicon.ico
--------------------------------------------------------------------------------
/Python/Embed for your customers/AppOwnsData/utils.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Microsoft Corporation.
2 | # Licensed under the MIT license.
3 |
4 | class Utils:
5 |
6 | def check_config(app):
7 | '''Returns a message to user for missing configuration
8 |
9 | Args:
10 | app (Flask): Flask app object
11 |
12 | Returns:
13 | string: Error info
14 | '''
15 |
16 | if app.config['AUTHENTICATION_MODE'] == '':
17 | return 'Please specify one of the two authentication modes'
18 | if app.config['AUTHENTICATION_MODE'].lower() == 'serviceprincipal' and app.config['TENANT_ID'] == '':
19 | return 'Tenant ID is not provided in the config.py file'
20 | elif app.config['REPORT_ID'] == '':
21 | return 'Report ID is not provided in config.py file'
22 | elif app.config['WORKSPACE_ID'] == '':
23 | return 'Workspace ID is not provided in config.py file'
24 | elif app.config['CLIENT_ID'] == '':
25 | return 'Client ID is not provided in config.py file'
26 | elif app.config['AUTHENTICATION_MODE'].lower() == 'masteruser':
27 | if app.config['POWER_BI_USER'] == '':
28 | return 'Master account username is not provided in config.py file'
29 | elif app.config['POWER_BI_PASS'] == '':
30 | return 'Master account password is not provided in config.py file'
31 | elif app.config['AUTHENTICATION_MODE'].lower() == 'serviceprincipal':
32 | if app.config['CLIENT_SECRET'] == '':
33 | return 'Client secret is not provided in config.py file'
34 | elif app.config['SCOPE_BASE'] == '':
35 | return 'Scope base is not provided in the config.py file'
36 | elif app.config['AUTHORITY_URL'] == '':
37 | return 'Authority URL is not provided in the config.py file'
38 |
39 | return None
--------------------------------------------------------------------------------
/Python/Embed for your customers/README.md:
--------------------------------------------------------------------------------
1 | # Power BI Embedded sample in Flask framework
2 |
3 |
4 | ### Requirements
5 |
6 | 1. [Python 3](https://www.python.org/downloads/)
7 |
8 | 2. IDE/code editor. We recommended using Visual Studio Code.
9 |
10 |
11 | ### Set up a Power BI app
12 |
13 | Follow the steps on [aka.ms/EmbedForCustomer](https://aka.ms/embedforcustomer)
14 |
15 |
16 | ### Set up Python Flask on a Windows machine
17 |
18 | 1. [Install](https://docs.python.org/3/using/index.html) [Python 3](https://www.python.org/downloads/) and add its installation path to the *Path* environment variable.
19 |
20 | 2. Run the following command in CMD/PowerShell in the path where [requirements.txt](./requirements.txt) file is located.
21 |
22 | `pip3 install -r requirements.txt`
23 |
24 |
25 | ### Run the application on localhost
26 |
27 | 1. Open IDE.
28 |
29 | 2. Open [AppOwnsData](./AppOwnsData) folder.
30 |
31 | 3. Fill in the required parameters in the [config.py](./AppOwnsData/config.py) file related to AAD app, Power BI report, workspace, and user account information.
32 |
33 | 4. Run the following command in CMD/PowerShell to start the application.
34 |
35 | `flask run`
36 |
37 |
38 | 5. Open **http://localhost:5000** in browser or follow the direction in the output log.
39 |
40 | > **Note:** Whenever you update the config file you must restart the app.
41 |
42 | #### Supported browsers:
43 |
44 | 1. Google Chrome
45 |
46 | 2. Microsoft Edge
47 |
48 | 3. Mozilla Firefox
49 |
50 | ### Important
51 |
52 | For security reasons, in a real world application, passwords and secrets should not be stored in config files. Instead, consider securing your credentials with an application such as Key Vault.
53 |
--------------------------------------------------------------------------------
/Python/Embed for your customers/requirements.txt:
--------------------------------------------------------------------------------
1 | flask
2 | requests
3 | msal
--------------------------------------------------------------------------------
/Python/Encrypt credentials/CloudConfigs/Power BI Global/config.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Microsoft Corporation.
2 | # Licensed under the MIT license.
3 |
4 | # Replace these configs with the one in the config.py file for sovereign cloud
5 |
6 | class BaseConfig(object):
7 |
8 | # Scope Base of AAD app. Use the below configuration to use all the permissions provided in the AAD app through Azure portal.
9 | SCOPE_BASE = ['https://analysis.windows.net/powerbi/api/.default']
10 |
11 | # URL used for initiating authorization request
12 | AUTHORITY_URL = 'https://login.microsoftonline.com/organizations'
13 |
14 | # End point URL for Power BI API
15 | POWER_BI_API_URL = 'https://api.powerbi.com/'
--------------------------------------------------------------------------------
/Python/Encrypt credentials/CloudConfigs/Power BI US Government/config.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Microsoft Corporation.
2 | # Licensed under the MIT license.
3 |
4 | # Replace these configs with the one in the config.py file for sovereign cloud
5 |
6 | class BaseConfig(object):
7 |
8 | # Scope Base of AAD app. Use the below configuration to use all the permissions provided in the AAD app through Azure portal.
9 | SCOPE_BASE = ['https://analysis.usgovcloudapi.net/powerbi/api/.default']
10 |
11 | # URL used for initiating authorization request
12 | AUTHORITY_URL = 'https://login.microsoftonline.com/organizations'
13 |
14 | # End point URL for Power BI API
15 | POWER_BI_API_URL = 'https://api.powerbigov.us/'
--------------------------------------------------------------------------------
/Python/Encrypt credentials/CloudConfigs/Power BI in Germany/config.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Microsoft Corporation.
2 | # Licensed under the MIT license.
3 |
4 | # Replace these configs with the one in the config.py file for sovereign cloud
5 |
6 | class BaseConfig(object):
7 |
8 | # Scope Base of AAD app. Use the below configuration to use all the permissions provided in the AAD app through Azure portal.
9 | SCOPE_BASE = ['https://analysis.cloudapi.de/powerbi/api/.default']
10 |
11 | # URL used for initiating authorization request
12 | AUTHORITY_URL = 'https://login.microsoftonline.de/organizations'
13 |
14 | # End point URL for Power BI API
15 | POWER_BI_API_URL = 'https://api.powerbi.de/'
--------------------------------------------------------------------------------
/Python/Encrypt credentials/CloudConfigs/Power BI operated by 21Vianet in China/config.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Microsoft Corporation.
2 | # Licensed under the MIT license.
3 |
4 | # Replace these configs with the one in the config.py file for sovereign cloud
5 |
6 | class BaseConfig(object):
7 |
8 | # Scope Base of AAD app. Use the below configuration to use all the permissions provided in the AAD app through Azure portal.
9 | SCOPE_BASE = ['https://analysis.chinacloudapi.cn/powerbi/api/.default']
10 |
11 | # URL used for initiating authorization request
12 | AUTHORITY_URL = 'https://login.chinacloudapi.cn/organizations'
13 |
14 | # End point URL for Power BI API
15 | POWER_BI_API_URL = 'https://api.powerbi.cn/'
--------------------------------------------------------------------------------
/Python/Encrypt credentials/Encryption sample/cgmanifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "Registrations": [
3 | {
4 | "Component": {
5 | "Type": "other",
6 | "Other": {
7 | "Name": "jquery",
8 | "Version": "3.5.1",
9 | "DownloadUrl": "https://code.jquery.com/jquery-3.5.1.min.js"
10 | }
11 | }
12 | },
13 | {
14 | "Component": {
15 | "Type": "other",
16 | "Other": {
17 | "Name": "bootstrap",
18 | "Version": "4.5.3",
19 | "DownloadUrl": "https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/js/bootstrap.min.js"
20 | }
21 | }
22 | },
23 | {
24 | "Component": {
25 | "Type": "other",
26 | "Other": {
27 | "Name": "bootstrap",
28 | "Version": "4.5.3",
29 | "DownloadUrl": "https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css"
30 | }
31 | }
32 | }
33 | ],
34 | "$schema": "https://json.schemastore.org/component-detection-manifest.json"
35 | }
--------------------------------------------------------------------------------
/Python/Encrypt credentials/Encryption sample/config.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Microsoft Corporation.
2 | # Licensed under the MIT license.
3 |
4 | class BaseConfig(object):
5 |
6 | # Can be set to 'MasterUser' or 'ServicePrincipal'
7 | AUTHENTICATION_MODE = 'ServicePrincipal'
8 |
9 | # Id of the Azure tenant in which AAD app and Power BI report is hosted. Required only for ServicePrincipal authentication mode.
10 | TENANT_ID = ''
11 |
12 | # Client Id (Application Id) of the AAD app
13 | CLIENT_ID = ''
14 |
15 | # Client Secret (App Secret) of the AAD app. Required only for ServicePrincipal authentication mode.
16 | CLIENT_SECRET = ''
17 |
18 | # Scope Base of AAD app. Use the below configuration to use all the permissions provided in the AAD app through Azure portal.
19 | SCOPE_BASE = ['https://analysis.windows.net/powerbi/api/.default']
20 |
21 | # URL used for initiating authorization request
22 | AUTHORITY_URL = 'https://login.microsoftonline.com/organizations'
23 |
24 | # End point URL for Power BI API
25 | POWER_BI_API_URL = 'https://api.powerbi.com/'
26 |
27 | # Master user email address. Required only for MasterUser authentication mode.
28 | POWER_BI_USER = ''
29 |
30 | # Master user password. Required only for MasterUser authentication mode.
31 | POWER_BI_PASS = ''
32 |
--------------------------------------------------------------------------------
/Python/Encrypt credentials/Encryption sample/models/credentialsdetails.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Microsoft Corporation.
2 | # Licensed under the MIT license.
3 |
4 | class CredentialsDetails:
5 | ENCRYPTION_ALGORITHM = 'RSA-OAEP'
6 |
7 | # Camel casing is used for the member variables as they are going to be serialized and camel case is standard for JSON keys
8 | credentialType = None
9 | credentials = None
10 | encryptedConnection = None
11 | privacyLevel = None
12 |
13 | def __init__(self, cred_type, serialized_credentials, encrypted_connection, privacy_level):
14 | self.credentialType = cred_type
15 | self.credentials = serialized_credentials
16 | self.encryptedConnection = encrypted_connection
17 | self.encryptionAlgorithm = CredentialsDetails.ENCRYPTION_ALGORITHM
18 | self.privacyLevel = privacy_level
19 |
--------------------------------------------------------------------------------
/Python/Encrypt credentials/Encryption sample/models/credentialsdetailsrequest.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Microsoft Corporation.
2 | # Licensed under the MIT license.
3 |
4 | class CredentialsDetailsRequest:
5 |
6 | # Camel casing is used for the member variables as they are going to be serialized and camel case is standard for JSON keys
7 | credentialDetails = None
8 |
9 | def __init__(self, credentials_details):
10 | self.credentialDetails = credentials_details
11 |
--------------------------------------------------------------------------------
/Python/Encrypt credentials/Encryption sample/models/publishdatasourcetogatewayrequest.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Microsoft Corporation.
2 | # Licensed under the MIT license.
3 |
4 | class PublishDatasourceToGatewayRequest:
5 |
6 | # Camel casing is used for the member variables as they are going to be serialized and camel case is standard for JSON keys
7 | dataSourceType = None
8 | connectionDetails = None
9 | credentialDetails = None
10 | datasourceName = None
11 |
12 | def __init__(self, data_source_type, connection_details, credentials_details, data_source_name):
13 | self.dataSourceType = data_source_type
14 | self.connectionDetails = connection_details
15 | self.credentialDetails = credentials_details
16 | self.datasourceName = data_source_name
17 |
--------------------------------------------------------------------------------
/Python/Encrypt credentials/Encryption sample/services/aadservice.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Microsoft Corporation.
2 | # Licensed under the MIT license.
3 |
4 | import msal
5 | from flask import current_app as app
6 | from utils import Utils
7 |
8 |
9 | class AadService:
10 |
11 | def get_access_token():
12 | ''' Generates and returns Access token
13 |
14 | Returns:
15 | string: Access token
16 | '''
17 |
18 | config_result = Utils.validate_config(app)
19 | if config_result:
20 | raise Exception(config_result)
21 |
22 | authenticate_mode = app.config['AUTHENTICATION_MODE']
23 | tenant_id = app.config['TENANT_ID']
24 | client_id = app.config['CLIENT_ID']
25 | username = app.config['POWER_BI_USER']
26 | password = app.config['POWER_BI_PASS']
27 | client_secret = app.config['CLIENT_SECRET']
28 | scope = app.config['SCOPE_BASE']
29 | authority = app.config['AUTHORITY_URL']
30 | response = None
31 |
32 | try:
33 | if authenticate_mode.lower() == 'masteruser':
34 |
35 | # Create a public client to authorize the app with the AAD app
36 | clientapp = msal.PublicClientApplication(client_id, authority=authority)
37 |
38 | # Make a client call if Access token is not available in cache
39 | response = clientapp.acquire_token_by_username_password(username, password, scopes=scope)
40 |
41 | # Service Principal auth is recommended by Microsoft to achieve App Owns Data Power BI embedding
42 | else:
43 | authority = authority.replace('organizations', tenant_id)
44 | clientapp = msal.ConfidentialClientApplication(client_id, client_credential=client_secret, authority=authority)
45 |
46 | # Make a client call if Access token is not available in cache
47 | response = clientapp.acquire_token_for_client(scopes=scope)
48 |
49 | return response['access_token']
50 |
51 | except KeyError:
52 | raise Exception(response['error_description'])
53 | except Exception as ex:
54 | raise Exception('Error retrieving Access token\n' + str(ex))
55 |
--------------------------------------------------------------------------------
/Python/Encrypt credentials/Encryption sample/services/asymmetrickeyencryptor.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Microsoft Corporation.
2 | # Licensed under the MIT license.
3 |
4 | import base64
5 | from helper.asymmetric1024keyencryptionhelper import Asymmetric1024KeyEncryptionHelper
6 | from helper.asymmetrichigherkeyencryptionhelper import AsymmetricHigherKeyEncryptionHelper
7 |
8 |
9 | class AsymmetricKeyEncryptor:
10 |
11 | MODULUS_SIZE = 128
12 | public_key = None
13 |
14 | def __init__(self, public_key):
15 | if not public_key:
16 | raise TypeError('public_key')
17 |
18 | if not public_key['exponent'] or public_key['exponent'] == '':
19 | raise TypeError("public_key['exponent']")
20 |
21 | if not public_key['modulus'] or public_key['modulus'] == '':
22 | raise TypeError("public_key['modulus']")
23 |
24 | self.public_key = public_key
25 |
26 | def encode_credentials(self, credentails_data):
27 | ''' Encodes the credentials based on modulus size
28 |
29 | Args:
30 | credentails_data (str): Credentials data to get encrypted
31 |
32 | Returns:
33 | String: Encrypted credentials
34 | '''
35 |
36 | if not credentails_data or credentails_data == '':
37 | raise TypeError('credentials data')
38 |
39 | plain_text_bytes = bytes(credentails_data, 'utf-8')
40 |
41 | # Convert strings to bytes object
42 | modulus_bytes = base64.b64decode(self.public_key['modulus'])
43 | exponent_bytes = base64.b64decode(self.public_key['exponent'])
44 |
45 | # Call the encryption helper based on the modulus size
46 | asymmetric_1024_key_encryptor_helper = Asymmetric1024KeyEncryptionHelper()
47 | asymmetric_higher_key_encryptor_helper = AsymmetricHigherKeyEncryptionHelper()
48 |
49 | if len(modulus_bytes) == self.MODULUS_SIZE:
50 | return asymmetric_1024_key_encryptor_helper.encrypt(plain_text_bytes, modulus_bytes, exponent_bytes)
51 | else:
52 | return asymmetric_higher_key_encryptor_helper.encrypt(plain_text_bytes, modulus_bytes, exponent_bytes)
53 |
--------------------------------------------------------------------------------
/Python/Encrypt credentials/Encryption sample/services/datavalidationservice.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Microsoft Corporation.
2 | # Licensed under the MIT license.
3 |
4 |
5 | class DataValidationService:
6 |
7 | def validate_creds(self, data):
8 | ''' Validates data for all the functionalities
9 |
10 | Args:
11 | data (dict): data
12 | '''
13 | cred_type = data['credType']
14 |
15 | if not data['credentialsArray'][0] or data['credentialsArray'][0] == '':
16 | raise KeyError('Credentials data')
17 |
18 | if (cred_type == 'Basic' or cred_type == 'Windows') and (not data['credentialsArray'][1] or data['credentialsArray'][1] == ''):
19 | raise KeyError('Credentials data')
20 |
21 |
22 | def validate_encrypt_data(self, data):
23 | ''' Validates data for Encrypt credentials functionality
24 |
25 | Args:
26 | data (dict): data
27 | '''
28 | gateway_id = data['gatewayId']
29 |
30 | if not gateway_id or gateway_id == '':
31 | raise KeyError('Gateway ID')
32 | else:
33 | self.validate_creds(data)
34 |
35 | def validate_add_data_source(self, data):
36 | ''' Validates data for Add data source functionality
37 |
38 | Args:
39 | data (dict): data
40 | '''
41 | gateway_id = data['gatewayId']
42 | data_source_type = data['dataSourceType']
43 | data_source_name = data['dataSourceName']
44 | connection_details = data['connectionDetails']
45 |
46 | if not gateway_id or gateway_id == '':
47 | raise KeyError('Gateway ID')
48 | elif not data_source_type or data_source_type == '':
49 | raise KeyError('Data source type')
50 | elif not data_source_name or data_source_name == '':
51 | raise KeyError('Data source name')
52 | elif not connection_details or connection_details == '':
53 | raise KeyError('Connection details')
54 | else:
55 | self.validate_creds(data)
56 |
--------------------------------------------------------------------------------
/Python/Encrypt credentials/Encryption sample/services/getdatasource.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Microsoft Corporation.
2 | # Licensed under the MIT license.
3 |
4 | import requests
5 | from flask import current_app as app
6 |
7 | class GetDatasourceService:
8 |
9 | headers = None
10 |
11 | def get_datasources_in_group(self, access_token, group_id, dataset_id):
12 | ''' Returns all the data sources from the given group
13 |
14 | Args:
15 | access_token (str): Access token to call API
16 | group_id (str): Group Id
17 | dataset_id (str): Dataset Id
18 |
19 | Returns:
20 | Response: Response from the API call
21 | '''
22 |
23 | self.headers = {'Content-Type': 'application/json', 'Authorization': 'Bearer ' + access_token}
24 |
25 | # https://docs.microsoft.com/en-us/rest/api/power-bi/datasets/getdatasourcesingroup
26 | endpoint_url = f'{app.config["POWER_BI_API_URL"]}v1.0/myorg/groups/{group_id}/datasets/{dataset_id}/datasources'
27 |
28 | api_response = requests.get(endpoint_url, headers=self.headers)
29 |
30 | return api_response
31 |
32 | def get_gateway(self, access_token, gateway_id):
33 | ''' Returns the gateway information
34 |
35 | Args:
36 | access_token (str): Access token to call API
37 | gateway_id (str): Gateway Id
38 |
39 | Returns:
40 | Response: Response from the API call
41 | '''
42 |
43 | self.headers = {'Content-Type': 'application/json', 'Authorization': 'Bearer ' + access_token}
44 |
45 | endpoint_url = f'{app.config["POWER_BI_API_URL"]}v1.0/myorg/gateways/{gateway_id}'
46 |
47 | api_response = requests.get(endpoint_url, headers=self.headers)
48 |
49 | return api_response
50 |
--------------------------------------------------------------------------------
/Python/Encrypt credentials/Encryption sample/static/css/index.css:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Microsoft Corporation.
2 | Licensed under the MIT license. */
3 |
4 | header {
5 | background-color: #007FFF;
6 | height: 75px;
7 | width: 100%;
8 | }
9 |
10 | header > div {
11 | color: #FFFFFF;
12 | font: bold 25.6px "segoe ui", arial, sans-serif;
13 | margin-left: 32px;
14 | padding-top: 19px;
15 | }
16 |
17 | main {
18 | margin: 0 auto;
19 | width: 100%;
20 | }
21 |
22 | section#text-container > div > div {
23 | font: 19px "segoe ui", arial, sans-serif;
24 | }
25 |
26 | .id-container {
27 | margin: 0 12px 0 16px;
28 | }
29 |
30 | .input-element {
31 | height: 30px;
32 | width: 280px;
33 | padding: 2px;
34 | }
35 |
36 | .send-button {
37 | width: 200px;
38 | }
39 |
40 | .password-text {
41 | margin-left: 24px;
42 | }
43 |
44 | #task-container {
45 | margin-bottom: 15px;
46 | }
47 |
48 | section#text-container {
49 | margin: 24px 40px;
50 | }
51 |
52 | footer > p {
53 | font: 16px "segoe ui", arial, sans-serif;
54 | }
55 |
56 | #get-data-sources {
57 | margin-top: 20px;
58 | }
59 |
60 | .gateway-container {
61 | display: none;
62 | margin-top: 20px;
63 | }
64 |
65 | .success-container {
66 | margin-left: 0;
67 | margin-right: 0;
68 | }
69 |
70 | .error-container {
71 | margin-left: 0;
72 | margin-right: 0;
73 | }
74 |
75 | .modal-dialog {
76 | max-width: min-content;
77 | min-width: 500px;
78 | }
79 |
80 | .add-datasource-container,
81 | .encrypt-credentials-container,
82 | #credential-windows,
83 | #credential-oauth2,
84 | #credential-basic {
85 | display: none;
86 | }
87 |
88 | #credential-key {
89 | display: block;
90 | }
91 |
92 | .inactive-text {
93 | color: #808080;
94 | }
95 |
96 | .active-text {
97 | color: #000000;
98 | }
99 |
--------------------------------------------------------------------------------
/Python/Encrypt credentials/Encryption sample/static/img/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/PowerBI-Developer-Samples/2970f6581bb6e6aa3403be858ffd968357807f5d/Python/Encrypt credentials/Encryption sample/static/img/favicon.ico
--------------------------------------------------------------------------------
/Python/Encrypt credentials/README.md:
--------------------------------------------------------------------------------
1 | # Power BI Embedded sample in Flask framework
2 |
3 |
4 | ### Requirements
5 |
6 | 1. [Python 3](https://www.python.org/downloads/)
7 |
8 | 2. IDE/code editor. We recommended using Visual Studio Code.
9 |
10 |
11 | ### Set up a Power BI app
12 |
13 | Follow the steps on [aka.ms/EmbedForCustomer](https://aka.ms/embedforcustomer)
14 |
15 |
16 | ### Set up Python Flask on a Windows machine
17 |
18 | 1. [Install](https://docs.python.org/3/using/index.html) [Python 3](https://www.python.org/downloads/) and add its installation path to the *Path* environment variable.
19 |
20 | 2. Run the following command in CMD/PowerShell in the path where [requirements.txt](./requirements.txt) file is located.
21 |
22 | `pip3 install -r requirements.txt`
23 |
24 |
25 | ### Run the application on localhost
26 |
27 | 1. Open IDE.
28 |
29 | 2. Open [Encryption sample](./Encryption%20sample) folder.
30 |
31 | 3. Fill in the required parameters in the [config.py](./Encryption%20sample/config.py) file related to AAD app, Power BI report, workspace, and user account information.
32 |
33 | 4. Run the following command in CMD/PowerShell to start the application.
34 |
35 | `flask run`
36 |
37 |
38 | 5. Open **http://localhost:5000** in browser or follow the direction in the output log.
39 |
40 | > **Note:**
41 | > 1. Whenever you update the config file you must restart the app.
42 | > 2. The Azure AD Service Principal which is used for authentication should have admin rights on the corresponding workspace.
43 | > 3. If Service Principal mode is used for authentication and on-premises gateway is used, then SP should be the gateway admin.
44 |
45 | #### Supported browsers:
46 |
47 | 1. Google Chrome
48 |
49 | 2. Microsoft Edge
50 |
51 | 3. Mozilla Firefox
52 |
53 | ### Important
54 |
55 | For security reasons, in a real world application, passwords and secrets should not be stored in config files. Instead, consider securing your credentials with an application such as Key Vault.
56 |
--------------------------------------------------------------------------------
/Python/Encrypt credentials/requirements.txt:
--------------------------------------------------------------------------------
1 | cryptography==3.4.6
2 | Flask==2.1.2
3 | msal==1.9.0
4 | requests==2.25.1
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ---
2 | topic: sample
3 | languages:
4 | - csharp
5 | - js
6 | - python
7 | - java
8 | - ts
9 | - powershell
10 | products:
11 | - power-bi
12 | - dotnet-core
13 | - dotnet
14 | - node-js
15 | - react
16 | - flask
17 | ---
18 |
19 | [](https://powerbi.visualstudio.com/Embedded/_build/latest?definitionId=2824&branchName=master)
20 |
21 | This repository contains Power BI Embedded solutions in 5 different frameworks to suit different scenarios as per requirements.
22 | In addition, it has samples for calling the Power BI REST APIs using PowerShell.
23 |
24 |
25 | **Available solutions for embedding Power BI content:**
26 | * Embed for your customers - aka App Owns Data
27 | * .NET Framework
28 | * .NET Core
29 | * Python
30 | * Java
31 | * Node JS
32 | * Embed for your organization - aka User Owns Data
33 | * .NET Framework
34 | * .NET Core
35 | * React TS
36 |
37 | Solutions for encrypting credentials and updating data sources are available in the following frameworks:
38 | * .NET Core
39 | * Python
40 | * Node JS
41 |
42 |
43 | > **Note:**
44 | > 1. README.md files specific to samples are present in their respective folders.
45 | > 2. Before running the samples on a Windows system, ensure that the length of their path location is not exceeding the [limit of 260 characters](https://docs.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation).
46 |
47 | [Power BI Developer documentation](https://docs.microsoft.com/en-us/power-bi/developer/)
48 |
49 | ## Support
50 |
51 | - **Feature Requests:** Submit your ideas and suggestions to the [Fabric Ideas Portal](https://ideas.fabric.microsoft.com/), where you can also vote on ideas from other developers.
52 | - **Bug Reports and Technical Assistance:** Visit the [Fabric Developer Community Forum](https://community.fabric.microsoft.com/t5/Developer/bd-p/Developer). Our team and community experts are ready to assist you.
53 | - **Additional Support:** Contact your account manager or reach out to the [Fabric Support Team](https://support.fabric.microsoft.com/en-us/support/).
--------------------------------------------------------------------------------
/React-TS/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | node_modules
5 | .pnp
6 | .pnp.js
7 |
8 | # testing
9 | coverage
10 |
11 | # production
12 | build
13 |
14 | # misc
15 | .DS_Store
16 | .env.local
17 | .env.development.local
18 | .env.test.local
19 | .env.production.local
20 |
21 | npm-debug.log*
22 | yarn-debug.log*
23 | yarn-error.log*
24 |
--------------------------------------------------------------------------------
/React-TS/Embed for your organization/CloudConfigs/Power BI Global/Config.ts:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------------
2 | // Copyright (c) Microsoft Corporation.
3 | // Licensed under the MIT license.
4 | // ----------------------------------------------------------------------------
5 |
6 | // Refer https://aka.ms/PowerBIPermissions for complete list of Power BI scopes
7 |
8 | // Replace this config with the one in the Config.ts file for sovereign cloud
9 |
10 | // URL used for initiating authorization request
11 | export const authorityUrl: string = "https://login.microsoftonline.com/common/";
12 |
13 | // End point URL for Power BI API
14 | export const powerBiApiUrl: string = "https://api.powerbi.com";
15 |
16 | // Scope for securing access token
17 | export const scopeBase: string[] = ["https://analysis.windows.net/powerbi/api/Report.Read.All"];
--------------------------------------------------------------------------------
/React-TS/Embed for your organization/CloudConfigs/Power BI US Government/Config.ts:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------------
2 | // Copyright (c) Microsoft Corporation.
3 | // Licensed under the MIT license.
4 | // ----------------------------------------------------------------------------
5 |
6 | // Refer https://aka.ms/PowerBIPermissions for complete list of Power BI scopes
7 |
8 | // Replace this config with the one in the Config.ts file for sovereign cloud
9 |
10 | // URL used for initiating authorization request
11 | export const authorityUrl: string = "https://login.microsoftonline.com/common/";
12 |
13 | // End point URL for Power BI API
14 | export const powerBiApiUrl: string = "https://api.powerbigov.us/";
15 |
16 | // Scope for securing access token
17 | export const scopeBase: string[] = ["https://analysis.usgovcloudapi.net/powerbi/api/Report.Read.All"];
--------------------------------------------------------------------------------
/React-TS/Embed for your organization/CloudConfigs/Power BI in Germany/Config.ts:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------------
2 | // Copyright (c) Microsoft Corporation.
3 | // Licensed under the MIT license.
4 | // ----------------------------------------------------------------------------
5 |
6 | // Refer https://aka.ms/PowerBIPermissions for complete list of Power BI scopes
7 |
8 | // Replace this config with the one in the Config.ts file for sovereign cloud
9 |
10 | // URL used for initiating authorization request
11 | export const authorityUrl: string = "https://login.microsoftonline.de/common/";
12 |
13 | // End point URL for Power BI API
14 | export const powerBiApiUrl: string = "https://api.powerbi.de/";
15 |
16 | // Scope for securing access token
17 | export const scopeBase: string[] = ["https://analysis.cloudapi.de/powerbi/api/Report.Read.All"];
--------------------------------------------------------------------------------
/React-TS/Embed for your organization/CloudConfigs/Power BI operated by 21Vianet in China/Config.ts:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------------
2 | // Copyright (c) Microsoft Corporation.
3 | // Licensed under the MIT license.
4 | // ----------------------------------------------------------------------------
5 |
6 | // Refer https://aka.ms/PowerBIPermissions for complete list of Power BI scopes
7 |
8 | // Replace this config with the one in the Config.ts file for sovereign cloud
9 |
10 | // URL used for initiating authorization request
11 | export const authorityUrl: string = "https://login.chinacloudapi.cn/common/";
12 |
13 | // End point URL for Power BI API
14 | export const powerBiApiUrl: string = "https://api.powerbi.cn/";
15 |
16 | // Scope for securing access token
17 | export const scopeBase: string[] = ["https://analysis.chinacloudapi.cn/powerbi/api/Report.Read.All"];
--------------------------------------------------------------------------------
/React-TS/Embed for your organization/UserOwnsData/.eslintrc.js:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------------
2 | // Copyright (c) Microsoft Corporation.
3 | // Licensed under the MIT license.
4 | // ----------------------------------------------------------------------------
5 |
6 | module.exports = {
7 | parser: "@typescript-eslint/parser", // Specifies the ESLint parser
8 | extends: [
9 | "plugin:react/recommended", // Uses the recommended rules from @eslint-plugin-react
10 | "plugin:@typescript-eslint/recommended" // Uses the recommended rules from @typescript-eslint/eslint-plugin
11 | ],
12 | parserOptions: {
13 | ecmaFeatures: {
14 | jsx: true // Allows for the parsing of JSX
15 | }
16 | },
17 | rules: {
18 | '@typescript-eslint/no-this-alias': [
19 | 'error',
20 | {
21 | allowDestructuring: true, // Allow `const { props, state } = this`; false by default
22 | allowedNames: ['thisObj'], // Allow `const self = this`; `[]` by default
23 | },
24 | ],
25 | '@typescript-eslint/no-empty-interface': [
26 | 'error',
27 | {
28 | allowSingleExtends: true
29 | }
30 | ]
31 | },
32 | settings: {
33 | react: {
34 | version: "detect" // Tells eslint-plugin-react to automatically detect the version of React to use
35 | }
36 | }
37 | };
--------------------------------------------------------------------------------
/React-TS/Embed for your organization/UserOwnsData/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "powerbi-embedded-sample",
3 | "version": "1.0.0",
4 | "private": true,
5 | "dependencies": {
6 | "@azure/msal-browser": "^3.7.1",
7 | "@azure/msal-react": "^2.0.10",
8 | "@types/react": "^16.9.23",
9 | "@types/react-dom": "^16.9.5",
10 | "powerbi-client": "^2.22.4",
11 | "react": "^16.13.0",
12 | "react-app-polyfill": "^1.0.6",
13 | "react-dom": "^16.13.0",
14 | "typescript": "^5.3.3"
15 | },
16 | "scripts": {
17 | "start": "react-scripts start",
18 | "build": "react-scripts build",
19 | "lint": "eslint **/*.{ts,tsx} --quiet --fix"
20 | },
21 | "eslintConfig": {
22 | "extends": "react-app"
23 | },
24 | "browserslist": {
25 | "production": [
26 | ">0.2%",
27 | "not dead",
28 | "not op_mini all"
29 | ],
30 | "development": [
31 | "last 1 chrome version",
32 | "last 1 firefox version",
33 | "last 1 safari version"
34 | ]
35 | },
36 | "devDependencies": {
37 | "@typescript-eslint/eslint-plugin": "^6.20.0",
38 | "@typescript-eslint/parser": "^6.20.0",
39 | "eslint": "^8.56.0",
40 | "eslint-plugin-react": "^7.19.0",
41 | "object-path": ">=0.11.5",
42 | "react-scripts": "^5.0.1"
43 | },
44 | "overrides": {
45 | "typescript": "^5.3.3"
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/React-TS/Embed for your organization/UserOwnsData/public/index.css:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Microsoft Corporation.
2 | Licensed under the MIT license. */
3 |
4 | #root {
5 | padding-left: 20vw;
6 | padding-top: 5%;
7 | width: 60vw;
8 | }
9 |
10 | @media only screen and (max-width: 1333.33px) {
11 | #root {
12 | padding-left: calc((100vw - 800px)/2);
13 | }
14 | }
15 |
16 | header {
17 | padding-left: 1%;
18 | padding-right: 1%;
19 | padding-top: 2%;
20 | }
21 |
22 | #title {
23 | color: #2A22F0;
24 | float: left;
25 | font: Lighter 30px Segoe UI;
26 | }
27 |
28 | #welcome {
29 | color: #2C2C2C;
30 | padding-top: 10px;
31 | text-align: right;
32 | }
33 |
--------------------------------------------------------------------------------
/React-TS/Embed for your organization/UserOwnsData/public/index.html:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | Power BI Embedded sample
13 |
14 |
15 |
16 |
17 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/React-TS/Embed for your organization/UserOwnsData/src/App.css:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Microsoft Corporation.
2 | Licensed under the MIT license. */
3 |
4 | #reportContainer {
5 | background: #EAEAEA;
6 | color: #6E6E6E;
7 | font: Lighter 40px Segoe UI;
8 | height: calc(0.5625 * 65vw); /* 16:9 aspect ratio */
9 | min-width: 800px;
10 | text-align: center;
11 | width: 100%;
12 | }
13 |
14 | @media only screen and (max-width: 1333.33px) {
15 | #reportContainer {
16 | height: calc(0.5625 * 870px); /* 16:9 aspect ratio */
17 | }
18 | }
19 |
20 | iframe {
21 | border: none;
22 | }
23 |
--------------------------------------------------------------------------------
/React-TS/Embed for your organization/UserOwnsData/src/Config.ts:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------------
2 | // Copyright (c) Microsoft Corporation.
3 | // Licensed under the MIT license.
4 | // ----------------------------------------------------------------------------
5 |
6 | /* eslint-disable @typescript-eslint/no-inferrable-types */
7 |
8 | // Scope Base of AAD app. Use the below configuration to use all the permissions provided in the AAD app through Azure portal.
9 | // Refer https://aka.ms/PowerBIPermissions for complete list of Power BI scopes
10 |
11 | // URL used for initiating authorization request
12 | export const authorityUrl: string = "https://login.microsoftonline.com/";
13 |
14 | // End point URL for Power BI API
15 | export const powerBiApiUrl: string = "https://api.powerbi.com/";
16 |
17 | // Scope for securing access token
18 | export const scopeBase: string[] = ["https://analysis.windows.net/powerbi/api/Report.Read.All"];
19 |
20 | // Client Id (Application Id) of the AAD app.
21 | export const clientId: string = "";
22 |
23 | // Id of the workspace where the report is hosted
24 | export const workspaceId: string = "";
25 |
26 | // Id of the report to be embedded
27 | export const reportId: string = "";
28 |
29 | // Directory (tenant) ID of the AAD app
30 | export const tenantId: string = "";
--------------------------------------------------------------------------------
/React-TS/Embed for your organization/UserOwnsData/src/index.tsx:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------------------------------
2 | // Copyright (c) Microsoft Corporation.
3 | // Licensed under the MIT license.
4 | // ----------------------------------------------------------------------------
5 |
6 | import { PublicClientApplication } from "@azure/msal-browser";
7 | import { MsalProvider } from "@azure/msal-react";
8 | import 'react-app-polyfill/ie11';
9 | import 'react-app-polyfill/stable';
10 | import React from 'react';
11 | import ReactDOM from 'react-dom';
12 |
13 | import App from './App';
14 | import * as config from "./Config";
15 |
16 | const msalInstanceProvider = new PublicClientApplication(generateMsalConfig());
17 |
18 | ReactDOM.render(
19 |
20 |
21 | ,
22 | document.getElementById('root'));
23 |
24 | // Refer https://docs.microsoft.com/en-us/azure/active-directory/develop/tutorial-v2-react#configure-your-javascript-spa
25 | function generateMsalConfig() {
26 | const msalConfig = {
27 | auth: {
28 | clientId: config.clientId,
29 | authority: `${config.authorityUrl}${config.tenantId}`,
30 | redirectUri: "http://localhost:3000",
31 | },
32 | cache: {
33 | cacheLocation: "sessionStorage", // This configures where your cache will be stored
34 | storeAuthStateInCookie: false, // Set this to "true" if you are having issues on IE11 or Edge
35 | }
36 | };
37 |
38 | return msalConfig;
39 | }
--------------------------------------------------------------------------------
/React-TS/Embed for your organization/UserOwnsData/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "lib": [
5 | "dom",
6 | "dom.iterable",
7 | "esnext"
8 | ],
9 | "allowJs": true,
10 | "skipLibCheck": true,
11 | "esModuleInterop": true,
12 | "allowSyntheticDefaultImports": true,
13 | "strict": true,
14 | "forceConsistentCasingInFileNames": true,
15 | "module": "esnext",
16 | "moduleResolution": "node",
17 | "resolveJsonModule": true,
18 | "isolatedModules": true,
19 | "noEmit": true,
20 | "jsx": "react",
21 | "suppressImplicitAnyIndexErrors": true
22 | },
23 | "include": [
24 | "src"
25 | ]
26 | }
27 |
--------------------------------------------------------------------------------
/React-TS/LICENSE.md:
--------------------------------------------------------------------------------
1 | |NPM Package | License |
2 | |:--------------- |:-------------------------------------------------------------------------------------------------:|
3 | |@types/react |[MIT](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/LICENSE) |
4 | |@types/react-dom |[MIT](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/LICENSE) |
5 | |@types/bluebird |[MIT](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/LICENSE) |
6 | |bluebird |[MIT](https://github.com/petkaantonov/bluebird/blob/master/LICENSE) |
7 | |eslint |[MIT](https://github.com/eslint/eslint/blob/master/LICENSE) |
8 | |eslint-plugin-react|[MIT](https://github.com/yannickcr/eslint-plugin-react/blob/master/LICENSE) |
9 | |msal |[MIT](https://github.com/AzureAD/microsoft-authentication-library-for-js#readme) |
10 | |powerbi-client |[MIT](https://github.com/microsoft/PowerBI-JavaScript/blob/master/LICENSE.txt) |
11 | |react |[MIT](https://github.com/facebook/react/blob/master/LICENSE) |
12 | |react-app-polyfill |[MIT](https://github.com/facebook/create-react-app/blob/master/packages/react-app-polyfill/LICENSE)|
13 | |react-scripts |[MIT](https://github.com/facebook/create-react-app/blob/master/packages/react-scripts/LICENSE) |
14 | |typescript |[Apache-2.0](https://github.com/microsoft/TypeScript/blob/master/LICENSE.txt) |
--------------------------------------------------------------------------------