Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/graasp/graasp-desktop int…
Browse files Browse the repository at this point in the history
…o 323/implement-a-tour-guide
  • Loading branch information
hasanagh committed Oct 7, 2020
2 parents 7610b53 + 406b2ff commit bfaa4fa
Show file tree
Hide file tree
Showing 58 changed files with 1,081 additions and 16,379 deletions.
43 changes: 43 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,49 @@

All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.

### [0.15.6](https://github.com/graasp/graasp-desktop/compare/v0.15.5...v0.15.6) (2020-09-30)

### Features

- add signin and signout actions, refactor dashboard ([442092b](https://github.com/graasp/graasp-desktop/commit/442092bae81ceb67fa8b1add4cc3ec6da6c8cce5))
- add switch for action enabled and action access ([2e20609](https://github.com/graasp/graasp-desktop/commit/2e20609f1dcb01d76c836ce1822e64a7ce886563))
- add teacher theme ([d95398b](https://github.com/graasp/graasp-desktop/commit/d95398b982c88427231d2ed4fccec289d96909e4)), closes [#283](https://github.com/graasp/graasp-desktop/issues/283)
- add user filter in dashboard ([8d81829](https://github.com/graasp/graasp-desktop/commit/8d81829eb57fdcdb4edd6f031ab4814ec726ad6d)), closes [#284](https://github.com/graasp/graasp-desktop/issues/284)
- add welcome screen when there si nothing to display in Home ([414cec5](https://github.com/graasp/graasp-desktop/commit/414cec5c0f27d2183a647a1f406e833f9542177b)), closes [#273](https://github.com/graasp/graasp-desktop/issues/273)
- close app from mainmenu ([8503ee5](https://github.com/graasp/graasp-desktop/commit/8503ee583467965f56f0b36ed969dd9f81a087cc)), closes [#282](https://github.com/graasp/graasp-desktop/issues/282)
- delete appInstanceResource and related file ([2d5b4e4](https://github.com/graasp/graasp-desktop/commit/2d5b4e4555b15556ca9b670a81840afd97a6f063))
- display username in drawer ([a03ae5e](https://github.com/graasp/graasp-desktop/commit/a03ae5eceb67ba2d9666871080014a1c3807f017)), closes [#240](https://github.com/graasp/graasp-desktop/issues/240)
- keep language when creating new user ([8845d5c](https://github.com/graasp/graasp-desktop/commit/8845d5c5804d7e8527ed708c25509bd9757df5b7))
- save file locally when receiving postFile message ([d308f36](https://github.com/graasp/graasp-desktop/commit/d308f3635ae818a875e22d9657002a19fd1908fe))

### Bug Fixes

- **sync:** add default protocol for remote space image ([3219d99](https://github.com/graasp/graasp-desktop/commit/3219d99a050411b5922ec63d2e750f613e6af506))
- fix saving login action twice on signin ([24a1155](https://github.com/graasp/graasp-desktop/commit/24a1155e262814b40ac7829e480dc89df47acbf6))
- **spaces nearby:** get correctly geolocation from user ([0a63a6a](https://github.com/graasp/graasp-desktop/commit/0a63a6a98c0a1d062575ff15ea0e93cb24f41ec4))
- define user in SignInScreen ([2c7aff3](https://github.com/graasp/graasp-desktop/commit/2c7aff36b329483a649c7861f438d2602185fbcf))
- display connexion status toastr only on change ([8a725c3](https://github.com/graasp/graasp-desktop/commit/8a725c38d12427946631383f704d19966ef8e516)), closes [#254](https://github.com/graasp/graasp-desktop/issues/254)
- do not add classroom when name already exists ([0c6c83e](https://github.com/graasp/graasp-desktop/commit/0c6c83eace335506301ac6c9eae5d7befb68be45)), closes [#300](https://github.com/graasp/graasp-desktop/issues/300)
- does not save action and resource when space is not saved ([0b5bb5d](https://github.com/graasp/graasp-desktop/commit/0b5bb5de37470d977e317aa5138926843472b638)), closes [#296](https://github.com/graasp/graasp-desktop/issues/296)
- fix database typo in user filter, fr translation ([83b90d6](https://github.com/graasp/graasp-desktop/commit/83b90d6185d43c64abf0d2a40f459c7b3a1184d4))
- fix minor test issues ([d023709](https://github.com/graasp/graasp-desktop/commit/d023709660cf79548d26b596c68e63512a116495))
- handle empty items in phases on space sync ([b82a02b](https://github.com/graasp/graasp-desktop/commit/b82a02bd41c0f3fc6c3b5ca4a21cdacd5b2b4f6e))
- remove space in classroom instead of in saved spaces ([0434c50](https://github.com/graasp/graasp-desktop/commit/0434c503c42be6ebf4b4a4456e9fe64d1dc1c33b))
- translations for sign in as guest ([76eaa8d](https://github.com/graasp/graasp-desktop/commit/76eaa8d6dad8316b0e01de58ba4cde4ff90290a1))
- use logger in postFile, refactor postFile ([d9145b6](https://github.com/graasp/graasp-desktop/commit/d9145b66623a75043387c2e42fe2711ec1faf775))

### Build System

- **deps-dev:** update version and release deps ([b677150](https://github.com/graasp/graasp-desktop/commit/b67715015f359d92e78fbd47dbe6624332e06e56))

### Tests

- update test to work with student as default user mode ([ef975ce](https://github.com/graasp/graasp-desktop/commit/ef975ce26dc5aa1393c0d489cf126656479ab2f4))

### Documentation

- add login and user mode docs ([40d6f35](https://github.com/graasp/graasp-desktop/commit/40d6f35555ebf66cd2f35ff1a06d0b1aaf48b2a6))

### [0.15.5](https://github.com/graasp/graasp-desktop/compare/v0.15.4...v0.15.5) (2020-06-05)

### Features
Expand Down
26 changes: 26 additions & 0 deletions docs/authentication/authenticaton-proposals.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# User Authentication

Since Graasp Desktop v.0.15.4, a user authentication is available in order for multiple users to use the application.

![Login Screen](./img/loginScreen.png)

The authentication process is triggered right at the launch of the application. It asks for a username before allowing access to the application. Each new username will create a corresponding user account on the fly. If a username already exists in the database, the user will sign in with the corresponding account and be able to access previously stored data.

One can use the application anonymously without restriction, but any saved data will not be retrievable after the user closes the session.

In order to automatically authenticate whenever the application is launched, the
current user session is stored in a dedicated part of the local storage and is used to sign
in. When the user signs out, the cached session is cleared and the application redirects
to the login screen.

## Alternative solution: Space-level Authentication (online)

Graasp offers a practical method for students to access spaces. From a link, before accessing a space, students create personal credentials, resulting in a Light account. This account allows to save data for this student for this space only.

If online data from Light users are required in Graasp Desktop, it is necessary to implement a authentication procedure triggered each time a space is visited.

However, as of today's requirements, Graasp Desktop is used in poorly connected countries. Trying to fetch data online is thus not necessary. Additionally, authenticating at a space-level is rather tedious and tends to be repetitive in a context where the user only consumes and visits spaces. Security should also be handled with high precautions.

The following schema depicts a proposed space-level login. Blue steps run while online, whereas grey steps are performed in an offline environment. If online, the application connects to and fetch the online account user data. If offline, the application skips the online procedure and immediately access the space.

![Space-level Authentication Flowchart](./img/spaceLevelAuthentication.png)
Binary file added docs/authentication/img/loginScreen.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
62 changes: 62 additions & 0 deletions docs/authentication/userMode.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# User Modes

Though different user accounts can be created to access the application and save personal data, spaces are shared among all the users. To handle these spaces (avoid unexpected action on other users), we divide users into different categories/modes/stakeholders, leading to different permissions.

## Stakeholders in Graasp Desktop

### Teachers

Teachers need to manage spaces (as they can online) and their students. Assuming that
spaces are exclusively created and edited on the main online platform, Graasp Desktop
is primarily a common pedagogical course support to provide the spaces to their classes
in an offline context.
Additionally, teachers use Graasp Desktop to gather and browse their students’ data in
order to gain insight of their progression throughout the courses, as well as to
eventually correct their submissions.

### Students

Students use Graasp Desktop to learn in offline environments, either during classes or
remotely at home. They visit spaces created by their teacher, and might also visit other
interesting spaces if they have a stable internet connection. Additionally, students
eventually save resources and leave activity traces while visiting spaces. Such data
results in interesting analytics of their learning sessions, that students can display to
evaluate their learning progression. Finally, students share their resources with their
friends or teachers in order to be evaluated.

### Developers

Even though they are not directly related to the pedagogical purpose of the
application, developers are necessary in order to maintain and improve the
functionalities of the Graasp Desktop application. For instance, they need full access to
the database and to all the application’s features, as well as particular development
tools to implement new features.

### Researchers

Graasp Desktop is an educational support to collect meaningful data from learners,
and researchers can use it to conduct their studies. They require specific applications
to track the users, as well as a mechanism to manage consent from users to have legal
access to their data.
While Developers and Researchers also have their importance in the development of
Graasp Desktop and could have their own modes, as part of this thesis, we only focus
on teacher and student differences in order to develop a teacher mode.

| Action | Student | Teacher |
| :-------------------------: | :------: | :------------------------------: |
| Visit a Space | yes | yes |
| Export a Space | yes | yes |
| Save a Space | no | yes |
| Add a Space | no | yes |
| Delete a Space | no | yes |
| Sync a Space | no | yes |
| Load a Space | no | yes |
| Load Space's data | no/yes\* | yes |
| Classrooms Functionalities | no | yes |
| Displayed data in Dashboard | own data | own and other users' shared data |

<center>*Student*'s and *Teacher*'s permissions comparison</center>

## Implementation

Since Graasp Desktop 0.15.4, the _Student_ and _Teacher_ modes are available. By default, a user is a _Student_. To become a _Teacher_, the setting **Student Mode** should be disabled in the settings. _Developer_ and _Research_ are not yet available.
89 changes: 45 additions & 44 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "graasp-desktop",
"version": "0.15.5",
"version": "0.15.6",
"description": "Desktop application for the Graasp ecosystem.",
"private": true,
"author": "React EPFL",
Expand All @@ -10,7 +10,7 @@
"Kim Lan Phan Hoang"
],
"engines": {
"node": "12"
"node": "14.3.0"
},
"license": "MIT",
"homepage": "./",
Expand Down Expand Up @@ -54,7 +54,7 @@
"dist:win:docker": "./scripts/buildWindowsWithDocker.sh",
"dist:all": "run-s dist:posix dist:win",
"release:manual": "run-s version dist:all",
"release": "git add CHANGELOG.md && standard-version -a && env-cmd -f ./.env electron-builder -ml && env-cmd -f ./.env electron-builder -w --x64 --ia32",
"release": "git fetch --tags && git add CHANGELOG.md && standard-version -a && env-cmd -f ./.env electron-builder -ml && env-cmd -f ./.env electron-builder -w --x64 --ia32",
"hooks:uninstall": "node node_modules/husky/husky.js uninstall",
"hooks:install": "node node_modules/husky/husky.js install",
"postinstall": "electron-builder install-app-deps",
Expand All @@ -69,92 +69,93 @@
"mocha": "mkdirp test/tmp && concurrently \"env-cmd -f ./.env.test react-scripts start\" \"wait-on http://localhost:3000 && mocha --require @babel/register \"test/**/*.test.js\"\""
},
"dependencies": {
"@material-ui/core": "4.9.4",
"@material-ui/core": "4.11.0",
"@material-ui/icons": "4.9.1",
"@sentry/browser": "5.13.0",
"@sentry/electron": "1.2.1",
"about-window": "1.13.2",
"@sentry/browser": "5.19.2",
"@sentry/electron": "1.4.0",
"about-window": "1.13.4",
"archiver": "3.1.1",
"bson-objectid": "1.3.0",
"bson-objectid": "1.3.1",
"chai": "4.2.0",
"cheerio": "1.0.0-rc.3",
"classnames": "2.2.6",
"clsx": "1.1.0",
"connected-react-router": "6.7.0",
"clsx": "1.1.1",
"connected-react-router": "6.8.0",
"download": "7.1.0",
"electron-devtools-installer": "2.2.4",
"electron-is-dev": "1.1.0",
"electron-log": "4.0.7",
"electron-is-dev": "1.2.0",
"electron-log": "4.2.2",
"electron-publisher-s3": "20.17.2",
"electron-updater": "4.2.2",
"electron-updater": "4.3.1",
"enzyme": "3.11.0",
"enzyme-adapter-react-16": "1.15.2",
"extract-zip": "1.6.7",
"fs-extra": "9.0.1",
"history": "4.10.1",
"i18next": "19.3.2",
"i18next": "19.6.2",
"immutable": "4.0.0-rc.12",
"is-online": "8.2.1",
"is-online": "8.4.0",
"katex": "0.11.1",
"lodash": "4.17.15",
"lodash": "4.17.19",
"lowdb": "1.0.0",
"md5": "2.2.1",
"mime-types": "2.1.26",
"mkdirp": "1.0.3",
"mime-types": "2.1.27",
"mkdirp": "1.0.4",
"mocha": "7.1.0",
"node-machine-id": "1.1.12",
"prop-types": "15.7.2",
"qs": "6.9.1",
"re-resizable": "6.2.0",
"react": "16.13.0",
"qs": "6.9.4",
"re-resizable": "6.5.4",
"react": "16.13.1",
"react-countup": "4.3.3",
"react-detect-offline": "2.4.0",
"react-dev-utils": "10.2.0",
"react-diff-viewer": "3.0.2",
"react-dom": "16.13.0",
"react-i18next": "11.3.3",
"react-immutable-proptypes": "2.1.0",
"react-dev-utils": "10.2.1",
"react-diff-viewer": "3.1.1",
"react-dom": "16.13.1",
"react-i18next": "11.7.0",
"react-immutable-proptypes": "2.2.0",
"react-joyride": "2.2.1",
"react-json-view": "1.19.1",
"react-loading": "2.0.3",
"react-quill": "1.3.3",
"react-quill": "1.3.5",
"react-redux": "7.2.0",
"react-redux-toastr": "7.6.4",
"react-router": "5.1.2",
"react-router-dom": "5.1.2",
"react-redux-toastr": "7.6.5",
"react-router": "5.2.0",
"react-router-dom": "5.2.0",
"react-select": "3.1.0",
"react-split-pane": "0.1.89",
"react-split-pane": "0.1.91",
"recharts": "1.8.5",
"redux": "4.0.5",
"redux-devtools-extension": "2.13.8",
"redux-promise": "0.6.0",
"redux-thunk": "2.3.0",
"request-promise": "4.2.5",
"rimraf": "3.0.2",
"universal-analytics": "0.4.20"
"universal-analytics": "0.4.23"
},
"devDependencies": {
"@babel/cli": "7.8.4",
"@babel/core": "7.9.0",
"@babel/plugin-transform-runtime": "7.9.0",
"@babel/preset-env": "7.9.0",
"@babel/register": "7.9.0",
"@babel/cli": "7.10.5",
"@babel/core": "7.10.5",
"@babel/plugin-transform-runtime": "7.10.5",
"@babel/preset-env": "7.10.4",
"@babel/register": "7.10.5",
"@commitlint/cli": "9.1.1",
"@commitlint/config-conventional": "9.1.1",
"codacy-coverage": "3.4.0",
"concurrently": "5.1.0",
"cross-env": "7.0.0",
"concurrently": "5.2.0",
"cross-env": "7.0.2",
"electron": "8.2.4",
"electron-builder": "22.3.2",
"electron-builder": "22.7.0",
"env-cmd": "10.1.0",
"enzyme-to-json": "3.4.4",
"eslint-config-airbnb": "18.0.1",
"eslint-config-prettier": "6.10.0",
"enzyme-to-json": "3.5.0",
"eslint-config-airbnb": "18.2.0",
"eslint-config-prettier": "6.11.0",
"eslint-plugin-mocha": "6.3.0",
"husky": "4.2.5",
"npm-run-all": "4.1.5",
"prettier": "1.19.1",
"pretty-quick": "2.0.1",
"react-scripts": "3.4.0",
"react-scripts": "3.4.1",
"redux-mock-store": "1.5.4",
"spectron": "10.0.1",
"standard-version": "8.0.2",
Expand Down
4 changes: 3 additions & 1 deletion public/app/config/channels.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,5 +71,7 @@ module.exports = {
GET_SPACE_IN_CLASSROOM_CHANNEL: 'classroom:space:get',
LOAD_SPACE_IN_CLASSROOM_CHANNEL: 'classroom:space:load',
GET_SPACE_TO_LOAD_IN_CLASSROOM_CHANNEL: 'classroom:space:load:get-space',
TOUR_COMPLETED_CHANNEL: 'tour:complete',
POST_FILE_CHANNEL: 'file:post',
DELETE_FILE_CHANNEL: 'file:delete',
COMPLETE_TOUR_CHANNEL: 'tour:complete',
};
8 changes: 8 additions & 0 deletions public/app/config/config.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// eslint-disable-next-line import/no-extraneous-dependencies
const { app } = require('electron');
const ObjectId = require('bson-objectid');
const isWindows = require('../utils/isWindows');

const tours = {
Expand Down Expand Up @@ -93,6 +94,12 @@ const ACTIONS_VERBS = {
LOGOUT: 'logout',
};

const buildFilePath = ({ userId, spaceId, name }) => {
// add generated id to handle duplicate files
const generatedId = ObjectId().str;
return `${VAR_FOLDER}/${spaceId}/files/${userId}/${generatedId}_${name}`;
};

module.exports = {
DEFAULT_LOGGING_LEVEL,
DEFAULT_PROTOCOL,
Expand All @@ -119,4 +126,5 @@ module.exports = {
VISIBILITIES,
DEFAULT_FORMAT,
ACTIONS_VERBS,
buildFilePath,
};
4 changes: 4 additions & 0 deletions public/app/config/messages.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,8 @@ const ERROR_GETTING_SPACE_IN_CLASSROOM_MESSAGE =
const ERROR_SETTING_ACTION_ACCESSIBILITY =
'There was an error setting the action accessibility';
const ERROR_SETTING_ACTIONS_AS_ENABLED = 'There was an error enabling actions';
const ERROR_POSTING_FILE_MESSAGE = 'There was an error uploading the file';
const ERROR_DELETING_FILE_MESSAGE = 'There was an error deleting the file';

module.exports = {
ERROR_GETTING_DEVELOPER_MODE,
Expand Down Expand Up @@ -172,4 +174,6 @@ module.exports = {
ERROR_INVALID_USERNAME_MESSAGE,
ERROR_SETTING_ACTION_ACCESSIBILITY,
ERROR_SETTING_ACTIONS_AS_ENABLED,
ERROR_POSTING_FILE_MESSAGE,
ERROR_DELETING_FILE_MESSAGE,
};
6 changes: 3 additions & 3 deletions public/app/listeners/completeTour.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const { TOUR_COMPLETED_CHANNEL } = require('../config/channels');
const { COMPLETE_TOUR_CHANNEL } = require('../config/channels');
const { ERROR_GENERAL } = require('../config/errors');
const logger = require('../logger');

Expand All @@ -8,10 +8,10 @@ const completeTour = (mainWindow, db) => async (event, { tourName }) => {
db.get('user')
.set(`tour.${tourName}`, true)
.write();
mainWindow.webContents.send(TOUR_COMPLETED_CHANNEL);
mainWindow.webContents.send(COMPLETE_TOUR_CHANNEL);
} catch (e) {
logger.error(e);
mainWindow.webContents.send(TOUR_COMPLETED_CHANNEL, ERROR_GENERAL);
mainWindow.webContents.send(COMPLETE_TOUR_CHANNEL, ERROR_GENERAL);
}
};

Expand Down
19 changes: 19 additions & 0 deletions public/app/listeners/deleteAppInstanceResource.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
const { DELETE_APP_INSTANCE_RESOURCE_CHANNEL } = require('../config/channels');
const { APP_INSTANCE_RESOURCES_COLLECTION } = require('../db');

const deleteAppInstanceResource = (mainWindow, db) => (event, payload = {}) => {
try {
const { appInstanceId: appInstance, id } = payload;

db.get(APP_INSTANCE_RESOURCES_COLLECTION)
.remove({ appInstance, id })
.write();

mainWindow.webContents.send(DELETE_APP_INSTANCE_RESOURCE_CHANNEL, payload);
} catch (e) {
console.error(e);
mainWindow.webContents.send(DELETE_APP_INSTANCE_RESOURCE_CHANNEL, null);
}
};

module.exports = deleteAppInstanceResource;
Loading

0 comments on commit bfaa4fa

Please sign in to comment.