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.
- package/.fx/configs/azure.parameters.Prod_EEA.json +15 -0
- package/.fx/configs/azure.parameters.dev.json +15 -0
- package/.fx/configs/config.Prod_EEA.json +10 -0
- package/.fx/configs/config.dev.json +10 -0
- package/.fx/configs/projectSettings.json +83 -0
- package/.fx/states/state.Prod_EEA.json +47 -0
- package/.fx/states/state.dev.json +47 -0
- package/.vscode/launch.json +91 -0
- package/.vscode/settings.json +6 -0
- package/.vscode/tasks.json +63 -0
- package/CHANGELOG.md +140 -0
- package/Jenkinsfile +166 -0
- package/LICENSE.md +9 -0
- package/README.md +55 -0
- package/api/.funcignore +11 -0
- package/api/extensions.csproj +11 -0
- package/api/getGraphData/function.json +27 -0
- package/api/getGraphData/index.js +147 -0
- package/api/host.json +11 -0
- package/api/package-lock.json +1546 -0
- package/api/package.json +17 -0
- package/api/proxies.json +4 -0
- package/package.json +25 -0
- package/tabs/.env.teamsfx.Prod_EEA +11 -0
- package/tabs/.env.teamsfx.dev +11 -0
- package/tabs/.eslintrc.json +48 -0
- package/tabs/.prettierrc +7 -0
- package/tabs/.stylelintrc.json +6 -0
- package/tabs/babel.config.js +3 -0
- package/tabs/package-lock.json +15564 -0
- package/tabs/package.json +88 -0
- package/tabs/public/auth-end.html +76 -0
- package/tabs/public/auth-start.html +178 -0
- package/tabs/public/deploy.png +0 -0
- package/tabs/public/favicon.ico +0 -0
- package/tabs/public/hello.png +0 -0
- package/tabs/public/index.html +20 -0
- package/tabs/public/publish.png +0 -0
- package/tabs/src/components/App.jsx +36 -0
- package/tabs/src/components/CustomColumnResizeIcon.jsx +68 -0
- package/tabs/src/components/CustomDrawer.jsx +51 -0
- package/tabs/src/components/EventDialogTitle.jsx +29 -0
- package/tabs/src/components/HtmlBox.jsx +18 -0
- package/tabs/src/components/Privacy.jsx +17 -0
- package/tabs/src/components/ResizableGrid.jsx +44 -0
- package/tabs/src/components/Tab.jsx +477 -0
- package/tabs/src/components/Tab.scss +138 -0
- package/tabs/src/components/TabConfig.jsx +51 -0
- package/tabs/src/components/TabPanel.jsx +29 -0
- package/tabs/src/components/TermsOfUse.jsx +17 -0
- package/tabs/src/components/UnderConstruction.jsx +24 -0
- package/tabs/src/components/UserMenu.jsx +109 -0
- package/tabs/src/components/_variables.scss +10 -0
- package/tabs/src/components/activity/Activity.jsx +301 -0
- package/tabs/src/components/activity/ConsultationList.jsx +297 -0
- package/tabs/src/components/activity/EventList.jsx +463 -0
- package/tabs/src/components/activity/GroupsTags.jsx +26 -0
- package/tabs/src/components/activity/Reporting.jsx +13 -0
- package/tabs/src/components/activity/activity.scss +153 -0
- package/tabs/src/components/event_rating/EventRating.jsx +92 -0
- package/tabs/src/components/event_rating/EventRatingDialog.jsx +46 -0
- package/tabs/src/components/event_registration/Approval.jsx +80 -0
- package/tabs/src/components/event_registration/ApprovalDialog.jsx +30 -0
- package/tabs/src/components/event_registration/ApprovalList.jsx +62 -0
- package/tabs/src/components/event_registration/EventRegistration.jsx +214 -0
- package/tabs/src/components/lib/useData.js +33 -0
- package/tabs/src/components/lib/useGraph.js +39 -0
- package/tabs/src/components/lib/useTeamsFx.js +55 -0
- package/tabs/src/components/my_country/AtAGlance.jsx +151 -0
- package/tabs/src/components/my_country/CountryProgress.jsx +92 -0
- package/tabs/src/components/my_country/DataReporters.jsx +13 -0
- package/tabs/src/components/my_country/GroupView.jsx +54 -0
- package/tabs/src/components/my_country/GroupsBoard.jsx +52 -0
- package/tabs/src/components/my_country/IndicatorCard.jsx +60 -0
- package/tabs/src/components/my_country/ManagementBoard.jsx +109 -0
- package/tabs/src/components/my_country/MyCountry.jsx +186 -0
- package/tabs/src/components/my_country/ProgressGauge.jsx +125 -0
- package/tabs/src/components/my_country/ScientificCommittee.jsx +13 -0
- package/tabs/src/components/my_country/YearlyProgress.jsx +41 -0
- package/tabs/src/components/my_country/my_country.scss +81 -0
- package/tabs/src/components/publications/Publications.jsx +13 -0
- package/tabs/src/components/self_service/UserEdit.jsx +334 -0
- package/tabs/src/components/self_service/UserEdit.scss +107 -0
- package/tabs/src/data/apiProvider.js +153 -0
- package/tabs/src/data/constants.json +7 -0
- package/tabs/src/data/hooks/useConfiguration.js +18 -0
- package/tabs/src/data/icsHelper.js +38 -0
- package/tabs/src/data/messages.json +39 -0
- package/tabs/src/data/provider.js +199 -0
- package/tabs/src/data/selfServiceProvider.js +59 -0
- package/tabs/src/data/selfServiceSharepointProvider.js +68 -0
- package/tabs/src/data/sharepointProvider.js +729 -0
- package/tabs/src/data/validator.js +25 -0
- package/tabs/src/data/validator.test.js +9 -0
- package/tabs/src/index.css +16 -0
- package/tabs/src/index.jsx +6 -0
- package/tabs/src/static/images/teams-icon.svg +1 -0
- package/tabs/src/utils/uiHelper.js +6 -0
- package/templates/appPackage/aad.template.json +133 -0
- package/templates/appPackage/manifest.template.json +58 -0
- package/templates/appPackage/resources/color.png +0 -0
- package/templates/appPackage/resources/outline.png +0 -0
- package/templates/azure/config.bicep +27 -0
- package/templates/azure/main.bicep +20 -0
- package/templates/azure/provision/frontendHosting.bicep +23 -0
- package/templates/azure/provision/function.bicep +82 -0
- package/templates/azure/provision/identity.bicep +14 -0
- package/templates/azure/provision/simpleAuth.bicep +44 -0
- package/templates/azure/provision.bicep +58 -0
- package/templates/azure/teamsFx/function.bicep +76 -0
- 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 @@
|
|
|
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,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
|
+
}
|
|
Binary file
|
|
Binary file
|
|
@@ -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
|
+
}
|