Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
ff5291d
Re-written as WebCrypto
yuval-po Jun 25, 2021
3929caa
First flows
yuval-po Jun 26, 2021
999dd61
Tmp
yuval-po Jul 2, 2021
aae395a
Cryto I.S cont. + documentation
yuval-po Jul 3, 2021
e792354
Reverted login to be non-async
yuval-po Jul 3, 2021
c504bec
Merge branch 'develop' into cryptocore
haimkastner Jul 4, 2021
3f1188b
Cleanup, initial integration, lint rules
yuval-po Jul 16, 2021
818cb8d
Added Weak Event. Needs validation
yuval-po Jul 17, 2021
71ede2d
Replaced node-sass with sass (Node16+ support)
yuval-po Aug 28, 2021
d0df8a8
Fixed lint error
yuval-po Aug 28, 2021
bdfac75
Integration Cont. (ts-events local compile!)
yuval-po Sep 11, 2021
fc551a8
Integration cont.
yuval-po Oct 2, 2021
a679d24
Fixed debouncing on NoteWrapper and set interval to 1500
yuval-po Oct 18, 2021
fc8b948
Notes socket encapsulation
yuval-po Nov 27, 2021
1b31362
Beta working
yuval-po Dec 3, 2021
af7f4a1
Basic working example
yuval-po Dec 10, 2021
0112f2d
Remove console logs
yuval-po Dec 10, 2021
0c505a2
Fixing single-note-tab state and decryption
yuval-po Dec 18, 2021
8450f9c
Added missing 'isInitialized' set
yuval-po Jan 7, 2022
2cece73
Docs
yuval-po Jan 7, 2022
e9558ad
Added 'Missing password' card when note is encrypted and password was…
yuval-po Jan 7, 2022
25ae6a9
CSS Updates + Decrypt button length check
yuval-po Jan 8, 2022
622ac0c
Add password loader
haimkastner Jan 8, 2022
7ada3f2
Add encryption mark
haimkastner Jan 8, 2022
bd91903
Add encryption component
haimkastner Jan 15, 2022
f95b38c
Log fixes
yuval-po Mar 25, 2022
dba43c8
Continued dev
yuval-po Apr 29, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,6 @@ VUE_APP_LOCAL_DEV="true"
VUE_APP_GITLAB_CLIENT_ID=""
VUE_APP_GITHUB_CLIENT_ID=""
VUE_APP_GOOGLE_CLIENT_ID=""

# The branch from which to build the OpenAPI client stubs
BACKEND_BRANCH="my-branch"
6 changes: 6 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ module.exports = {
"no-debugger": process.env.NODE_ENV === "production" ? "warn" : "off",
"vue/require-valid-default-prop": "off",
"import/no-unresolved": "off",
"@typescript-eslint/no-inferrable-types": "off",
},
overrides: [
{
Expand Down Expand Up @@ -63,6 +64,11 @@ module.exports = {
"no-continue": "off",
"no-plusplus": "off",
"no-console": "off",
"no-underscore-dangle": ["error", { "allowAfterThis": true }],
"no-trailing-spaces": "error",
"spaced-comment": ["error", "always", { "exceptions": ["#region", "#endregion"] }],
"no-return-await": "off",
"@typescript-eslint/return-await": "off",
}
},
{
Expand Down
22,073 changes: 21,645 additions & 428 deletions package-lock.json

Large diffs are not rendered by default.

14 changes: 9 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,24 @@
"prepare": "node scripts/generate-api.js"
},
"dependencies": {
"base64-js": "^1.5.1",
"core-js": "^3.6.5",
"lodash.debounce": "^4.0.8",
"primeicons": "^4.1.0",
"primevue": "^3.3.5",
"quill": "^1.3.7",
"sass": "^1.38.2",
"vue": "^3.0.0",
"vue-class-component": "^8.0.0-0",
"vue-router": "^4.0.0-0"
"vue-router": "^4.0.0-0",
"weak-event": "^2.0.5"
},
"devDependencies": {
"@types/chai": "^4.2.11",
"@types/lodash.debounce": "^4.0.6",
"@types/mocha": "^5.2.4",
"@typescript-eslint/eslint-plugin": "^4.18.0",
"@typescript-eslint/parser": "^4.18.0",
"@typescript-eslint/eslint-plugin": "^4.31.0",
"@typescript-eslint/parser": "^4.31.0",
"@vue/cli-plugin-babel": "~4.5.0",
"@vue/cli-plugin-e2e-cypress": "~4.5.0",
"@vue/cli-plugin-eslint": "~4.5.0",
Expand All @@ -50,9 +55,8 @@
"eslint-plugin-vue": "^7.12.1",
"jszip": "^3.6.0",
"node-fetch": "^2.6.1",
"node-sass": "^4.12.0",
"prettier": "^2.3.2",
"sass-loader": "^8.0.2",
"typescript": "~4.1.5"
"typescript": "^4.4.2"
}
}
22 changes: 18 additions & 4 deletions scripts/generate-api.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,23 @@
/* eslint-disable no-useless-escape */
/* eslint-disable no-multi-str */
/* eslint-disable import/no-extraneous-dependencies */
/* eslint-disable import/first */
import * as dotenv from 'dotenv';
import fs, { existsSync } from 'fs';
// load environment variable from .env file before all
if (existsSync('.env')) {
console.log('Env file exists and will be loaded');
dotenv.config();
}

import nodeFetch from 'node-fetch';
import fs from 'fs';
import path from 'path';
import jszip from 'jszip';

// #region Commons
// Build API based on develop branch, unless it's build for main branch, then use main branch API.
const ENV_BRANCH = process.env.GITHUB_REF !== 'main' ? 'develop' : 'main';
const ENV_BRANCH = process.env.BACKEND_BRANCH ?? (process.env.GITHUB_REF !== 'main' ? 'develop' : 'main');
console.log(`Generating OpenAPI client stubs for branch '${ENV_BRANCH}'`);
const SELF_NAME = 'generate-api.js';
const NODE_BUFFER = 'nodebuffer';

Expand Down Expand Up @@ -145,6 +154,11 @@ async function createApiTs(jsZip) {
return proxiesToEmit;
}

function fixChannelSpecImports(spec) {
const imports = 'import { SetNoteContentParams } from "./api";';
return spec.replace(/import.+from.+';/, imports);
}

/**
* Emits a class containing, for each class name in `proxiesToEmit` a static getter returning a dynamic proxy of the API object
* @description **Note:** This method requires that the output directory already exists. The output file may or may not exist
Expand Down Expand Up @@ -213,6 +227,6 @@ function emitProxiesFile(proxiesToEmit) {

// Download the latest channel TS spec API
const channelSpecResponse = await nodeFetch(`https://raw.githubusercontent.com/coffee-paste/coffee-paste-backend/${ENV_BRANCH}/src/core/channel.protocol.ts`);
const channelSpecBuffer = await channelSpecResponse.buffer();
fs.writeFileSync(path.join(CHANNEL_SPEC_PATH), channelSpecBuffer);
const fixedSpec = fixChannelSpecImports((await channelSpecResponse.buffer()).toString('utf-8'));
fs.writeFileSync(path.join(CHANNEL_SPEC_PATH), fixedSpec);
})();
4 changes: 2 additions & 2 deletions src/common-constants/note-constants.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Note } from '@/infrastructure/generated/api';
import { INote } from '@/infrastructure/notes/note-interfaces';

enum NoteStringPrefix {
NewNote = 'New note',
Expand All @@ -13,7 +13,7 @@ function formatNewNoteName(newNoteIndex: number) {
* @param notes The exists notes collection
* @returns The suggested new note name.
*/
export function generateNewNoteName(notes: Note[]): string {
export function generateNewNoteName(notes: INote[]): string {
// Filter out all notes that not match prefix, then map to names to string array, and sort by string value
const relevantNames = notes
.filter((n) => n.name?.startsWith(NoteStringPrefix.NewNote))
Expand Down
10 changes: 0 additions & 10 deletions src/components/common/global.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,6 @@
class GlobalConfig {
private baseDashboardUri = `${window.location.protocol}//${window.location.hostname}${window.location.port ? `:${window.location.port}` : ''}`;

private channelSession: string;

public get ChannelSession(): string {
return this.channelSession || '';
}

public set ChannelSession(channelSession: string) {
this.channelSession = channelSession;
}

public get BaseDashboardUri(): string {
return this.baseDashboardUri;
}
Expand Down
4 changes: 3 additions & 1 deletion src/components/common/interfaces/base-interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ export interface IVueMenuItem {
* @type {Function}
* @memberof IVueMenuItem
*/
command?: () => void;
// This is a somewhat generic callback function. No explicit type here
// eslint-disable-next-line @typescript-eslint/no-explicit-any
command?: (e?: any) => void;

/**
* External link to navigate when item is clicked
Expand Down
169 changes: 169 additions & 0 deletions src/components/encryption/set-encryption.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
<template>
<Card class="decryption-required-card">
<template #header>
<div :class="isDecryptionRequiredIcon" class="large-icon" />
</template>
<template #title>
<div class="password-is-required-title">{{ passwordRequiredMessage ? 'ENCRYPTED NOTE' : 'SUBMIT ENCRYPTION' }}</div>
</template>
<template #content>
<div class="content-container">
<Divider />
<div v-if="passwordRequiredMessage" class="content-line">{{ passwordRequiredMessage }}</div>
<div v-if="isPasswordBasedDecryptionRequired">
<div class="password-input">
<span class="password-input-text">{{ passwordCodeNameMessage }}</span>
<Password v-model="decryptionPassword" class="password-input-box-margins" :toggleMask="true" :feedback="false" />
<Button
:disabled="passwordDecryptButtonDisabled"
:label="passwordRequiredMessage ? 'Decrypt' : 'Submit'"
class="decrypt-button"
@click="onDecrypt"
/>
</div>
</div>
</div>
</template>
</Card>
</template>

<script lang="ts">
import { defineComponent } from 'vue';
import { PrimeIcons } from 'primevue/api';
import Password from 'primevue/password';
import { Encryption } from '@/infrastructure/generated/api';
import { ToastDuration, ToastSeverity } from '@/common-constants/prime-constants';
import { loadPassword } from '../../infrastructure/crypto/handlers/password-loader';

const SetEncryptionComponent = defineComponent({
components: { Password },
emits: {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
encryptionConfigured: (e: MouseEvent) => true,
},

props: {
passwordRequiredMessage: null,
passwordVersionCodeName: null,
encryption: null,
},

data() {
return {
isDecryptionRequiredIcon: PrimeIcons.LOCK,
decryptionPassword: '',
};
},

computed: {
isPasswordBasedDecryptionRequired(): boolean {
return this.$props.encryption === Encryption.PASSWORD;
},
passwordCodeNameMessage(): string {
return `Enter the password corresponding to the code-name '${this.$props.passwordVersionCodeName}':`;
},
passwordDecryptButtonDisabled(): boolean {
return this.decryptionPassword.length <= 0;
},
},

methods: {
onEncryptionConfigured(e: MouseEvent): void {
this.$emit('encryptionConfigured', e);
},
async onDecrypt(e: MouseEvent): Promise<void> {
const logPrefix: string = '[SetEncryptionComponent.onDecrypt]';
console.log(`${logPrefix} Preparing decryption core for encryption method ${this.$props.encryption} code ${this.$props.passwordVersionCodeName} ...`);

let succeeded = false;
if (this.$props.encryption === Encryption.PASSWORD) {
succeeded = await loadPassword(this.decryptionPassword);
}

if (!succeeded) {
console.error(
`${logPrefix} Failed to create/store a master key from a user-given password encryption method ${this.$props.encryption} code ${this.$props.passwordVersionCodeName}`
);
this.$toast.add({
severity: ToastSeverity.Warn,
summary: 'Failed to prepare decryption module',
detail: 'Please re-load the page and retry the operation',
life: ToastDuration.Long,
});
return;
}

console.log(
`${logPrefix} Successfully prepared a cryptography core for '${this.$props.encryption}' encryption, version '${this.$props.passwordVersionCodeName}'`
);

this.onEncryptionConfigured(e);
},
},
});

export const SetEncryption = SetEncryptionComponent;
export default SetEncryption;
</script>

<style lang="scss" scoped>
.decryption-required-card {
width: 80vw;
display: inline-block;
font-size: 1rem;

.password-is-required-title {
}

.p-divider-solid {
border-top-style: solid;
border-top-width: 0.15rem;
margin-top: 0.25rem;
margin-bottom: 2rem;
}

.large-icon {
font-size: 5vh;
margin-top: 3rem;
margin-bottom: 0.5rem;
}

.content-container {
width: 95%;
display: inline-block;
text-align: left;
.content-line {
&.--first {
margin-top: 0rem;
}

margin-top: 0.5rem;
margin-bottom: 0.5rem;
}
}

.password-input {
margin-top: 2em;

.password-input-text {
margin-right: 1.5rem;
}

.password-input-box-margins {
margin-top: 1rem;
margin-right: 0.8rem;
}

::v-deep(.p-password-input) {
padding-top: 0.5em;
padding-bottom: 0.5em;
width: 100%;
}

.decrypt-button {
margin-top: 0.5rem;
height: 2.3rem;
}
}
}
</style>
Loading