CD #33
This commit is contained in:
parent
05554fe7ca
commit
387ece8b2f
@ -14,7 +14,12 @@ Custom Frontend and Backend that is similar to Discord.
|
||||
|
||||
1. Clone the repo.
|
||||
2. Generate SSH keys.
|
||||
From app folder: `mkdir -p backend/keys && ssh-keygen -t rsa -b 2048 -m PEM -f backend/keys/accord.app`
|
||||
From app folder:
|
||||
```
|
||||
mkdir -p backend/keys
|
||||
&& ssh-keygen -t rsa -b 2048 -m PEM -f backend/keys/jwt
|
||||
&& openssl rand -rand /dev/urandom 256 > backend/keys/message
|
||||
```
|
||||
3. Install npm packages.
|
||||
From app folder: `cd frontend && npm i && cd ../backend && npm i`
|
||||
|
||||
|
1879
backend/package-lock.json
generated
1879
backend/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -16,6 +16,7 @@
|
||||
"chai-things": "^0.2.0",
|
||||
"colors": "^1.4.0",
|
||||
"cors": "^2.8.5",
|
||||
"crypto-js": "^4.1.1",
|
||||
"dotenv": "^8.2.0",
|
||||
"express": "^4.17.1",
|
||||
"express-async-errors": "^3.1.1",
|
||||
@ -37,7 +38,8 @@
|
||||
"socket.io": "^4.0.0",
|
||||
"socket.io-client": "^4.0.0",
|
||||
"ts-node": "^9.1.1",
|
||||
"typescript": "^4.2.3"
|
||||
"typescript": "^4.2.3",
|
||||
"un": "^0.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/chai": "^4.2.14",
|
||||
@ -46,6 +48,7 @@
|
||||
"@types/chai-things": "^0.0.34",
|
||||
"@types/colors": "^1.2.1",
|
||||
"@types/cors": "^2.8.7",
|
||||
"@types/crypto-js": "^4.0.2",
|
||||
"@types/dotenv": "^8.2.0",
|
||||
"@types/express": "^4.17.11",
|
||||
"@types/express-rate-limit": "^5.1.1",
|
||||
|
@ -1,8 +1,12 @@
|
||||
import got from 'got/dist/source';
|
||||
import DBWrapper from './db-wrapper';
|
||||
import { Channel } from './models/channel';
|
||||
import { Message, MessageDocument } from './models/message';
|
||||
import { generateSnowflake } from './snowflake-entity';
|
||||
import AES from 'crypto-js/aes';
|
||||
import { readFileSync } from 'fs';
|
||||
import { resolve } from 'path';
|
||||
|
||||
const messageKey = readFileSync(resolve(`./keys/message`), 'utf-8');
|
||||
|
||||
export default class Messages extends DBWrapper<string, MessageDocument> {
|
||||
public async get(id: string | undefined) {
|
||||
@ -20,7 +24,7 @@ export default class Messages extends DBWrapper<string, MessageDocument> {
|
||||
_id: generateSnowflake(),
|
||||
authorId,
|
||||
channelId,
|
||||
content,
|
||||
encryptedContent: AES.encrypt(content, messageKey).ciphertext.words,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -2,11 +2,18 @@ import { Document, model, Schema } from 'mongoose';
|
||||
import patterns from '../../types/patterns';
|
||||
import { createdAtToDate, useId } from '../../utils/utils';
|
||||
import { generateSnowflake } from '../snowflake-entity';
|
||||
import AES from 'crypto-js/aes';
|
||||
import { readFileSync } from 'fs';
|
||||
import { resolve } from 'path';
|
||||
|
||||
const messageKey = readFileSync(resolve(`./keys/message`), 'utf-8');
|
||||
|
||||
export interface MessageDocument extends Document, Entity.Message {
|
||||
_id: string | never;
|
||||
id: string;
|
||||
createdAt: never;
|
||||
encryptedContent: number[];
|
||||
content: never;
|
||||
}
|
||||
|
||||
export const Message = model<MessageDocument>('message', new Schema({
|
||||
@ -24,6 +31,8 @@ export const Message = model<MessageDocument>('message', new Schema({
|
||||
required: [true, 'Channel ID is required'],
|
||||
validate: [patterns.snowflake, 'Invalid Snowflake ID'],
|
||||
},
|
||||
encryptedContent: { type: Array },
|
||||
// TODO: eventually remove
|
||||
content: {
|
||||
type: String,
|
||||
minlength: [1, 'Content too short'],
|
||||
@ -40,4 +49,16 @@ export const Message = model<MessageDocument>('message', new Schema({
|
||||
url: String,
|
||||
}),
|
||||
updatedAt: Date,
|
||||
}, { toJSON: { getters: true } }).method('toClient', useId));
|
||||
}, { toJSON: { getters: true } })
|
||||
// TODO: refactor
|
||||
.method('toClient', function(this: MessageDocument) {
|
||||
const obj = this.toObject();
|
||||
|
||||
this.id = this._id;
|
||||
delete this._id;
|
||||
|
||||
this.content = AES.decrypt(this['encryptedContent'], messageKey);
|
||||
delete this.encryptedContent;
|
||||
|
||||
return obj;
|
||||
}));
|
||||
|
@ -68,7 +68,7 @@ export default class Users extends DBWrapper<string, UserDocument> {
|
||||
|
||||
public async createToken(user: SelfUserDocument, expire = true) {
|
||||
// too insecure to keep in memory
|
||||
const key = await readFileAsync('./keys/accord.app', { encoding: 'utf-8' });
|
||||
const key = await readFileAsync('./keys/jwt', { encoding: 'utf-8' });
|
||||
return jwt.sign(
|
||||
{ id: user.id },
|
||||
key,
|
||||
@ -81,7 +81,7 @@ export default class Users extends DBWrapper<string, UserDocument> {
|
||||
}
|
||||
public async verifyToken(token: string | undefined): Promise<string> {
|
||||
// too insecure to keep in memory
|
||||
const key = await readFileAsync('./keys/accord.app', { encoding: 'utf-8' });
|
||||
const key = await readFileAsync('./keys/jwt', { encoding: 'utf-8' });
|
||||
const decoded = jwt.verify(token as string, key, { algorithms: ['RS256'] }) as UserToken;
|
||||
return decoded?.id;
|
||||
}
|
||||
|
@ -37,40 +37,40 @@ console.log(`${space(48 * 3)}TESTS${space(54 * 2)}`.bgWhite.black);
|
||||
execSync(`kill -9 $(lsof -i :${process.env.PORT} | tail -n 1 | cut -d ' ' -f5) 2>> /dev/null`);
|
||||
} catch {}
|
||||
|
||||
// import('./integration/routes/auth-routes.tests');
|
||||
// import('./integration/routes/invites-routes.tests');
|
||||
// import('./integration/routes/guilds-routes.tests');
|
||||
// import('./integration/routes/channel-routes.tests');
|
||||
import('./integration/routes/auth-routes.tests');
|
||||
import('./integration/routes/invites-routes.tests');
|
||||
import('./integration/routes/guilds-routes.tests');
|
||||
import('./integration/routes/channel-routes.tests');
|
||||
|
||||
// import('./integration/ws/channel-create.tests');
|
||||
// // TODO: import('./integration/ws/channel-delete.tests');
|
||||
// // TODO: import('./integration/ws/channel-update.tests');
|
||||
// import('./integration/ws/guild-member-add.tests'); //fail
|
||||
// import('./integration/ws/guild-member-remove.tests'); //fail
|
||||
// import('./integration/ws/guild-member-update.tests'); // fail
|
||||
// import('./integration/ws/guild-create.tests'); // fail
|
||||
// import('./integration/ws/guild-delete.tests'); // fail
|
||||
// import('./integration/ws/guild-update.tests'); // fail
|
||||
// import('./integration/ws/invite-create.tests'); //fail
|
||||
// import('./integration/ws/invite-delete.tests'); //fail
|
||||
// import('./integration/ws/message-create.tests'); //fail
|
||||
// import('./integration/ws/message-update.tests'); // fail
|
||||
// import('./integration/ws/message-delete.tests'); // fail
|
||||
// import('./integration/ws/ready.tests');
|
||||
// import('./integration/ws/user-update.tests');
|
||||
// import('./integration/ws/ws-guard.tests');
|
||||
import('./integration/ws/channel-create.tests');
|
||||
// TODO: import('./integration/ws/channel-delete.tests');
|
||||
// TODO: import('./integration/ws/channel-update.tests');
|
||||
import('./integration/ws/guild-member-add.tests'); //fail
|
||||
import('./integration/ws/guild-member-remove.tests'); //fail
|
||||
import('./integration/ws/guild-member-update.tests'); // fail
|
||||
import('./integration/ws/guild-create.tests'); // fail
|
||||
import('./integration/ws/guild-delete.tests'); // fail
|
||||
import('./integration/ws/guild-update.tests'); // fail
|
||||
import('./integration/ws/invite-create.tests'); //fail
|
||||
import('./integration/ws/invite-delete.tests'); //fail
|
||||
import('./integration/ws/message-create.tests'); //fail
|
||||
import('./integration/ws/message-update.tests'); // fail
|
||||
import('./integration/ws/message-delete.tests'); // fail
|
||||
import('./integration/ws/ready.tests');
|
||||
import('./integration/ws/user-update.tests');
|
||||
import('./integration/ws/ws-guard.tests');
|
||||
import('./integration/data/roles.tests');
|
||||
|
||||
// import('./unit/models/app.tests');
|
||||
// import('./unit/models/channel.tests');
|
||||
// import('./unit/models/guild.tests');
|
||||
// import('./unit/models/guild-member.tests');
|
||||
// import('./unit/models/invite.tests');
|
||||
// import('./unit/models/message.tests');
|
||||
// import('./unit/models/role.tests');
|
||||
// import('./unit/models/user.tests');
|
||||
// import('./unit/snowflake-entity.tests');
|
||||
// import('./unit/ws/ws-cooldowns.tests');
|
||||
import('./unit/models/app.tests');
|
||||
import('./unit/models/channel.tests');
|
||||
import('./unit/models/guild.tests');
|
||||
import('./unit/models/guild-member.tests');
|
||||
import('./unit/models/invite.tests');
|
||||
import('./unit/models/message.tests');
|
||||
import('./unit/models/role.tests');
|
||||
import('./unit/models/user.tests');
|
||||
import('./unit/snowflake-entity.tests');
|
||||
import('./unit/ws/ws-cooldowns.tests');
|
||||
})();
|
||||
|
||||
// needs to be here, or tests won't run
|
||||
|
Loading…
x
Reference in New Issue
Block a user