Skip to content

Commit

Permalink
Luminus Authentication (#534)
Browse files Browse the repository at this point in the history
* initial

* add port
  • Loading branch information
jiachen247 authored and rrtheonlyone committed Jun 6, 2019
1 parent d42011b commit 553a24c
Show file tree
Hide file tree
Showing 14 changed files with 43 additions and 42 deletions.
2 changes: 1 addition & 1 deletion .env.example
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
REACT_APP_IVLE_KEY=your_ivle_key_here
REACT_APP_LUMINUS_CLIENT_ID=your_luminus_client_id_here
REACT_APP_VERSION=$npm_package_version
REACT_APP_BACKEND_URL=http://localhost:4001
REACT_APP_USE_BACKEND=TRUE
13 changes: 5 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,12 @@

1. Install a stable version of NodeJS (tested: Node 10.15.0).
2. Run `npm install` to install dependencies.
3. Copy the `.env.example` file as `.env` and set the variable `REACT_APP_IVLE_KEY`
to contain your IVLE Lapi key.
4. Run `npm start` to start the server at `localhost:80`. Admin permissions may
be required for your OS to serve at port 80.
5. If running cadet without ngix, `npm run cors-proxy` to solve CORS problems.
3. Copy the `.env.example` file as `.env` and set the variable `REACT_APP_CLIENT_ID`
to contain your LumiNUS api key.
4. Run `npm start` to start the server at `localhost:8075`. Admin permissions may
be required for your OS to serve at port 8075.
5. If running cadet without nginx, `npm run cors-proxy` to solve CORS problems.

## IVLE LAPI Key
For NUS students, you can access your IVLE LAPI key [here](https://ivle.nus.edu.sg/LAPI/default.aspx).

## For Windows Users

### Running cadet-frontend
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"format:tsx": "prettier --list-different \"src/**/*.{ts,tsx}\"",
"format:scss": "prettier --list-different --parser scss \"src/**/*.scss\"",
"format:ci": "npm run format:tsx && npm run format:scss",
"start-js": "cross-env BROWSER=none PORT=80 react-scripts-ts start",
"start-js": "cross-env BROWSER=none PORT=8075 react-scripts-ts start",
"start": "npm-run-all -p watch-css start-js",
"test": "react-scripts-ts test --env=jsdom",
"test-coveralls": "./scripts/coverage-fix.sh do && react-scripts-ts test --env=jsdom --coverage --coverageReporters=text-lcov | coveralls",
Expand Down
4 changes: 2 additions & 2 deletions src/actions/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ import * as actionTypes from './actionTypes';

import { Role } from '../reducers/states';

export const fetchAuth: ActionCreator<actionTypes.IAction> = (ivleToken: string) => ({
export const fetchAuth: ActionCreator<actionTypes.IAction> = (luminusCode: string) => ({
type: actionTypes.FETCH_AUTH,
payload: ivleToken
payload: luminusCode
});

export const fetchAnnouncements = () => ({
Expand Down
2 changes: 1 addition & 1 deletion src/components/Application.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ const toAcademy = (props: IApplicationProps) =>
: () => <Academy accessToken={props.accessToken} role={props.role!} />;

const toLogin = (props: IApplicationProps) => () => (
<Login ivleToken={qs.parse(props.location.search).token} />
<Login luminusCode={qs.parse(props.location.search).code} />
);

const parsePlayground = (props: IApplicationProps) => {
Expand Down
14 changes: 7 additions & 7 deletions src/components/Login.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,17 @@ import { NavLink } from 'react-router-dom';
type LoginProps = DispatchProps & OwnProps;

export type DispatchProps = {
handleFetchAuth: (ivleToken: string) => void;
handleFetchAuth: (luminusCode: string) => void;
handleLogin: () => void;
};

export type OwnProps = {
ivleToken?: string;
luminusCode?: string;
};

const Login: React.SFC<LoginProps> = props => {
if (props.ivleToken) {
startFetchAuth(props.ivleToken, props.handleFetchAuth);
if (props.luminusCode) {
startFetchAuth(props.luminusCode, props.handleFetchAuth);
return (
<div className="Login pt-dark">
<Card className="login-card pt-elevation-4">
Expand Down Expand Up @@ -48,12 +48,12 @@ const Login: React.SFC<LoginProps> = props => {
}
};

const startFetchAuth = (ivleToken: string, handleFetchAuth: DispatchProps['handleFetchAuth']) =>
handleFetchAuth(ivleToken);
const startFetchAuth = (luminusCode: string, handleFetchAuth: DispatchProps['handleFetchAuth']) =>
handleFetchAuth(luminusCode);

const loginButton = (handleClick: () => void) => (
<Button className="pt-large" rightIcon="log-in" onClick={handleClick}>
Log in with IVLE
Log in with LumiNUS
</Button>
);

Expand Down
2 changes: 1 addition & 1 deletion src/components/NavigationBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ const NavigationBar: React.SFC<INavigationBarProps> = props => (
activeClassName="pt-active"
className="NavigationBar__link pt-button pt-minimal"
target="_blank"
to={LINKS.IVLE}
to={LINKS.LUMINUS}
>
<Icon icon={IconNames.BOOK} />
<div className="navbar-button-text hidden-xs">News &amp; Material</div>
Expand Down
6 changes: 3 additions & 3 deletions src/components/__tests__/Login.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import Login from '../Login';
test('Login renders correctly', () => {
const props = {
handleLogin: () => {},
handleFetchAuth: (ivleToken: string) => {}
handleFetchAuth: (luminusCode: string) => {}
};
const app = <Login {...props} />;
const tree = shallow(app);
Expand All @@ -16,8 +16,8 @@ test('Login renders correctly', () => {
test('Loading login renders correctly', () => {
const props = {
handleLogin: () => {},
handleFetchAuth: (ivleToken: string) => {},
ivleToken: '1VL3 T0K3N'
handleFetchAuth: (luminusCode: string) => {},
luminusCode: 'Luminus Code'
};
const app = <Login {...props} />;
const tree = shallow(app);
Expand Down
2 changes: 1 addition & 1 deletion src/components/__tests__/__snapshots__/Login.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ exports[`Login renders correctly 1`] = `
<div className=\\"login-body\\">
<Blueprint2.ButtonGroup fill={true} vertical={true}>
<Blueprint2.Button className=\\"pt-large\\" rightIcon=\\"log-in\\" onClick={[Function: handleLogin]}>
Log in with IVLE
Log in with LumiNUS
</Blueprint2.Button>
<NavLink to=\\"/playground\\" activeClassName=\\"active\\" aria-current=\\"page\\">
<Blueprint2.Button className=\\"pt-large\\" rightIcon=\\"code\\">
Expand Down
4 changes: 2 additions & 2 deletions src/components/__tests__/__snapshots__/NavigationBar.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ exports[`NavigationBar renders "Not logged in" correctly 1`] = `
Source Academy
</Blueprint2.NavbarHeading>
</NavLink>
<NavLink activeClassName=\\"pt-active\\" className=\\"NavigationBar__link pt-button pt-minimal\\" target=\\"_blank\\" to=\\"https://ivle.nus.edu.sg/v1/Module/Student/default.aspx?CourseID=a6579f36-4d7d-41fb-b394-92a00b78148b\\" aria-current=\\"page\\">
<NavLink activeClassName=\\"pt-active\\" className=\\"NavigationBar__link pt-button pt-minimal\\" target=\\"_blank\\" to=\\"https://luminus.nus.edu.sg/modules/57290e55-335a-4c09-b904-a795572d6cda\\" aria-current=\\"page\\">
<Blueprint2.Icon icon=\\"book\\" />
<div className=\\"navbar-button-text hidden-xs\\">
News &amp; Material
Expand Down Expand Up @@ -55,7 +55,7 @@ exports[`NavigationBar renders correctly with username 1`] = `
Source Academy
</Blueprint2.NavbarHeading>
</NavLink>
<NavLink activeClassName=\\"pt-active\\" className=\\"NavigationBar__link pt-button pt-minimal\\" target=\\"_blank\\" to=\\"https://ivle.nus.edu.sg/v1/Module/Student/default.aspx?CourseID=a6579f36-4d7d-41fb-b394-92a00b78148b\\" aria-current=\\"page\\">
<NavLink activeClassName=\\"pt-active\\" className=\\"NavigationBar__link pt-button pt-minimal\\" target=\\"_blank\\" to=\\"https://luminus.nus.edu.sg/modules/57290e55-335a-4c09-b904-a795572d6cda\\" aria-current=\\"page\\">
<Blueprint2.Icon icon=\\"book\\" />
<div className=\\"navbar-button-text hidden-xs\\">
News &amp; Material
Expand Down
8 changes: 4 additions & 4 deletions src/components/academy/game/create-initializer.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,19 @@ export default function (StoryXMLPlayer, story, username, attemptedAll) {
case 'textbook':
return window.open(LINKS.TEXTBOOK, '_blank');
case 'announcements':
return window.open(LINKS.IVLE);
return window.open(LINKS.LUMINUS);
case 'lesson_plan':
return history.push('/academy/missions');
case 'students':
return history.push(LINKS.PIAZZA);
case 'materials':
return window.open(LINKS.IVLE);
return window.open(LINKS.LUMINUS);
case 'IDE':
return history.push('/playground');
case 'path':
return history.push('/academy/paths');
default:
return window.open(LINKS.IVLE);
return window.open(LINKS.LUMINUS);
}
},
pickUpCollectible: function () { },
Expand All @@ -48,7 +48,7 @@ export default function (StoryXMLPlayer, story, username, attemptedAll) {
};

function openWristDevice() {
window.open(LINKS.IVLE);
window.open(LINKS.LUMINUS);
}

function startGame(div, canvas, saveData) {
Expand Down
8 changes: 4 additions & 4 deletions src/sagas/backend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ type Tokens = {

function* backendSaga(): SagaIterator {
yield takeEvery(actionTypes.FETCH_AUTH, function*(action) {
const ivleToken = (action as actionTypes.IAction).payload;
const tokens = yield call(postAuth, ivleToken);
const luminusCode = (action as actionTypes.IAction).payload;
const tokens = yield call(postAuth, luminusCode);
const user = tokens ? yield call(getUser, tokens) : null;
if (tokens && user) {
// Use dispatch instead of saga's put to guarantee the reducer has
Expand Down Expand Up @@ -263,9 +263,9 @@ function* backendSaga(): SagaIterator {
/**
* POST /auth
*/
async function postAuth(ivleToken: string): Promise<Tokens | null> {
async function postAuth(luminusCode: string): Promise<Tokens | null> {
const response = await request('auth', 'POST', {
body: { login: { ivle_token: ivleToken } },
body: { login: { luminus_code: luminusCode } },
errorMessage: 'Could not login. Please contact the module administrator.'
});
if (response) {
Expand Down
12 changes: 7 additions & 5 deletions src/sagas/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { ExternalLibraryNames } from '../components/assessment/assessmentShape';
import { mockBackendSaga } from '../mocks/backend';
import { externalLibraries } from '../reducers/externalLibraries';
import { defaultEditorValue, IState, IWorkspaceState } from '../reducers/states';
import { IVLE_KEY, USE_BACKEND } from '../utils/constants';
import { LUMINUS_CLIENT_ID, USE_BACKEND } from '../utils/constants';
import { showSuccessMessage, showWarningMessage } from '../utils/notification';
import { highlightLine, inspectorUpdate, visualiseEnv } from '../utils/slangHelper';
import backendSaga from './backend';
Expand Down Expand Up @@ -325,10 +325,12 @@ function* workspaceSaga(): SagaIterator {

function* loginSaga(): SagaIterator {
yield takeEvery(actionTypes.LOGIN, function*() {
const apiLogin = 'https://ivle.nus.edu.sg/api/login/';
const key = IVLE_KEY;
const callback = `${window.location.protocol}//${window.location.hostname}/login`;
window.location.href = `${apiLogin}?apikey=${key}&url=${callback}`;
const apiLogin = 'https://luminus.nus.edu.sg/v2/auth/connect/authorize';
const clientId = LUMINUS_CLIENT_ID;
const callback = `${window.location.protocol}//${window.location.hostname}:${
window.location.port
}/login`;
window.location.href = `${apiLogin}?client_id=${clientId}&redirect_uri=${callback}&response_type=code&scope=profile`;
yield undefined;
});
}
Expand Down
6 changes: 4 additions & 2 deletions src/utils/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as dotenv from 'dotenv';

dotenv.config();

export const IVLE_KEY = process.env.REACT_APP_IVLE_KEY;
export const LUMINUS_CLIENT_ID = process.env.REACT_APP_LUMINUS_CLIENT_ID;
export const VERSION = process.env.REACT_APP_VERSION;
export const BACKEND_URL = process.env.REACT_APP_BACKEND_URL;
export const USE_BACKEND =
Expand All @@ -13,7 +13,9 @@ export const USE_BACKEND =
export enum LINKS {
GITHUB_ISSUES = 'https://github.com/source-academy/cadet-frontend/issues',
GITHUB_ORG = 'https://github.com/source-academy',
IVLE = 'https://ivle.nus.edu.sg/v1/Module/Student/default.aspx?CourseID=a6579f36-4d7d-41fb-b394-92a00b78148b',

// TODO: REPLACE WITH LINK TO LUMINUS
LUMINUS = 'https://luminus.nus.edu.sg/modules/57290e55-335a-4c09-b904-a795572d6cda',
PIAZZA = 'https://piazza.com/nus.edu.sg/fall2018/cs1101s',
SHAREDB_SERVER = 'api2.sourceacademy.nus.edu.sg/',
SOURCE_DOCS = 'https://www.comp.nus.edu.sg/~cs1101s/source/',
Expand Down

0 comments on commit 553a24c

Please sign in to comment.