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

Commit b33ee68

Browse files
authored
Merge pull request #26 from CodeWe-projet/dev
Dev
2 parents 13c6cb0 + ad25d13 commit b33ee68

25 files changed

+1269
-302
lines changed

LICENCE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MIT License
22

3-
Copyright (c) 2020 Dewilde Alexandre, Dubois Brieuc and Fischer Nicolas
3+
Copyright (c) 2020 Dewilde Alexandre, Dubois Brieuc and Technicguy Theo
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

Privacy Policy - CodeWe.docx

-33.6 KB
Binary file not shown.

Terms and Conditions - CodeWe.docx

-52.3 KB
Binary file not shown.

src/app.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,22 @@ const index = require('./routes/index');
1616
const editor = require('./routes/editor');
1717
const legal = require('./routes/legal');
1818
const config = require('./config/config');
19+
const ssl = config.SSL;
1920

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

24+
if (ssl) {
25+
app.use('*', function (req, res, next) {
26+
if (req.secure) {
27+
next();
28+
} else {
29+
const target = (req.headers.host.includes(':') ? req.headers.host.split(':')[0] : req.headers.host) + ':' + config.PORT;
30+
res.redirect('https://' + target + req.url);
31+
}
32+
});
33+
}
34+
2335
// Configure views folder
2436
nunjucks.configure(path.join(__dirname, 'views'), {
2537
autoescape: true,
@@ -51,7 +63,6 @@ app.use('/', index);
5163
app.use('/editor', editor);
5264
app.use('/legal', legal);
5365

54-
5566
// 404 error
5667
app.all('*', (req, res) => {
5768
res.status(404).render('404.html', {production: config.PRODUCTION, client_versobe: config.CLIENT_VERBOSE});

src/config/config dist.json

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,16 @@
11
{
22
"DEBUG" : true,
3-
"HOST": "localhost",
4-
"PORT": 5000,
5-
"DB_TYPE": "mysql",
63
"PRODUCTION": false,
74
"CLIENT_VERBOSE": 2,
5+
"HOST": "localhost",
6+
"PORT": 5000,
7+
"DB_URL": "mongodb://host:port/?retryWrites=true&w=majority",
8+
"DAYS_TO_DELETE_DOCUMENT": 7,
89
"DISCORD_WEBHOOK": null,
910
"SSL": false,
1011
"KEY_FILE_SSL": null,
1112
"CERT_FILE_SSL" : null,
12-
"DB_CONFIG": {
13-
"DB_HOST": "db",
14-
"DB_USERNAME": "root",
15-
"DB_PASSWORD": "root",
16-
"DB_DATABASE": "codewe",
17-
"DB_PORT": "3306"
18-
},
13+
"REDIRECT_PORT": null,
1914
"METRICS": false,
2015
"METRICS_PORT": 8000
2116
}

src/db/MongoDB.js

Lines changed: 113 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
const { MongoClient, ObjectID } = require("mongodb");
2+
var crypto = require('crypto');
23
const configs = require('../config/config');
34
const utils = require('../utils');
45

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

1314

1415
class MongoDB {
15-
constructor (username, password, host, database, port) {
16-
let url = `mongodb://${username}:${password}@${host}:${port}/?retryWrites=true&w=majority`;
17-
this.client = new MongoClient(url);
16+
constructor (url) {
17+
this.client = new MongoClient(url, {
18+
useNewUrlParser: true,
19+
useUnifiedTopology: true
20+
});
1821
}
1922

2023
async connect () {
2124
try {
2225
this.db = await this.client.connect();
2326
this.codeWe = await this.db.db('codewe');
2427
this.documentsCollection = await this.codeWe.collection('codewe');
28+
this.usersCollection = await this.codeWe.collection('users');
2529
} catch (err) {
2630
if (configs.DEBUG) {
2731
console.error('Error with db connection');
@@ -30,29 +34,29 @@ class MongoDB {
3034
}
3135
}
3236

33-
async createDocument () {
37+
async createDocument (language) {
3438
let doc = {
3539
content: baseCode,
3640
creationDate: Date.now(),
3741
lastViewedDate: Date.now(),
3842
customDocumentName: '',
3943
documentOwner: '',
4044
editors: [],
41-
linkEdit: '',
45+
documentLink: '',
4246
linkView: '',
43-
language: '',
47+
language: language,
4448
tab: 4
4549
};
4650
try {
4751
let results = (await this.documentsCollection.insertOne(doc));
4852
const documentLink = utils.uuid(results.insertedId.toString());
49-
this.documentsCollection.updateOne({_id: results.insertedId}, {$set: {documentLink: documentLink}})
53+
const linkView = utils.uuid(documentLink);
54+
this.documentsCollection.updateOne({_id: results.insertedId}, {$set: {documentLink: documentLink, linkView: linkView}});
5055
return documentLink;
5156
} catch (err) {
5257
if (configs.DEBUG) {
5358
console.error('Error when creating a new document');
5459
}
55-
throw new Error(err);
5660
}
5761

5862
}
@@ -64,94 +68,171 @@ class MongoDB {
6468
if (configs.DEBUG) {
6569
console.error('Error when fetching document');
6670
}
67-
throw new Error(err);
71+
}
72+
}
73+
74+
async createUser(userId, secretToken) {
75+
try {
76+
await this.usersCollection.insertOne({
77+
userId: userId,
78+
secretToken: crypto.createHash('sha256').update(secretToken).digest('base64')
79+
});
80+
return 'Success';
81+
} catch (err) {
82+
if (configs.DEBUG) {
83+
console.error('Error when creating user');
84+
}
85+
}
86+
}
87+
88+
async checkUserSecretToken(userId, secretToken) {
89+
try {
90+
const user = await this.usersCollection.findOne({userId: userId});
91+
return (user.secretToken == crypto.createHash('sha256').update(secretToken).digest('base64'));
92+
} catch (err) {
93+
if (configs.DEBUG) {
94+
console.error('Error when checking user secret token');
95+
}
96+
return 'Error';
6897
}
6998
}
7099

71100
async setLine (documentLink, uuid, content) {
72101
try {
73-
await this.documentsCollection.updateOne({documentLink: documentLink, 'content.uuid': uuid}, {$set: {'content.$.content': content}});
102+
await this.documentsCollection.updateOne({documentLink: documentLink, 'content.uuid': uuid}, {$set: {'content.$.content': content.slice(0, 5000)}});
103+
return 'Succes';
74104
} catch (err) {
75105
if (configs.DEBUG) {
76106
console.error('Error when changing line content');
77107
}
78-
throw new Error(err);
79108
}
80109
}
81110

82111
async newLine (documentLink, previousUuid, uuid, content) {
83112
// Insert a line at the right place
84-
//TODO is it possible in one operation ?
113+
//TODO is it possible in one operation ?
85114
// TODO is it possible to implement with bulk?
86115
try {
87116
let doc = await this.documentsCollection.findOne({documentLink: documentLink});
88117
let index = doc.content.findIndex(line => {
89118
return line.uuid == previousUuid;
90119
});
91-
this.documentsCollection.updateOne({documentLink: documentLink}, {
92-
$push: {
93-
content: {
94-
$each : [{uuid: uuid, content: content}],
95-
$position : index + 1
120+
if (index) {
121+
this.documentsCollection.updateOne({documentLink: documentLink}, {
122+
$push: {
123+
content: {
124+
$each : [{uuid: uuid, content: content.slice(0, 5000)}],
125+
$position : index + 1
126+
}
96127
}
97-
}
98-
});
128+
});
129+
}
130+
return 'Succes';
99131
} catch (err) {
100132
if (configs.DEBUG) {
101133
console.error('Error when adding a new line to document');
102134
}
103-
throw new Error(err);
104135
}
105136
}
106137

107138
async deleteLine (documentLink, uuid) {
108139
try {
109140
// Delete line at the right place
110141
await this.documentsCollection.updateOne({documentLink: documentLink}, {$pull: {content: {uuid: uuid}}});
142+
return 'Succes';
111143
} catch (err) {
112144
if (configs.DEBUG) {
113145
console.error('Error when deleting a line in document');
114146
}
115-
throw new Error(err);
116147
}
117148

118149
}
119150

151+
async changeParam(documentLink, param, newValue) {
152+
try {
153+
const update = {};
154+
update[param] = newValue;
155+
await this.documentsCollection.updateOne({documentLink: documentLink}, {$set: update});
156+
return 'Succes';
157+
} catch (err) {
158+
if (configs.DEBUG) {
159+
console.error(err);
160+
}
161+
}
162+
}
163+
164+
async changeCustomName(documentLink, newName) {
165+
return this.changeParam(documentLink, 'customDocumentName', newName);
166+
}
167+
168+
async changeTabSize(documentLink, newTabSize) {
169+
if (Number.isInteger(newTabSize)) {
170+
return this.changeParam(documentLink, 'tab', newTabSize);
171+
}
172+
}
173+
174+
async changeLanguage(documentLink, newLanguage) {
175+
if (["python"].includes(newLanguage)) {
176+
return this.changeParam(documentLink, 'language', newLanguage);
177+
}
178+
}
179+
180+
async addNewEditors(documentLink, newEditorsId) {
181+
try {
182+
await this.documentsCollection.updateOne({documentLink: documentLink}, {$addToSet: {editors: newEditorsId}});
183+
return 'Success';
184+
} catch (err) {
185+
if (configs.DEBUG) {
186+
console.error(error);
187+
}
188+
}
189+
}
190+
191+
async updateLastViewedDate(documentLink) {
192+
return this.changeParam(documentLink, 'lastViewedDate', Date.now());
193+
}
194+
195+
async deleteOldDocuments(days) {
196+
const oldTimestamp = Date.now() - 1000 * 60 * 60 * 24 * days;
197+
return this.documentsCollection.deleteMany({'lastViewedDate': {$lt : oldTimestamp} });
198+
}
199+
120200
async applyRequests (documentLink, requests) {
121201
// TODO look to use bulk write
202+
let success = true;
122203
try {
204+
// Avoid too many requests
205+
requests = requests.slice(0, 50);
123206
for (let request of requests) {
124207
let requestType = request.type;
125208
let data = request.data;
209+
let results = ""
126210
switch (requestType) {
127211
case 'set-line':
128-
await this.setLine(documentLink, data.id, data.content);
212+
results = await this.setLine(documentLink, data.id, data.content);
213+
if (!results) success = false;
129214
break;
130215
case 'new-line':
131-
await this.newLine(documentLink, data.previous, data.id, data.content);
216+
results = await this.newLine(documentLink, data.previous, data.id, data.content);
217+
if (!results) success = false;
132218
break;
133219
case 'delete-line':
134-
await this.deleteLine(documentLink, data.id);
220+
results = await this.deleteLine(documentLink, data.id);
221+
if (!results) success = false;
135222
break;
136223
}
137224
}
225+
return success;
138226
} catch (err) {
139227
if (configs.DEBUG) {
140228
console.error('Error when applying requests');
141229
}
142-
throw new Error(err);
143230
}
144231
}
145232
}
146233

147234
function getDB () {
148-
db = new MongoDB(
149-
configs.DB_CONFIG.DB_USERNAME,
150-
configs.DB_CONFIG.DB_PASSWORD,
151-
configs.DB_CONFIG.DB_HOST,
152-
configs.DB_CONFIG.DB_DATABASE,
153-
configs.DB_CONFIG.DB_PORT
154-
);
235+
db = new MongoDB(configs.DB_URL);
155236
db.connect();
156237
return db;
157238
}

src/publics/js/dev/page/editor/editable.js

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -137,16 +137,18 @@ export default class Editable{
137137

138138
const line = getNodeFromAttribute('uuid');
139139

140-
if(!line) return;
140+
if(!line){
141+
e.preventDefault();
142+
temporaryCardAlert('Editor', 'Sorry, your action has been canceled because you are not on any line.', 5000);
143+
return;
144+
}
141145

142146
if(!anchorParent.hasAttribute('uuid')
143147
|| !focusParent.hasAttribute('uuid')
144148
|| ((Caret.getBeginPosition(line) === 0
145149
|| Caret.getEndPosition(line) === 0)
146150
) && anchorParent !== focusParent){
147-
e.preventDefault();
148-
temporaryCardAlert('Override', 'Sorry, you can\'t override the first char of a line', 5000);
149-
return;
151+
Caret.setRangeStart(line, 1);
150152
}
151153

152154
switch (e.keyCode) {
@@ -155,6 +157,11 @@ export default class Editable{
155157
this.insertTab();
156158
break;
157159
case 13: // enter
160+
if(e.shiftKey){
161+
temporaryCardAlert('Shift+Enter', 'Please just use Enter to avoid any bugs.', 5000);
162+
e.preventDefault();
163+
return;
164+
}
158165
if(this.keepSpace){
159166
Debug.debug('Prevent action when trying to add new line (key is probably maintain).');
160167
e.preventDefault();

src/publics/js/dev/utils/caret.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,22 @@ export default class Caret{
6767
}
6868
}
6969

70+
71+
/**
72+
* Set the start range of the user caret on specified position in element or children
73+
* @param {HTMLElement|Node} element
74+
* @param {number} position
75+
*/
76+
static setRangeStart(element, position) {
77+
if (position >= 0) {
78+
let selection = document.getSelection();
79+
80+
let range = Caret.createRange(element, {count: position});
81+
selection.getRangeAt(0).setStart(range.endContainer, range.endOffset);
82+
83+
}
84+
}
85+
7086
/**
7187
* Get the position of the end of the user selection
7288
* Based on https://stackoverflow.com/a/4812022/11247647

src/routes/editor.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,11 @@ const router = express.Router();
4141
router.get('/:docId', async (req, res, next) => {
4242
try {
4343
let document = (await db.getDocument(req.params.docId));
44-
if (document) {
44+
if (document) { // && (document.public || (document.editors.includes(req.body.userId) && db.checkUserSecretToken(req.body.userId, secretkey)))
4545
document.document_id = req.params.docId;
4646
res.render('editor.html', {document: document, production: config.PRODUCTION, client_versobe: config.CLIENT_VERBOSE});
4747
}
48+
// else if (!document.public)
4849
else {
4950
res.status(404).render('404.html', {production: config.PRODUCTION, client_versobe: config.CLIENT_VERBOSE})
5051
}

0 commit comments

Comments
 (0)