Fix things

This commit is contained in:
Troplo 2020-10-01 17:36:46 +10:00
parent 6991709666
commit 0cf9f72d3f
22 changed files with 622 additions and 270 deletions

View File

@ -1,5 +1,10 @@
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
"presets": [
[
"@babel/preset-env",
{
"useBuiltIns": "entry"
}
]
]
}

View File

@ -4,6 +4,7 @@
<meta charset="utf-8" name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://kit-pro.fontawesome.com/releases/v5.14.0/js/fontawesome.js">
<title>Kaverti</title>
<script src="https://polyfill.io/v3/polyfill.min.js?features=es2015%2Ces2016%2Ces2018%2Ces2019%2Ces2017%2Ces6%2Ces5%2Ces7%2Cdefault%2CIntl%2Cblissfuljs"></script>
</head>
<body>
<div id="app"></div>

View File

@ -26,7 +26,9 @@
"buefy": "^0.8.20",
"child_process": "^1.0.2",
"core-js": "^3.6.4",
"corejs": "^1.0.0",
"d3": "^4.9.1",
"es6-promise": "^4.2.8",
"fs": "0.0.1-security",
"highlight.js": "^9.10.0",
"lodash.throttle": "^4.1.1",
@ -38,7 +40,6 @@
"sass-loader": "^8.0.2",
"socket.io-client": "^2.1.1",
"vue": "^2.6.11",
"vue-analytics": "^5.22.1",
"vue-axios": "^2.0.2",
"vue-matomo": "^3.14.0-0",
"vue-router": "^2.7.0",
@ -48,10 +49,18 @@
"vuex": "^2.1.1"
},
"devDependencies": {
"@babel/core": "^7.11.6",
"@babel/plugin-proposal-class-properties": "^7.5.5",
"@babel/plugin-proposal-decorators": "^7.6.0",
"@babel/plugin-transform-runtime": "^7.6.2",
"@babel/preset-env": "^7.11.5",
"@babel/preset-typescript": "^7.6.0",
"@babel/runtime": "^7.11.2",
"@vue/cli-plugin-babel": "^4.5.2",
"@vue/cli-plugin-eslint": "~4.3.0",
"@vue/cli-service": "~4.3.0",
"babel-eslint": "^10.1.0",
"babel-loader": "^8.0.6",
"eslint": "^6.7.2",
"eslint-plugin-vue": "^6.2.2",
"vue-cli-plugin-sitemap": "^2.2.0",

View File

@ -6,6 +6,7 @@
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="/favicon.ico">
<title>Kaverti</title>
<script src="https://polyfill.io/v3/polyfill.min.js?features=es2015%2Ces2016%2Ces2018%2Ces2019%2Ces2017%2Ces6%2Ces5%2Ces7%2Cdefault%2CIntl%2Cblissfuljs"></script>
</head>
<body>
<noscript>

0
frontend/src/.babelrc.js Normal file
View File

View File

@ -38,18 +38,21 @@
<template>
<div id='app'>
<main>
<modal-window v-model='showAjaxErrorsModal' style='z-index: 100' width='25rem' :no-padding='true'>
<modal-window v-model='showAjaxErrorsModal' style='z-index: 100' width='25rem' :no-padding='true' :is-error="true">
<div slot="header">
Oh uh!
</div>
<div slot='main'>
<p :key='error' v-for='error in this.$store.state.ajaxErrors' style='margin: 1rem;'>{{error}}</p>
</div>
<button
slot='footer'
class='button button--modal'
style='z-index: 100' width='25rem'
class='button is-info'
style='z-index: 100; width: 100%;'
@click='showAjaxErrorsModal = false'
ref='ajaxErrorsModalButton'
>
OK
Okay
</button>
</modal-window>
<b-modal :can-cancel="false" :active="connModal" @update:active="value => connModal = value" v-model="connModal" full-screen>
@ -68,9 +71,10 @@
@input='closeAccountModal'
:no-padding='true'
:hide-footer='true'
:hide-header="true"
>
<tab-view
:tabs='["Register", "Login"]'
:tabs='["Register", "Login", "Recovery"]'
v-model="showAccountTab"
padding='true'
slot='main'
@ -190,6 +194,35 @@
</div>
</form>
</template>
<template slot='Recovery'>
<p style='margin-top: 0;'>
{{name}} Account Recovery
</p>
<form @submit.prevent='doRecovery'>
<fancy-input
v-model='recovery.email'
:error='recovery.errors.email'
placeholder='Email'
width='100%'
>
</fancy-input>
<div style='margin-top: 0.5rem;'>
<b-button
class='is-info'
style="width: 55%"
:loading='recovery.loading'
@click='doRecovery'
>
Send email
</b-button>
&nbsp;
<b-button style="float: right" class="is-danger-passive" @click='closeAccountModal'>
Cancel
</b-button>
</div>
</form>
</template>
</tab-view>
</modal-window>
<template>
@ -371,6 +404,15 @@
hash: ''
}
},
recovery: {
email: '',
loading: false,
errors: {
email: ''
}
},
loadingLogout: false,
showMenu: false,
connModal: true,
@ -454,8 +496,6 @@
this.$store.commit('setAdmin', res.data.admin)
this.$socket.emit('accountEvent')
this.$router.push('/')
}).catch(err => {
this.loadingLogout = false
this.ajaxErrorHandler(err)
@ -487,6 +527,15 @@
this.signup.errors.email = ''
this.signup.errors.passkey = ''
},
clearRecovery () {
this.recovery.email = ''
this.$store.commit('setToken', null)
this.$store.commit('setPassKey', null)
},
clearRecoveryErrors () {
this.recovery.errors.email = ''
},
pollConn() {
this.polling = setInterval(() => {
this.retryConnection()
@ -663,6 +712,54 @@
}
})
})
},
doRecovery () {
this.clearRecoveryErrors()
if(!this.recovery.email.trim().length) {
this.recovery.errors.email = 'Email must not be blank'
return
}
this.recovery.loading = true
this.axios.post(`/api/v1/users/recovery`, {
email: this.recovery.email
}).then(res => {
this.recovery.loading = false
this.$store.commit('setUsername', res.data.username)
this.$store.commit('setAdmin', res.data.admin)
this.closeAccountModal()
this.axios.get('/api/v1/userinfo')
.then(res => {
this.$store.commit('setUsername', res.data.username)
this.$store.commit('setEmail', res.data.email)
this.$store.commit('setEmailVerified', res.data.emailVerified)
this.$store.commit('setAdmin', res.data.admin)
this.$store.commit('setKoins', res.data.koins)
this.closeConn()
}).catch(err => {
this.showConn()
this.pollConn()
if(err.response.data.errors[0].name === 'noSettings') {
this.showConn()
this.pollConn()
} else {
this.showConn()
this.pollConn()
}
})
}).catch(e => {
this.recovery.loading = false
this.ajaxErrorHandler(e, (error) => {
let path = error.path
if(this.recovery.errors[path] !== undefined && this.recovery.errors[path] !== undefined) {
this.recovery.errors[path] = error.message
}
})
})
}
},
mounted () {

View File

@ -3,7 +3,7 @@ module.exports = function(vuex) {
let errors = []
if(res.response === undefined || res.response.data.errors === undefined) {
errors.push('Oh uh! An unknown network connection problem occurred, Please contact a Kaverti staff member for assistance. (SERV_FAIL)')
errors.push('Something went wrong connecting to the Kaverti service, maybe try again later.')
} else {
res.response.data.errors.forEach(error => {
let path = error.path

View File

@ -0,0 +1,141 @@
<template>
<modal-window class='b-dialog' :class='{"modal_window--show": value}' @click.self='closeModal'>
<div class='modal_window dialog' :class='{"modal_window--show": value}' :style='{"width": width || "20rem"}'>
<div
class='modal_window__loading_overlay'
:class='{
"modal_window__loading_overlay--show": loading
}'
>
<loading-icon></loading-icon>
</div>
<span
class='modal_window__close'
@click='closeModal'
v-if='closeButton'
>
<font-awesome-icon :icon='["fa", "times"]' />
</span>
<div class='modal_window__main' :class='{ "modal_window__main--no_padding": noPadding }'>
<slot name='main'></slot>
</div>
<div class='modal_window__footer' v-if='!hideFooter'>
<slot name='footer'></slot>
</div>
</div>
</modal-window>
</template>
<script>
import LoadingIcon from './LoadingIcon'
export default {
name: 'ModalWindow',
props: ['value', 'width', 'close-button', 'hide-footer', 'no-padding', 'loading', 'is-error'],
components: { LoadingIcon },
methods: {
closeModal () {
this.$emit('input', false)
}
}
}
</script>
<style lang='scss' scoped>
@import '../assets/scss/variables.scss';
.modal_window__overlay {
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
align-items: center;
justify-content: center;
position: fixed;
z-index: 3;
top: 0;
left: 0;
opacity: 0;
pointer-events: none;
transition: opacity 0.3s;
@at-root #{&}--show {
opacity: 1;
pointer-events: all;
transition: opacity 0.3s;
}
}
.modal_window {
box-shadow: 0 14px 28px rgba(0,0,0,0.15), 0 10px 10px rgba(0,0,0,0.10);
background-color: #fff;
opacity: 0;
position: relative;
border-radius: 0.25rem;
pointer-events: none;
transform: scale(1.1);
transition: margin-top 0.3s, opacity 0.3s, transform 0.3s;
@at-root #{&}__loading_overlay {
position: absolute;
left: 0;
top: 0;
height: 100%;
width: 100%;
z-index: 5;
background-color: rgba(0, 0, 0, 0.3);
display: flex;
align-items: center;
justify-content: center;
pointer-events: none;
opacity: 0;
transition: all 0.2s;
@at-root #{&}--show {
pointer-events: all;
opacity: 1;
}
}
@at-root #{&}__main {
padding: 0 1rem 1rem 1rem;
border-radius: 0.25rem;
@at-root #{&}--no_padding {
padding: 0;
}
}
@at-root #{&}__footer {
background-color: $color__lightgray--darkest;
border-radius: 0 0 0.25rem 0.25rem;
display: flex;
justify-content: flex-end;
padding: 0.35rem 1rem;
}
@at-root #{&}__close {
position: absolute;
right: 0.7rem;
top: 0.5rem;
transition: color 0.2s;
cursor: pointer;
color: $color__gray--darkest;
&:hover {
color: $color__darkgray--primary;
}
}
@at-root #{&}--show {
margin-top: 0;
transform: scale(1);
opacity: 1;
pointer-events: all;
transition: all 0.3s;
}
}
</style>

View File

@ -1,6 +1,6 @@
<template>
<div class='modal_window__overlay' :class='{"modal_window--show": value}' @click.self='closeModal'>
<div class='modal_window' :class='{"modal_window--show": value}' :style='{"width": width || "20rem"}'>
<div class='modal_window dialog' :class='{"modal_window--show": value}' :style='{"width": width || "20rem"}'>
<div
class='modal_window__loading_overlay'
:class='{
@ -17,12 +17,21 @@
>
<font-awesome-icon :icon='["fa", "times"]' />
</span>
<div class='modal_window__main' :class='{ "modal_window__main--no_padding": noPadding }'>
<slot name='main'></slot>
</div>
<div class='modal_window__footer' v-if='!hideFooter'>
<slot name='footer'></slot>
</div>
<header class="modal-card-head" v-if='!hideHeader'>
<p class="modal-card-title">
<slot name='header'></slot>
</p>
</header>
<section>
<div class="media">
<div class="media-content">
<slot name="main"></slot>
</div>
</div>
</section>
<footer class="modal-card-foot" v-if='!hideFooter'>
<slot name='footer'></slot>
</footer>
</div>
</div>
</template>
@ -32,7 +41,7 @@
export default {
name: 'ModalWindow',
props: ['value', 'width', 'close-button', 'hide-footer', 'no-padding', 'loading'],
props: ['value', 'width', 'close-button', 'hide-footer', 'no-padding', 'loading', 'hide-header', 'is-error'],
components: { LoadingIcon },
methods: {
closeModal () {
@ -138,4 +147,4 @@
transition: all 0.3s;
}
}
</style>
</style>

View File

@ -184,7 +184,7 @@
if(text.length) {
this.quoteY = coords.top - rootCoords.top - 30;
this.quoteX = coords.left - rootCoords.left;
this.quoteSelection = '~ ' + text.replace(/\n/g, '\n~ ') + '\n\n';
this.quoteSelection = '> ' + text.replace(/\n/g, '\n> ') + '\n\n';
this.showQuote = true;
} else {
this.showQuote = false;

View File

@ -149,7 +149,7 @@ export default {
if(text.length) {
this.quoteY = coords.top - rootCoords.top - 30;
this.quoteX = coords.left - rootCoords.left;
this.quoteSelection = '~ ' + text.replace(/\n/g, '\n~ ') + '\n\n';
this.quoteSelection = '> ' + text.replace(/\n/g, '\n> ') + '\n\n';
this.showQuote = true;
} else {
this.showQuote = false;

View File

@ -8,6 +8,7 @@
:class='{ "admin__menu__item--selected" : route.route.includes(selected) }'
@click='$router.push("/admin/" + route.route)'
>
<b-dialog>Not mobile optimized</b-dialog>
<div>
<i :class='["fas", "fa-",route.icon]' class='admin__menu__item__icon' />
</div>

View File

@ -2,7 +2,7 @@
<section class="hero is-info is-fullheight-with-navbar">
<div class="hero-body">
<div class="container">
<div class="box" v-if="!$store.state.emailVerified">
<div class="box" v-if="!$store.state.emailVerified && $store.state.username">
<article class="media">
<div class="media-content">
<center>
@ -16,7 +16,20 @@
</div>
</article>
</div>
<div class="box" v-if="$store.state.emailVerified">
<div class="box" v-if="!$store.state.username">
<article class="media">
<div class="media-content">
<center>
<i class="fas fa-envelope-open" style="color:#0a8bff; font-size: 30px;"></i>
<div class="content">
<h1>You need to be logged in to perform this action.</h1>
<p>Please login, and try again.</p>
</div>
</center>
</div>
</article>
</div>
<div class="box" v-if="$store.state.emailVerified && $store.state.username">
<article class="media">
<div class="media-content">
<center>

View File

@ -2,7 +2,7 @@
<center>
<div class="column is-9">
<h1>Privacy Policy</h1>
<h2>Last updated on the 16th of August 2020</h2>
<h2>Last updated on the 1st of October 2020</h2>
<p>Welcome to Kaverti, Kaverti is a platform that allows users to socialize and customize their avatars.</p>
<h2>Stored user information:</h2>
<p>Kaverti needs to store some user information for our platform to work, and for the best experience imaginable. So what does it store?</p>
@ -20,7 +20,7 @@
<b>
<table>
<ol>
<li><b>Koins</b> - Koins are our virtual currency, this allows users to purchase items from the marketplace, Koins can be purchased individually as one time purchases, or obtained daily, your daily Koins will increase if you buy the Premium monthly subscription which can be cancelled at any time. Your Koin count is available for everyone to see on your profile, this may be removed in the future.</li>
<li><b>Koins</b> - Koins are our virtual currency, this allows users to purchase items from the marketplace, Koins can be purchased individually as one time purchases, or obtained daily, your daily Koins will increase if you buy the Premium monthly subscription which can be cancelled at any time.</li>
<li><b>Post and thread count</b> - Kaverti keeps track of how many posts and threads you've made, and can be publicly viewable.</li>
<li><b>Join date</b> - Kaverti keeps a record on when you've created your account, and can be viewed on your profile or user list.</li>
<li><b>Updated date</b> - Kaverti keeps a record on when you've updated your post, account or Marketplace item.</li>
@ -32,7 +32,7 @@
<b>
<table>
<ol>
<li>However, we do use the Google Analytics service for keeping track on visit and website analytics, to see if we're growing or not, if you have an AdBlocker on your router, or browser, usually it blocks Google Analytics, which is perfectly fine, we do not force anyone to disable such programs to get the same experience as other people without an ad blocking program.</li>
<li>However, we do use Analytics software ("Matomo self-hosted") for keeping track on visit and website analytics, to see if we're growing or not, if you have an AdBlocker on your router, or browser, it will generally block this software, which we allow, we do not force anyone to disable such programs to get the same experience as other people without an ad blocking program, this data does not get accessed by anyone other then Kaverti, as the data is hosted on the Australian Kaverti servers for privacy reasons.</li>
</ol>
</table>
</b>

View File

@ -25,11 +25,8 @@
<span v-else-if='notification.type === "reply"'>Post reply</span>
<span>
<span class='notification_button__menu__item__header__date'>{{notification.createdAt | formatDate }}</span>
</span> <span
@click.stop='deleteNotification(notification.id)'
>&times;</span>
</span>
</div>
<br>
<div>
<span v-if='isYouOrDeleted(notification.PostNotification.User)'>
{{ notification.PostNotification.User ? 'You' : '[deleted]' }}
@ -41,6 +38,9 @@
wrote
"{{notification.PostNotification.Post.content | stripTags | truncate(50)}}"
</div>
<b-button
@click.stop='deleteNotification(notification.id)'
>Close</b-button>
</div>
<div v-if='!notifications.length'>
@ -302,16 +302,6 @@
background-color: $color__lightgray--primary;
}
@at-root #{&}--uninteracted {
background-color: rgba(13, 71, 161, 0.1);
border-bottom-color: $color__gray--darkest;
&:hover {
background-color: rgba(13, 71, 161, 0.2);
}
}
@at-root #{&}__link {
font-weight: 400;
cursor: pointer;

View File

@ -1,6 +1,7 @@
import 'babel-polyfill'
import NProgress from 'nprogress'
import io from 'socket.io-client'
import "core-js/stable";
window.onload = () => {
let div = document.createElement('div');

View File

@ -25,7 +25,7 @@ export default new Vuex.Store({
koins: '',
email: '',
emailVerified: '',
clientVersion: '0.159-stable',
clientVersion: '0.162-stable',
latestClientVersion: '',
token: null,

View File

View File

@ -75,6 +75,28 @@
semver "^5.4.1"
source-map "^0.5.0"
"@babel/core@^7.11.6":
version "7.11.6"
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.11.6.tgz#3a9455dc7387ff1bac45770650bc13ba04a15651"
integrity sha512-Wpcv03AGnmkgm6uS6k8iwhIwTrcP0m17TL1n1sy7qD0qelDu4XNeW0dN0mHfa+Gei211yDaLoEe/VlbXQzM4Bg==
dependencies:
"@babel/code-frame" "^7.10.4"
"@babel/generator" "^7.11.6"
"@babel/helper-module-transforms" "^7.11.0"
"@babel/helpers" "^7.10.4"
"@babel/parser" "^7.11.5"
"@babel/template" "^7.10.4"
"@babel/traverse" "^7.11.5"
"@babel/types" "^7.11.5"
convert-source-map "^1.7.0"
debug "^4.1.0"
gensync "^1.0.0-beta.1"
json5 "^2.1.2"
lodash "^4.17.19"
resolve "^1.3.2"
semver "^5.4.1"
source-map "^0.5.0"
"@babel/generator@^7.11.0":
version "7.11.0"
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.11.0.tgz#4b90c78d8c12825024568cbe83ee6c9af193585c"
@ -84,6 +106,15 @@
jsesc "^2.5.1"
source-map "^0.5.0"
"@babel/generator@^7.11.5", "@babel/generator@^7.11.6":
version "7.11.6"
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.11.6.tgz#b868900f81b163b4d464ea24545c61cbac4dc620"
integrity sha512-DWtQ1PV3r+cLbySoHrwn9RWEgKMBLLma4OBQloPRyDYvc5msJM9kvTLo1YnlJd1P/ZuKbdli3ijr5q3FvAF3uA==
dependencies:
"@babel/types" "^7.11.5"
jsesc "^2.5.1"
source-map "^0.5.0"
"@babel/generator@^7.9.6":
version "7.9.6"
resolved "https://npm.open-registry.dev/@babel/generator/-/generator-7.9.6.tgz#5408c82ac5de98cda0d77d8124e99fa1f2170a43"
@ -427,6 +458,11 @@
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.11.3.tgz#9e1eae46738bcd08e23e867bab43e7b95299a8f9"
integrity sha512-REo8xv7+sDxkKvoxEywIdsNFiZLybwdI7hcT5uEPyQrSMB4YQ973BfC9OOrD/81MaIjh6UxdulIQXkjmiH3PcA==
"@babel/parser@^7.11.5":
version "7.11.5"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.11.5.tgz#c7ff6303df71080ec7a4f5b8c003c58f1cf51037"
integrity sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q==
"@babel/parser@^7.7.0", "@babel/parser@^7.8.6", "@babel/parser@^7.9.6":
version "7.9.6"
resolved "https://npm.open-registry.dev/@babel/parser/-/parser-7.9.6.tgz#3b1bbb30dabe600cd72db58720998376ff653bc7"
@ -441,7 +477,7 @@
"@babel/helper-remap-async-to-generator" "^7.10.4"
"@babel/plugin-syntax-async-generators" "^7.8.0"
"@babel/plugin-proposal-class-properties@^7.10.4":
"@babel/plugin-proposal-class-properties@^7.10.4", "@babel/plugin-proposal-class-properties@^7.5.5":
version "7.10.4"
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.10.4.tgz#a33bf632da390a59c7a8c570045d1115cd778807"
integrity sha512-vhwkEROxzcHGNu2mzUC0OFFNXdZ4M23ib8aRRcJSsW8BZK9pQMD7QB7csl97NBbgGZO7ZyHUyKDnxzOaP4IrCg==
@ -457,6 +493,15 @@
"@babel/helper-create-class-features-plugin" "^7.8.3"
"@babel/helper-plugin-utils" "^7.8.3"
"@babel/plugin-proposal-decorators@^7.6.0":
version "7.10.5"
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.10.5.tgz#42898bba478bc4b1ae242a703a953a7ad350ffb4"
integrity sha512-Sc5TAQSZuLzgY0664mMDn24Vw2P8g/VhyLyGPaWiHahhgLqeZvcGeyBZOrJW0oSKIK2mvQ22a1ENXBIQLhrEiQ==
dependencies:
"@babel/helper-create-class-features-plugin" "^7.10.5"
"@babel/helper-plugin-utils" "^7.10.4"
"@babel/plugin-syntax-decorators" "^7.10.4"
"@babel/plugin-proposal-decorators@^7.8.3":
version "7.8.3"
resolved "https://npm.open-registry.dev/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.8.3.tgz#2156860ab65c5abf068c3f67042184041066543e"
@ -578,6 +623,13 @@
dependencies:
"@babel/helper-plugin-utils" "^7.10.4"
"@babel/plugin-syntax-decorators@^7.10.4":
version "7.10.4"
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.10.4.tgz#6853085b2c429f9d322d02f5a635018cdeb2360c"
integrity sha512-2NaoC6fAk2VMdhY1eerkfHV+lVYC1u8b+jmRJISqANCJlTxYy19HGdIkkQtix2UtkcPuPu+IlDgrVseZnU03bw==
dependencies:
"@babel/helper-plugin-utils" "^7.10.4"
"@babel/plugin-syntax-decorators@^7.8.3":
version "7.8.3"
resolved "https://npm.open-registry.dev/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.8.3.tgz#8d2c15a9f1af624b0025f961682a9d53d3001bda"
@ -892,6 +944,16 @@
resolve "^1.8.1"
semver "^5.5.1"
"@babel/plugin-transform-runtime@^7.6.2":
version "7.11.5"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.11.5.tgz#f108bc8e0cf33c37da031c097d1df470b3a293fc"
integrity sha512-9aIoee+EhjySZ6vY5hnLjigHzunBlscx9ANKutkeWTJTx6m5Rbq6Ic01tLvO54lSusR+BxV7u4UDdCmXv5aagg==
dependencies:
"@babel/helper-module-imports" "^7.10.4"
"@babel/helper-plugin-utils" "^7.10.4"
resolve "^1.8.1"
semver "^5.5.1"
"@babel/plugin-transform-shorthand-properties@^7.10.4":
version "7.10.4"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.10.4.tgz#9fd25ec5cdd555bb7f473e5e6ee1c971eede4dd6"
@ -1028,6 +1090,80 @@
levenary "^1.1.1"
semver "^5.5.0"
"@babel/preset-env@^7.11.5":
version "7.11.5"
resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.11.5.tgz#18cb4b9379e3e92ffea92c07471a99a2914e4272"
integrity sha512-kXqmW1jVcnB2cdueV+fyBM8estd5mlNfaQi6lwLgRwCby4edpavgbFhiBNjmWA3JpB/yZGSISa7Srf+TwxDQoA==
dependencies:
"@babel/compat-data" "^7.11.0"
"@babel/helper-compilation-targets" "^7.10.4"
"@babel/helper-module-imports" "^7.10.4"
"@babel/helper-plugin-utils" "^7.10.4"
"@babel/plugin-proposal-async-generator-functions" "^7.10.4"
"@babel/plugin-proposal-class-properties" "^7.10.4"
"@babel/plugin-proposal-dynamic-import" "^7.10.4"
"@babel/plugin-proposal-export-namespace-from" "^7.10.4"
"@babel/plugin-proposal-json-strings" "^7.10.4"
"@babel/plugin-proposal-logical-assignment-operators" "^7.11.0"
"@babel/plugin-proposal-nullish-coalescing-operator" "^7.10.4"
"@babel/plugin-proposal-numeric-separator" "^7.10.4"
"@babel/plugin-proposal-object-rest-spread" "^7.11.0"
"@babel/plugin-proposal-optional-catch-binding" "^7.10.4"
"@babel/plugin-proposal-optional-chaining" "^7.11.0"
"@babel/plugin-proposal-private-methods" "^7.10.4"
"@babel/plugin-proposal-unicode-property-regex" "^7.10.4"
"@babel/plugin-syntax-async-generators" "^7.8.0"
"@babel/plugin-syntax-class-properties" "^7.10.4"
"@babel/plugin-syntax-dynamic-import" "^7.8.0"
"@babel/plugin-syntax-export-namespace-from" "^7.8.3"
"@babel/plugin-syntax-json-strings" "^7.8.0"
"@babel/plugin-syntax-logical-assignment-operators" "^7.10.4"
"@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0"
"@babel/plugin-syntax-numeric-separator" "^7.10.4"
"@babel/plugin-syntax-object-rest-spread" "^7.8.0"
"@babel/plugin-syntax-optional-catch-binding" "^7.8.0"
"@babel/plugin-syntax-optional-chaining" "^7.8.0"
"@babel/plugin-syntax-top-level-await" "^7.10.4"
"@babel/plugin-transform-arrow-functions" "^7.10.4"
"@babel/plugin-transform-async-to-generator" "^7.10.4"
"@babel/plugin-transform-block-scoped-functions" "^7.10.4"
"@babel/plugin-transform-block-scoping" "^7.10.4"
"@babel/plugin-transform-classes" "^7.10.4"
"@babel/plugin-transform-computed-properties" "^7.10.4"
"@babel/plugin-transform-destructuring" "^7.10.4"
"@babel/plugin-transform-dotall-regex" "^7.10.4"
"@babel/plugin-transform-duplicate-keys" "^7.10.4"
"@babel/plugin-transform-exponentiation-operator" "^7.10.4"
"@babel/plugin-transform-for-of" "^7.10.4"
"@babel/plugin-transform-function-name" "^7.10.4"
"@babel/plugin-transform-literals" "^7.10.4"
"@babel/plugin-transform-member-expression-literals" "^7.10.4"
"@babel/plugin-transform-modules-amd" "^7.10.4"
"@babel/plugin-transform-modules-commonjs" "^7.10.4"
"@babel/plugin-transform-modules-systemjs" "^7.10.4"
"@babel/plugin-transform-modules-umd" "^7.10.4"
"@babel/plugin-transform-named-capturing-groups-regex" "^7.10.4"
"@babel/plugin-transform-new-target" "^7.10.4"
"@babel/plugin-transform-object-super" "^7.10.4"
"@babel/plugin-transform-parameters" "^7.10.4"
"@babel/plugin-transform-property-literals" "^7.10.4"
"@babel/plugin-transform-regenerator" "^7.10.4"
"@babel/plugin-transform-reserved-words" "^7.10.4"
"@babel/plugin-transform-shorthand-properties" "^7.10.4"
"@babel/plugin-transform-spread" "^7.11.0"
"@babel/plugin-transform-sticky-regex" "^7.10.4"
"@babel/plugin-transform-template-literals" "^7.10.4"
"@babel/plugin-transform-typeof-symbol" "^7.10.4"
"@babel/plugin-transform-unicode-escapes" "^7.10.4"
"@babel/plugin-transform-unicode-regex" "^7.10.4"
"@babel/preset-modules" "^0.1.3"
"@babel/types" "^7.11.5"
browserslist "^4.12.0"
core-js-compat "^3.6.2"
invariant "^2.2.2"
levenary "^1.1.1"
semver "^5.5.0"
"@babel/preset-modules@^0.1.3":
version "0.1.3"
resolved "https://npm.open-registry.dev/@babel/preset-modules/-/preset-modules-0.1.3.tgz#13242b53b5ef8c883c3cf7dddd55b36ce80fbc72"
@ -1047,7 +1183,7 @@
"@babel/helper-plugin-utils" "^7.10.4"
"@babel/plugin-transform-typescript" "^7.10.4"
"@babel/runtime@^7.0.0", "@babel/runtime@^7.11.0":
"@babel/runtime@^7.0.0", "@babel/runtime@^7.11.0", "@babel/runtime@^7.11.2":
version "7.11.2"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.11.2.tgz#f549c13c754cc40b87644b9fa9f09a6a95fe0736"
integrity sha512-TeWkU52so0mPtDcaCTxNBI/IHiz0pZgr8VEFqXFtZWpYD08ZB6FaSwVAS8MKRQAP3bYKiVjwysOJgMFY28o6Tw==
@ -1094,6 +1230,21 @@
globals "^11.1.0"
lodash "^4.17.19"
"@babel/traverse@^7.11.5":
version "7.11.5"
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.11.5.tgz#be777b93b518eb6d76ee2e1ea1d143daa11e61c3"
integrity sha512-EjiPXt+r7LiCZXEfRpSJd+jUMnBd4/9OUv7Nx3+0u9+eimMwJmG0Q98lw4/289JCoxSE8OolDMNZaaF/JZ69WQ==
dependencies:
"@babel/code-frame" "^7.10.4"
"@babel/generator" "^7.11.5"
"@babel/helper-function-name" "^7.10.4"
"@babel/helper-split-export-declaration" "^7.11.0"
"@babel/parser" "^7.11.5"
"@babel/types" "^7.11.5"
debug "^4.1.0"
globals "^11.1.0"
lodash "^4.17.19"
"@babel/traverse@^7.7.0", "@babel/traverse@^7.9.6":
version "7.9.6"
resolved "https://npm.open-registry.dev/@babel/traverse/-/traverse-7.9.6.tgz#5540d7577697bf619cc57b92aa0f1c231a94f442"
@ -1118,6 +1269,15 @@
lodash "^4.17.19"
to-fast-properties "^2.0.0"
"@babel/types@^7.11.5":
version "7.11.5"
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.11.5.tgz#d9de577d01252d77c6800cee039ee64faf75662d"
integrity sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==
dependencies:
"@babel/helper-validator-identifier" "^7.10.4"
lodash "^4.17.19"
to-fast-properties "^2.0.0"
"@babel/types@^7.4.4", "@babel/types@^7.7.0", "@babel/types@^7.8.3", "@babel/types@^7.8.6", "@babel/types@^7.9.5", "@babel/types@^7.9.6":
version "7.9.6"
resolved "https://npm.open-registry.dev/@babel/types/-/types-7.9.6.tgz#2c5502b427251e9de1bd2dff95add646d95cc9f7"
@ -2113,7 +2273,7 @@ babel-eslint@^10.1.0:
eslint-visitor-keys "^1.0.0"
resolve "^1.12.0"
babel-loader@^8.1.0:
babel-loader@^8.0.6, babel-loader@^8.1.0:
version "8.1.0"
resolved "https://npm.open-registry.dev/babel-loader/-/babel-loader-8.1.0.tgz#c611d5112bd5209abe8b9fa84c3e4da25275f1c3"
integrity sha512-7q7nC1tYOrqvUrN3LQK4GwSk/TQorZSOlO9C+RZDZpODgyN4ZlCqE5q9cDsyWOliN+aU9B4JX01xK9eJXowJLw==
@ -3122,6 +3282,11 @@ core-util-is@1.0.2, core-util-is@~1.0.0:
resolved "https://npm.open-registry.dev/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
corejs@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/corejs/-/corejs-1.0.0.tgz#6d19351be6bb85ec96c60fd69c9ce087ad3f0d66"
integrity sha1-bRk1G+a7heyWxg/WnJzgh60/DWY=
cosmiconfig@^5.0.0:
version "5.2.1"
resolved "https://npm.open-registry.dev/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a"
@ -4212,6 +4377,11 @@ es-to-primitive@^1.2.1:
is-date-object "^1.0.1"
is-symbol "^1.0.2"
es6-promise@^4.2.8:
version "4.2.8"
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a"
integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==
escalade@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.0.2.tgz#6a580d70edb87880f22b4c91d0d56078df6962c4"
@ -9710,11 +9880,6 @@ vm-browserify@^1.0.1:
resolved "https://npm.open-registry.dev/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0"
integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==
vue-analytics@^5.22.1:
version "5.22.1"
resolved "https://registry.yarnpkg.com/vue-analytics/-/vue-analytics-5.22.1.tgz#9d6b32da56daee1b9dfb23a267b50349a03f710f"
integrity sha512-HPKQMN7gfcUqS5SxoO0VxqLRRSPkG1H1FqglsHccz6BatBatNtm/Vyy8brApktZxNCfnAkrSVDpxg3/FNDeOgQ==
vue-axios@^2.0.2:
version "2.1.5"
resolved "https://npm.open-registry.dev/vue-axios/-/vue-axios-2.1.5.tgz#1af4bf1218ed71309c76afb38d0f683e312c24a7"

View File

@ -47,7 +47,7 @@ let Errors = {
401
],
requestNotAuthorized: [
'You do not have sufficient permissions to do that action.',
'You aren\'t logged in, or you don\'t have permissions to perform this action.',
401
],
verifyEmail: [

View File

@ -31,89 +31,7 @@ function setUserSession(req, res, username, UserId, admin) {
if(admin) { req.session.admin = true }
}
router.post('/email-send', emailLimiter, async (req, res, next) => {
const mailGenerator = new MailGen({
theme: 'salted',
product: {
name: 'Kaverti',
link: 'https://kaverti.com'
},
})
let queryObj = {
attributes: {include: ['email', 'emailVerified', 'emailToken', 'username']},
where: {username: req.session.username}
}
let user = await User.findOne(queryObj)
await user.rand()
const verifyEmail = {
body: {
name: user.username,
intro: 'Welcome to Kaverti',
action: {
instructions: 'Please verify your account via the button below',
button: {
color: '#33b5e5',
text: 'Verify account',
link: 'https://kaverti.com/verify/?token=' + user.emailToken,
},
},
},
}
const emailTemplate = mailGenerator.generate(verifyEmail)
const message = {
to: user.email,
from: 'automailer@kaverti.com',
subject: 'Kaverti account verification',
html: emailTemplate
}
const sendMail = async () => {
try {
sgMail.setApiKey("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")
return sgMail.send(message)
} catch (error) {
throw new Error(error.message)
}
}
try {
if(user.emailVerified) {
throw Errors.alreadyVerified
} else {
const sent = await sendMail()
if (sent) {
res.send({ message: 'Email has been sent, check your spam if you can\'t find it!' })
}
}
} catch (error) {
throw new Error(error.message)
}
});
router.get('/email-verify/:token', async (req, res) => {
try {
let queryObj = {
attributes: {include: ['emailToken', 'emailVerified']},
where: { username: req.session.username }
}
let user = await User.findOne(queryObj)
if (user.emailToken == req.params.token) {
user.emailVerify()
res.status(200)
res.json({
success: "true"
})
} else {
res.status(400)
res.json({
errors: [Errors.invalidParameter('token', 'Invalid token')]
})
}
} catch (e) {
res.status(400)
res.json({
errors: [Errors.invalidParameter('token', 'Invalid token')]
})
}
});
router.post('/oidfhuisadhi8243', emailLimiter, async (req, res) => {
try {
await Ban.isIpBanned(req.ip)
@ -326,61 +244,6 @@ router.get('/:username/picture', async (req, res, next) => {
}
} catch (e) { next(e) }
})
router.all('*', (req, res, next) => {
if(req.session.username) {
next()
} else {
res.status(401)
res.json({
errors: [Errors.requestNotAuthorized]
})
}
})
router.put('/:username', async (req, res, next) => {
try {
if(req.session.username !== req.params.username) {
throw Errors.requestNotAuthorized
}
await Ban.ReadOnlyMode(req.session.username)
if(req.autosan.body.description !== undefined) {
let user = await User.update({ description: req.autosan.body.description }, { where: {
username: req.session.username
}})
res.json({ success: true })
} else if(
req.body.currentPassword !== undefined &&
req.body.newPassword !== undefined
) {
let user = await User.findOne({
where: {
username: req.session.username
}
})
await user.updatePassword(req.body.currentPassword, req.body.newPassword)
res.json({success: true})
} else if(
req.body.emailCurrentPassword !== undefined &&
req.body.newEmail !== undefined
) {
let user = await User.findOne({where: {
username: req.session.username
}})
await user.updateEmail(req.body.emailCurrentPassword, req.body.newEmail)
res.json({ success: true })
} else {
res.json({ success: false })
}
} catch (e) { next(e) }
})
router.get('/', async function(req, res) {
try {
let sortFields = {
@ -441,4 +304,58 @@ router.get('/', async function(req, res) {
}
})
router.all('*', (req, res, next) => {
if(req.session.username) {
next()
} else {
res.status(401)
res.json({
errors: [Errors.requestNotAuthorized]
})
}
})
router.put('/:username', async (req, res, next) => {
try {
if(req.session.username !== req.params.username) {
throw Errors.requestNotAuthorized
}
await Ban.ReadOnlyMode(req.session.username)
if(req.autosan.body.description !== undefined) {
let user = await User.update({ description: req.autosan.body.description }, { where: {
username: req.session.username
}})
res.json({ success: true })
} else if(
req.body.currentPassword !== undefined &&
req.body.newPassword !== undefined
) {
let user = await User.findOne({
where: {
username: req.session.username
}
})
await user.updatePassword(req.body.currentPassword, req.body.newPassword)
res.json({success: true})
} else if(
req.body.emailCurrentPassword !== undefined &&
req.body.newEmail !== undefined
) {
let user = await User.findOne({where: {
username: req.session.username
}})
await user.updateEmail(req.body.emailCurrentPassword, req.body.newEmail)
res.json({ success: true })
} else {
res.json({ success: false })
}
} catch (e) { next(e) }
})
module.exports = router;

View File

@ -31,89 +31,7 @@ function setUserSession(req, res, username, UserId, admin) {
if(admin) { req.session.admin = true }
}
router.post('/email-send', emailLimiter, async (req, res, next) => {
const mailGenerator = new MailGen({
theme: 'salted',
product: {
name: 'Kaverti',
link: 'https://kaverti.com'
},
})
let queryObj = {
attributes: {include: ['email', 'emailVerified', 'emailToken', 'username']},
where: {username: req.session.username}
}
let user = await User.findOne(queryObj)
await user.rand()
const verifyEmail = {
body: {
name: user.username,
intro: 'Welcome to Kaverti',
action: {
instructions: 'Please verify your account via the button below',
button: {
color: '#33b5e5',
text: 'Verify account',
link: 'https://kaverti.com/verify/?token=' + user.emailToken,
},
},
},
}
const emailTemplate = mailGenerator.generate(verifyEmail)
const message = {
to: user.email,
from: 'automailer@kaverti.com',
subject: 'Kaverti account verification',
html: emailTemplate
}
const sendMail = async () => {
try {
sgMail.setApiKey("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")
return sgMail.send(message)
} catch (error) {
throw new Error(error.message)
}
}
try {
if(user.emailVerified) {
throw Errors.alreadyVerified
} else {
const sent = await sendMail()
if (sent) {
res.send({ message: 'Email has been sent, check your spam if you can\'t find it!' })
}
}
} catch (error) {
throw new Error(error.message)
}
});
router.get('/email-verify/:token', async (req, res) => {
try {
let queryObj = {
attributes: {include: ['emailToken', 'emailVerified']},
where: { username: req.session.username }
}
let user = await User.findOne(queryObj)
if (user.emailToken == req.params.token) {
user.emailVerify()
res.status(200)
res.json({
success: "true"
})
} else {
res.status(400)
res.json({
errors: [Errors.invalidParameter('token', 'Invalid token')]
})
}
} catch (e) {
res.status(400)
res.json({
errors: [Errors.invalidParameter('token', 'Invalid token')]
})
}
});
router.post('/oidfhuisadhi8243', async (req, res) => {
try {
await Ban.isIpBanned(req.ip)
@ -343,4 +261,88 @@ router.get('/', async function(req, res) {
}
})
router.post('/email-send', emailLimiter, async (req, res, next) => {
const mailGenerator = new MailGen({
theme: 'salted',
product: {
name: 'Kaverti',
link: 'https://kaverti.com'
},
})
let queryObj = {
attributes: {include: ['email', 'emailVerified', 'emailToken', 'username']},
where: {username: req.session.username}
}
let user = await User.findOne(queryObj)
await user.rand()
const verifyEmail = {
body: {
name: user.username,
intro: 'Welcome to Kaverti',
action: {
instructions: 'Please verify your account via the button below',
button: {
color: '#33b5e5',
text: 'Verify account',
link: 'https://kaverti.com/verify/?token=' + user.emailToken,
},
},
},
}
const emailTemplate = mailGenerator.generate(verifyEmail)
const message = {
to: user.email,
from: 'automailer@kaverti.com',
subject: 'Kaverti account verification',
html: emailTemplate
}
const sendMail = async () => {
try {
sgMail.setApiKey("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")
return sgMail.send(message)
} catch (error) {
throw new Error(error.message)
}
}
try {
if(user.emailVerified) {
throw Errors.alreadyVerified
} else {
const sent = await sendMail()
if (sent) {
res.send({ message: 'Email has been sent, check your spam if you can\'t find it!' })
}
}
} catch (error) {
throw new Error(error.message)
}
});
router.get('/email-verify/:token', async (req, res) => {
try {
let queryObj = {
attributes: {include: ['emailToken', 'emailVerified']},
where: { username: req.session.username }
}
let user = await User.findOne(queryObj)
if (user.emailToken == req.params.token) {
user.emailVerify()
res.status(200)
res.json({
success: "true"
})
} else {
res.status(400)
res.json({
errors: [Errors.invalidParameter('token', 'Invalid token')]
})
}
} catch (e) {
res.status(400)
res.json({
errors: [Errors.invalidParameter('token', 'Invalid token')]
})
}
});
module.exports = router;