Skip to content
This repository has been archived by the owner on Mar 10, 2024. It is now read-only.

Commit

Permalink
Merge pull request #26 from CodeWe-projet/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
BhasherBEL authored Nov 26, 2020
2 parents 13c6cb0 + ad25d13 commit b33ee68
Show file tree
Hide file tree
Showing 25 changed files with 1,269 additions and 302 deletions.
2 changes: 1 addition & 1 deletion LICENCE.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2020 Dewilde Alexandre, Dubois Brieuc and Fischer Nicolas
Copyright (c) 2020 Dewilde Alexandre, Dubois Brieuc and Technicguy Theo

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
Binary file removed Privacy Policy - CodeWe.docx
Binary file not shown.
Binary file removed Terms and Conditions - CodeWe.docx
Binary file not shown.
13 changes: 12 additions & 1 deletion src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,22 @@ const index = require('./routes/index');
const editor = require('./routes/editor');
const legal = require('./routes/legal');
const config = require('./config/config');
const ssl = config.SSL;

const app = express();
app.disable("x-powered-by");

if (ssl) {
app.use('*', function (req, res, next) {
if (req.secure) {
next();
} else {
const target = (req.headers.host.includes(':') ? req.headers.host.split(':')[0] : req.headers.host) + ':' + config.PORT;
res.redirect('https://' + target + req.url);
}
});
}

// Configure views folder
nunjucks.configure(path.join(__dirname, 'views'), {
autoescape: true,
Expand Down Expand Up @@ -51,7 +63,6 @@ app.use('/', index);
app.use('/editor', editor);
app.use('/legal', legal);


// 404 error
app.all('*', (req, res) => {
res.status(404).render('404.html', {production: config.PRODUCTION, client_versobe: config.CLIENT_VERBOSE});
Expand Down
15 changes: 5 additions & 10 deletions src/config/config dist.json
Original file line number Diff line number Diff line change
@@ -1,21 +1,16 @@
{
"DEBUG" : true,
"HOST": "localhost",
"PORT": 5000,
"DB_TYPE": "mysql",
"PRODUCTION": false,
"CLIENT_VERBOSE": 2,
"HOST": "localhost",
"PORT": 5000,
"DB_URL": "mongodb://host:port/?retryWrites=true&w=majority",
"DAYS_TO_DELETE_DOCUMENT": 7,
"DISCORD_WEBHOOK": null,
"SSL": false,
"KEY_FILE_SSL": null,
"CERT_FILE_SSL" : null,
"DB_CONFIG": {
"DB_HOST": "db",
"DB_USERNAME": "root",
"DB_PASSWORD": "root",
"DB_DATABASE": "codewe",
"DB_PORT": "3306"
},
"REDIRECT_PORT": null,
"METRICS": false,
"METRICS_PORT": 8000
}
145 changes: 113 additions & 32 deletions src/db/MongoDB.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const { MongoClient, ObjectID } = require("mongodb");
var crypto = require('crypto');
const configs = require('../config/config');
const utils = require('../utils');

Expand All @@ -12,16 +13,19 @@ const baseCode = [


class MongoDB {
constructor (username, password, host, database, port) {
let url = `mongodb://${username}:${password}@${host}:${port}/?retryWrites=true&w=majority`;
this.client = new MongoClient(url);
constructor (url) {
this.client = new MongoClient(url, {
useNewUrlParser: true,
useUnifiedTopology: true
});
}

async connect () {
try {
this.db = await this.client.connect();
this.codeWe = await this.db.db('codewe');
this.documentsCollection = await this.codeWe.collection('codewe');
this.usersCollection = await this.codeWe.collection('users');
} catch (err) {
if (configs.DEBUG) {
console.error('Error with db connection');
Expand All @@ -30,29 +34,29 @@ class MongoDB {
}
}

async createDocument () {
async createDocument (language) {
let doc = {
content: baseCode,
creationDate: Date.now(),
lastViewedDate: Date.now(),
customDocumentName: '',
documentOwner: '',
editors: [],
linkEdit: '',
documentLink: '',
linkView: '',
language: '',
language: language,
tab: 4
};
try {
let results = (await this.documentsCollection.insertOne(doc));
const documentLink = utils.uuid(results.insertedId.toString());
this.documentsCollection.updateOne({_id: results.insertedId}, {$set: {documentLink: documentLink}})
const linkView = utils.uuid(documentLink);
this.documentsCollection.updateOne({_id: results.insertedId}, {$set: {documentLink: documentLink, linkView: linkView}});
return documentLink;
} catch (err) {
if (configs.DEBUG) {
console.error('Error when creating a new document');
}
throw new Error(err);
}

}
Expand All @@ -64,94 +68,171 @@ class MongoDB {
if (configs.DEBUG) {
console.error('Error when fetching document');
}
throw new Error(err);
}
}

async createUser(userId, secretToken) {
try {
await this.usersCollection.insertOne({
userId: userId,
secretToken: crypto.createHash('sha256').update(secretToken).digest('base64')
});
return 'Success';
} catch (err) {
if (configs.DEBUG) {
console.error('Error when creating user');
}
}
}

async checkUserSecretToken(userId, secretToken) {
try {
const user = await this.usersCollection.findOne({userId: userId});
return (user.secretToken == crypto.createHash('sha256').update(secretToken).digest('base64'));
} catch (err) {
if (configs.DEBUG) {
console.error('Error when checking user secret token');
}
return 'Error';
}
}

async setLine (documentLink, uuid, content) {
try {
await this.documentsCollection.updateOne({documentLink: documentLink, 'content.uuid': uuid}, {$set: {'content.$.content': content}});
await this.documentsCollection.updateOne({documentLink: documentLink, 'content.uuid': uuid}, {$set: {'content.$.content': content.slice(0, 5000)}});
return 'Succes';
} catch (err) {
if (configs.DEBUG) {
console.error('Error when changing line content');
}
throw new Error(err);
}
}

async newLine (documentLink, previousUuid, uuid, content) {
// Insert a line at the right place
//TODO is it possible in one operation ?
//TODO is it possible in one operation ?
// TODO is it possible to implement with bulk?
try {
let doc = await this.documentsCollection.findOne({documentLink: documentLink});
let index = doc.content.findIndex(line => {
return line.uuid == previousUuid;
});
this.documentsCollection.updateOne({documentLink: documentLink}, {
$push: {
content: {
$each : [{uuid: uuid, content: content}],
$position : index + 1
if (index) {
this.documentsCollection.updateOne({documentLink: documentLink}, {
$push: {
content: {
$each : [{uuid: uuid, content: content.slice(0, 5000)}],
$position : index + 1
}
}
}
});
});
}
return 'Succes';
} catch (err) {
if (configs.DEBUG) {
console.error('Error when adding a new line to document');
}
throw new Error(err);
}
}

async deleteLine (documentLink, uuid) {
try {
// Delete line at the right place
await this.documentsCollection.updateOne({documentLink: documentLink}, {$pull: {content: {uuid: uuid}}});
return 'Succes';
} catch (err) {
if (configs.DEBUG) {
console.error('Error when deleting a line in document');
}
throw new Error(err);
}

}

async changeParam(documentLink, param, newValue) {
try {
const update = {};
update[param] = newValue;
await this.documentsCollection.updateOne({documentLink: documentLink}, {$set: update});
return 'Succes';
} catch (err) {
if (configs.DEBUG) {
console.error(err);
}
}
}

async changeCustomName(documentLink, newName) {
return this.changeParam(documentLink, 'customDocumentName', newName);
}

async changeTabSize(documentLink, newTabSize) {
if (Number.isInteger(newTabSize)) {
return this.changeParam(documentLink, 'tab', newTabSize);
}
}

async changeLanguage(documentLink, newLanguage) {
if (["python"].includes(newLanguage)) {
return this.changeParam(documentLink, 'language', newLanguage);
}
}

async addNewEditors(documentLink, newEditorsId) {
try {
await this.documentsCollection.updateOne({documentLink: documentLink}, {$addToSet: {editors: newEditorsId}});
return 'Success';
} catch (err) {
if (configs.DEBUG) {
console.error(error);
}
}
}

async updateLastViewedDate(documentLink) {
return this.changeParam(documentLink, 'lastViewedDate', Date.now());
}

async deleteOldDocuments(days) {
const oldTimestamp = Date.now() - 1000 * 60 * 60 * 24 * days;
return this.documentsCollection.deleteMany({'lastViewedDate': {$lt : oldTimestamp} });
}

async applyRequests (documentLink, requests) {
// TODO look to use bulk write
let success = true;
try {
// Avoid too many requests
requests = requests.slice(0, 50);
for (let request of requests) {
let requestType = request.type;
let data = request.data;
let results = ""
switch (requestType) {
case 'set-line':
await this.setLine(documentLink, data.id, data.content);
results = await this.setLine(documentLink, data.id, data.content);
if (!results) success = false;
break;
case 'new-line':
await this.newLine(documentLink, data.previous, data.id, data.content);
results = await this.newLine(documentLink, data.previous, data.id, data.content);
if (!results) success = false;
break;
case 'delete-line':
await this.deleteLine(documentLink, data.id);
results = await this.deleteLine(documentLink, data.id);
if (!results) success = false;
break;
}
}
return success;
} catch (err) {
if (configs.DEBUG) {
console.error('Error when applying requests');
}
throw new Error(err);
}
}
}

function getDB () {
db = new MongoDB(
configs.DB_CONFIG.DB_USERNAME,
configs.DB_CONFIG.DB_PASSWORD,
configs.DB_CONFIG.DB_HOST,
configs.DB_CONFIG.DB_DATABASE,
configs.DB_CONFIG.DB_PORT
);
db = new MongoDB(configs.DB_URL);
db.connect();
return db;
}
Expand Down
15 changes: 11 additions & 4 deletions src/publics/js/dev/page/editor/editable.js
Original file line number Diff line number Diff line change
Expand Up @@ -137,16 +137,18 @@ export default class Editable{

const line = getNodeFromAttribute('uuid');

if(!line) return;
if(!line){
e.preventDefault();
temporaryCardAlert('Editor', 'Sorry, your action has been canceled because you are not on any line.', 5000);
return;
}

if(!anchorParent.hasAttribute('uuid')
|| !focusParent.hasAttribute('uuid')
|| ((Caret.getBeginPosition(line) === 0
|| Caret.getEndPosition(line) === 0)
) && anchorParent !== focusParent){
e.preventDefault();
temporaryCardAlert('Override', 'Sorry, you can\'t override the first char of a line', 5000);
return;
Caret.setRangeStart(line, 1);
}

switch (e.keyCode) {
Expand All @@ -155,6 +157,11 @@ export default class Editable{
this.insertTab();
break;
case 13: // enter
if(e.shiftKey){
temporaryCardAlert('Shift+Enter', 'Please just use Enter to avoid any bugs.', 5000);
e.preventDefault();
return;
}
if(this.keepSpace){
Debug.debug('Prevent action when trying to add new line (key is probably maintain).');
e.preventDefault();
Expand Down
16 changes: 16 additions & 0 deletions src/publics/js/dev/utils/caret.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,22 @@ export default class Caret{
}
}


/**
* Set the start range of the user caret on specified position in element or children
* @param {HTMLElement|Node} element
* @param {number} position
*/
static setRangeStart(element, position) {
if (position >= 0) {
let selection = document.getSelection();

let range = Caret.createRange(element, {count: position});
selection.getRangeAt(0).setStart(range.endContainer, range.endOffset);

}
}

/**
* Get the position of the end of the user selection
* Based on https://stackoverflow.com/a/4812022/11247647
Expand Down
3 changes: 2 additions & 1 deletion src/routes/editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,11 @@ const router = express.Router();
router.get('/:docId', async (req, res, next) => {
try {
let document = (await db.getDocument(req.params.docId));
if (document) {
if (document) { // && (document.public || (document.editors.includes(req.body.userId) && db.checkUserSecretToken(req.body.userId, secretkey)))
document.document_id = req.params.docId;
res.render('editor.html', {document: document, production: config.PRODUCTION, client_versobe: config.CLIENT_VERBOSE});
}
// else if (!document.public)
else {
res.status(404).render('404.html', {production: config.PRODUCTION, client_versobe: config.CLIENT_VERBOSE})
}
Expand Down
Loading

0 comments on commit b33ee68

Please sign in to comment.