Skip to content

Commit 9dcc485

Browse files
committed
GAME-73
1 parent 7cdfbe5 commit 9dcc485

File tree

11 files changed

+73
-6
lines changed

11 files changed

+73
-6
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,7 @@ The PlatformRoute model has several useful options:
273273
| `authRequired?: boolean` | Requiring authentication for a route means that users who are not logged in will be redirected to the Login Form when they try to access the route. |
274274
| `route: string` | The route property is the path to the route, relative to its parent(s). |
275275
| `title: string` | The title property is the text that will appear in the Tools or Utils Selectors (this is irrelevant on hidden routes). |
276+
| `rolesRequired: Array<string>` | Requiring roles for a route means that users who do not own the roles will be presented with restricted page when they try to access the route. |
276277

277278
## Git
278279

src-ts/lib/profile-provider/profile-functions/profile-factory/profile.factory.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,7 @@ export function create(profile: UserProfile, token: TokenModel): UserProfile {
1414
// rolees.
1515
profile.isCustomer = !!token.roles?.some(role => role === UserRole.customer)
1616
profile.isMember = !profile.isCustomer
17+
// store roles for custom capability checks
18+
profile.roles = token.roles
1719
return profile
1820
}

src-ts/lib/profile-provider/user-profile.model.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ export interface UserProfile {
1010
isMember?: boolean
1111
lastName: string
1212
photoURL?: string
13+
roles?: Array<string>,
1314
status: string
1415
updatedAt: number
15-
userId: number
16+
userId: number,
1617
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
.contentLayout {
2+
width: 100%;
3+
padding-bottom: 0;
4+
5+
.contentLayout-outer {
6+
width: 100%;
7+
8+
.contentLayout-inner {
9+
width: 100%;
10+
overflow: visible;
11+
}
12+
}
13+
}
14+
15+
.container {
16+
display: flex;
17+
padding-top: 26px;
18+
19+
a {
20+
color: #0D61BF;
21+
22+
&:hover {
23+
color: #0D61BF;
24+
text-decoration: underline;
25+
}
26+
}
27+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { ReactElement } from 'react'
2+
3+
import { ContentLayout } from '..'
4+
5+
import styles from './RestrictedPage.module.scss'
6+
7+
export const RestrictedPage: ReactElement =
8+
<ContentLayout
9+
contentClass={styles['contentLayout']}
10+
outerClass={styles['contentLayout-outer']}
11+
innerClass={styles['contentLayout-inner']}
12+
title='Thanks for visiting'
13+
>
14+
<div className={styles.container}>
15+
<p>Unfortenatly, you are not permitted to access the site. If you feel you should be able to, please contact us at <a href='mailto:support@topcoder.com'>support@topcoder.com</a>.</p>
16+
</div>
17+
</ContentLayout>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { RestrictedPage } from './RestrictedPage'

src-ts/lib/route-provider/platform-route.model.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ export interface PlatformRoute {
77
element: JSX.Element
88
hidden?: boolean
99
memberOnly?: boolean
10+
rolesRequired?: Array<string>
1011
route: string
1112
title?: string
1213
}

src-ts/lib/route-provider/require-auth-provider/require-auth.provider.tsx

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,37 @@
11
import { useContext } from 'react'
22

33
import { profileContext, ProfileContextData } from '../../profile-provider'
4+
import { RestrictedPage } from '../../restricted-page'
45

56
interface RequireAuthProviderProps {
67
children: JSX.Element
7-
loginUrl: string
8+
loginUrl: string,
9+
rolesRequired?: Array<string>,
810
}
911

1012
function RequireAuthProvider(props: RequireAuthProviderProps): JSX.Element {
1113

1214
const profileContextData: ProfileContextData = useContext(profileContext)
1315
const { profile, initialized }: ProfileContextData = profileContextData
1416

15-
// if we have a profile or we're not initialized yet, just return the children
16-
if (!initialized || !!profile) {
17+
// if we're not initialized yet, just return the children
18+
if (!initialized) {
1719
return props.children
1820
}
1921

22+
// if we have a profile and `rolesRequired` is configured for the route
23+
// check the user's roles, allow access or show restricted page
24+
if (!!profile) {
25+
if (props.rolesRequired) {
26+
if (!profile.roles) { return RestrictedPage }
27+
const intersection: Array<string> = profile.roles?.filter(r => props.rolesRequired?.includes(r))
28+
if (intersection.length !== props.rolesRequired.length) { return RestrictedPage }
29+
return props.children
30+
} else {
31+
return props.children
32+
}
33+
}
34+
2035
// redirect to the login page
2136
window.location.href = props.loginUrl
2237
return <></>

src-ts/lib/route-provider/route.provider.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ export const RouteProvider: FC<RouteProviderProps> = (props: RouteProviderProps)
124124
const routeElement: JSX.Element = !route.authRequired
125125
? route.element
126126
: (
127-
<RequireAuthProvider loginUrl={authUrlLogin()}>
127+
<RequireAuthProvider loginUrl={authUrlLogin()} rolesRequired={route.rolesRequired}>
128128
{route.element}
129129
</RequireAuthProvider>
130130
)

src-ts/tools/gamification-admin/GamificationAdmin.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88

99
export const toolTitle: string = 'Gamification Admin'
1010
export const baseUrl: string = '/gamification-admin'
11+
export const rolesRequired: Array<string> = ['Gamification Admin']
1112

1213
const GamificationAdmin: FC<{}> = () => {
1314

0 commit comments

Comments
 (0)