eionet2-dashboard 3.1.7 → 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.nvmrc +1 -0
- package/.vscode/launch.json +1 -0
- package/.vscode/settings.json +1 -2
- package/.vscode/tasks.json +1 -1
- package/CHANGELOG.md +14 -1
- package/Jenkinsfile +2 -2
- package/aad.manifest.json +118 -114
- package/api/extensions.csproj +1 -2
- package/api/getGraphData/function.json +1 -6
- package/api/getGraphData/index.js +62 -63
- package/api/host.json +1 -1
- package/api/package-lock.json +479 -1353
- package/api/package.json +8 -4
- package/env/.env.Prod_EEA +1 -1
- package/env/.env.dev +2 -1
- package/package.json +1 -1
- package/tabs/.env.teamsfx.dev +1 -0
- package/tabs/eslint.config.mjs +69 -0
- package/tabs/package-lock.json +21626 -13872
- package/tabs/package.json +58 -49
- package/tabs/public/auth-end.html +1 -1
- package/tabs/public/auth-start.html +3 -3
- package/tabs/src/components/App.jsx +38 -16
- package/tabs/src/components/Tab.jsx +8 -4
- package/tabs/src/components/Tab.scss +8 -8
- package/tabs/src/components/activity/activity.scss +8 -8
- package/tabs/src/components/lib/useTeamsAuth.js +87 -0
- package/tabs/src/components/my_country/my_country.scss +2 -2
- package/tabs/src/components/self_service/UserEdit.jsx +1 -1
- package/tabs/src/components/self_service/UserEdit.scss +5 -5
- package/tabs/src/data/apiProvider.js +23 -10
- package/tabs/src/data/provider.js +1 -1
- package/tabs/src/data/selfServiceSharepointProvider.js +1 -1
- package/tabs/src/data/sharepointProvider.js +1 -1
- package/tabs/src/index.css +0 -1
- package/tabs/src/index.jsx +8 -2
- package/tabs/yarn.lock +6453 -5770
- package/teamsapp.local.yml +10 -9
- package/teamsapp.yml +9 -9
- package/templates/azure/provision/function.bicep +16 -6
- package/tabs/src/components/lib/useGraph.js +0 -39
- package/tabs/src/components/lib/useTeamsFx.js +0 -55
package/.nvmrc
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
24
|
package/.vscode/launch.json
CHANGED
package/.vscode/settings.json
CHANGED
package/.vscode/tasks.json
CHANGED
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
},
|
|
22
22
|
"args": {
|
|
23
23
|
"prerequisites": [
|
|
24
|
-
"nodejs", // Validate if Node.js is installed.
|
|
24
|
+
//"nodejs", // Validate if Node.js is installed.
|
|
25
25
|
"m365Account", // Sign-in prompt for Microsoft 365 account, then validate if the account enables the sideloading permission.
|
|
26
26
|
"portOccupancy" // Validate available ports to ensure those debug ones are not occupied.
|
|
27
27
|
],
|
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,20 @@ All notable changes to this project will be documented in this file. Dates are d
|
|
|
4
4
|
|
|
5
5
|
Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
|
6
6
|
|
|
7
|
+
### [3.2.0](https://github.com/eea/eionet2-dashboard/compare/3.1.7...3.2.0) - 18 February 2026
|
|
8
|
+
|
|
9
|
+
#### :bug: Bug Fixes
|
|
10
|
+
|
|
11
|
+
- fix: email filtering( Refs #297435) [Mihai Nicolae - [`a0ea6d0`](https://github.com/eea/eionet2-dashboard/commit/a0ea6d014642868e3ac7cb2ef7462408b2d11bbd)]
|
|
12
|
+
|
|
13
|
+
#### :house: Internal changes
|
|
14
|
+
|
|
15
|
+
- chore: build fix [Mihai Nicolae - [`0e2ec2c`](https://github.com/eea/eionet2-dashboard/commit/0e2ec2c1ce3f8e92a4d89d8aef6ff0fcefb2c7c3)]
|
|
16
|
+
- chore: format [Mihai Nicolae - [`df7b3e5`](https://github.com/eea/eionet2-dashboard/commit/df7b3e54cf5c9bd97a2e87477259d7cebef126d3)]
|
|
17
|
+
- chore: formatting [Mihai Nicolae - [`e85e1cb`](https://github.com/eea/eionet2-dashboard/commit/e85e1cb927ac9adeaf4ae853dbb300f13cf6c75a)]
|
|
18
|
+
- chore: node build version [Mihai Nicolae - [`cc21733`](https://github.com/eea/eionet2-dashboard/commit/cc21733609aa8a6749ad1ba00424690c41d659ae)]
|
|
19
|
+
- chore: build fix [Mihai Nicolae - [`328bc71`](https://github.com/eea/eionet2-dashboard/commit/328bc71f4d3677d86b912e1d6f1e4d01f193f6c2)]
|
|
20
|
+
|
|
7
21
|
### [3.1.7](https://github.com/eea/eionet2-dashboard/compare/3.1.4...3.1.7) - 6 February 2026
|
|
8
22
|
|
|
9
23
|
#### :rocket: New Features
|
|
@@ -20,7 +34,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
|
|
20
34
|
#### :bug: Bug Fixes
|
|
21
35
|
|
|
22
36
|
- fix: correct email filtering (Refs #297435) [Mihai Nicolae - [`469a593`](https://github.com/eea/eionet2-dashboard/commit/469a593e71bf153e5ecc6c7d022ffeeb0fe7284d)]
|
|
23
|
-
- fix: send correct notification [Mihai Nicolae - [`2d422b9`](https://github.com/eea/eionet2-dashboard/commit/2d422b9defaf23bd430561fb65f86d2dcc7954b4)]
|
|
24
37
|
|
|
25
38
|
#### :house: Internal changes
|
|
26
39
|
|
package/Jenkinsfile
CHANGED
|
@@ -5,7 +5,7 @@ pipeline {
|
|
|
5
5
|
environment {
|
|
6
6
|
GIT_NAME = "eionet2-dashboard"
|
|
7
7
|
SONARQUBE_TAGS = "eionet2"
|
|
8
|
-
PATH = "${tool '
|
|
8
|
+
PATH = "${tool 'NodeJS24'}/bin:${tool 'SonarQubeScanner'}/bin:$PATH"
|
|
9
9
|
}
|
|
10
10
|
stages{
|
|
11
11
|
|
|
@@ -37,7 +37,7 @@ pipeline {
|
|
|
37
37
|
steps {
|
|
38
38
|
script{
|
|
39
39
|
checkout scm
|
|
40
|
-
tool '
|
|
40
|
+
tool 'NodeJS24'
|
|
41
41
|
tool 'SonarQubeScanner'
|
|
42
42
|
sh "cd tabs; yarn install"
|
|
43
43
|
}
|
package/aad.manifest.json
CHANGED
|
@@ -1,133 +1,137 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
"
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
"
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
"resourceAccess": [
|
|
23
|
-
{
|
|
24
|
-
"id": "User.Read.All",
|
|
25
|
-
"type": "Role"
|
|
26
|
-
},
|
|
27
|
-
{
|
|
28
|
-
"id": "Sites.Read.All",
|
|
29
|
-
"type": "Role"
|
|
30
|
-
},
|
|
31
|
-
{
|
|
32
|
-
"id": "OnlineMeetings.Read.All",
|
|
33
|
-
"type": "Role"
|
|
34
|
-
},
|
|
35
|
-
{
|
|
36
|
-
"id": "User.Read",
|
|
37
|
-
"type": "Scope"
|
|
38
|
-
},
|
|
39
|
-
{
|
|
40
|
-
"id": "Mail.Send",
|
|
41
|
-
"type": "Role"
|
|
42
|
-
},
|
|
43
|
-
{
|
|
44
|
-
"id": "User.ReadWrite.All",
|
|
45
|
-
"type": "Role"
|
|
46
|
-
},
|
|
47
|
-
{
|
|
48
|
-
"id": "Sites.ReadWrite.All",
|
|
49
|
-
"type": "Role"
|
|
50
|
-
}
|
|
51
|
-
]
|
|
52
|
-
}
|
|
53
|
-
],
|
|
54
|
-
"oauth2Permissions": [
|
|
55
|
-
{
|
|
56
|
-
"adminConsentDescription": "Allows Teams to call the app's web APIs as the current user.",
|
|
57
|
-
"adminConsentDisplayName": "Teams can access app's web APIs",
|
|
58
|
-
"id": "${{AAD_APP_ACCESS_AS_USER_PERMISSION_ID}}",
|
|
59
|
-
"isEnabled": true,
|
|
60
|
-
"type": "User",
|
|
61
|
-
"userConsentDescription": "Enable Teams to call this app's web APIs with the same rights that you have",
|
|
62
|
-
"userConsentDisplayName": "Teams can access app's web APIs and make requests on your behalf",
|
|
63
|
-
"value": "access_as_user"
|
|
64
|
-
}
|
|
2
|
+
"id": "${{AAD_APP_OBJECT_ID}}",
|
|
3
|
+
"appId": "${{AAD_APP_CLIENT_ID}}",
|
|
4
|
+
"displayName": "${{CONFIG__MANIFEST__APPNAME__SHORT}}-aad",
|
|
5
|
+
"identifierUris": [
|
|
6
|
+
"api://${{PROVISIONOUTPUT__FRONTENDHOSTINGOUTPUT__DOMAIN}}/${{AAD_APP_CLIENT_ID}}"
|
|
7
|
+
],
|
|
8
|
+
"signInAudience": "AzureADMyOrg",
|
|
9
|
+
"api": {
|
|
10
|
+
"requestedAccessTokenVersion": 2,
|
|
11
|
+
"oauth2PermissionScopes": [
|
|
12
|
+
{
|
|
13
|
+
"adminConsentDescription": "Allows Teams to call the app's web APIs as the current user.",
|
|
14
|
+
"adminConsentDisplayName": "Teams can access app's web APIs",
|
|
15
|
+
"id": "${{AAD_APP_ACCESS_AS_USER_PERMISSION_ID}}",
|
|
16
|
+
"isEnabled": true,
|
|
17
|
+
"type": "User",
|
|
18
|
+
"userConsentDescription": "Enable Teams to call this app's web APIs with the same rights that you have",
|
|
19
|
+
"userConsentDisplayName": "Teams can access app's web APIs and make requests on your behalf",
|
|
20
|
+
"value": "access_as_user"
|
|
21
|
+
}
|
|
65
22
|
],
|
|
66
23
|
"preAuthorizedApplications": [
|
|
24
|
+
{
|
|
25
|
+
"appId": "1fec8e78-bce4-4aaf-ab1b-5451cc387264",
|
|
26
|
+
"delegatedPermissionIds": [
|
|
27
|
+
"${{AAD_APP_ACCESS_AS_USER_PERMISSION_ID}}"
|
|
28
|
+
]
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"appId": "5e3ce6c0-2b1f-4285-8d4b-75ee78787346",
|
|
32
|
+
"delegatedPermissionIds": [
|
|
33
|
+
"${{AAD_APP_ACCESS_AS_USER_PERMISSION_ID}}"
|
|
34
|
+
]
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"appId": "d3590ed6-52b3-4102-aeff-aad2292ab01c",
|
|
38
|
+
"delegatedPermissionIds": [
|
|
39
|
+
"${{AAD_APP_ACCESS_AS_USER_PERMISSION_ID}}"
|
|
40
|
+
]
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"appId": "00000002-0000-0ff1-ce00-000000000000",
|
|
44
|
+
"delegatedPermissionIds": [
|
|
45
|
+
"${{AAD_APP_ACCESS_AS_USER_PERMISSION_ID}}"
|
|
46
|
+
]
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"appId": "bc59ab01-8403-45c6-8796-ac3ef710b3e3",
|
|
50
|
+
"delegatedPermissionIds": [
|
|
51
|
+
"${{AAD_APP_ACCESS_AS_USER_PERMISSION_ID}}"
|
|
52
|
+
]
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"appId": "0ec893e0-5785-4de6-99da-4ed124e5296c",
|
|
56
|
+
"delegatedPermissionIds": [
|
|
57
|
+
"${{AAD_APP_ACCESS_AS_USER_PERMISSION_ID}}"
|
|
58
|
+
]
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
"appId": "4765445b-32c6-49b0-83e6-1d93765276ca",
|
|
62
|
+
"delegatedPermissionIds": [
|
|
63
|
+
"${{AAD_APP_ACCESS_AS_USER_PERMISSION_ID}}"
|
|
64
|
+
]
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
"appId": "4345a7b9-9a63-4910-a426-35363201d503",
|
|
68
|
+
"delegatedPermissionIds": [
|
|
69
|
+
"${{AAD_APP_ACCESS_AS_USER_PERMISSION_ID}}"
|
|
70
|
+
]
|
|
71
|
+
}
|
|
72
|
+
]
|
|
73
|
+
},
|
|
74
|
+
"info": {},
|
|
75
|
+
"optionalClaims": {
|
|
76
|
+
"idToken": [],
|
|
77
|
+
"accessToken": [
|
|
78
|
+
{
|
|
79
|
+
"name": "idtyp",
|
|
80
|
+
"source": null,
|
|
81
|
+
"essential": false,
|
|
82
|
+
"additionalProperties": []
|
|
83
|
+
}
|
|
84
|
+
],
|
|
85
|
+
"saml2Token": []
|
|
86
|
+
},
|
|
87
|
+
"publicClient": {
|
|
88
|
+
"redirectUris": []
|
|
89
|
+
},
|
|
90
|
+
"requiredResourceAccess": [
|
|
91
|
+
{
|
|
92
|
+
"resourceAppId": "00000003-0000-0000-c000-000000000000",
|
|
93
|
+
"resourceAccess": [
|
|
67
94
|
{
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
"${{AAD_APP_ACCESS_AS_USER_PERMISSION_ID}}"
|
|
71
|
-
]
|
|
72
|
-
},
|
|
73
|
-
{
|
|
74
|
-
"appId": "5e3ce6c0-2b1f-4285-8d4b-75ee78787346",
|
|
75
|
-
"permissionIds": [
|
|
76
|
-
"${{AAD_APP_ACCESS_AS_USER_PERMISSION_ID}}"
|
|
77
|
-
]
|
|
95
|
+
"id": "df021288-bdef-4463-88db-98f22de89214",
|
|
96
|
+
"type": "Role"
|
|
78
97
|
},
|
|
79
98
|
{
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
"${{AAD_APP_ACCESS_AS_USER_PERMISSION_ID}}"
|
|
83
|
-
]
|
|
99
|
+
"id": "332a536c-c7ef-4017-ab91-336970924f0d",
|
|
100
|
+
"type": "Role"
|
|
84
101
|
},
|
|
85
102
|
{
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
"${{AAD_APP_ACCESS_AS_USER_PERMISSION_ID}}"
|
|
89
|
-
]
|
|
103
|
+
"id": "c1684f21-1984-47fa-9d61-2dc8c296bb70",
|
|
104
|
+
"type": "Role"
|
|
90
105
|
},
|
|
91
106
|
{
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
"${{AAD_APP_ACCESS_AS_USER_PERMISSION_ID}}"
|
|
95
|
-
]
|
|
107
|
+
"id": "e1fe6dd8-ba31-4d61-89e7-88639da4683d",
|
|
108
|
+
"type": "Scope"
|
|
96
109
|
},
|
|
97
110
|
{
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
"${{AAD_APP_ACCESS_AS_USER_PERMISSION_ID}}"
|
|
101
|
-
]
|
|
111
|
+
"id": "b633e1c5-b582-4048-a93e-9f11b44c7e96",
|
|
112
|
+
"type": "Role"
|
|
102
113
|
},
|
|
103
114
|
{
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
"${{AAD_APP_ACCESS_AS_USER_PERMISSION_ID}}"
|
|
107
|
-
]
|
|
115
|
+
"id": "741f803b-c850-494e-b5df-cde7c675a1ca",
|
|
116
|
+
"type": "Role"
|
|
108
117
|
},
|
|
109
118
|
{
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
"${{AAD_APP_ACCESS_AS_USER_PERMISSION_ID}}"
|
|
113
|
-
]
|
|
119
|
+
"id": "9492366f-7969-46a4-8d15-ed1a20078fff",
|
|
120
|
+
"type": "Role"
|
|
114
121
|
}
|
|
122
|
+
]
|
|
123
|
+
}
|
|
124
|
+
],
|
|
125
|
+
"web": {
|
|
126
|
+
"redirectUris": [
|
|
127
|
+
"${{PROVISIONOUTPUT__FRONTENDHOSTINGOUTPUT__ENDPOINT}}/auth-end.html"
|
|
115
128
|
],
|
|
116
|
-
"
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
"
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
"type": "Web"
|
|
123
|
-
},
|
|
124
|
-
{
|
|
125
|
-
"url": "${{PROVISIONOUTPUT__FRONTENDHOSTINGOUTPUT__ENDPOINT}}/auth-end.html?clientId=${{AAD_APP_CLIENT_ID}}",
|
|
126
|
-
"type": "Spa"
|
|
127
|
-
},
|
|
128
|
-
{
|
|
129
|
-
"url": "${{PROVISIONOUTPUT__FRONTENDHOSTINGOUTPUT__ENDPOINT}}/blank-auth-end.html",
|
|
130
|
-
"type": "Spa"
|
|
131
|
-
}
|
|
129
|
+
"implicitGrantSettings": {}
|
|
130
|
+
},
|
|
131
|
+
"spa": {
|
|
132
|
+
"redirectUris": [
|
|
133
|
+
"${{PROVISIONOUTPUT__FRONTENDHOSTINGOUTPUT__ENDPOINT}}/auth-end.html?clientId=${{AAD_APP_CLIENT_ID}}",
|
|
134
|
+
"${{PROVISIONOUTPUT__FRONTENDHOSTINGOUTPUT__ENDPOINT}}/blank-auth-end.html"
|
|
132
135
|
]
|
|
133
|
-
}
|
|
136
|
+
}
|
|
137
|
+
}
|
package/api/extensions.csproj
CHANGED
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
<DefaultItemExcludes>**</DefaultItemExcludes>
|
|
6
6
|
</PropertyGroup>
|
|
7
7
|
<ItemGroup>
|
|
8
|
-
<PackageReference Include="Microsoft.Azure.WebJobs.Extensions.TeamsFx" Version="0.1.*" />
|
|
9
8
|
<PackageReference Include="Microsoft.Azure.WebJobs.Script.ExtensionsMetadataGenerator" Version="1.1.3" />
|
|
10
9
|
</ItemGroup>
|
|
11
|
-
</Project>
|
|
10
|
+
</Project>
|
|
@@ -1,26 +1,16 @@
|
|
|
1
1
|
require("isomorphic-fetch");
|
|
2
|
-
const
|
|
2
|
+
const { ConfidentialClientApplication } = require("@azure/msal-node");
|
|
3
|
+
const { Client } = require("@microsoft/microsoft-graph-client");
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
|
-
* This function handles requests from
|
|
6
|
-
* The HTTP request
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* This function initializes the teamsfx SDK with the configuration and calls these APIs:
|
|
10
|
-
* - OnBehalfOfUserCredential() - Construct credential with the received SSO token and initialized configuration.
|
|
11
|
-
* - getUserInfo() - Get the user's information from the received SSO token.
|
|
12
|
-
* - createMicrosoftGraphClient() - Get a graph client to access user's Microsoft 365 data.
|
|
13
|
-
*
|
|
14
|
-
* The response contains multiple message blocks constructed into a JSON object, including:
|
|
15
|
-
* - An echo of the request body.
|
|
16
|
-
* - The display name encoded in the SSO token.
|
|
17
|
-
* - Current user's Microsoft 365 profile if the user has consented.
|
|
6
|
+
* This function handles requests from the Teams tab client.
|
|
7
|
+
* The HTTP request must include a Teams SSO token in the Authorization header.
|
|
8
|
+
* This function performs OBO (on-behalf-of) to call Microsoft Graph.
|
|
18
9
|
*
|
|
19
10
|
* @param {Context} context - The Azure Functions context object.
|
|
20
11
|
* @param {HttpRequest} req - The HTTP request.
|
|
21
|
-
* @param {teamsfxContext} { [key: string]: any; } - The context generated by teamsfx binding.
|
|
22
12
|
*/
|
|
23
|
-
module.exports = async function (context, req
|
|
13
|
+
module.exports = async function (context, req) {
|
|
24
14
|
context.log("HTTP trigger function processed a request.");
|
|
25
15
|
|
|
26
16
|
// Initialize response.
|
|
@@ -33,72 +23,81 @@ module.exports = async function (context, req, teamsfxContext) {
|
|
|
33
23
|
res.body.receivedHTTPRequestBody = req.body || "";
|
|
34
24
|
|
|
35
25
|
|
|
36
|
-
//
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
26
|
+
// Prepare access token.
|
|
27
|
+
const authHeader = req.headers && (req.headers.authorization || req.headers.Authorization);
|
|
28
|
+
const accessToken = authHeader && authHeader.startsWith("Bearer ")
|
|
29
|
+
? authHeader.slice("Bearer ".length)
|
|
30
|
+
: null;
|
|
31
|
+
if (!accessToken) {
|
|
41
32
|
return {
|
|
42
|
-
status:
|
|
33
|
+
status: 400,
|
|
43
34
|
body: {
|
|
44
|
-
error: "
|
|
35
|
+
error: "No access token was found in request header. Expected Authorization: Bearer <token>.",
|
|
45
36
|
},
|
|
46
37
|
};
|
|
47
38
|
}
|
|
48
39
|
|
|
49
|
-
|
|
50
|
-
const
|
|
51
|
-
|
|
40
|
+
const method = req.method.toLowerCase();
|
|
41
|
+
const credentialType =
|
|
42
|
+
method !== "get" ? (req.body && req.body.credentialType) : req.query.credentialType;
|
|
43
|
+
const eTag = method == 'patch' ? req.body.eTag : undefined;
|
|
44
|
+
|
|
45
|
+
const tenantId = process.env.M365_TENANT_ID;
|
|
46
|
+
const clientId = process.env.M365_CLIENT_ID;
|
|
47
|
+
const clientSecret = process.env.M365_CLIENT_SECRET;
|
|
48
|
+
const authorityHost = process.env.M365_AUTHORITY_HOST || "https://login.microsoftonline.com";
|
|
49
|
+
const graphScopes = (process.env.GRAPH_SCOPES || "https://graph.microsoft.com/.default")
|
|
50
|
+
.split(/[,\s]+/)
|
|
51
|
+
.map((scope) => scope.trim())
|
|
52
|
+
.filter(Boolean);
|
|
53
|
+
|
|
54
|
+
if (!tenantId || !clientId || !clientSecret) {
|
|
52
55
|
return {
|
|
53
|
-
status:
|
|
56
|
+
status: 500,
|
|
54
57
|
body: {
|
|
55
|
-
error: "
|
|
58
|
+
error: "Missing required M365_* configuration for OBO.",
|
|
56
59
|
},
|
|
57
60
|
};
|
|
58
61
|
}
|
|
59
62
|
|
|
63
|
+
const msalClient = new ConfidentialClientApplication({
|
|
64
|
+
auth: {
|
|
65
|
+
clientId,
|
|
66
|
+
clientSecret,
|
|
67
|
+
authority: `${authorityHost}/${tenantId}`,
|
|
68
|
+
},
|
|
69
|
+
});
|
|
60
70
|
|
|
61
|
-
|
|
62
|
-
// Construct credential.
|
|
63
|
-
let credential;
|
|
64
|
-
const method = req.method.toLowerCase();
|
|
65
|
-
const credentialType = method != "get" ? req.body && req.body.credentialType : req.query.credentialType;
|
|
66
|
-
const eTag = method == 'patch' ? req.body.eTag : undefined;
|
|
67
71
|
try {
|
|
68
|
-
|
|
72
|
+
let tokenResult;
|
|
73
|
+
if (credentialType === "app") {
|
|
74
|
+
tokenResult = await msalClient.acquireTokenByClientCredential({
|
|
75
|
+
scopes: graphScopes,
|
|
76
|
+
});
|
|
77
|
+
} else {
|
|
78
|
+
tokenResult = await msalClient.acquireTokenOnBehalfOf({
|
|
79
|
+
oboAssertion: accessToken,
|
|
80
|
+
scopes: graphScopes,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (!tokenResult || !tokenResult.accessToken) {
|
|
69
85
|
return {
|
|
70
86
|
status: 500,
|
|
71
87
|
body: {
|
|
72
|
-
error:
|
|
88
|
+
error:
|
|
89
|
+
credentialType === "app"
|
|
90
|
+
? "Failed to obtain Graph access token via client credentials."
|
|
91
|
+
: "Failed to obtain Graph access token via OBO.",
|
|
73
92
|
},
|
|
74
93
|
};
|
|
75
94
|
}
|
|
76
95
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
break;
|
|
81
|
-
case ("app"):
|
|
82
|
-
credential = new teamsfx.M365TenantCredential();
|
|
83
|
-
break;
|
|
84
|
-
}
|
|
96
|
+
const graphClient = Client.init({
|
|
97
|
+
authProvider: (done) => done(null, tokenResult.accessToken),
|
|
98
|
+
});
|
|
85
99
|
|
|
86
|
-
|
|
87
|
-
context.log.error(e);
|
|
88
|
-
return {
|
|
89
|
-
status: 500,
|
|
90
|
-
body: {
|
|
91
|
-
error:
|
|
92
|
-
"Failed to obtain on-behalf-of credential using your accessToken. " +
|
|
93
|
-
"Ensure your function app is configured with the right Azure AD App registration.",
|
|
94
|
-
},
|
|
95
|
-
};
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
// Create a graph client to access user's Microsoft 365 data after user has consented.
|
|
99
|
-
try {
|
|
100
|
-
const graphClient = teamsfx.createMicrosoftGraphClient(credential);
|
|
101
|
-
graphClient.config.defaultVersion = 'beta';
|
|
100
|
+
//graphClient.config.defaultVersion = 'beta';
|
|
102
101
|
let path = "";
|
|
103
102
|
let result;
|
|
104
103
|
|
|
@@ -134,7 +133,7 @@ module.exports = async function (context, req, teamsfxContext) {
|
|
|
134
133
|
break;
|
|
135
134
|
}
|
|
136
135
|
|
|
137
|
-
if (result
|
|
136
|
+
if (result?.type == 'image/jpeg') {
|
|
138
137
|
res.headers = {
|
|
139
138
|
'Content-Type': 'image/jpeg',
|
|
140
139
|
}
|
|
@@ -147,8 +146,8 @@ module.exports = async function (context, req, teamsfxContext) {
|
|
|
147
146
|
|
|
148
147
|
} catch (e) {
|
|
149
148
|
return {
|
|
150
|
-
status: e.statusCode,
|
|
151
|
-
body: e.body
|
|
149
|
+
status: e.statusCode || e.status || 500,
|
|
150
|
+
body: e.body || { error: e.message },
|
|
152
151
|
};
|
|
153
152
|
}
|
|
154
153
|
|
package/api/host.json
CHANGED