eionet2-dashboard 1.4.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.
Files changed (111) hide show
  1. package/.fx/configs/azure.parameters.Prod_EEA.json +15 -0
  2. package/.fx/configs/azure.parameters.dev.json +15 -0
  3. package/.fx/configs/config.Prod_EEA.json +10 -0
  4. package/.fx/configs/config.dev.json +10 -0
  5. package/.fx/configs/projectSettings.json +83 -0
  6. package/.fx/states/state.Prod_EEA.json +47 -0
  7. package/.fx/states/state.dev.json +47 -0
  8. package/.vscode/launch.json +91 -0
  9. package/.vscode/settings.json +6 -0
  10. package/.vscode/tasks.json +63 -0
  11. package/CHANGELOG.md +140 -0
  12. package/Jenkinsfile +166 -0
  13. package/LICENSE.md +9 -0
  14. package/README.md +55 -0
  15. package/api/.funcignore +11 -0
  16. package/api/extensions.csproj +11 -0
  17. package/api/getGraphData/function.json +27 -0
  18. package/api/getGraphData/index.js +147 -0
  19. package/api/host.json +11 -0
  20. package/api/package-lock.json +1546 -0
  21. package/api/package.json +17 -0
  22. package/api/proxies.json +4 -0
  23. package/package.json +25 -0
  24. package/tabs/.env.teamsfx.Prod_EEA +11 -0
  25. package/tabs/.env.teamsfx.dev +11 -0
  26. package/tabs/.eslintrc.json +48 -0
  27. package/tabs/.prettierrc +7 -0
  28. package/tabs/.stylelintrc.json +6 -0
  29. package/tabs/babel.config.js +3 -0
  30. package/tabs/package-lock.json +15564 -0
  31. package/tabs/package.json +88 -0
  32. package/tabs/public/auth-end.html +76 -0
  33. package/tabs/public/auth-start.html +178 -0
  34. package/tabs/public/deploy.png +0 -0
  35. package/tabs/public/favicon.ico +0 -0
  36. package/tabs/public/hello.png +0 -0
  37. package/tabs/public/index.html +20 -0
  38. package/tabs/public/publish.png +0 -0
  39. package/tabs/src/components/App.jsx +36 -0
  40. package/tabs/src/components/CustomColumnResizeIcon.jsx +68 -0
  41. package/tabs/src/components/CustomDrawer.jsx +51 -0
  42. package/tabs/src/components/EventDialogTitle.jsx +29 -0
  43. package/tabs/src/components/HtmlBox.jsx +18 -0
  44. package/tabs/src/components/Privacy.jsx +17 -0
  45. package/tabs/src/components/ResizableGrid.jsx +44 -0
  46. package/tabs/src/components/Tab.jsx +477 -0
  47. package/tabs/src/components/Tab.scss +138 -0
  48. package/tabs/src/components/TabConfig.jsx +51 -0
  49. package/tabs/src/components/TabPanel.jsx +29 -0
  50. package/tabs/src/components/TermsOfUse.jsx +17 -0
  51. package/tabs/src/components/UnderConstruction.jsx +24 -0
  52. package/tabs/src/components/UserMenu.jsx +109 -0
  53. package/tabs/src/components/_variables.scss +10 -0
  54. package/tabs/src/components/activity/Activity.jsx +301 -0
  55. package/tabs/src/components/activity/ConsultationList.jsx +297 -0
  56. package/tabs/src/components/activity/EventList.jsx +463 -0
  57. package/tabs/src/components/activity/GroupsTags.jsx +26 -0
  58. package/tabs/src/components/activity/Reporting.jsx +13 -0
  59. package/tabs/src/components/activity/activity.scss +153 -0
  60. package/tabs/src/components/event_rating/EventRating.jsx +92 -0
  61. package/tabs/src/components/event_rating/EventRatingDialog.jsx +46 -0
  62. package/tabs/src/components/event_registration/Approval.jsx +80 -0
  63. package/tabs/src/components/event_registration/ApprovalDialog.jsx +30 -0
  64. package/tabs/src/components/event_registration/ApprovalList.jsx +62 -0
  65. package/tabs/src/components/event_registration/EventRegistration.jsx +214 -0
  66. package/tabs/src/components/lib/useData.js +33 -0
  67. package/tabs/src/components/lib/useGraph.js +39 -0
  68. package/tabs/src/components/lib/useTeamsFx.js +55 -0
  69. package/tabs/src/components/my_country/AtAGlance.jsx +151 -0
  70. package/tabs/src/components/my_country/CountryProgress.jsx +92 -0
  71. package/tabs/src/components/my_country/DataReporters.jsx +13 -0
  72. package/tabs/src/components/my_country/GroupView.jsx +54 -0
  73. package/tabs/src/components/my_country/GroupsBoard.jsx +52 -0
  74. package/tabs/src/components/my_country/IndicatorCard.jsx +60 -0
  75. package/tabs/src/components/my_country/ManagementBoard.jsx +109 -0
  76. package/tabs/src/components/my_country/MyCountry.jsx +186 -0
  77. package/tabs/src/components/my_country/ProgressGauge.jsx +125 -0
  78. package/tabs/src/components/my_country/ScientificCommittee.jsx +13 -0
  79. package/tabs/src/components/my_country/YearlyProgress.jsx +41 -0
  80. package/tabs/src/components/my_country/my_country.scss +81 -0
  81. package/tabs/src/components/publications/Publications.jsx +13 -0
  82. package/tabs/src/components/self_service/UserEdit.jsx +334 -0
  83. package/tabs/src/components/self_service/UserEdit.scss +107 -0
  84. package/tabs/src/data/apiProvider.js +153 -0
  85. package/tabs/src/data/constants.json +7 -0
  86. package/tabs/src/data/hooks/useConfiguration.js +18 -0
  87. package/tabs/src/data/icsHelper.js +38 -0
  88. package/tabs/src/data/messages.json +39 -0
  89. package/tabs/src/data/provider.js +199 -0
  90. package/tabs/src/data/selfServiceProvider.js +59 -0
  91. package/tabs/src/data/selfServiceSharepointProvider.js +68 -0
  92. package/tabs/src/data/sharepointProvider.js +729 -0
  93. package/tabs/src/data/validator.js +25 -0
  94. package/tabs/src/data/validator.test.js +9 -0
  95. package/tabs/src/index.css +16 -0
  96. package/tabs/src/index.jsx +6 -0
  97. package/tabs/src/static/images/teams-icon.svg +1 -0
  98. package/tabs/src/utils/uiHelper.js +6 -0
  99. package/templates/appPackage/aad.template.json +133 -0
  100. package/templates/appPackage/manifest.template.json +58 -0
  101. package/templates/appPackage/resources/color.png +0 -0
  102. package/templates/appPackage/resources/outline.png +0 -0
  103. package/templates/azure/config.bicep +27 -0
  104. package/templates/azure/main.bicep +20 -0
  105. package/templates/azure/provision/frontendHosting.bicep +23 -0
  106. package/templates/azure/provision/function.bicep +82 -0
  107. package/templates/azure/provision/identity.bicep +14 -0
  108. package/templates/azure/provision/simpleAuth.bicep +44 -0
  109. package/templates/azure/provision.bicep +58 -0
  110. package/templates/azure/teamsFx/function.bicep +76 -0
  111. package/templates/azure/teamsFx/simpleAuth.bicep +43 -0
@@ -0,0 +1,25 @@
1
+ let mandatoryText = 'Please fill out this field!';
2
+
3
+ export function validatePhone(value) {
4
+ if (value) {
5
+ let reg = new RegExp(/^-?[+0-9. -]+$/).test(value);
6
+ if (!reg) {
7
+ return 'Only numbers and characters +, -, . are allowed.';
8
+ }
9
+ }
10
+ }
11
+
12
+ export function validateName(value) {
13
+ if (!value) {
14
+ return mandatoryText;
15
+ }
16
+ if (value.length < 2) {
17
+ return 'Please enter at least 2 characters!';
18
+ }
19
+ }
20
+
21
+ export function validateMandatoryField(value) {
22
+ if ((Array.isArray(value) && !value.length) || !value) {
23
+ return mandatoryText;
24
+ }
25
+ }
@@ -0,0 +1,9 @@
1
+ const validator = require('./validator');
2
+
3
+ test('validateName', () => {
4
+ expect(validator.validateName('t')).toBe('Please enter at least 2 characters!');
5
+ });
6
+
7
+ test('validateMandatoryField-alwaysFail', () => {
8
+ expect(validator.validateMandatoryField('test')).toBe(undefined);
9
+ });
@@ -0,0 +1,16 @@
1
+ * {
2
+ box-sizing: border-box;
3
+ /* outline: 1px dashed #f00; */
4
+ }
5
+
6
+ body {
7
+ margin: 5em;
8
+ font-family: 'Roboto Flex', sans-serif;
9
+ -webkit-font-smoothing: antialiased;
10
+ -moz-osx-font-smoothing: grayscale;
11
+ background-color: #eeeeee;
12
+ }
13
+
14
+ .main {
15
+ background-color: white;
16
+ }
@@ -0,0 +1,6 @@
1
+ import React from 'react';
2
+ import ReactDOM from 'react-dom';
3
+ import App from './components/App';
4
+ import './index.css';
5
+
6
+ ReactDOM.render(<App />, document.getElementById('root'));
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="24px" height="24px"><path fill="#5059c9" d="M44,22v8c0,3.314-2.686,6-6,6s-6-2.686-6-6V20h10C43.105,20,44,20.895,44,22z M38,16 c2.209,0,4-1.791,4-4c0-2.209-1.791-4-4-4s-4,1.791-4,4C34,14.209,35.791,16,38,16z"/><path fill="#7b83eb" d="M35,22v11c0,5.743-4.841,10.356-10.666,9.978C19.019,42.634,15,37.983,15,32.657V20h18 C34.105,20,35,20.895,35,22z M25,17c3.314,0,6-2.686,6-6s-2.686-6-6-6s-6,2.686-6,6S21.686,17,25,17z"/><circle cx="25" cy="11" r="6" fill="#7b83eb"/><path d="M26,33.319V20H15v12.657c0,1.534,0.343,3.008,0.944,4.343h6.374C24.352,37,26,35.352,26,33.319z" opacity=".05"/><path d="M15,20v12.657c0,1.16,0.201,2.284,0.554,3.343h6.658c1.724,0,3.121-1.397,3.121-3.121V20H15z" opacity=".07"/><path d="M24.667,20H15v12.657c0,0.802,0.101,1.584,0.274,2.343h6.832c1.414,0,2.56-1.146,2.56-2.56V20z" opacity=".09"/><linearGradient id="DqqEodsTc8fO7iIkpib~Na" x1="4.648" x2="23.403" y1="14.648" y2="33.403" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#5961c3"/><stop offset="1" stop-color="#3a41ac"/></linearGradient><path fill="url(#DqqEodsTc8fO7iIkpib~Na)" d="M22,34H6c-1.105,0-2-0.895-2-2V16c0-1.105,0.895-2,2-2h16c1.105,0,2,0.895,2,2v16 C24,33.105,23.105,34,22,34z"/><path fill="#fff" d="M18.068,18.999H9.932v1.72h3.047v8.28h2.042v-8.28h3.047V18.999z"/></svg>
@@ -0,0 +1,6 @@
1
+ export function a11yProps(index) {
2
+ return {
3
+ id: `simple-tab-${index}`,
4
+ 'aria-controls': `simple-tabpanel-${index}`,
5
+ };
6
+ }
@@ -0,0 +1,133 @@
1
+ {
2
+ "id": "{{state.fx-resource-aad-app-for-teams.objectId}}",
3
+ "appId": "{{state.fx-resource-aad-app-for-teams.clientId}}",
4
+ "name": "{{config.manifest.appName.short}}-aad",
5
+ "accessTokenAcceptedVersion": 2,
6
+ "signInAudience": "AzureADMyOrg",
7
+ "optionalClaims": {
8
+ "idToken": [],
9
+ "accessToken": [
10
+ {
11
+ "name": "idtyp",
12
+ "source": null,
13
+ "essential": false,
14
+ "additionalProperties": []
15
+ }
16
+ ],
17
+ "saml2Token": []
18
+ },
19
+ "requiredResourceAccess": [
20
+ {
21
+ "resourceAppId": "Microsoft Graph",
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": "{{state.fx-resource-aad-app-for-teams.oauth2PermissionScopeId}}",
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
+ }
65
+ ],
66
+ "preAuthorizedApplications": [
67
+ {
68
+ "appId": "1fec8e78-bce4-4aaf-ab1b-5451cc387264",
69
+ "permissionIds": [
70
+ "{{state.fx-resource-aad-app-for-teams.oauth2PermissionScopeId}}"
71
+ ]
72
+ },
73
+ {
74
+ "appId": "5e3ce6c0-2b1f-4285-8d4b-75ee78787346",
75
+ "permissionIds": [
76
+ "{{state.fx-resource-aad-app-for-teams.oauth2PermissionScopeId}}"
77
+ ]
78
+ },
79
+ {
80
+ "appId": "d3590ed6-52b3-4102-aeff-aad2292ab01c",
81
+ "permissionIds": [
82
+ "{{state.fx-resource-aad-app-for-teams.oauth2PermissionScopeId}}"
83
+ ]
84
+ },
85
+ {
86
+ "appId": "00000002-0000-0ff1-ce00-000000000000",
87
+ "permissionIds": [
88
+ "{{state.fx-resource-aad-app-for-teams.oauth2PermissionScopeId}}"
89
+ ]
90
+ },
91
+ {
92
+ "appId": "bc59ab01-8403-45c6-8796-ac3ef710b3e3",
93
+ "permissionIds": [
94
+ "{{state.fx-resource-aad-app-for-teams.oauth2PermissionScopeId}}"
95
+ ]
96
+ },
97
+ {
98
+ "appId": "0ec893e0-5785-4de6-99da-4ed124e5296c",
99
+ "permissionIds": [
100
+ "{{state.fx-resource-aad-app-for-teams.oauth2PermissionScopeId}}"
101
+ ]
102
+ },
103
+ {
104
+ "appId": "4765445b-32c6-49b0-83e6-1d93765276ca",
105
+ "permissionIds": [
106
+ "{{state.fx-resource-aad-app-for-teams.oauth2PermissionScopeId}}"
107
+ ]
108
+ },
109
+ {
110
+ "appId": "4345a7b9-9a63-4910-a426-35363201d503",
111
+ "permissionIds": [
112
+ "{{state.fx-resource-aad-app-for-teams.oauth2PermissionScopeId}}"
113
+ ]
114
+ }
115
+ ],
116
+ "identifierUris": [
117
+ "{{state.fx-resource-aad-app-for-teams.applicationIdUris}}"
118
+ ],
119
+ "replyUrlsWithType": [
120
+ {
121
+ "url": "{{state.fx-resource-aad-app-for-teams.frontendEndpoint}}/auth-end.html",
122
+ "type": "Web"
123
+ },
124
+ {
125
+ "url": "{{state.fx-resource-aad-app-for-teams.frontendEndpoint}}/auth-end.html?clientId={{state.fx-resource-aad-app-for-teams.clientId}}",
126
+ "type": "Spa"
127
+ },
128
+ {
129
+ "url": "{{state.fx-resource-aad-app-for-teams.frontendEndpoint}}/blank-auth-end.html",
130
+ "type": "Spa"
131
+ }
132
+ ]
133
+ }
@@ -0,0 +1,58 @@
1
+ {
2
+ "$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.11/MicrosoftTeams.schema.json",
3
+ "manifestVersion": "1.11",
4
+ "version": "0.0.4",
5
+ "id": "{{state.fx-resource-appstudio.teamsAppId}}",
6
+ "packageName": "com.microsoft.teams.extension",
7
+ "developer": {
8
+ "name": "European Environment Agency",
9
+ "websiteUrl": "{{{state.fx-resource-frontend-hosting.endpoint}}}",
10
+ "privacyUrl": "{{{state.fx-resource-frontend-hosting.endpoint}}}/index.html#/privacy",
11
+ "termsOfUseUrl": "{{{state.fx-resource-frontend-hosting.endpoint}}}/index.html#/termsofuse"
12
+ },
13
+ "icons": {
14
+ "color": "resources/color.png",
15
+ "outline": "resources/outline.png"
16
+ },
17
+ "name": {
18
+ "short": "{{config.manifest.appName.short}}",
19
+ "full": "{{config.manifest.appName.full}}"
20
+ },
21
+ "description": {
22
+ "short": "Eionet Dashboard",
23
+ "full": "Available to all Eionet users and shows relevant country information & events and consultations"
24
+ },
25
+ "accentColor": "#FFFFFF",
26
+ "bots": [],
27
+ "composeExtensions": [],
28
+ "configurableTabs": [
29
+ {
30
+ "configurationUrl": "{{{state.fx-resource-frontend-hosting.endpoint}}}/index.html#/config",
31
+ "canUpdateConfiguration": true,
32
+ "scopes": [
33
+ "team",
34
+ "groupchat"
35
+ ]
36
+ }
37
+ ],
38
+ "staticTabs": [
39
+ {
40
+ "entityId": "dashboard",
41
+ "name": "Eionet2 Dashboard",
42
+ "contentUrl": "{{{state.fx-resource-frontend-hosting.endpoint}}}/index.html#/tab",
43
+ "websiteUrl": "{{{state.fx-resource-frontend-hosting.endpoint}}}/index.html#/tab",
44
+ "scopes": [
45
+ "personal"
46
+ ]
47
+ }
48
+ ],
49
+ "permissions": [
50
+ "identity",
51
+ "messageTeamMembers"
52
+ ],
53
+ "validDomains": [],
54
+ "webApplicationInfo": {
55
+ "id": "{{state.fx-resource-aad-app-for-teams.clientId}}",
56
+ "resource": "{{{state.fx-resource-aad-app-for-teams.applicationIdUris}}}"
57
+ }
58
+ }
@@ -0,0 +1,27 @@
1
+ @secure()
2
+ param provisionParameters object
3
+ param provisionOutputs object
4
+ var simpleAuthCurrentAppSettings = list('${provisionOutputs.simpleAuthOutput.value.webAppResourceId}/config/appsettings', '2021-02-01').properties
5
+
6
+ module teamsFxSimpleAuthConfig './teamsFx/simpleAuth.bicep' = {
7
+ name: 'addTeamsFxSimpleAuthConfiguration'
8
+ params: {
9
+ provisionParameters: provisionParameters
10
+ provisionOutputs: provisionOutputs
11
+ currentAppSettings: simpleAuthCurrentAppSettings
12
+ }
13
+ }
14
+ // Get existing app settings and site config for merge
15
+ var functionCurrentConfigs = reference('${provisionOutputs.functionOutput.value.functionAppResourceId}/config/web', '2021-02-01')
16
+ var functionCurrentAppSettings = list('${provisionOutputs.functionOutput.value.functionAppResourceId}/config/appsettings', '2021-02-01').properties
17
+
18
+ // Merge TeamsFx configurations to Azure Functions resources
19
+ module teamsFxFunctionConfig './teamsFx/function.bicep' = {
20
+ name: 'addTeamsFxFunctionConfiguration'
21
+ params: {
22
+ provisionParameters: provisionParameters
23
+ provisionOutputs: provisionOutputs
24
+ currentConfigs: functionCurrentConfigs
25
+ currentAppSettings: functionCurrentAppSettings
26
+ }
27
+ }
@@ -0,0 +1,20 @@
1
+ @secure()
2
+ param provisionParameters object
3
+
4
+ module provision './provision.bicep' = {
5
+ name: 'provisionResources'
6
+ params: {
7
+ provisionParameters: provisionParameters
8
+ }
9
+ }
10
+
11
+ module teamsFxConfig './config.bicep' = {
12
+ name: 'addTeamsFxConfigurations'
13
+ params: {
14
+ provisionParameters: provisionParameters
15
+ provisionOutputs: provision
16
+ }
17
+ }
18
+
19
+ output provisionOutput object = provision
20
+ output teamsFxConfigurationOutput object = contains(reference(resourceId('Microsoft.Resources/deployments', teamsFxConfig.name), '2020-06-01'), 'outputs') ? teamsFxConfig : {}
@@ -0,0 +1,23 @@
1
+ @secure()
2
+ param provisionParameters object
3
+ var resourceBaseName = provisionParameters.resourceBaseName
4
+ var storageName = contains(provisionParameters, 'frontendHostingStorageName') ? provisionParameters['frontendHostingStorageName'] : '${resourceBaseName}tab'
5
+ var storageSku = contains(provisionParameters, 'frontendHostingStorageSku') ? provisionParameters['frontendHostingStorageSku'] : 'Standard_LRS'
6
+
7
+ resource storage 'Microsoft.Storage/storageAccounts@2021-06-01' = {
8
+ kind: 'StorageV2'
9
+ location: resourceGroup().location
10
+ name: storageName
11
+ properties: {
12
+ supportsHttpsTrafficOnly: true
13
+ }
14
+ sku: {
15
+ name: storageSku // You can follow https://aka.ms/teamsfx-bicep-add-param-tutorial to add frontendHostingStorageSku property to provisionParameters to override the default value "Standard_LRS".
16
+ }
17
+ }
18
+
19
+ var siteDomain = replace(replace(storage.properties.primaryEndpoints.web, 'https://', ''), '/', '')
20
+
21
+ output resourceId string = storage.id
22
+ output endpoint string = 'https://${siteDomain}'
23
+ output domain string = siteDomain
@@ -0,0 +1,82 @@
1
+ @secure()
2
+ param provisionParameters object
3
+ param userAssignedIdentityId string
4
+
5
+ var resourceBaseName = provisionParameters.resourceBaseName
6
+ var serverfarmsName = contains(provisionParameters, 'functionServerfarmsName') ? provisionParameters['functionServerfarmsName'] : '${resourceBaseName}api' // Try to read name for App Service Plan from parameters
7
+ var serverfarmsSku = contains(provisionParameters, 'functionServerfarmsSku') ? provisionParameters['functionServerfarmsSku'] : 'Y1' // Try to read SKU for App Service Plan from parameters
8
+ var functionAppName = contains(provisionParameters, 'functionWebappName') ? provisionParameters['functionWebappName'] : '${resourceBaseName}api' // Try to read name for Azure Functions from parameters
9
+ var storageName = contains(provisionParameters, 'functionStorageName') ? provisionParameters['functionStorageName'] : '${resourceBaseName}api' // Try to read name for Azure Storage from parameters
10
+ var storageSku = contains(provisionParameters, 'functionStorageSku') ? provisionParameters['functionStorageSku'] : 'Standard_LRS' // Try to read SKU for Azure Storage from parameters
11
+
12
+ // Compute resources for Azure Functions
13
+ resource serverfarms 'Microsoft.Web/serverfarms@2021-02-01' = {
14
+ name: serverfarmsName
15
+ kind: 'functionapp'
16
+ location: resourceGroup().location
17
+ sku: {
18
+ name: serverfarmsSku // You can follow https://aka.ms/teamsfx-bicep-add-param-tutorial to add functionServerfarmsSku property to provisionParameters to override the default value "Y1".
19
+ }
20
+ }
21
+
22
+ // Azure Functions that hosts your function code
23
+ resource functionApp 'Microsoft.Web/sites@2021-02-01' = {
24
+ name: functionAppName
25
+ kind: 'functionapp'
26
+ location: resourceGroup().location
27
+ properties: {
28
+ serverFarmId: serverfarms.id
29
+ keyVaultReferenceIdentity: userAssignedIdentityId // Use given user assigned identity to access Key Vault
30
+ siteConfig: {
31
+ appSettings: [
32
+ {
33
+ name: 'AzureWebJobsDashboard'
34
+ value: 'DefaultEndpointsProtocol=https;AccountName=${storage.name};AccountKey=${listKeys(storage.id, storage.apiVersion).keys[0].value};EndpointSuffix=${environment().suffixes.storage}' // Azure Functions internal setting
35
+ }
36
+ {
37
+ name: 'AzureWebJobsStorage'
38
+ value: 'DefaultEndpointsProtocol=https;AccountName=${storage.name};AccountKey=${listKeys(storage.id, storage.apiVersion).keys[0].value};EndpointSuffix=${environment().suffixes.storage}' // Azure Functions internal setting
39
+ }
40
+ {
41
+ name: 'FUNCTIONS_EXTENSION_VERSION'
42
+ value: '~3' // Use Azure Functions runtime v3
43
+ }
44
+ {
45
+ name: 'FUNCTIONS_WORKER_RUNTIME'
46
+ value: 'node' // Set runtime to NodeJS
47
+ }
48
+ {
49
+ name: 'WEBSITE_CONTENTAZUREFILECONNECTIONSTRING'
50
+ value: 'DefaultEndpointsProtocol=https;AccountName=${storage.name};AccountKey=${listKeys(storage.id, storage.apiVersion).keys[0].value};EndpointSuffix=${environment().suffixes.storage}' // Azure Functions internal setting
51
+ }
52
+ {
53
+ name: 'WEBSITE_RUN_FROM_PACKAGE'
54
+ value: '1' // Run Azure Functions from a package file
55
+ }
56
+ {
57
+ name: 'WEBSITE_NODE_DEFAULT_VERSION'
58
+ value: '~14' // Set NodeJS version to 14.x
59
+ }
60
+ ]
61
+ }
62
+ }
63
+ identity: {
64
+ type: 'UserAssigned'
65
+ userAssignedIdentities: {
66
+ '${userAssignedIdentityId}': {} // The identity is used to access other Azure resources
67
+ }
68
+ }
69
+ }
70
+
71
+ // Azure Storage is required when creating Azure Functions instance
72
+ resource storage 'Microsoft.Storage/storageAccounts@2021-06-01' = {
73
+ name: storageName
74
+ kind: 'StorageV2'
75
+ location: resourceGroup().location
76
+ sku: {
77
+ name: storageSku // You can follow https://aka.ms/teamsfx-bicep-add-param-tutorial to add functionStorageSku property to provisionParameters to override the default value "Standard_LRS".
78
+ }
79
+ }
80
+
81
+ output functionEndpoint string = 'https://${functionApp.properties.defaultHostName}'
82
+ output functionAppResourceId string = functionApp.id
@@ -0,0 +1,14 @@
1
+ @secure()
2
+ param provisionParameters object
3
+ var resourceBaseName = provisionParameters.resourceBaseName
4
+ var identityName = contains(provisionParameters, 'userAssignedIdentityName') ? provisionParameters['userAssignedIdentityName'] : '${resourceBaseName}'
5
+
6
+ resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = {
7
+ name: identityName
8
+ location: resourceGroup().location
9
+ }
10
+
11
+ output identityName string = identityName
12
+ output identityClientId string = managedIdentity.properties.clientId
13
+ output identityResourceId string = managedIdentity.id
14
+ output identityPrincipalId string = managedIdentity.properties.principalId
@@ -0,0 +1,44 @@
1
+ @secure()
2
+ param provisionParameters object
3
+ param userAssignedIdentityId string
4
+ var resourceBaseName = provisionParameters.resourceBaseName
5
+ var sku = contains(provisionParameters, 'simpleAuthSku') ? provisionParameters['simpleAuthSku'] : 'F1'
6
+ var serverFarmsName = contains(provisionParameters, 'simpleAuthServerFarmsName') ? provisionParameters['simpleAuthServerFarmsName'] : '${resourceBaseName}simpleAuth'
7
+ var webAppName = contains(provisionParameters, 'simpleAuthWebAppName') ? provisionParameters['simpleAuthWebAppName'] : '${resourceBaseName}simpleAuth'
8
+ var simpleAuthPackageUri = contains(provisionParameters, 'simpleAuthPackageUri') ? provisionParameters['simpleAuthPackageUri'] : 'https://github.com/OfficeDev/TeamsFx/releases/download/simpleauth@0.1.0/Microsoft.TeamsFx.SimpleAuth_0.1.0.zip'
9
+
10
+ resource serverFarms 'Microsoft.Web/serverfarms@2021-02-01' = {
11
+ name: serverFarmsName
12
+ location: resourceGroup().location
13
+ sku: {
14
+ name: sku
15
+ }
16
+ kind: 'app'
17
+ }
18
+
19
+ resource webApp 'Microsoft.Web/sites@2021-02-01' = {
20
+ kind: 'app'
21
+ name: webAppName
22
+ location: resourceGroup().location
23
+ properties: {
24
+ serverFarmId: serverFarms.id
25
+ keyVaultReferenceIdentity: userAssignedIdentityId
26
+ }
27
+ identity: {
28
+ type: 'UserAssigned'
29
+ userAssignedIdentities: {
30
+ '${userAssignedIdentityId}': {}
31
+ }
32
+ }
33
+ }
34
+
35
+ resource simpleAuthDeploy 'Microsoft.Web/sites/extensions@2021-02-01' = {
36
+ parent: webApp
37
+ name: 'MSDeploy'
38
+ properties: {
39
+ packageUri: simpleAuthPackageUri
40
+ }
41
+ }
42
+
43
+ output webAppResourceId string = webApp.id
44
+ output endpoint string = 'https://${webApp.properties.defaultHostName}'
@@ -0,0 +1,58 @@
1
+ @secure()
2
+ param provisionParameters object
3
+ // Resources for frontend hosting
4
+ module frontendHostingProvision './provision/frontendHosting.bicep' = {
5
+ name: 'frontendHostingProvision'
6
+ params: {
7
+ provisionParameters: provisionParameters
8
+ }
9
+ }
10
+
11
+ output frontendHostingOutput object = {
12
+ teamsFxPluginId: 'fx-resource-frontend-hosting'
13
+ domain: frontendHostingProvision.outputs.domain
14
+ endpoint: frontendHostingProvision.outputs.endpoint
15
+ storageResourceId: frontendHostingProvision.outputs.resourceId
16
+ }
17
+ // Resources for identity
18
+ module userAssignedIdentityProvision './provision/identity.bicep' = {
19
+ name: 'userAssignedIdentityProvision'
20
+ params: {
21
+ provisionParameters: provisionParameters
22
+ }
23
+ }
24
+
25
+ output identityOutput object = {
26
+ teamsFxPluginId: 'fx-resource-identity'
27
+ identityName: userAssignedIdentityProvision.outputs.identityName
28
+ identityResourceId: userAssignedIdentityProvision.outputs.identityResourceId
29
+ identityClientId: userAssignedIdentityProvision.outputs.identityClientId
30
+ }
31
+ // Resources for Simple Auth
32
+ module simpleAuthProvision './provision/simpleAuth.bicep' = {
33
+ name: 'simpleAuthProvision'
34
+ params: {
35
+ provisionParameters: provisionParameters
36
+ userAssignedIdentityId: userAssignedIdentityProvision.outputs.identityResourceId
37
+ }
38
+ }
39
+
40
+ output simpleAuthOutput object = {
41
+ teamsFxPluginId: 'fx-resource-simple-auth'
42
+ endpoint: simpleAuthProvision.outputs.endpoint
43
+ webAppResourceId: simpleAuthProvision.outputs.webAppResourceId
44
+ }
45
+ // Resources for Azure Functions
46
+ module functionProvision './provision/function.bicep' = {
47
+ name: 'functionProvision'
48
+ params: {
49
+ provisionParameters: provisionParameters
50
+ userAssignedIdentityId: userAssignedIdentityProvision.outputs.identityResourceId
51
+ }
52
+ }
53
+
54
+ output functionOutput object = {
55
+ teamsFxPluginId: 'fx-resource-function'
56
+ functionAppResourceId: functionProvision.outputs.functionAppResourceId
57
+ functionEndpoint: functionProvision.outputs.functionEndpoint
58
+ }
@@ -0,0 +1,76 @@
1
+ // Auto generated content, please customize files under provision folder
2
+
3
+ @secure()
4
+ param provisionParameters object
5
+ param provisionOutputs object
6
+ @secure()
7
+ param currentConfigs object
8
+ @secure()
9
+ param currentAppSettings object
10
+
11
+ var functionAppName = split(provisionOutputs.functionOutput.value.functionAppResourceId, '/')[8]
12
+
13
+ var m365ClientId = provisionParameters['m365ClientId']
14
+
15
+ var m365ClientSecret = provisionParameters['m365ClientSecret']
16
+
17
+ var m365TenantId = provisionParameters['m365TenantId']
18
+ var m365OauthAuthorityHost = provisionParameters['m365OauthAuthorityHost']
19
+ var oauthAuthority = uri(m365OauthAuthorityHost, m365TenantId)
20
+
21
+ var tabAppDomain = provisionOutputs.frontendHostingOutput.value.domain
22
+ var tabAppEndpoint = provisionOutputs.frontendHostingOutput.value.endpoint
23
+
24
+
25
+ var m365ApplicationIdUri = 'api://${tabAppDomain}/${m365ClientId}'
26
+
27
+ var teamsMobileOrDesktopAppClientId = '1fec8e78-bce4-4aaf-ab1b-5451cc387264'
28
+ var teamsWebAppClientId = '5e3ce6c0-2b1f-4285-8d4b-75ee78787346'
29
+ var officeWebAppClientId1 = '4345a7b9-9a63-4910-a426-35363201d503'
30
+ var officeWebAppClientId2 = '4765445b-32c6-49b0-83e6-1d93765276ca'
31
+ var officeDesktopAppClientId = '0ec893e0-5785-4de6-99da-4ed124e5296c'
32
+ var outlookDesktopAppClientId = 'd3590ed6-52b3-4102-aeff-aad2292ab01c'
33
+ var outlookWebAppClientId1 = '00000002-0000-0ff1-ce00-000000000000'
34
+ var outlookWebAppClientId2 = 'bc59ab01-8403-45c6-8796-ac3ef710b3e3'
35
+ var authorizedClientApplicationIds = '${teamsMobileOrDesktopAppClientId};${teamsWebAppClientId};${officeWebAppClientId1};${officeWebAppClientId2};${officeDesktopAppClientId};${outlookDesktopAppClientId};${outlookWebAppClientId1};${outlookWebAppClientId2}'
36
+
37
+ var currentAllowedOrigins = empty(currentConfigs.cors) ? [] : currentConfigs.cors.allowedOrigins
38
+
39
+ resource appConfig 'Microsoft.Web/sites/config@2021-02-01' = {
40
+ name: '${functionAppName}/web'
41
+ kind: 'functionapp'
42
+ properties: {
43
+ cors: {
44
+ allowedOrigins: union(currentAllowedOrigins, [
45
+ tabAppEndpoint // allow requests from tab app
46
+ ])
47
+ }
48
+ }
49
+ }
50
+ resource appSettings 'Microsoft.Web/sites/config@2021-02-01' = {
51
+ name: '${functionAppName}/appsettings'
52
+ properties: union({
53
+ API_ENDPOINT: provisionOutputs.functionOutput.value.functionEndpoint // Azure Functions endpoint
54
+ ALLOWED_APP_IDS: authorizedClientApplicationIds // Only allow tokens issued by these AAD applications
55
+ M365_CLIENT_ID: m365ClientId // Client id of AAD application
56
+ M365_CLIENT_SECRET: m365ClientSecret // Client secret of AAD application
57
+ M365_TENANT_ID: m365TenantId // Tenant id of AAD application
58
+ M365_AUTHORITY_HOST: m365OauthAuthorityHost // AAD authority host
59
+ M365_APPLICATION_ID_URI: m365ApplicationIdUri // Application ID URI of AAD application
60
+ IDENTITY_ID: provisionOutputs.identityOutput.value.identityClientId // User assigned identity id, the identity is used to access other Azure resources
61
+ }, currentAppSettings) // Merge new settings with existing settings
62
+ }
63
+
64
+ resource authSettings 'Microsoft.Web/sites/config@2021-02-01' = {
65
+ name: '${functionAppName}/authsettings'
66
+ properties: {
67
+ enabled: true // Validate access token in request authorization header
68
+ defaultProvider: 'AzureActiveDirectory'
69
+ clientId: m365ClientId
70
+ issuer: '${oauthAuthority}/v2.0' // Issuer of access token
71
+ allowedAudiences: [ // Only allow tokens with following audiences
72
+ m365ClientId
73
+ m365ApplicationIdUri
74
+ ]
75
+ }
76
+ }