@openeventkit/event-site 2.0.128-beta.5 → 2.0.128
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/env.template +1 -0
- package/package.json +1 -1
- package/src/actions/clock-actions.js +17 -16
- package/src/actions/security-actions.js +32 -0
- package/src/cms/config/collections/configurationsCollection/navbar/index.js +46 -16
- package/src/cms/config/collections/configurationsCollection/navbar/typeDefs.js +1 -2
- package/src/cms/config/collections/configurationsCollection/siteSettings/index.js +5 -4
- package/src/cms/config/collections/contentPagesCollection/index.js +20 -5
- package/src/components/AuthComponent.js +2 -2
- package/src/components/Navbar/index.js +40 -35
- package/src/components/RegistrationLiteComponent.js +2 -2
- package/src/components/UserNavbar.js +15 -16
- package/src/content/navbar/index.json +5 -5
- package/src/routes/WithAuthzRoute.js +7 -7
- package/src/routes/authorization-callback-route.js +18 -19
- package/src/styles/colors.scss +13 -7
- package/src/styles/fonts.scss +11 -16
- package/src/templates/content-page/index.js +2 -2
- package/src/templates/login-page.js +8 -8
- package/src/templates/token-expire-page.js +10 -10
- package/src/utils/authorizedGroups.js +1 -1
- package/src/utils/envVariables.js +2 -0
- package/src/cms/config/utils.js +0 -4
- package/src/utils/pageAccessConstants.js +0 -16
package/env.template
CHANGED
package/package.json
CHANGED
|
@@ -1,24 +1,25 @@
|
|
|
1
|
-
import { createAction } from
|
|
1
|
+
import { createAction } from "openstack-uicore-foundation/lib/utils/actions";
|
|
2
|
+
import { PHASES, getSummitPhase, getEventPhase } from "@utils/phasesUtils";
|
|
3
|
+
import { updateVotingPeriodsPhase } from "../actions/presentation-actions";
|
|
4
|
+
import { sanitizeHash } from "../actions/security-actions";
|
|
2
5
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
export const
|
|
8
|
-
export const
|
|
9
|
-
export const
|
|
10
|
-
export const
|
|
11
|
-
export const EVENT_PHASE_DURING = 'EVENT_PHASE_DURING';
|
|
12
|
-
export const EVENT_PHASE_AFTER = 'EVENT_PHASE_AFTER';
|
|
13
|
-
export const EVENT_PHASE_ADD = 'EVENT_PHASE_ADD';
|
|
14
|
-
export const UPDATE_CLOCK = 'UPDATE_CLOCK';
|
|
6
|
+
export const SUMMIT_PHASE_AFTER = "SUMMIT_PHASE_AFTER";
|
|
7
|
+
export const SUMMIT_PHASE_DURING = "SUMMIT_PHASE_DURING";
|
|
8
|
+
export const SUMMIT_PHASE_BEFORE = "SUMMIT_PHASE_BEFORE";
|
|
9
|
+
export const EVENT_PHASE_BEFORE = "EVENT_PHASE_BEFORE";
|
|
10
|
+
export const EVENT_PHASE_DURING = "EVENT_PHASE_DURING";
|
|
11
|
+
export const EVENT_PHASE_AFTER = "EVENT_PHASE_AFTER";
|
|
12
|
+
export const EVENT_PHASE_ADD = "EVENT_PHASE_ADD";
|
|
13
|
+
export const UPDATE_CLOCK = "UPDATE_CLOCK";
|
|
15
14
|
|
|
16
15
|
export const updateClock = (timestamp) => (dispatch) => {
|
|
17
|
-
|
|
18
16
|
dispatch(createAction(UPDATE_CLOCK)({ timestamp }));
|
|
17
|
+
|
|
19
18
|
dispatch(updateSummitPhase());
|
|
20
19
|
dispatch(updateEventsPhase());
|
|
21
20
|
dispatch(updateVotingPeriodsPhase());
|
|
21
|
+
|
|
22
|
+
dispatch(sanitizeHash());
|
|
22
23
|
};
|
|
23
24
|
|
|
24
25
|
export const updateSummitPhase = () => (dispatch, getState) => {
|
|
@@ -89,5 +90,5 @@ export const updateEventsPhase = () => (dispatch, getState) => {
|
|
|
89
90
|
break;
|
|
90
91
|
}
|
|
91
92
|
}
|
|
92
|
-
})
|
|
93
|
-
};
|
|
93
|
+
});
|
|
94
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { getEnvVariable, HASH_SANITIZE_TOKENS } from "@utils/envVariables";
|
|
2
|
+
|
|
3
|
+
export const sanitizeHash = () => (dispatch, getState) => {
|
|
4
|
+
const { userState: { isAuthorized } } = getState();
|
|
5
|
+
|
|
6
|
+
if (!isAuthorized) {
|
|
7
|
+
const tokens = getEnvVariable(HASH_SANITIZE_TOKENS)?.split(",") ?? [];
|
|
8
|
+
|
|
9
|
+
if (tokens.length > 0) {
|
|
10
|
+
const url = new URL(window.location.href);
|
|
11
|
+
let fragment = url.hash;
|
|
12
|
+
let shouldUpdate = false;
|
|
13
|
+
|
|
14
|
+
tokens.forEach(token => {
|
|
15
|
+
if (fragment.includes(`${token}=`)) {
|
|
16
|
+
shouldUpdate = true;
|
|
17
|
+
fragment = fragment
|
|
18
|
+
.split("&")
|
|
19
|
+
.filter(fragmentToken => !fragmentToken.includes(`${token}=`))
|
|
20
|
+
.join("&")
|
|
21
|
+
.replace("#&", "#")
|
|
22
|
+
.replace("#?", "#")
|
|
23
|
+
.replace("#", "");
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
if (shouldUpdate) {
|
|
28
|
+
window.history.replaceState({}, "", `${url.pathname}${fragment ? `#${fragment}` : ""}`);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
};
|
|
@@ -2,13 +2,40 @@ import {
|
|
|
2
2
|
booleanField,
|
|
3
3
|
stringField,
|
|
4
4
|
selectField,
|
|
5
|
+
selectOption,
|
|
5
6
|
listField
|
|
6
7
|
} from "../../../fields";
|
|
7
8
|
|
|
8
|
-
import {
|
|
9
|
-
|
|
9
|
+
import {
|
|
10
|
+
NAVBAR_FILE_PATH
|
|
11
|
+
} from "@utils/filePath";
|
|
12
|
+
|
|
13
|
+
const PAGE_RESTRICTIONS = {
|
|
14
|
+
any: "ANY",
|
|
15
|
+
activity: "ACTIVITY",
|
|
16
|
+
marketing: "MARKETING",
|
|
17
|
+
lobby: "LOBBY",
|
|
18
|
+
show: "SHOW",
|
|
19
|
+
customPage: "CUSTOM_PAGE"
|
|
20
|
+
};
|
|
10
21
|
|
|
11
|
-
|
|
22
|
+
const getPageRestrictionsOptions = () =>
|
|
23
|
+
Object.entries(PAGE_RESTRICTIONS).map(([key, value]) => selectOption({ label: value, value: value }));
|
|
24
|
+
|
|
25
|
+
/*
|
|
26
|
+
- file: "src/content/navbar.json"
|
|
27
|
+
label: "Navbar"
|
|
28
|
+
name: "navbar"
|
|
29
|
+
fields:
|
|
30
|
+
- {label: "Navbar", name: "items", widget: list, fields: [
|
|
31
|
+
{label: "Title", name: "title", widget: string},
|
|
32
|
+
{label: "Link", name: "link", widget: string},
|
|
33
|
+
{label: "Display?", name: "display", widget: boolean, required: false},
|
|
34
|
+
{label: "Requires Auth?", name: "requiresAuth", widget: boolean, required: false, default: false},
|
|
35
|
+
{label: "Show only at Show Time?", name: "showOnlyAtShowTime", widget: boolean, required: false, default: false},
|
|
36
|
+
{label: "Show only on page", name: "pageRestriction", widget: select, multiple: true, default: ["ANY"], options: ["ANY", "MARKETING", "LOBBY", "ACTIVITY", "SHOW", "CUSTOM_PAGE"]},
|
|
37
|
+
]}
|
|
38
|
+
*/
|
|
12
39
|
|
|
13
40
|
const navbar = {
|
|
14
41
|
label: "Navbar",
|
|
@@ -32,29 +59,32 @@ const navbar = {
|
|
|
32
59
|
name: "display",
|
|
33
60
|
required: false
|
|
34
61
|
}),
|
|
35
|
-
|
|
36
|
-
label: "
|
|
37
|
-
name: "
|
|
38
|
-
|
|
39
|
-
default:
|
|
40
|
-
options: mapObjectToSelectOptions(USER_REQUIREMENTS)
|
|
41
|
-
}),
|
|
42
|
-
selectField({
|
|
43
|
-
label: "Show only on Page",
|
|
44
|
-
name: "pageRestriction",
|
|
45
|
-
multiple: true,
|
|
46
|
-
default: [PAGE_RESTRICTIONS.any],
|
|
47
|
-
options: mapObjectToSelectOptions(PAGE_RESTRICTIONS)
|
|
62
|
+
booleanField({
|
|
63
|
+
label: "Requires Auth?",
|
|
64
|
+
name: "requiresAuth",
|
|
65
|
+
required: false,
|
|
66
|
+
default: false
|
|
48
67
|
}),
|
|
49
68
|
booleanField({
|
|
50
69
|
label: "Show only at Show Time?",
|
|
51
70
|
name: "showOnlyAtShowTime",
|
|
52
71
|
required: false,
|
|
53
72
|
default: false
|
|
73
|
+
}),
|
|
74
|
+
selectField({
|
|
75
|
+
label: "Show only on page",
|
|
76
|
+
name: "pageRestriction",
|
|
77
|
+
multiple: true,
|
|
78
|
+
default: [PAGE_RESTRICTIONS.any],
|
|
79
|
+
options: getPageRestrictionsOptions()
|
|
54
80
|
})
|
|
55
81
|
]
|
|
56
82
|
})
|
|
57
83
|
]
|
|
58
84
|
};
|
|
59
85
|
|
|
86
|
+
export {
|
|
87
|
+
PAGE_RESTRICTIONS
|
|
88
|
+
};
|
|
89
|
+
|
|
60
90
|
export default navbar;
|
|
@@ -21,8 +21,6 @@ import {
|
|
|
21
21
|
IDP_BASE_URL
|
|
22
22
|
} from "@utils/envVariables";
|
|
23
23
|
|
|
24
|
-
import { mapObjectToSelectOptions } from "../../../utils";
|
|
25
|
-
|
|
26
24
|
const FONT_FORMATS = {
|
|
27
25
|
truetype: "ttf",
|
|
28
26
|
opentype: "otf",
|
|
@@ -31,6 +29,9 @@ const FONT_FORMATS = {
|
|
|
31
29
|
eot: "eot"
|
|
32
30
|
};
|
|
33
31
|
|
|
32
|
+
const getFontFormatOptions = () =>
|
|
33
|
+
Object.entries(FONT_FORMATS).map(([key, value]) => selectOption({ label: value, value: value }));
|
|
34
|
+
|
|
34
35
|
const siteSettings = {
|
|
35
36
|
label: "Site Settings",
|
|
36
37
|
name: "site-settings",
|
|
@@ -150,7 +151,7 @@ const siteSettings = {
|
|
|
150
151
|
name: "fontFormat",
|
|
151
152
|
multiple: false,
|
|
152
153
|
required: false,
|
|
153
|
-
options:
|
|
154
|
+
options: getFontFormatOptions()
|
|
154
155
|
})
|
|
155
156
|
],
|
|
156
157
|
}),
|
|
@@ -169,7 +170,7 @@ const siteSettings = {
|
|
|
169
170
|
name: "fontFormat",
|
|
170
171
|
multiple: false,
|
|
171
172
|
required: false,
|
|
172
|
-
options:
|
|
173
|
+
options: getFontFormatOptions()
|
|
173
174
|
})
|
|
174
175
|
]
|
|
175
176
|
})
|
|
@@ -1,16 +1,27 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
collectionDefaults
|
|
3
|
+
} from "../../patterns";
|
|
2
4
|
|
|
3
5
|
import {
|
|
4
6
|
hiddenField,
|
|
5
7
|
stringField,
|
|
6
8
|
selectField,
|
|
9
|
+
selectOption,
|
|
7
10
|
markdownField
|
|
8
11
|
} from "../../fields";
|
|
9
12
|
|
|
10
|
-
import {
|
|
11
|
-
|
|
13
|
+
import {
|
|
14
|
+
CONTENT_PAGES_DIR_PATH
|
|
15
|
+
} from "@utils/filePath";
|
|
16
|
+
|
|
17
|
+
const USER_REQUIREMENTS = {
|
|
18
|
+
none: "NONE",
|
|
19
|
+
loggedIn: "LOGGED_IN",
|
|
20
|
+
hasTicket: "HAS_TICKET"
|
|
21
|
+
};
|
|
12
22
|
|
|
13
|
-
|
|
23
|
+
const getUserRequirementsOptions = () =>
|
|
24
|
+
Object.entries(USER_REQUIREMENTS).map(([key, value]) => selectOption({ label: value, value: value }));
|
|
14
25
|
|
|
15
26
|
const contentPagesCollection = {
|
|
16
27
|
...collectionDefaults({
|
|
@@ -38,7 +49,7 @@ const contentPagesCollection = {
|
|
|
38
49
|
name: "userRequirement",
|
|
39
50
|
multiple: false,
|
|
40
51
|
default: USER_REQUIREMENTS.none,
|
|
41
|
-
options:
|
|
52
|
+
options: getUserRequirementsOptions()
|
|
42
53
|
}),
|
|
43
54
|
markdownField({
|
|
44
55
|
label: "Body",
|
|
@@ -47,4 +58,8 @@ const contentPagesCollection = {
|
|
|
47
58
|
]
|
|
48
59
|
};
|
|
49
60
|
|
|
61
|
+
export {
|
|
62
|
+
USER_REQUIREMENTS
|
|
63
|
+
};
|
|
64
|
+
|
|
50
65
|
export default contentPagesCollection;
|
|
@@ -17,7 +17,7 @@ import IconButton from "./IconButton";
|
|
|
17
17
|
import Link from "./Link";
|
|
18
18
|
|
|
19
19
|
import { getDefaultLocation, validateIdentityProviderButtons } from "@utils/loginUtils";
|
|
20
|
-
import { userHasAccessLevel,
|
|
20
|
+
import { userHasAccessLevel, VirtualAccessLevel } from "@utils/authorizedGroups";
|
|
21
21
|
import useSiteSettings from "@utils/useSiteSettings";
|
|
22
22
|
import { PHASES } from "@utils/phasesUtils";
|
|
23
23
|
|
|
@@ -49,7 +49,7 @@ const AuthComponent = ({
|
|
|
49
49
|
const [otpError, setOtpError] = useState(false);
|
|
50
50
|
|
|
51
51
|
const hasVirtualBadge = useMemo(() =>
|
|
52
|
-
userProfile ? userHasAccessLevel(userProfile.summit_tickets,
|
|
52
|
+
userProfile ? userHasAccessLevel(userProfile.summit_tickets, VirtualAccessLevel) : false
|
|
53
53
|
, [userProfile]);
|
|
54
54
|
const defaultPath = getDefaultLocation(eventRedirect, hasVirtualBadge);
|
|
55
55
|
|
|
@@ -4,11 +4,11 @@ import { connect } from "react-redux";
|
|
|
4
4
|
import { navigate } from "gatsby";
|
|
5
5
|
import NavbarTemplate from "./template";
|
|
6
6
|
|
|
7
|
-
import { userHasAccessLevel,
|
|
7
|
+
import { userHasAccessLevel, VirtualAccessLevel } from "@utils/authorizedGroups";
|
|
8
8
|
import { getDefaultLocation } from "@utils/loginUtils";
|
|
9
9
|
|
|
10
10
|
import { PHASES } from "@utils/phasesUtils";
|
|
11
|
-
import {
|
|
11
|
+
import { PAGE_RESTRICTIONS } from "../../cms/config/collections/configurationsCollection/navbar";
|
|
12
12
|
|
|
13
13
|
import navbarContent from "content/navbar/index.json";
|
|
14
14
|
|
|
@@ -17,8 +17,6 @@ const Navbar = ({
|
|
|
17
17
|
summitPhase,
|
|
18
18
|
summit,
|
|
19
19
|
isLoggedUser,
|
|
20
|
-
isAuthorized,
|
|
21
|
-
hasTicket,
|
|
22
20
|
idpProfile,
|
|
23
21
|
userProfile,
|
|
24
22
|
eventRedirect
|
|
@@ -26,57 +24,64 @@ const Navbar = ({
|
|
|
26
24
|
|
|
27
25
|
// we store this calculation to use it later
|
|
28
26
|
const hasVirtualBadge = useMemo(() =>
|
|
29
|
-
userProfile ? userHasAccessLevel(userProfile.summit_tickets,
|
|
27
|
+
userProfile ? userHasAccessLevel(userProfile.summit_tickets, VirtualAccessLevel) : false
|
|
30
28
|
, [userProfile]);
|
|
31
29
|
|
|
32
30
|
const defaultPath = getDefaultLocation(eventRedirect, hasVirtualBadge);
|
|
33
31
|
|
|
34
|
-
const meetsUserRequirement = (userRequirement) => {
|
|
35
|
-
switch (userRequirement) {
|
|
36
|
-
case USER_REQUIREMENTS.none:
|
|
37
|
-
return true;
|
|
38
|
-
case USER_REQUIREMENTS.loggedIn:
|
|
39
|
-
return isLoggedUser || isAuthorized;
|
|
40
|
-
case USER_REQUIREMENTS.hasTicket:
|
|
41
|
-
return hasTicket || isAuthorized;
|
|
42
|
-
default:
|
|
43
|
-
return false;
|
|
44
|
-
}
|
|
45
|
-
};
|
|
46
|
-
|
|
47
32
|
const isCustomPage = (path) => {
|
|
48
33
|
return !isMarketingPage(path) &&
|
|
49
34
|
!isShowPage(path) &&
|
|
50
35
|
!isProfilePage(path) &&
|
|
51
36
|
!isMySchedulePage(path) &&
|
|
52
37
|
!isExtraQuestionsPage(path);
|
|
53
|
-
}
|
|
38
|
+
}
|
|
54
39
|
|
|
55
|
-
const isMySchedulePage = (path) =>
|
|
40
|
+
const isMySchedulePage = (path) => {
|
|
41
|
+
return path.startsWith("/a/my-schedule");
|
|
42
|
+
}
|
|
56
43
|
|
|
57
|
-
const isProfilePage = (path) =>
|
|
44
|
+
const isProfilePage = (path) => {
|
|
45
|
+
return path.startsWith("/a/profile");
|
|
46
|
+
}
|
|
58
47
|
|
|
59
|
-
const isExtraQuestionsPage = (path) =>
|
|
48
|
+
const isExtraQuestionsPage = (path) => {
|
|
49
|
+
return path.startsWith("/a/extra-questions");
|
|
50
|
+
}
|
|
60
51
|
|
|
61
|
-
const isMarketingPage = (path) =>
|
|
52
|
+
const isMarketingPage = (path) => {
|
|
53
|
+
return path === '/';
|
|
54
|
+
}
|
|
62
55
|
|
|
63
|
-
const isLobbyPage = (path) =>
|
|
56
|
+
const isLobbyPage = (path) => {
|
|
57
|
+
return path === '/a' || path === '/a/';
|
|
58
|
+
}
|
|
64
59
|
|
|
65
|
-
const isActivityPage = (path) =>
|
|
60
|
+
const isActivityPage = (path) => {
|
|
61
|
+
return path.startsWith("/a/event");
|
|
62
|
+
}
|
|
66
63
|
|
|
67
|
-
const isSponsorPage = (path) =>
|
|
64
|
+
const isSponsorPage = (path) => {
|
|
65
|
+
return path.startsWith("/a/sponsor");
|
|
66
|
+
}
|
|
68
67
|
|
|
69
|
-
const isSchedulePage = (path) =>
|
|
68
|
+
const isSchedulePage = (path) => {
|
|
69
|
+
return path.startsWith("/a/schedule");
|
|
70
|
+
}
|
|
70
71
|
|
|
71
|
-
const isShowPage = (path) =>
|
|
72
|
+
const isShowPage = (path) => {
|
|
73
|
+
return isLobbyPage(path) || // lobby
|
|
74
|
+
isActivityPage(path) || // activity
|
|
75
|
+
isSponsorPage(path) || // expo hall or sponsor page
|
|
76
|
+
isSchedulePage(path);// schedule
|
|
77
|
+
}
|
|
72
78
|
|
|
73
79
|
// we assume that all pages under /a/* requires auth except /a/schedule
|
|
74
|
-
// item.
|
|
80
|
+
// item.requiresAuth allows to mark specific pages that are not under /a/* pattern.
|
|
75
81
|
const showItem = (item) => {
|
|
76
82
|
// check if we have location defined, if so use the path name , else if window is defined use the window.location
|
|
77
83
|
// as a fallback
|
|
78
|
-
const currentPath = location ? location.pathname
|
|
79
|
-
|
|
84
|
+
const currentPath = location ? location.pathname: (typeof window !== "undefined" ? window.location.pathname: "");
|
|
80
85
|
const passPageRestriction = !item.pageRestriction ||
|
|
81
86
|
item.link === currentPath || // if we are on the same page then show it
|
|
82
87
|
item.pageRestriction.includes(PAGE_RESTRICTIONS.any) ||
|
|
@@ -84,10 +89,11 @@ const Navbar = ({
|
|
|
84
89
|
(item.pageRestriction.includes(PAGE_RESTRICTIONS.marketing) && isMarketingPage(currentPath)) ||
|
|
85
90
|
(item.pageRestriction.includes(PAGE_RESTRICTIONS.lobby) && isLobbyPage(currentPath)) ||
|
|
86
91
|
(item.pageRestriction.includes(PAGE_RESTRICTIONS.show) && isShowPage(currentPath)) ||
|
|
87
|
-
(item.pageRestriction.includes(PAGE_RESTRICTIONS.customPage) && isCustomPage(currentPath))
|
|
92
|
+
(item.pageRestriction.includes(PAGE_RESTRICTIONS.customPage) && isCustomPage(currentPath))
|
|
93
|
+
;
|
|
88
94
|
|
|
89
95
|
return item.display &&
|
|
90
|
-
|
|
96
|
+
(!item.requiresAuth || isLoggedUser) &&
|
|
91
97
|
(!item.showOnlyAtShowTime || summitPhase >= PHASES.DURING) &&
|
|
92
98
|
passPageRestriction;
|
|
93
99
|
};
|
|
@@ -109,6 +115,7 @@ const Navbar = ({
|
|
|
109
115
|
);
|
|
110
116
|
};
|
|
111
117
|
|
|
118
|
+
|
|
112
119
|
const mapStateToProps = ({
|
|
113
120
|
clockState,
|
|
114
121
|
settingState,
|
|
@@ -119,8 +126,6 @@ const mapStateToProps = ({
|
|
|
119
126
|
summit: summitState.summit,
|
|
120
127
|
summitPhase: clockState.summit_phase,
|
|
121
128
|
isLoggedUser: loggedUserState.isLoggedUser,
|
|
122
|
-
isAuthorized: userState.isAuthorized,
|
|
123
|
-
hasTicket: userState.hasTicket,
|
|
124
129
|
idpProfile: userState.idpProfile,
|
|
125
130
|
userProfile: userState.userProfile,
|
|
126
131
|
// TODO: move to site settings i/o marketing page settings
|
|
@@ -24,7 +24,7 @@ import "summit-registration-lite/dist/index.css";
|
|
|
24
24
|
import useSiteSettings from "@utils/useSiteSettings";
|
|
25
25
|
import useMarketingSettings, { MARKETING_SETTINGS_KEYS } from "@utils/useMarketingSettings";
|
|
26
26
|
import { getEnvVariable, SUMMIT_API_BASE_URL, OAUTH2_CLIENT_ID, REGISTRATION_BASE_URL, SUPPORT_EMAIL } from "@utils/envVariables";
|
|
27
|
-
import { userHasAccessLevel,
|
|
27
|
+
import { userHasAccessLevel, VirtualAccessLevel } from "@utils/authorizedGroups";
|
|
28
28
|
import { validateIdentityProviderButtons } from "@utils/loginUtils";
|
|
29
29
|
import { triggerTagManagerTrackEvent } from "@utils/eventTriggers";
|
|
30
30
|
|
|
@@ -136,7 +136,7 @@ const RegistrationLiteComponent = ({
|
|
|
136
136
|
loading: loadingProfile || loadingIDP,
|
|
137
137
|
// only show info if its not a recent purchase
|
|
138
138
|
ticketOwned: userProfile?.summit_tickets?.length > 0,
|
|
139
|
-
|
|
139
|
+
hasVirtualAccessLevel: userHasAccessLevel(userProfile?.summit_tickets, VirtualAccessLevel),
|
|
140
140
|
ownedTickets: attendee?.ticket_types || [],
|
|
141
141
|
authUser: (provider) => onClickLogin(provider),
|
|
142
142
|
getPasswordlessCode: getPasswordlessCode,
|
|
@@ -1,16 +1,15 @@
|
|
|
1
|
-
import React from
|
|
2
|
-
import { Link } from
|
|
3
|
-
import { connect } from
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { Link } from 'gatsby'
|
|
3
|
+
import { connect } from 'react-redux'
|
|
4
4
|
|
|
5
|
-
import
|
|
6
|
-
import
|
|
5
|
+
import styles from '../styles/navbar.module.scss';
|
|
6
|
+
import LogoutButton from './LogoutButton';
|
|
7
|
+
import ProfilePopupComponent from './ProfilePopupComponent';
|
|
7
8
|
|
|
8
|
-
import { updateProfilePicture, updateProfile } from
|
|
9
|
+
import { updateProfilePicture, updateProfile } from '../actions/user-actions'
|
|
9
10
|
|
|
10
|
-
import { getDefaultLocation } from
|
|
11
|
-
import {
|
|
12
|
-
|
|
13
|
-
import styles from "../styles/navbar.module.scss";
|
|
11
|
+
import { getDefaultLocation } from '../utils/loginUtils';
|
|
12
|
+
import {userHasAccessLevel, VirtualAccessLevel} from "../utils/authorizedGroups";
|
|
14
13
|
|
|
15
14
|
const UserNavbar = class extends React.Component {
|
|
16
15
|
|
|
@@ -19,7 +18,7 @@ const UserNavbar = class extends React.Component {
|
|
|
19
18
|
this.state = {
|
|
20
19
|
active: false,
|
|
21
20
|
showProfile: false,
|
|
22
|
-
navBarActiveClass:
|
|
21
|
+
navBarActiveClass: '',
|
|
23
22
|
}
|
|
24
23
|
}
|
|
25
24
|
|
|
@@ -33,9 +32,9 @@ const UserNavbar = class extends React.Component {
|
|
|
33
32
|
|
|
34
33
|
handleTogglePopup = (profile) => {
|
|
35
34
|
if (profile) {
|
|
36
|
-
document.body.classList.add(
|
|
35
|
+
document.body.classList.add('is-clipped');
|
|
37
36
|
} else {
|
|
38
|
-
document.body.classList.remove(
|
|
37
|
+
document.body.classList.remove('is-clipped');
|
|
39
38
|
}
|
|
40
39
|
this.setState({showProfile: profile})
|
|
41
40
|
}
|
|
@@ -54,7 +53,7 @@ const UserNavbar = class extends React.Component {
|
|
|
54
53
|
navBarActiveClass: `${styles.isActive}`,
|
|
55
54
|
})
|
|
56
55
|
: this.setState({
|
|
57
|
-
navBarActiveClass:
|
|
56
|
+
navBarActiveClass: '',
|
|
58
57
|
})
|
|
59
58
|
}
|
|
60
59
|
)
|
|
@@ -67,7 +66,7 @@ const UserNavbar = class extends React.Component {
|
|
|
67
66
|
|
|
68
67
|
// we store this calculation to use it later
|
|
69
68
|
const hasVirtualBadge =
|
|
70
|
-
userProfile ? userHasAccessLevel(userProfile.summit_tickets,
|
|
69
|
+
userProfile ? userHasAccessLevel(userProfile.summit_tickets, VirtualAccessLevel) : false;
|
|
71
70
|
|
|
72
71
|
let defaultPath = getDefaultLocation(eventRedirect, hasVirtualBadge);
|
|
73
72
|
|
|
@@ -144,4 +143,4 @@ const mapStateToProps = ({ settingState, userState }) => ({
|
|
|
144
143
|
userProfile: userState.userProfile
|
|
145
144
|
});
|
|
146
145
|
|
|
147
|
-
export default connect(mapStateToProps, { updateProfilePicture, updateProfile })(UserNavbar)
|
|
146
|
+
export default connect(mapStateToProps, { updateProfilePicture, updateProfile })(UserNavbar)
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"title": "Lobby",
|
|
5
5
|
"link": "/a/",
|
|
6
6
|
"display": true,
|
|
7
|
-
"
|
|
7
|
+
"requiresAuth": true,
|
|
8
8
|
"pageRestriction": [
|
|
9
9
|
"ANY"
|
|
10
10
|
]
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"title": "My Tickets",
|
|
14
14
|
"link": "/a/my-tickets",
|
|
15
15
|
"display": true,
|
|
16
|
-
"
|
|
16
|
+
"requiresAuth": true,
|
|
17
17
|
"pageRestriction": [
|
|
18
18
|
"ANY"
|
|
19
19
|
]
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"title": "Schedule",
|
|
23
23
|
"link": "/a/schedule",
|
|
24
24
|
"display": true,
|
|
25
|
-
"
|
|
25
|
+
"requiresAuth": false,
|
|
26
26
|
"pageRestriction": [
|
|
27
27
|
"ANY"
|
|
28
28
|
]
|
|
@@ -31,13 +31,13 @@
|
|
|
31
31
|
"title": "My Schedule",
|
|
32
32
|
"link": "/a/my-schedule",
|
|
33
33
|
"display": true,
|
|
34
|
-
"
|
|
34
|
+
"requiresAuth": false
|
|
35
35
|
},
|
|
36
36
|
{
|
|
37
37
|
"title": "My Profile",
|
|
38
38
|
"link": "/a/profile",
|
|
39
39
|
"display": true,
|
|
40
|
-
"
|
|
40
|
+
"requiresAuth": true,
|
|
41
41
|
"pageRestriction": [
|
|
42
42
|
"ANY"
|
|
43
43
|
]
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import React, {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import React, {useEffect, useState, useMemo} from "react";
|
|
2
|
+
import {connect} from "react-redux";
|
|
3
|
+
import {navigate} from "gatsby";
|
|
4
4
|
import { pick } from "@gatsbyjs/reach-router";
|
|
5
5
|
import { getUserProfile, requireExtraQuestions } from "../actions/user-actions";
|
|
6
6
|
import HeroComponent from "../components/HeroComponent";
|
|
7
|
-
import { userHasAccessLevel,
|
|
7
|
+
import { userHasAccessLevel, VirtualAccessLevel } from "../utils/authorizedGroups";
|
|
8
8
|
|
|
9
9
|
const pathsRequiringVirtualBadge = [
|
|
10
10
|
{ path: "/a/" },
|
|
@@ -12,7 +12,7 @@ const pathsRequiringVirtualBadge = [
|
|
|
12
12
|
{ path: "/a/posters" },
|
|
13
13
|
{ path: "/a/sponsors" },
|
|
14
14
|
{ path: "/a/posters/:trackGroupId" },
|
|
15
|
-
{ path: "/a/poster/:presentationId/" }
|
|
15
|
+
{ path: "/a/poster/:presentationId/" },
|
|
16
16
|
];
|
|
17
17
|
|
|
18
18
|
/**
|
|
@@ -44,7 +44,7 @@ const WithAuthzRoute = ({
|
|
|
44
44
|
|
|
45
45
|
// we store this calculation to use it later
|
|
46
46
|
const hasVirtualBadge = useMemo(() =>
|
|
47
|
-
userProfile ? userHasAccessLevel(userProfile.summit_tickets,
|
|
47
|
+
userProfile ? userHasAccessLevel(userProfile.summit_tickets, VirtualAccessLevel) : false,
|
|
48
48
|
[userProfile.summit_tickets]);
|
|
49
49
|
|
|
50
50
|
const userIsReady = () => {
|
|
@@ -98,7 +98,7 @@ const WithAuthzRoute = ({
|
|
|
98
98
|
return children;
|
|
99
99
|
};
|
|
100
100
|
|
|
101
|
-
const mapStateToProps = ({
|
|
101
|
+
const mapStateToProps = ({userState}) => ({
|
|
102
102
|
userProfile: userState.userProfile,
|
|
103
103
|
isAuthorized: userState.isAuthorized,
|
|
104
104
|
hasTicket: userState.hasTicket,
|
|
@@ -11,20 +11,19 @@
|
|
|
11
11
|
* limitations under the License.
|
|
12
12
|
**/
|
|
13
13
|
|
|
14
|
-
import React from
|
|
15
|
-
import URI from "urijs"
|
|
16
|
-
import { navigate } from "gatsby"
|
|
14
|
+
import React from 'react'
|
|
15
|
+
import URI from "urijs"
|
|
16
|
+
import { navigate } from "gatsby"
|
|
17
17
|
import { Redirect } from "@gatsbyjs/reach-router";
|
|
18
|
-
import { connect } from
|
|
18
|
+
import { connect } from 'react-redux';
|
|
19
19
|
import AbstractAuthorizationCallbackRoute from "openstack-uicore-foundation/lib/security/abstract-auth-callback-route";
|
|
20
|
-
import { getUserProfile, addToSchedule, removeFromSchedule } from
|
|
20
|
+
import { getUserProfile, addToSchedule, removeFromSchedule } from '../actions/user-actions'
|
|
21
21
|
import HeroComponent from "../components/HeroComponent";
|
|
22
|
-
import { getEnvVariable, IDP_BASE_URL, OAUTH2_CLIENT_ID } from
|
|
23
|
-
import { getPendingAction } from
|
|
22
|
+
import { getEnvVariable, IDP_BASE_URL, OAUTH2_CLIENT_ID } from '../utils/envVariables'
|
|
23
|
+
import { getPendingAction } from '../utils/schedule';
|
|
24
24
|
|
|
25
|
-
import
|
|
26
|
-
|
|
27
|
-
import "../styles/bulma.scss";
|
|
25
|
+
import '../styles/bulma.scss';
|
|
26
|
+
import {userHasAccessLevel, VirtualAccessLevel} from "../utils/authorizedGroups";
|
|
28
27
|
|
|
29
28
|
class AuthorizationCallbackRoute extends AbstractAuthorizationCallbackRoute {
|
|
30
29
|
|
|
@@ -37,16 +36,16 @@ class AuthorizationCallbackRoute extends AbstractAuthorizationCallbackRoute {
|
|
|
37
36
|
const pendingAction = getPendingAction();
|
|
38
37
|
if (pendingAction) {
|
|
39
38
|
const { action, event } = pendingAction;
|
|
40
|
-
action ===
|
|
39
|
+
action === 'ADD_EVENT' ? this.props.addToSchedule(event) : this.props.removeFromSchedule(event);
|
|
41
40
|
}
|
|
42
41
|
backUrl = URI.decode(backUrl);
|
|
43
42
|
// fallback
|
|
44
|
-
if(!backUrl || backUrl ==
|
|
45
|
-
backUrl =
|
|
43
|
+
if(!backUrl || backUrl == '')
|
|
44
|
+
backUrl = '/';
|
|
46
45
|
let { userProfile } = this.props;
|
|
47
46
|
// if redirect to lobby first time if we have virtual access
|
|
48
|
-
if(backUrl ==
|
|
49
|
-
backUrl =
|
|
47
|
+
if(backUrl == '/' && userProfile && userHasAccessLevel(userProfile.summit_tickets, VirtualAccessLevel)){
|
|
48
|
+
backUrl = '/a/';
|
|
50
49
|
}
|
|
51
50
|
navigate(backUrl);
|
|
52
51
|
});
|
|
@@ -55,9 +54,9 @@ class AuthorizationCallbackRoute extends AbstractAuthorizationCallbackRoute {
|
|
|
55
54
|
_redirect2Error(error) {
|
|
56
55
|
console.log(`AuthorizationCallbackRoute error ${error}`);
|
|
57
56
|
if (
|
|
58
|
-
error.includes(
|
|
59
|
-
error.includes(
|
|
60
|
-
) return <Redirect to={
|
|
57
|
+
error.includes('access_denied') ||
|
|
58
|
+
error.includes('consent_required')
|
|
59
|
+
) return <Redirect to={'/'} noThrow />;
|
|
61
60
|
return <Redirect to={`/error?error=${error}`} noThrow/>;
|
|
62
61
|
}
|
|
63
62
|
|
|
@@ -88,4 +87,4 @@ export default connect(mapStateToProps, {
|
|
|
88
87
|
getUserProfile,
|
|
89
88
|
addToSchedule,
|
|
90
89
|
removeFromSchedule,
|
|
91
|
-
})(AuthorizationCallbackRoute)
|
|
90
|
+
})(AuthorizationCallbackRoute)
|
package/src/styles/colors.scss
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Warning:
|
|
3
|
+
* Dont edit this file by hand, has been generated by colors scss util
|
|
4
|
+
* Uses default colors as base and then overriden by colors set via marketing
|
|
5
|
+
**/
|
|
6
|
+
|
|
7
|
+
$color_accent: #ff5e32;
|
|
2
8
|
$color_alerts: #ff0000;
|
|
3
9
|
$color_background_light: #ffffff;
|
|
4
10
|
$color_background_dark: #000000;
|
|
@@ -19,16 +25,16 @@ $color_input_text_color_light: #363636;
|
|
|
19
25
|
$color_input_text_color_dark: #ffffff;
|
|
20
26
|
$color_input_text_color_disabled_light: #ffffff;
|
|
21
27
|
$color_input_text_color_disabled_dark: #ffffff;
|
|
22
|
-
$color_primary: #
|
|
23
|
-
$color_primary_contrast: #
|
|
24
|
-
$color_secondary: #
|
|
25
|
-
$color_secondary_contrast: #
|
|
28
|
+
$color_primary: #6d6e71;
|
|
29
|
+
$color_primary_contrast: #f1f2f2;
|
|
30
|
+
$color_secondary: #00CEC4;
|
|
31
|
+
$color_secondary_contrast: #ff5e32;
|
|
26
32
|
$color_text_light: #ffffff;
|
|
27
33
|
$color_text_med: #828282;
|
|
28
|
-
$color_text_dark: #
|
|
34
|
+
$color_text_dark: #333333;
|
|
29
35
|
$color_text_input_hints_light: #7b7b7b;
|
|
30
36
|
$color_text_input_hints_dark: #7b7b7b;
|
|
31
|
-
$color_text_input_hints: #
|
|
37
|
+
$color_text_input_hints: #c4c4c4;
|
|
32
38
|
|
|
33
39
|
:root {
|
|
34
40
|
--color_primary: #{$color_primary};
|
package/src/styles/fonts.scss
CHANGED
|
@@ -1,31 +1,26 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Warning:
|
|
3
|
+
* Dont edit this file by hand, has been generated by fonts scss util
|
|
4
|
+
* Generated with font values set via CMS
|
|
5
|
+
**/
|
|
6
|
+
|
|
7
|
+
$font-family: 'Nunito Sans', sans-serif;
|
|
2
8
|
|
|
3
9
|
:root {
|
|
4
|
-
--font_family:
|
|
10
|
+
--font_family: #{$font-family};
|
|
5
11
|
}
|
|
6
12
|
|
|
7
|
-
@font-face {
|
|
8
|
-
font-family: "BuilderExtended";
|
|
9
|
-
src: url("/fonts/buildersans-regular.woff") format("woff");
|
|
10
|
-
font-weight: normal;
|
|
11
|
-
}
|
|
12
|
-
@font-face {
|
|
13
|
-
font-family: "BuilderExtended";
|
|
14
|
-
src: url("/fonts/builderextended-semibold.woff") format("woff");
|
|
15
|
-
font-weight: bold;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
13
|
%font-regular {
|
|
19
|
-
font-family:
|
|
14
|
+
font-family: 'Nunito Sans', sans-serif;
|
|
20
15
|
font-weight: 400;
|
|
21
16
|
}
|
|
22
17
|
|
|
23
18
|
%font-semi {
|
|
24
|
-
font-family:
|
|
19
|
+
font-family: 'Nunito Sans', sans-serif;
|
|
25
20
|
font-weight: 600;
|
|
26
21
|
}
|
|
27
22
|
|
|
28
23
|
%font-bold {
|
|
29
|
-
font-family:
|
|
24
|
+
font-family: 'Nunito Sans', sans-serif;
|
|
30
25
|
font-weight: 700;
|
|
31
26
|
}
|
|
@@ -7,9 +7,9 @@ import { MDXProvider } from "@mdx-js/react";
|
|
|
7
7
|
import ContentPageTemplate from "./template";
|
|
8
8
|
import Layout from "../../components/Layout";
|
|
9
9
|
import Seo from "../../components/Seo";
|
|
10
|
-
import { titleFromPathname } from "
|
|
10
|
+
import { titleFromPathname } from "../../utils/urlFormating";
|
|
11
11
|
|
|
12
|
-
import { USER_REQUIREMENTS } from "
|
|
12
|
+
import { USER_REQUIREMENTS } from "../../cms/config/collections/contentPagesCollection";
|
|
13
13
|
|
|
14
14
|
const ContentPage = ({
|
|
15
15
|
data,
|
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
import React, {useMemo} from
|
|
2
|
-
import { connect } from
|
|
3
|
-
import { navigate } from "gatsby"
|
|
1
|
+
import React, {useMemo} from 'react'
|
|
2
|
+
import { connect } from 'react-redux'
|
|
3
|
+
import { navigate } from "gatsby"
|
|
4
4
|
|
|
5
|
-
import Layout from
|
|
6
|
-
import AuthComponent from
|
|
5
|
+
import Layout from '../components/Layout'
|
|
6
|
+
import AuthComponent from '../components/AuthComponent'
|
|
7
7
|
|
|
8
|
-
import { getDefaultLocation } from
|
|
9
|
-
import {userHasAccessLevel,
|
|
8
|
+
import { getDefaultLocation } from '../utils/loginUtils'
|
|
9
|
+
import {userHasAccessLevel, VirtualAccessLevel} from "../utils/authorizedGroups";
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
export const LoginPageTemplate = ({ loggedUserState, eventRedirect, location, userProfile }) => {
|
|
13
13
|
|
|
14
14
|
// we store this calculation to use it later
|
|
15
15
|
const hasVirtualBadge = useMemo(() =>
|
|
16
|
-
userProfile ? userHasAccessLevel(userProfile.summit_tickets,
|
|
16
|
+
userProfile ? userHasAccessLevel(userProfile.summit_tickets, VirtualAccessLevel) : false,
|
|
17
17
|
[userProfile]);
|
|
18
18
|
|
|
19
19
|
if (loggedUserState.isLoggedUser) {
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import React from
|
|
2
|
-
import PropTypes from
|
|
3
|
-
import { connect } from
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import PropTypes from 'prop-types'
|
|
3
|
+
import { connect } from 'react-redux'
|
|
4
4
|
|
|
5
5
|
import URI from "urijs";
|
|
6
|
-
import { handleResetReducers } from
|
|
7
|
-
import { doLogin } from
|
|
6
|
+
import { handleResetReducers } from '../actions/event-actions'
|
|
7
|
+
import { doLogin } from 'openstack-uicore-foundation/lib/security/methods'
|
|
8
8
|
|
|
9
|
-
import { getDefaultLocation } from
|
|
9
|
+
import { getDefaultLocation } from '../utils/loginUtils';
|
|
10
10
|
|
|
11
|
-
import HeroComponent from
|
|
12
|
-
import { userHasAccessLevel,
|
|
11
|
+
import HeroComponent from '../components/HeroComponent'
|
|
12
|
+
import { userHasAccessLevel, VirtualAccessLevel } from "../utils/authorizedGroups";
|
|
13
13
|
|
|
14
14
|
export const TokenExpirePageTemplate = class extends React.Component {
|
|
15
15
|
|
|
@@ -22,10 +22,10 @@ export const TokenExpirePageTemplate = class extends React.Component {
|
|
|
22
22
|
|
|
23
23
|
// we store this calculation to use it later
|
|
24
24
|
const hasVirtualBadge =
|
|
25
|
-
userProfile ? userHasAccessLevel(userProfile.summit_tickets,
|
|
25
|
+
userProfile ? userHasAccessLevel(userProfile.summit_tickets, VirtualAccessLevel) : false;
|
|
26
26
|
|
|
27
27
|
let defaultPath = getDefaultLocation(eventRedirect, hasVirtualBadge);
|
|
28
|
-
let previousLocation = location.state?.backUrl && location.state.backUrl !==
|
|
28
|
+
let previousLocation = location.state?.backUrl && location.state.backUrl !== '/auth/expired' ? location.state.backUrl : defaultPath;
|
|
29
29
|
let backUrl = URI.encode(previousLocation);
|
|
30
30
|
|
|
31
31
|
setTimeout(() => {
|
|
@@ -26,6 +26,7 @@ export const REAL_TIME_UPDATES_STRATEGY = "REAL_TIME_UPDATES_STRATEGY";
|
|
|
26
26
|
export const TIMEINTERVALSINCE1970_API_URL = "TIMEINTERVALSINCE1970_API_URL";
|
|
27
27
|
export const ABLY_API_KEY = "ABLY_API_KEY";
|
|
28
28
|
export const GOOGLE_TAGMANAGER_ID = "GOOGLE_TAGMANAGER_ID";
|
|
29
|
+
export const HASH_SANITIZE_TOKENS = "HASH_SANITIZE_TOKENS";
|
|
29
30
|
|
|
30
31
|
const processEnv = {
|
|
31
32
|
/**
|
|
@@ -63,6 +64,7 @@ const processEnv = {
|
|
|
63
64
|
TIMEINTERVALSINCE1970_API_URL: process.env.GATSBY_TIMEINTERVALSINCE1970_API_URL,
|
|
64
65
|
ABLY_API_KEY: process.env.GATSBY_ABLY_API_KEY,
|
|
65
66
|
GOOGLE_TAGMANAGER_ID: process.env.GATSBY_GOOGLE_TAGMANAGER_ID,
|
|
67
|
+
HASH_SANITIZE_TOKENS: process.env.GATSBY_HASH_SANITIZE_TOKENS
|
|
66
68
|
}
|
|
67
69
|
|
|
68
70
|
export const getEnvVariable = (name) => {
|
package/src/cms/config/utils.js
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
const USER_REQUIREMENTS = {
|
|
2
|
-
none: "NONE",
|
|
3
|
-
loggedIn: "LOGGED_IN",
|
|
4
|
-
hasTicket: "HAS_TICKET"
|
|
5
|
-
};
|
|
6
|
-
|
|
7
|
-
const PAGE_RESTRICTIONS = {
|
|
8
|
-
any: "ANY",
|
|
9
|
-
activity: "ACTIVITY",
|
|
10
|
-
marketing: "MARKETING",
|
|
11
|
-
lobby: "LOBBY",
|
|
12
|
-
show: "SHOW",
|
|
13
|
-
customPage: "CUSTOM_PAGE"
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
export { USER_REQUIREMENTS, PAGE_RESTRICTIONS };
|