Skip to content

Commit

Permalink
[MINI-5706] Fix for Access Token permission issue (#238)
Browse files Browse the repository at this point in the history
* Fix for Access Token permission issue
  • Loading branch information
rleojoseph authored Jan 6, 2023
1 parent 7ac91ef commit c44f1cf
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 63 deletions.
2 changes: 1 addition & 1 deletion .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# See https://help.github.com/en/articles/about-code-owners

@rakutentech/miniapp-technology
* @rakutentech/miniapp-technology
2 changes: 1 addition & 1 deletion .github/pull_request_template
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ Explain your rationale of technical decisions you made (unless discussed before)
Add links to github/jira issues, design documents and other relevant resources (e.g. previous discussions, platform/tool documentation etc.)

# Checklist
- [ ] I have completed all steps in the [Contribution Checklist](../.github/CONTRIBUTING.md#checklist)
- [ ] I have completed all steps in the [Contribution Checklist](../blob/master.github/CONTRIBUTING.md#checklist)
110 changes: 63 additions & 47 deletions js-miniapp-sample/src/pages/auth-token.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import {
FormGroup,
Typography,
CardContent,
ListItemText,
FormControl,
TextField,
} from '@material-ui/core';
Expand All @@ -19,6 +18,7 @@ import {
CustomPermissionName,
CustomPermissionStatus,
AccessTokenData,
MiniAppError,
} from 'js-miniapp-sdk';
import { connect } from 'react-redux';

Expand Down Expand Up @@ -70,37 +70,45 @@ const useStyles = makeStyles((theme) => ({
const initialState = {
isLoading: false,
isError: false,
hasRequestedPermissions: false,
error: null,
permissionDenied: false,
};

const dataFetchReducer = (state, action) => {
switch (action.type) {
case 'FETCH_INIT':
case 'TOKEN_FETCH_INIT':
return {
...state,
isLoading: true,
isError: false,
hasRequestedPermissions: false,
error: null,
permissionDenied: false,
};
case 'FETCH_SUCCESS':
case 'TOKEN_FETCH_SUCCESS':
return {
...state,
isLoading: false,
isError: false,
hasRequestedPermissions: true,
error: null,
permissionDenied: false,
};
case 'FETCH_FAILURE':
case 'TOKEN_FETCH_FAILURE':
return {
...state,
isLoading: false,
isError: true,
error:
(typeof action.miniAppError == 'string'
? action.miniAppError
: action.miniAppError.message) || '',
(typeof action.error == 'string'
? action.error
: action.error.message) || '',
};
case 'PERMISSION_FAILURE':
return {
...state,
isLoading: false,
isError: false,
error: null,
permissionDenied: true,
};
default:
throw new Error();
Expand All @@ -110,6 +118,7 @@ const dataFetchReducer = (state, action) => {
type AuthTokenProps = {
permissions: CustomPermissionName[],
accessToken: AccessTokenData,
error: MiniAppError,
getAccessToken: (audience: string, scopes: string[]) => Promise<string>,
requestPermissions: (
permissions: CustomPermission[]
Expand Down Expand Up @@ -152,19 +161,17 @@ function AuthToken(props: AuthTokenProps) {
permission.status === CustomPermissionStatus.ALLOWED
)
.map((permission) => permission.name);
if (!hasPermission(CustomPermissionName.ACCESS_TOKEN, permissions)) {
requestAccessToken();
} else {
dispatch({ type: 'PERMISSION_FAILURE', permissionDenied: true });
}
} else {
dispatch({ type: 'PERMISSION_FAILURE', permissionDenied: true });
}
})
.then((permissions) =>
Promise.all([
hasPermission(CustomPermissionName.ACCESS_TOKEN, permissions)
? props.getAccessToken(scope.audience, scope.scopes)
: null,
])
)
.then(() => dispatch({ type: 'FETCH_SUCCESS' }))
.catch((miniAppError) => {
console.error(miniAppError);
dispatch({ type: 'FETCH_FAILURE', miniAppError });
.catch((error) => {
dispatch({ type: 'PERMISSION_FAILURE', permissionDenied: true });
});
}

Expand All @@ -173,10 +180,21 @@ function AuthToken(props: AuthTokenProps) {
return permissionList.indexOf(permission) > -1;
}

function requestAccessToken() {
props
.getAccessToken(scope.audience, scope.scopes)
.then((permissions) => {
dispatch({ type: 'TOKEN_FETCH_SUCCESS' });
})
.catch((e) => {
dispatch({ type: 'TOKEN_FETCH_FAILURE', error: e });
});
}

function handleClick(e) {
if (!state.isLoading) {
e.preventDefault();
dispatch({ type: 'FETCH_INIT' });
dispatch({ type: 'TOKEN_FETCH_INIT' });
requestAccessTokenPermission();
}
}
Expand All @@ -201,19 +219,6 @@ function AuthToken(props: AuthTokenProps) {
);
}

function AccessToken() {
const hasDeniedPermission =
state.hasRequestedPermissions &&
!hasPermission(CustomPermissionName.ACCESS_TOKEN);

return hasDeniedPermission ? (
<ListItemText
primary="Access Token permission is denied by the user."
className={classes.red}
/>
) : null;
}

return (
<GreyCard height="auto">
<CardContent>
Expand All @@ -239,30 +244,41 @@ function AuthToken(props: AuthTokenProps) {
</FormControl>
</Fragment>
{ButtonWrapper()}
{!state.isLoading && !state.isError && props.accessToken && (
<Typography variant="body1" className={classes.success}>
Token: {props.accessToken.token}
</Typography>
)}
{!state.isLoading && !state.isError && props.accessToken && (
<Typography variant="body1" className={classes.success}>
Valid until: {displayDate(props.accessToken.validUntil)}
{!state.isLoading &&
!state.isError &&
!state.permissionDenied &&
props.accessToken && (
<Typography variant="body1" className={classes.success}>
Token: {props.accessToken.token}
</Typography>
)}
{!state.isLoading &&
!state.isError &&
!state.permissionDenied &&
props.accessToken && (
<Typography variant="body1" className={classes.success}>
Valid until: {displayDate(props.accessToken.validUntil)}
</Typography>
)}
{!state.isLoading && state.isError && !state.permissionDenied && (
<Typography variant="body1" className={classes.red}>
{state.error}
</Typography>
)}
{!state.isLoading && state.isError && (
{!state.isLoading && state.permissionDenied && (
<Typography variant="body1" className={classes.red}>
Something went wrong, please try again later.
ACCESS_TOKEN Permission is denied by the user
</Typography>
)}
<div>{AccessToken()}</div>
</FormGroup>
</CardContent>
</GreyCard>
);
}

const mapStateToProps = (state) => {
const mapStateToProps = (state, props) => {
return {
...props,
permissions: state.permissions,
accessToken: state.user.accessToken,
error: state.error,
Expand Down
9 changes: 6 additions & 3 deletions js-miniapp-sample/src/services/permissions/actions.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
import MiniApp, {
CustomPermission,
CustomPermissionResult,
MiniAppError,
} from 'js-miniapp-sdk';

import {
REQUEST_PERMISSIONS_SUCCESS,
REQUEST_PERMISSIONS_FAILURE,
} from './types';

type PermissionsSuccessAction = {
type PermissionsAction = {
type: String,
permissions: CustomPermissionResult[],
error: MiniAppError
};

const requestCustomPermissions = (
Expand All @@ -26,13 +28,14 @@ const requestCustomPermissions = (

return permissions;
})
.catch((_) => {
.catch((e) => {
dispatch({
type: REQUEST_PERMISSIONS_FAILURE,
error: e,
});
});
};
};

export { requestCustomPermissions };
export type { PermissionsSuccessAction };
export type { PermissionsAction };
36 changes: 27 additions & 9 deletions js-miniapp-sample/src/services/permissions/reducers.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,23 @@
import { CustomPermissionName, CustomPermissionStatus } from 'js-miniapp-sdk';

import type { PermissionsSuccessAction } from './actions';
import { REQUEST_PERMISSIONS_SUCCESS } from './types';
import type { PermissionsAction } from './actions';
import { REQUEST_PERMISSIONS_SUCCESS, REQUEST_PERMISSIONS_FAILURE } from './types';

const defaultState: CustomPermissionName[] = [];
type PermissionsState = {
type: REQUEST_PERMISSIONS_FAILURE,
permissions: CustomPermissionResult[],
error: MiniAppError
};

const defaultState: PermissionsState = {
type: undefined,
permissions: [],
error: null
};

const grantedPermissionsReducer = (
const PermissionsReducer = (
state: CustomPermissionName[] = defaultState,
action: PermissionsSuccessAction
action: PermissionsAction
): CustomPermissionName[] => {
switch (action.type) {
case REQUEST_PERMISSIONS_SUCCESS:
Expand All @@ -17,15 +27,23 @@ const grantedPermissionsReducer = (
const allowed = action.permissions
.filter((it) => it.status === CustomPermissionStatus.ALLOWED)
.map((it) => it.name);

const array = state
const array = state.permissions
.concat(allowed)
.filter((permission) => denied.indexOf(permission) <= -1);

return Array.from(new Set(array));
return {
type: REQUEST_PERMISSIONS_SUCCESS,
permissions: array,
error: action.error,
};
case REQUEST_PERMISSIONS_FAILURE:
return {
...defaultState,
error: action.error,
};
default:
return state;
}
};

export { grantedPermissionsReducer };
export { PermissionsReducer };
4 changes: 2 additions & 2 deletions js-miniapp-sample/src/services/reducers.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@ import {
SecureStorageStatusReducer,
} from './landing/reducers';
import MessageReducer from './message/reducers';
import { grantedPermissionsReducer } from './permissions/reducers';
import { PermissionsReducer } from './permissions/reducers';
import storageReducer from './secure-storage/reducers';
import userReducer from './user/reducers';
import { UUIDReducer } from './uuid/reducers';

export default combineReducers({
message: MessageReducer,
home: HomeStateReducer,
permissions: grantedPermissionsReducer,
permissions: PermissionsReducer,
user: userReducer,
uuid: UUIDReducer,
info: HostEnvironmentInfoReducer,
Expand Down

0 comments on commit c44f1cf

Please sign in to comment.